{"version":3,"file":"retry.min.cjs","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":["defaultUntil","response","ok","retry","delayTimer","delayRamp","defaultDelayRamp","maxAttempts","until","onRetry","retryOnNetworkError","resolveWithLatestResponse","next","opts","numberOfAttemptsMade","checkStatus","error","Promise","resolve","then","done","reject","setTimeout","url","options","values","_a","_b","delay","catch","Error"],"mappings":"mBA6FAA,EAAAC,GAAAA,GAAAA,EAAAC,GAEMC,EAAA,EAAAC,aAA4C,IAAcC,YAAAC,EAC1CC,cACrB,GAAAC,QAAAR,EAAAS,UAAA,KAAAC,sBAAA,EAAAC,4BAAA,GAAA,CAAA,IACKC,MAAsCC,KAE1B,IAAAC,EAEhB,QAQWC,GAAcd,EAAIe,IACvBC,QAAAC,QAAuBV,EAACP,EAAAe,IAAAG,MAAAC,GAGZA,EA8BTnB,GAAAU,EAAAV,EAAAe,EAAAC,QAAAI,OAAAL,GAAAf,QA5BMM,GAAEO,GAAAP,EAGJ,IAAAU,SAAmCC,mBAE/BI,YAAW,KACkB,mBAApBb,EACdQ,QAAgBC,QAAAT,EAAA,CACVR,WACKe,QACLO,MACAC,QAAKX,KACLM,MAAG,CAAAM,EAAA,CAAA,KACH,IAAAC,IACER,EAAMN,EAAe,QAANc,EAAMD,GAAAA,EAAAF,WAAA,IAAAG,EAAAA,EAAAH,EAAA,QAAAI,EAAAF,GAAAA,EAAAD,eAAA,IAAAG,EAAAA,EAAAd,GAAA,IAG1BK,EAAAN,EAAAW,EAAAV,GAAM,GACLe,EAAA,IACDT,KAAAJ,GAAAc,OAAAb,IACF,IAAON,EACF,MAAAM,EACN,OAAwBD,EAAA,KAAAC,EAAA,IAI3Bf,GAAAU,EAAAV,EAAAgB,QAAAI,OAAAL,GAAA,IAAAc,MAAA,oCAML,OAAElB,EAAAW,EAAAV,GACHM,KAAAJ,UAEUC,IACR,IAAIN,EACJ,MAAMM,EACL,OAAwBD,EAAA,KAAAC,EAAA,GACtB,SAIVb"}