{"version":3,"file":"retry.min.mjs","sources":["../../../src/middlewares/retry.ts"],"sourcesContent":["import type { ConfiguredMiddleware, WretchOptions } from \"../types.js\"\n\n/* Types */\n\nexport type DelayRampFunction = (delay: number, nbOfAttempts: number) => number\nexport type UntilFunction = (response?: Response, error?: Error) => boolean | Promise<boolean>\nexport type OnRetryFunctionResponse = { url?: string; options?: WretchOptions } | undefined\nexport type OnRetryFunction = (args: {\n  response?: Response,\n  error?: Error,\n  url: string,\n  options: WretchOptions\n}) => void | OnRetryFunctionResponse | Promise<OnRetryFunctionResponse>\nexport type RetryOptions = {\n  /**\n   * The timer between each attempt in milliseconds.\n   *\n   * _Default: `500`_\n   */\n  delayTimer?: number,\n  /**\n   * The custom function that is used to calculate the actual delay based on the the timer & the number of attemps.\n   *\n   * _Default: `delay * nbOfAttemps`_\n   */\n  delayRamp?: DelayRampFunction,\n  /**\n   * The maximum number of retries before resolving the promise with the last error. Specifying 0 means infinite retries.\n   *\n   * _Default: `10`_\n   */\n  maxAttempts?: number,\n  /**\n   * The request will be retried until that condition is satisfied.\n   *\n   * _Default: `response && response.ok`_\n   */\n  until?: UntilFunction,\n  /**\n   * Callback that will get executed before retrying the request. If this function returns an object having url and/or options properties, they will override existing values in the retried request.\n   *\n   * _Default: `undefined`_\n   */\n  onRetry?: OnRetryFunction,\n  /**\n   * If true, will retry the request if a network error was thrown. Will also provide an 'error' argument to the `onRetry` and `until` methods.\n   *\n   * _Default: `false`_\n   */\n  retryOnNetworkError?: boolean,\n  /**\n   * If true, the request will be resolved with the latest response instead of rejected with an error.\n   *\n   * _Default: `false`_\n   */\n  resolveWithLatestResponse?: boolean\n}\n\n/**\n * ## Retry middleware\n *\n * #### Retries a request multiple times in case of an error (or until a custom condition is true).\n *\n * ```ts\n * import wretch from 'wretch'\n * import { retry } from 'wretch/middlewares'\n *\n * wretch().middlewares([\n *   retry({\n *     // Options - defaults below\n *     delayTimer: 500,\n *     delayRamp: (delay, nbOfAttempts) => delay * nbOfAttempts,\n *     maxAttempts: 10,\n *     until: (response, error) => response && response.ok,\n *     onRetry: null,\n *     retryOnNetworkError: false,\n *     resolveWithLatestResponse: false\n *   })\n * ])\n *\n * // You can also return a Promise, which is useful if you want to inspect the body:\n * wretch().middlewares([\n *   retry({\n *     until: response =>\n *       response.clone().json().then(body =>\n *         body.field === 'something'\n *       )\n *   })\n * ])\n * ```\n */\nexport type RetryMiddleware = (options?: RetryOptions) => ConfiguredMiddleware\n\n/* Defaults */\n\nconst defaultDelayRamp: DelayRampFunction = (delay, nbOfAttempts) => (\n  delay * nbOfAttempts\n)\nconst defaultUntil: UntilFunction = response => response && response.ok\n\nexport const retry: RetryMiddleware = ({\n  delayTimer = 500,\n  delayRamp = defaultDelayRamp,\n  maxAttempts = 10,\n  until = defaultUntil,\n  onRetry = null,\n  retryOnNetworkError = false,\n  resolveWithLatestResponse = false\n} = {}) => {\n\n  return next => (url, opts) => {\n    let numberOfAttemptsMade = 0\n\n    const checkStatus = (response?: Response, error?: Error) => {\n      return Promise.resolve(until(response, error)).then(done => {\n        // If the response is not suitable\n        if (!done) {\n          numberOfAttemptsMade++\n\n          if (!maxAttempts || numberOfAttemptsMade <= maxAttempts) {\n            // We need to recurse until we have a correct response and chain the checks\n            return new Promise(resolve => {\n              const delay = delayRamp(delayTimer, numberOfAttemptsMade)\n              setTimeout(() => {\n                if (typeof onRetry === \"function\") {\n                  Promise.resolve(onRetry({\n                    response,\n                    error,\n                    url,\n                    options: opts\n                  })).then((values = {}) => {\n                    resolve(next((values && values.url) ?? url, (values && values.options) ?? opts))\n                  })\n                } else {\n                  resolve(next(url, opts))\n                }\n              }, delay)\n            }).then(checkStatus).catch(error => {\n              if (!retryOnNetworkError)\n                throw error\n              return checkStatus(null, error)\n            })\n          } else {\n            return !!response && resolveWithLatestResponse ? response : Promise.reject(error || new Error(\"Number of attempts exceeded.\"))\n          }\n        }\n\n        return !!response && resolveWithLatestResponse ? response : error ? Promise.reject(error) : response\n      })\n    }\n\n    return next(url, opts)\n      .then(checkStatus)\n      .catch(error => {\n        if (!retryOnNetworkError)\n          throw error\n        return checkStatus(null, error)\n      })\n  }\n}\n"],"names":["defaultDelayRamp","delay","nbOfAttempts","defaultUntil","response","ok","retry","delayTimer","delayRamp","maxAttempts","until","onRetry","retryOnNetworkError","resolveWithLatestResponse","next","url","opts","numberOfAttemptsMade","checkStatus","error","Promise","resolve","then","done","reject","setTimeout","options","values","_a","_b","catch","Error"],"mappings":"AA+FA,MAAMA,EAAsC,CAACC,EAAOC,IAClDD,EAAQC,EAEJC,EAA8BC,GAAYA,GAAYA,EAASC,GAExDC,EAAyB,EACpCC,aAAa,IACbC,YAAYR,EACZS,cAAc,GACdC,QAAQP,EACRQ,UAAU,KACVC,sBAAsB,EACtBC,4BAA4B,GAC1B,KAEKC,GAAQ,CAACC,EAAKC,KACnB,IAAIC,EAAuB,EAE3B,MAAMC,EAAc,CAACd,EAAqBe,IACjCC,QAAQC,QAAQX,EAAMN,EAAUe,IAAQG,MAAKC,GAE7CA,EA+BInB,GAAYS,EAA4BT,EAAWe,EAAQC,QAAQI,OAAOL,GAASf,GA9B1Fa,KAEKR,GAAeQ,GAAwBR,EAEnC,IAAIW,SAAQC,IACjB,MAAMpB,EAAQO,EAAUD,EAAYU,GACpCQ,YAAW,KACc,mBAAZd,EACTS,QAAQC,QAAQV,EAAQ,CACtBP,WACAe,QACAJ,MACAW,QAASV,KACPM,MAAK,CAACK,EAAS,CAAA,aACjBN,EAAQP,EAA+B,QAA1Bc,EAACD,GAAUA,EAAOZ,WAAQ,IAAAa,EAAAA,EAAAb,EAAmC,QAA9Bc,EAACF,GAAUA,EAAOD,eAAY,IAAAG,EAAAA,EAAAb,GAAM,IAGlFK,EAAQP,EAAKC,EAAKC,GACnB,GACAf,EAAM,IACRqB,KAAKJ,GAAaY,OAAMX,IACzB,IAAKP,EACH,MAAMO,EACR,OAAOD,EAAY,KAAMC,EAAM,IAGxBf,GAAYS,EAA4BT,EAAWgB,QAAQI,OAAOL,GAAS,IAAIY,MAAM,oCAQtG,OAAOjB,EAAKC,EAAKC,GACdM,KAAKJ,GACLY,OAAMX,IACL,IAAKP,EACH,MAAMO,EACR,OAAOD,EAAY,KAAMC,EAAM,GAC/B"}