{"version":3,"file":"index.mjs","sources":[""],"sourcesContent":["export type TRetryOptions = {\n  backoff?: number;\n  baseDelay?: number;\n  maxDelay?: number;\n  maxRetries?: number;\n  onRetry?: (error: unknown, retry: number) => void;\n  shouldRetry?: (error: unknown, retry: number) => boolean | Promise<boolean>;\n  signal?: AbortSignal | null;\n};\n\nexport type TGetRetriedFnArgs = Parameters<typeof getRetriedFn>;\n\nexport type TGetRetriedFnReturn = ReturnType<typeof getRetriedFn>;\n\nconst getAbortReason = (signal: AbortSignal): unknown => {\n  return signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\");\n};\n\nconst waitForRetry = async (delay: number, signal: AbortSignal | null): Promise<void> => {\n  if (signal?.aborted) {\n    throw getAbortReason(signal);\n  }\n  await new Promise<void>((resolve, reject) => {\n    const timer = setTimeout(() => {\n      signal?.removeEventListener(\"abort\", abort);\n      resolve();\n    }, delay);\n    const abort = (): void => {\n      clearTimeout(timer);\n      signal?.removeEventListener(\"abort\", abort);\n      reject(signal ? getAbortReason(signal) : undefined);\n    };\n    signal?.addEventListener(\"abort\", abort, { once: true });\n  });\n};\n\n/**\n * Returns an async function that retries rejected calls with exponential backoff.\n * @template T\n * @param {T} fn Source function\n * @param {TRetryOptions} [options={}] Retry policy\n * @returns {(...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>} Retrying function\n * @throws {TypeError} getRetriedFn: options are invalid\n * @example\n * const loadWithRetry = getRetriedFn(loadData, { maxRetries: 2, baseDelay: 100 });\n * @example\n * // Retry a transient API request with exponential backoff and cancellation\n * const controller = new AbortController();\n * const fetchWithRetry = getRetriedFn(fetchProducts, {\n *   maxRetries: 3,\n *   baseDelay: 250,\n *   signal: controller.signal,\n * });\n */\nexport const getRetriedFn = <T extends (...args: any[]) => any>(\n  fn: T,\n  options: TRetryOptions = {}\n): ((...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>) => {\n  if (typeof fn !== \"function\") {\n    throw new TypeError(\"getRetriedFn: fn must be a function\");\n  }\n  if (!options || typeof options !== \"object\" || Array.isArray(options)) {\n    throw new TypeError(\"getRetriedFn: options must be a plain object\");\n  }\n  const {\n    backoff = 2,\n    baseDelay = 0,\n    maxDelay = Infinity,\n    maxRetries = 2,\n    onRetry,\n    shouldRetry = () => true,\n    signal = null,\n  } = options;\n  if (!Number.isInteger(maxRetries) || maxRetries < 0) {\n    throw new TypeError(\"getRetriedFn: maxRetries must be a non-negative integer\");\n  }\n  if (typeof baseDelay !== \"number\" || !Number.isFinite(baseDelay) || baseDelay < 0) {\n    throw new TypeError(\"getRetriedFn: baseDelay must be a non-negative finite number\");\n  }\n  if (typeof backoff !== \"number\" || !Number.isFinite(backoff) || backoff < 1) {\n    throw new TypeError(\"getRetriedFn: backoff must be a finite number greater than or equal to 1\");\n  }\n  if (typeof maxDelay !== \"number\" || Number.isNaN(maxDelay) || maxDelay < 0) {\n    throw new TypeError(\"getRetriedFn: maxDelay must be a non-negative number or Infinity\");\n  }\n  if (typeof shouldRetry !== \"function\" || (onRetry !== undefined && typeof onRetry !== \"function\")) {\n    throw new TypeError(\"getRetriedFn: retry callbacks must be functions\");\n  }\n\n  return async function retriedFunction(\n    this: unknown,\n    ...args: Parameters<T>\n  ): Promise<Awaited<ReturnType<T>>> {\n    let retry = 0;\n    while (true) {\n      if (signal?.aborted) {\n        throw getAbortReason(signal);\n      }\n      try {\n        return await fn.apply(this, args) as Awaited<ReturnType<T>>;\n      } catch (error) {\n        retry += 1;\n        if (retry > maxRetries || !(await shouldRetry(error, retry))) {\n          throw error;\n        }\n        onRetry?.(error, retry);\n        const delay = Math.min(maxDelay, baseDelay * backoff ** (retry - 1));\n        await waitForRetry(delay, signal);\n      }\n    }\n  };\n};\n"],"names":["getAbortReason","signal","reason","DOMException","waitForRetry","async","delay","aborted","Promise","resolve","reject","timer","setTimeout","removeEventListener","abort","clearTimeout","undefined","addEventListener","once","getRetriedFn","fn","options","TypeError","Array","isArray","backoff","baseDelay","maxDelay","Infinity","maxRetries","onRetry","shouldRetry","Number","isInteger","isFinite","isNaN","retriedFunction","args","retry","apply","this","error","Math","min"],"mappings":"AAcA,MAAMA,eAAkBC,QACfA,OAAOC,QAAU,IAAIC,aAAa,4BAA6B,cAGxE,MAAMC,aAAeC,MAAOC,MAAeL,UACzC,GAAIA,QAAQM,QACV,MAAMP,eAAeC,cAEjB,IAAIO,QAAc,CAACC,QAASC,UAChC,MAAMC,MAAQC,WAAW,KACvBX,QAAQY,oBAAoB,QAASC,OACrCL,WACCH,OACH,MAAMQ,MAAQ,KACZC,aAAaJ,OACbV,QAAQY,oBAAoB,QAASC,OACrCJ,OAAOT,OAASD,eAAeC,aAAUe,IAE3Cf,QAAQgB,iBAAiB,QAASH,MAAO,CAAEI,KAAM,UAsB9C,MAAMC,aAAe,CAC1BC,GACAC,QAAyB,MAEzB,UAAWD,KAAO,WAChB,MAAM,IAAIE,UAAU,uCAEtB,IAAKD,gBAAkBA,UAAY,UAAYE,MAAMC,QAAQH,SAC3D,MAAM,IAAIC,UAAU,gDAEtB,MAAMG,QACJA,QAAU,EAACC,UACXA,UAAY,EAACC,SACbA,SAAWC,SAAQC,WACnBA,WAAa,EAACC,QACdA,QAAOC,YACPA,YAAc,IAAM,KAAI9B,OACxBA,OAAS,MACPoB,QACJ,IAAKW,OAAOC,UAAUJ,aAAeA,WAAa,EAChD,MAAM,IAAIP,UAAU,2DAEtB,UAAWI,YAAc,WAAaM,OAAOE,SAASR,YAAcA,UAAY,EAC9E,MAAM,IAAIJ,UAAU,gEAEtB,UAAWG,UAAY,WAAaO,OAAOE,SAAST,UAAYA,QAAU,EACxE,MAAM,IAAIH,UAAU,4EAEtB,UAAWK,WAAa,UAAYK,OAAOG,MAAMR,WAAaA,SAAW,EACvE,MAAM,IAAIL,UAAU,oEAEtB,UAAWS,cAAgB,YAAeD,eAAYd,UAAoBc,UAAY,WACpF,MAAM,IAAIR,UAAU,mDAGtB,OAAOjB,eAAe+B,mBAEjBC,MAEH,IAAIC,MAAQ,EACZ,MAAO,KAAM,CACX,GAAIrC,QAAQM,QACV,MAAMP,eAAeC,QAEvB,IACE,aAAamB,GAAGmB,MAAMC,KAAMH,KAC9B,CAAE,MAAOI,OACPH,OAAS,EACT,GAAIA,MAAQT,mBAAsBE,YAAYU,MAAOH,OACnD,MAAMG,MAERX,UAAUW,MAAOH,OACjB,MAAMhC,MAAQoC,KAAKC,IAAIhB,SAAUD,UAAYD,UAAYa,MAAQ,UAC3DlC,aAAaE,MAAOL,OAC5B,CACF,CACF"}