foxts
Version:
Opinionated collection of common TypeScript utils by @SukkaW
1 lines • 2.36 kB
JavaScript
import{isAbortErrorLike as t}from"../abort-error/index.mjs";import{extractErrorMessage as e,isErrorLikeObject as r}from"../extract-error-message/index.mjs";import{isNetworkError as o}from"../is-network-error/index.mjs";import{noop as i,trueFn as n}from"../noop/index.mjs";import{waitWithAbort as a}from"../wait/index.mjs";const{round:s}=Math,m=Error,c=TypeError;function f(t,e,r=0,o=!1){if(Number.isNaN(e))throw new c(`Expected \`${t}\` to be a valid number${o?" or Infinity":""}, got NaN.`);if(!o&&!Number.isFinite(e))throw new c(`Expected \`${t}\` to be a finite number.`);if(e<r)throw new c(`Expected \`${t}\` to be \u{2265} ${r}.`)}class u extends m{name="AsyncRetryAbortError";cause;constructor(t){if(super("string"==typeof t?t:e(t,!1)??"Aborted"),"string"==typeof t){const e=new m(t);e.stack=this.stack,this.cause=e}else r(t)?(this.cause=t,this.message=t.message):this.cause=t}}async function w(e,r,i,n,m){if(e instanceof u)throw e.cause;if(e instanceof c&&!o(e)||t(e))throw e;const f=i.retries-(r-1),w={error:e,attemptNumber:r,retriesLeft:f};await i.onFailedAttempt(w),r>1&&await i.onRetry(e,r-1);const h=Date.now();if(h-n>=m||r>=i.retries+1||!await i.shouldRetry(w))throw e;let d=s((i.randomize?Math.random()+1:1)*i.minTimeout*i.factor**(r-1));d>i.maxTimeout&&(d=i.maxTimeout);const y=m-(h-n);if(y<=0)throw e;let b=d;d>y&&(b=y),b>0&&await a(b,i.signal,i.unref),i.signal?.throwIfAborted()}function h(t){throw new u(t??"Aborted")}async function d(t,e={}){e.signal?.throwIfAborted();const r={...e};r.retries??=10,r.forever??=!1,r.factor??=2,r.minTimeout??=1e3,r.maxTimeout??=1/0,r.randomize??=!0,r.onFailedAttempt??=i,r.onRetry??=i,r.shouldRetry??=n,r.forever&&(r.retries=1/0),f("retries",r.retries,0,!0),f("factor",r.factor,0,!1),f("minTimeout",r.minTimeout,0,!1),f("maxTimeout",r.maxTimeout,0,!0);const o=r.maxRetryTime??1/0;f("maxRetryTime",o,0,!0),r.minTimeout<1&&(r.minTimeout=1),r.factor<=0&&(r.factor=1);let a=0;const s=Date.now();for(;a<r.retries+1;){a++;try{r.signal?.throwIfAborted();const e=await t(h,a);return r.signal?.throwIfAborted(),e}catch(e){let t=e;"object"==typeof e&&e&&"bail"in e&&e.bail&&(t=new u(e)),await w(t,a,r,s,o)}}throw new m("Retry attempts exhausted without throwing an error.")}function y(t,e){return function(...r){return d(()=>t.apply(this,r),e)}}export{u as AsyncRetryAbortError,d as asyncRetry,y as makeRetriable};