{"version":3,"file":"retry.mjs","names":[],"sources":["../src/retry.ts"],"sourcesContent":["type Milliseconds = number;\n\ntype RetryOptions = Partial<{\n  /**\n   * The initial delay before the first retry.\n   *\n   * @default 125\n   */\n  initialDelay: Milliseconds;\n  /**\n   * The maximum delay between retries.\n   * The delay between retries will never exceed this value.\n   * If set to 0, the delay will increase indefinitely.\n   *\n   * @default 0\n   */\n  maxDelayBetweenRetries: Milliseconds;\n  /**\n   * The multiplier for the exponential backoff.\n   *\n   * @default 2\n   */\n  factor: number;\n  /**\n   * A function to determine if the operation should be retried.\n   * The callback accepts the error that was thrown and the number of iterations.\n   * The iterations variable references the number of retries AFTER attempt\n   * that caused the error and starts at 1 (as in, this is the 1st, 2nd, nth retry).\n   *\n   * @default (error, iterations) => iterations < 5\n   */\n  shouldRetry: (error: unknown, iterations: number) => boolean;\n  /**\n   * Controls whether the helper should retry the operation immediately once before applying exponential backoff.\n   * The delay for the immediate retry is 100ms.\n   *\n   * @default false\n   */\n  retryImmediately: boolean;\n  /**\n   * If true, the intervals will be multiplied by a factor in the range of [1,2].\n   *\n   * @default true\n   */\n  jitter: boolean;\n\n  /**\n   * A callback that is invoked before each retry attempt.\n   * The callback receives the iteration number (starting from 1 for the first retry).\n   * This can be used to modify request parameters, add headers, etc.\n   */\n  onBeforeRetry?: (iteration: number) => void | Promise<void>;\n}>;\n\nconst defaultOptions = {\n  initialDelay: 125,\n  maxDelayBetweenRetries: 0,\n  factor: 2,\n  shouldRetry: (_: unknown, iteration: number) => iteration < 5,\n  retryImmediately: false,\n  jitter: true,\n};\n\nconst RETRY_IMMEDIATELY_DELAY = 100;\n\nconst sleep = async (ms: Milliseconds) => new Promise(s => setTimeout(s, ms));\n\nconst applyJitter = (delay: Milliseconds, jitter: boolean) => {\n  return jitter ? delay * (1 + Math.random()) : delay;\n};\n\nconst createExponentialDelayAsyncFn = (\n  opts: Required<Pick<RetryOptions, 'initialDelay' | 'maxDelayBetweenRetries' | 'factor' | 'jitter'>>,\n) => {\n  let timesCalled = 0;\n\n  const calculateDelayInMs = () => {\n    const constant = opts.initialDelay;\n    const base = opts.factor;\n    let delay = constant * Math.pow(base, timesCalled);\n    delay = applyJitter(delay, opts.jitter);\n    return Math.min(opts.maxDelayBetweenRetries || delay, delay);\n  };\n\n  return async (): Promise<void> => {\n    await sleep(calculateDelayInMs());\n    timesCalled++;\n  };\n};\n\n/**\n * Retries a callback until it succeeds or the shouldRetry function returns false.\n * See {@link RetryOptions} for the available options.\n */\nexport const retry = async <T>(callback: () => T | Promise<T>, options: RetryOptions = {}): Promise<T> => {\n  let iterations = 0;\n  const { shouldRetry, initialDelay, maxDelayBetweenRetries, factor, retryImmediately, jitter, onBeforeRetry } = {\n    ...defaultOptions,\n    ...options,\n  };\n\n  const delay = createExponentialDelayAsyncFn({\n    initialDelay,\n    maxDelayBetweenRetries,\n    factor,\n    jitter,\n  });\n\n  while (true) {\n    try {\n      return await callback();\n    } catch (e) {\n      iterations++;\n      if (!shouldRetry(e, iterations)) {\n        throw e;\n      }\n\n      if (onBeforeRetry) {\n        await onBeforeRetry(iterations);\n      }\n\n      if (retryImmediately && iterations === 1) {\n        await sleep(applyJitter(RETRY_IMMEDIATELY_DELAY, jitter));\n      } else {\n        await delay();\n      }\n    }\n  }\n};\n"],"mappings":";AAsDA,MAAM,iBAAiB;CACrB,cAAc;CACd,wBAAwB;CACxB,QAAQ;CACR,cAAc,GAAY,cAAsB,YAAY;CAC5D,kBAAkB;CAClB,QAAQ;AACV;AAEA,MAAM,0BAA0B;AAEhC,MAAM,QAAQ,OAAO,OAAqB,IAAI,SAAQ,MAAK,WAAW,GAAG,EAAE,CAAC;AAE5E,MAAM,eAAe,OAAqB,WAAoB;CAC5D,OAAO,SAAS,SAAS,IAAI,KAAK,OAAO,KAAK;AAChD;AAEA,MAAM,iCACJ,SACG;CACH,IAAI,cAAc;CAElB,MAAM,2BAA2B;EAC/B,MAAM,WAAW,KAAK;EACtB,MAAM,OAAO,KAAK;EAClB,IAAI,QAAQ,WAAW,KAAK,IAAI,MAAM,WAAW;EACjD,QAAQ,YAAY,OAAO,KAAK,MAAM;EACtC,OAAO,KAAK,IAAI,KAAK,0BAA0B,OAAO,KAAK;CAC7D;CAEA,OAAO,YAA2B;EAChC,MAAM,MAAM,mBAAmB,CAAC;EAChC;CACF;AACF;;;;;AAMA,MAAa,QAAQ,OAAU,UAAgC,UAAwB,CAAC,MAAkB;CACxG,IAAI,aAAa;CACjB,MAAM,EAAE,aAAa,cAAc,wBAAwB,QAAQ,kBAAkB,QAAQ,kBAAkB;EAC7G,GAAG;EACH,GAAG;CACL;CAEA,MAAM,QAAQ,8BAA8B;EAC1C;EACA;EACA;EACA;CACF,CAAC;CAED,OAAO,MACL,IAAI;EACF,OAAO,MAAM,SAAS;CACxB,SAAS,GAAG;EACV;EACA,IAAI,CAAC,YAAY,GAAG,UAAU,GAC5B,MAAM;EAGR,IAAI,eACF,MAAM,cAAc,UAAU;EAGhC,IAAI,oBAAoB,eAAe,GACrC,MAAM,MAAM,YAAY,yBAAyB,MAAM,CAAC;OAExD,MAAM,MAAM;CAEhB;AAEJ"}