UNPKG

foxts

Version:

Opinionated collection of common TypeScript utils by @SukkaW

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