import { focusManager } from './focusManager.mjs'; import { onlineManager } from './onlineManager.mjs'; import { sleep } from './utils.mjs'; function defaultRetryDelay(failureCount) { return Math.min(1000 * 2 ** failureCount, 30000); } function canFetch(networkMode) { return (networkMode != null ? networkMode : 'online') === 'online' ? onlineManager.isOnline() : true; } class CancelledError { constructor(options) { this.revert = options == null ? void 0 : options.revert; this.silent = options == null ? void 0 : options.silent; } } function isCancelledError(value) { return value instanceof CancelledError; } function createRetryer(config) { let isRetryCancelled = false; let failureCount = 0; let isResolved = false; let continueFn; let promiseResolve; let promiseReject; const promise = new Promise((outerResolve, outerReject) => { promiseResolve = outerResolve; promiseReject = outerReject; }); const cancel = cancelOptions => { if (!isResolved) { reject(new CancelledError(cancelOptions)); config.abort == null ? void 0 : config.abort(); } }; const cancelRetry = () => { isRetryCancelled = true; }; const continueRetry = () => { isRetryCancelled = false; }; const shouldPause = () => !focusManager.isFocused() || config.networkMode !== 'always' && !onlineManager.isOnline(); const resolve = value => { if (!isResolved) { isResolved = true; config.onSuccess == null ? void 0 : config.onSuccess(value); continueFn == null ? void 0 : continueFn(); promiseResolve(value); } }; const reject = value => { if (!isResolved) { isResolved = true; config.onError == null ? void 0 : config.onError(value); continueFn == null ? void 0 : continueFn(); promiseReject(value); } }; const pause = () => { return new Promise(continueResolve => { continueFn = value => { const canContinue = isResolved || !shouldPause(); if (canContinue) { continueResolve(value); } return canContinue; }; config.onPause == null ? void 0 : config.onPause(); }).then(() => { continueFn = undefined; if (!isResolved) { config.onContinue == null ? void 0 : config.onContinue(); } }); }; // Create loop function const run = () => { // Do nothing if already resolved if (isResolved) { return; } let promiseOrValue; // Execute query try { promiseOrValue = config.fn(); } catch (error) { promiseOrValue = Promise.reject(error); } Promise.resolve(promiseOrValue).then(resolve).catch(error => { var _config$retry, _config$retryDelay; // Stop if the fetch is already resolved if (isResolved) { return; } // Do we need to retry the request? const retry = (_config$retry = config.retry) != null ? _config$retry : 3; const retryDelay = (_config$retryDelay = config.retryDelay) != null ? _config$retryDelay : defaultRetryDelay; const delay = typeof retryDelay === 'function' ? retryDelay(failureCount, error) : retryDelay; const shouldRetry = retry === true || typeof retry === 'number' && failureCount < retry || typeof retry === 'function' && retry(failureCount, error); if (isRetryCancelled || !shouldRetry) { // We are done if the query does not need to be retried reject(error); return; } failureCount++; // Notify on fail config.onFail == null ? void 0 : config.onFail(failureCount, error); // Delay sleep(delay) // Pause if the document is not visible or when the device is offline .then(() => { if (shouldPause()) { return pause(); } return; }).then(() => { if (isRetryCancelled) { reject(error); } else { run(); } }); }); }; // Start loop if (canFetch(config.networkMode)) { run(); } else { pause().then(run); } return { promise, cancel, continue: () => { const didContinue = continueFn == null ? void 0 : continueFn(); return didContinue ? promise : Promise.resolve(); }, cancelRetry, continueRetry }; } export { CancelledError, canFetch, createRetryer, isCancelledError }; //# sourceMappingURL=retryer.mjs.map