tryo 0.13.5 → 0.13.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +15 -7
- package/dist/index.d.ts +15 -7
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var D=Object.defineProperty;var fe=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var we=(e,r,t)=>r in e?D(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var be=(e,r)=>{for(var t in r)D(e,t,{get:r[t],enumerable:!0})},he=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of Ee(r))!Te.call(e,o)&&o!==t&&D(e,o,{get:()=>r[o],enumerable:!(n=fe(r,o))||n.enumerable});return e};var Re=e=>he(D({},"__esModule",{value:!0}),e);var d=(e,r,t)=>we(e,typeof r!="symbol"?r+"":r,t);var De={};be(De,{RetryStrategies:()=>ee,TypedError:()=>f,all:()=>le,allOrThrow:()=>ce,asMilliseconds:()=>b,asRetryCount:()=>h,default:()=>S,errorRule:()=>X,orThrow:()=>ue,run:()=>ae,runOrThrow:()=>ie,tryo:()=>S});module.exports=Re(De);var f=class extends Error{constructor(t,n){var o,i;super(t);d(this,"cause");d(this,"title");d(this,"meta");d(this,"status");d(this,"raw");d(this,"path");d(this,"timestamp");d(this,"retryable");this.timestamp=Date.now(),this.retryable=(o=n.retryable)!=null?o:!0,this.name=this.constructor.name,this.cause=n.cause,this.title=n.title,this.meta=(i=n.meta)!=null?i:{},this.status=n.status,this.raw=n.raw,this.path=n.path,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}is(t){return this.code===t}withMeta(t){return Object.assign(this,{meta:t})}withStatus(t){return Object.assign(this,{status:t})}withCause(t){return Object.assign(this,{cause:t})}withPath(t){return this.path=t,this}withRaw(t){return Object.assign(this,{raw:t})}withRetryable(t){return this.retryable=t,this}toJSON(){return{name:this.name,code:this.code,title:this.title,message:this.message,timestamp:this.timestamp,retryable:this.retryable,cause:this.cause,raw:this.raw,path:this.path,stack:this.stack}}},P=class extends f{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0});d(this,"code","TIMEOUT")}};var F=class extends f{constructor(t,n){super(`Circuit breaker is open, reset after ${t}ms`,{cause:n,retryable:!1});d(this,"code","CIRCUIT_OPEN")}};var B=class extends f{constructor(t,n){super(t,{cause:n});d(this,"code","UNKNOWN")}};var b=e=>{if(e<0||!Number.isFinite(e))throw new Error(`Invalid milliseconds: must be a non-negative finite number, got ${e}`);return e},h=e=>{if(e<0||!Number.isInteger(e))throw new Error(`Invalid retry count: must be a non-negative integer, got ${e}`);return e},H=e=>{if(e<1||!Number.isInteger(e))throw new Error(`Invalid concurrency limit: must be a positive integer, got ${e}`);return e},Y=e=>{if(e<0||e>100||!Number.isFinite(e))throw new Error(`Invalid percentage: must be between 0 and 100, got ${e}`);return e};var _=class{constructor(r){d(this,"state");d(this,"config");this.config={failureThreshold:h(r.failureThreshold),resetTimeout:b(r.resetTimeout),halfOpenRequests:h(r.halfOpenRequests),shouldCountAsFailure:r.shouldCountAsFailure},this.state={state:"closed",failureCount:0,halfOpenCount:0}}async canExecute(){if(this.updateStateIfNeeded(),this.state.state==="open")return!1;if(this.state.state==="half-open"){if(this.state.halfOpenCount>=this.config.halfOpenRequests)return!1;this.state={...this.state,halfOpenCount:this.state.halfOpenCount+1}}return!0}async recordSuccess(){switch(this.state.state){case"closed":this.state={...this.state,failureCount:0};break;case"half-open":this.state={state:"closed",failureCount:0,halfOpenCount:0};break;case"open":break}}async recordFailure(r){var o,i,s;if(!((s=(i=(o=this.config).shouldCountAsFailure)==null?void 0:i.call(o,r))!=null?s:!0))return;let n=new Date;switch(this.state.state){case"closed":{let a=this.state.failureCount+1;a>=this.config.failureThreshold?this.state={state:"open",failureCount:a,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:a,lastFailureTime:n};break}case"half-open":this.state={state:"open",failureCount:this.state.failureCount+1,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break;case"open":this.state={...this.state,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break}}getState(){return this.updateStateIfNeeded(),{...this.state,canExecute:this.state.state!=="open"}}createOpenError(){let r=this.state.nextAttemptTime?b(Math.max(0,this.state.nextAttemptTime.getTime()-Date.now())):this.config.resetTimeout;return new F(r)}forceState(r){this.state={state:r,failureCount:0,halfOpenCount:0}}reset(){this.state={state:"closed",failureCount:0,halfOpenCount:0}}updateStateIfNeeded(){this.state.state==="open"&&this.state.nextAttemptTime&&new Date>=this.state.nextAttemptTime&&(this.state={...this.state,state:"half-open",halfOpenCount:0})}};var G=(e,r)=>t=>{for(let n of e){let o=n(t);if(o!==null)return o}return r(t)},Q=e=>r=>r instanceof f?r:r instanceof Error?new e(r.message,r):typeof r=="string"?new e(r):new e("Unknown error occurred",r);var Ce=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},xe=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},ge=e=>{var r;if(e instanceof Error){let t=e.message.toLowerCase();if(e.name==="TypeError"&&(t.includes("fetch")&&t.includes("failed")||t.includes("network"))||t.includes("fetch")&&t.includes("failed")||t.includes("network"))return!0}if(xe(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},ke=e=>typeof e=="object"&&e!==null,U=class{constructor(r){this.predicate=r}toCode(r){return new q(this.predicate,r)}toError(r){return t=>{var l;if(!this.predicate(t))return null;let n=r(t),o=n.code,i=Object.hasOwn(n,"cause")?n.cause:t,s=(l=n.meta)!=null?l:{};class a extends f{constructor(){let c=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:i,meta:s,status:n.status,retryable:n.retryable,raw:c,path:n.path});d(this,"code",o)}}return new a}}};function Oe(e,r){let t=new U(i=>i instanceof e);if(r)return t.toError(r);let o=i=>{if(!(i instanceof e))return null;if(i instanceof f)return i;let s=i,a=typeof s.code=="string"&&s.code.length>0?s.code:"UNKNOWN",l=Object.hasOwn(s,"cause"),u=Object.hasOwn(s,"raw");class y extends f{constructor(){super(s.message||a,{title:typeof s.title=="string"?s.title:void 0,cause:l?s.cause:i,meta:ke(s.meta)?s.meta:{},status:typeof s.status=="number"?s.status:void 0,retryable:typeof s.retryable=="boolean"?s.retryable:void 0,raw:u?s.raw:i,path:typeof s.path=="string"?s.path:void 0});d(this,"code",a)}}return new y};return o.toCode=t.toCode.bind(t),o.toError=t.toError.bind(t),o}var q=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){return t=>{var l;if(!this.predicate(t))return null;let n=r(t),o=Object.hasOwn(n,"cause")?n.cause:t,i=(l=n.meta)!=null?l:{},s=this.errorCode;class a extends f{constructor(){let p=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:o,meta:i,status:n.status,retryable:n.retryable,raw:p,path:n.path});d(this,"code",s)}}return new a}}},R={when:e=>new U(e),instance:Oe},x={typed:(e=>e instanceof f?e:null),abort:R.when(e=>e instanceof Error&&e.name==="AbortError").toCode("ABORTED").with(e=>({message:e.message||"Operation was aborted",cause:e,retryable:!1,raw:e})),timeout:R.when(e=>e instanceof Error&&e.name==="TimeoutError").toCode("TIMEOUT").with(e=>({message:e.message||"Operation timed out",cause:e,raw:e})),network:R.when(e=>ge(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:R.when(e=>{var n;if(!Ce(e))return!1;let r=e,t=(n=r.status)!=null?n:r.statusCode;return typeof t=="number"&&t>=400}).toCode("HTTP").with(e=>{var n;let r=(n=e.status)!=null?n:e.statusCode,t=typeof r=="number"&&(r>=500||r===429);return{message:e.message||`HTTP ${r!=null?r:"error"} error`,cause:e,status:typeof r=="number"?r:void 0,retryable:t,raw:e}}),unknown:R.when(e=>e instanceof Error&&!(e instanceof f)).toCode("UNKNOWN").with(e=>({message:e.message||"Unknown error occurred",cause:e,raw:e}))};var Ae=[x.typed,x.abort,x.timeout,x.http,x.network,x.unknown];var X={when:e=>R.when(e),instance:R.instance},Z=Ae;var ee={fixed:e=>({type:"fixed",delay:e}),exponential:(e,r=2,t)=>({type:"exponential",base:e,factor:r,maxDelay:t}),fibonacci:(e,r)=>({type:"fibonacci",base:e,maxDelay:r}),custom:e=>({type:"custom",calculate:e})},re=(e,r,t)=>{switch(e.type){case"fixed":return e.delay;case"exponential":{let n=e.base*e.factor**(Number(r)-1);return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"fibonacci":{let n=e.base*Se(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},Se=e=>{if(e<=1)return 1;let r=1,t=1;for(let n=2;n<=e;n++){let o=r+t;r=t,t=o}return t},te=e=>{switch(e.type){case"fixed":{if(e.delay<0)throw new Error("Fixed delay must be non-negative");break}case"exponential":if(e.base<=0)throw new Error("Exponential base delay must be positive");if(e.factor<=1)throw new Error("Exponential factor must be greater than 1");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Exponential max delay must be positive");break;case"fibonacci":if(e.base<=0)throw new Error("Fibonacci base delay must be positive");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Fibonacci max delay must be positive");break;case"custom":break;default:{let r=e;throw new Error(`Unknown strategy type: ${r}`)}}};var ne=(e,r)=>new Promise((t,n)=>{if(r!=null&&r.aborted){n(new DOMException("Aborted","AbortError"));return}let o=a=>{r&&a&&r.removeEventListener("abort",a)},i,s=()=>{i&&clearTimeout(i),o(s),n(new DOMException("Aborted","AbortError"))};i=setTimeout(()=>{o(s),t()},e),r==null||r.addEventListener("abort",s,{once:!0})}),oe=(e,r,t,n)=>new Promise((o,i)=>{if(t!=null&&t.aborted){i(new DOMException("Aborted","AbortError"));return}let s=!1,a=setTimeout(()=>{var y;s=!0,u(),i((y=n==null?void 0:n())!=null?y:new Error(`Operation timed out after ${r}ms`))},r),l=()=>{s||(s=!0,u(),i(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(a),t==null||t.removeEventListener("abort",l)};t==null||t.addEventListener("abort",l,{once:!0}),e.then(y=>{s||(s=!0,u(),o(y))},y=>{s||(s=!0,u(),i(y))})});var Ne=e=>{var s,a,l;if(e.toError)return e.toError;let r=(s=e.rulesMode)!=null?s:"extend",t=(a=e.rules)!=null?a:[],n=Z,o=(l=e.fallback)!=null?l:(u=>Q(B)(u)),i=r==="replace"?t:[...t,...n];return G(i,o)},Me=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":Y(e.ratio);return;case"custom":return;default:{let r=e;throw new Error(`Unsupported jitter configuration: ${r}`)}}},$=e=>{let r=e;return r.timeout!==void 0&&(r={...r,timeout:Number(b(r.timeout))}),r.concurrency!==void 0&&(r={...r,concurrency:Number.isFinite(r.concurrency)?Number(H(r.concurrency)):r.concurrency}),r.retry&&(te(r.retry.strategy),Me(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(h(r.retry.maxRetries))}}),r},W=class e{constructor(r={}){d(this,"circuitBreaker");d(this,"config");d(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:o,toError:i,mapError:s,...a}=r,l=Ne(r),u={...a,errorHandling:{normalizer:l,mapError:s}};this.config=$(u),u.circuitBreaker&&(this.circuitBreaker=new _(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var i,s,a,l,u,y;let n=$({...this.config,...t});if(this.circuitBreaker){let c=(i=this.lastCircuitState)!=null?i:this.circuitBreaker.getState().state,p=await this.circuitBreaker.canExecute(),T=this.circuitBreaker.getState().state;if(c!==T)try{(a=(s=n.hooks)==null?void 0:s.onCircuitStateChange)==null||a.call(s,c,T)}catch{}if(this.lastCircuitState=T,!p)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let o=await Ie(r,n);if(this.circuitBreaker){let c=(l=this.lastCircuitState)!=null?l:this.circuitBreaker.getState().state;o.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(o.error);let p=this.circuitBreaker.getState().state;if(c!==p)try{(y=(u=n.hooks)==null?void 0:u.onCircuitStateChange)==null||y.call(u,c,p)}catch{}this.lastCircuitState=p}return o}async runOrThrow(r,t={}){return this.orThrow(r,t)}async orThrow(r,t={}){let n=await this.run(r,t);if(n.ok)return n.data;throw n.error}async all(r,t={}){var y;let n=$({...this.config,...t}),o=(y=n.concurrency)!=null?y:Number.POSITIVE_INFINITY,i=Number.isFinite(o)?Number(H(o)):Number.POSITIVE_INFINITY;if(i===Number.POSITIVE_INFINITY)return Promise.all(r.map(c=>this.run(c,n)));let s=new Array(r.length),a=0,l=async()=>{var c;for(;a<r.length&&!((c=n.signal)!=null&&c.aborted);){let p=a++;if(p>=r.length)break;let T=r[p];T&&(s[p]=await this.run(T,n))}},u=Array.from({length:Math.min(i,r.length)},()=>l());await Promise.all(u);for(let c=0;c<r.length;c++)if(!(c in s)){let p=r[c];p&&(s[c]=await this.run(p,n))}return s}async allOrThrow(r,t={}){return(await this.all(r,t)).map(o=>{if(!o.ok)throw o.error;return o.data})}partitionAll(r){let t=[],n=[],o=[],i=[],s=[];for(let a of r){if(a.type==="success"){t.push(a);continue}switch(n.push(a),a.type){case"failure":o.push(a);break;case"aborted":i.push(a);break;case"timeout":s.push(a);break}}return{ok:t,errors:n,failure:o,aborted:i,timeout:s}}getCircuitBreakerState(){var r;return(r=this.circuitBreaker)==null?void 0:r.getState()}resetCircuitBreaker(){var r;(r=this.circuitBreaker)==null||r.reset()}getConfig(){return{...this.config}}withConfig(r){var l,u;let{errorHandling:t,...n}=this.config,{errorHandling:o,...i}=r,s=(l=o==null?void 0:o.normalizer)!=null?l:t.normalizer,a=(u=o==null?void 0:o.mapError)!=null?u:t.mapError;return new e({...n,...i,toError:s,mapError:a})}};function S(e={}){let r=new W(e);return{run:(t,n)=>r.run(t,n),orThrow:(t,n)=>r.orThrow(t,n),runOrThrow:(t,n)=>r.runOrThrow(t,n),all:(t,n)=>r.all(t,n),allOrThrow:(t,n)=>r.allOrThrow(t,n),partitionAll:t=>r.partitionAll(t),withConfig:t=>r.withConfig(t)}}async function Ie(e,r){let{signal:t,ignoreAbort:n=!0,timeout:o,retry:i,errorHandling:s,hooks:a,logger:l}=r,u=(C,...m)=>{try{C==null||C(...m)}catch{}},y,c=0,p=0,T=[],k=Date.now(),{signal:O,cleanup:de}=se(t),M=C=>({totalAttempts:c,totalRetries:c>0?Number(c)-1:0,totalDuration:Date.now()-k,lastError:C,retryHistory:T});try{if(O.aborted){u(a==null?void 0:a.onAbort,O);let m=s.normalizer(new DOMException("Aborted","AbortError")),w=s.mapError?s.mapError(m):m;return{type:"aborted",ok:!1,data:null,error:w,metrics:{totalAttempts:c,totalRetries:p,totalDuration:Date.now()-k,lastError:w,retryHistory:T}}}let C=async()=>{var I,g,K;let m=1,w=h((I=i==null?void 0:i.maxRetries)!=null?I:0);for(;;){c=m;let V=new AbortController,{signal:L,cleanup:ye}=se(O,V.signal);try{let v=Promise.resolve(e({signal:L})),A=o?await oe(v,o,L,()=>(V.abort(),new P(b(o)))):await v;return u(a==null?void 0:a.onSuccess,A,M()),u(l==null?void 0:l.info,`Task succeeded on attempt ${m}`),A}catch(v){let A=s.normalizer(v),E=s.mapError?s.mapError(A):A;if(y=E,E.code==="ABORTED"&&u(a==null?void 0:a.onAbort,L),n&&E.code==="ABORTED"||(u(a==null?void 0:a.onError,E,M(E)),u(l==null?void 0:l.error,`Task failed on attempt ${m}`,E)),E.code==="ABORTED"||E.retryable===!1)throw E;if(m<=Number(w)){let J=i==null?void 0:i.shouldRetry,pe={totalAttempts:Number(c),elapsedTime:Date.now()-k,startTime:new Date(k),lastDelay:(g=T[T.length-1])!=null&&g.delay?Number((K=T[T.length-1])==null?void 0:K.delay):void 0};if(!J||J(m,E,pe)){let me=i?re(i.strategy,m,E):0,z=ve(me,i==null?void 0:i.jitter),j=b(z);T.push({attempt:m,error:E,delay:j,timestamp:new Date}),u(a==null?void 0:a.onRetry,m,E,z),u(l==null?void 0:l.info,`Retrying in ${z}ms (attempt ${m+1})`),m+=1,await ne(j,O);continue}}throw E}finally{ye()}}};try{let m=await C(),w=M();return p=w.totalRetries,u(a==null?void 0:a.onFinally,w),{type:"success",ok:!0,data:m,error:null,metrics:w}}catch(m){let w=y!=null?y:s.normalizer(m),I=w.code==="TIMEOUT"?"timeout":w.code==="ABORTED"?"aborted":"failure",g=M(w);return p=g.totalRetries,u(a==null?void 0:a.onFinally,g),{type:I,ok:!1,data:null,error:w,metrics:g}}}finally{de()}}function se(...e){let r=new AbortController,t=e.filter(o=>o!==void 0);if(t.length===0)return{signal:r.signal,cleanup:()=>{}};if(t.some(o=>o.aborted))return r.abort(),{signal:r.signal,cleanup:()=>{}};let n=[];for(let o of t){let i=()=>r.abort();o.addEventListener("abort",i,{once:!0}),n.push({signal:o,abort:i})}return{signal:r.signal,cleanup:()=>{for(let o of n)o.signal.removeEventListener("abort",o.abort)}}}function ve(e,r){if(!r||r.type==="none"||e<=0)return e;switch(r.type){case"full":{let t=Number(r.ratio)/100,n=Math.max(0,Number(e)*(1-t)),o=Number(e);return n+Math.random()*(o-n)}case"equal":{let t=Number(r.ratio)/100,n=Number(e)*t/2;return Number(e)-n+Math.random()*n}case"custom":return r.calculate(e);default:return r}}var N=S(),ae=N.run,ie=N.runOrThrow,ue=N.orThrow,le=N.all,ce=N.allOrThrow;0&&(module.exports={RetryStrategies,TypedError,all,allOrThrow,asMilliseconds,asRetryCount,errorRule,orThrow,run,runOrThrow,tryo});
|
|
1
|
+
"use strict";var D=Object.defineProperty;var fe=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var Te=(e,r,t)=>r in e?D(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var be=(e,r)=>{for(var t in r)D(e,t,{get:r[t],enumerable:!0})},he=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of Ee(r))!we.call(e,o)&&o!==t&&D(e,o,{get:()=>r[o],enumerable:!(n=fe(r,o))||n.enumerable});return e};var Re=e=>he(D({},"__esModule",{value:!0}),e);var d=(e,r,t)=>Te(e,typeof r!="symbol"?r+"":r,t);var De={};be(De,{RetryStrategies:()=>ee,TypedError:()=>f,all:()=>ce,allOrThrow:()=>le,asMilliseconds:()=>b,asRetryCount:()=>h,default:()=>S,errorRule:()=>X,orThrow:()=>ue,run:()=>ae,runOrThrow:()=>ie,tryo:()=>S});module.exports=Re(De);var f=class extends Error{constructor(t,n){var o,i;super(t);d(this,"cause");d(this,"title");d(this,"meta");d(this,"status");d(this,"raw");d(this,"path");d(this,"timestamp");d(this,"retryable");this.timestamp=Date.now(),this.retryable=(o=n.retryable)!=null?o:!0,this.name=this.constructor.name,this.cause=n.cause,this.title=n.title,this.meta=(i=n.meta)!=null?i:{},this.status=n.status,this.raw=n.raw,this.path=n.path,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}is(t){return this.code===t}withMeta(t){return Object.assign(this,{meta:t})}withStatus(t){return Object.assign(this,{status:t})}withCause(t){return Object.assign(this,{cause:t})}withPath(t){return this.path=t,this}withRaw(t){return Object.assign(this,{raw:t})}withRetryable(t){return this.retryable=t,this}toJSON(){return{name:this.name,code:this.code,title:this.title,message:this.message,timestamp:this.timestamp,retryable:this.retryable,cause:this.cause,raw:this.raw,path:this.path,stack:this.stack}}},P=class extends f{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0});d(this,"code","TIMEOUT")}};var F=class extends f{constructor(t,n){super(`Circuit breaker is open, reset after ${t}ms`,{cause:n,retryable:!1});d(this,"code","CIRCUIT_OPEN")}};var B=class extends f{constructor(t,n){super(t,{cause:n});d(this,"code","UNKNOWN")}};var b=e=>{if(e<0||!Number.isFinite(e))throw new Error(`Invalid milliseconds: must be a non-negative finite number, got ${e}`);return e},h=e=>{if(e<0||!Number.isInteger(e))throw new Error(`Invalid retry count: must be a non-negative integer, got ${e}`);return e},H=e=>{if(e<1||!Number.isInteger(e))throw new Error(`Invalid concurrency limit: must be a positive integer, got ${e}`);return e},Y=e=>{if(e<0||e>100||!Number.isFinite(e))throw new Error(`Invalid percentage: must be between 0 and 100, got ${e}`);return e};var _=class{constructor(r){d(this,"state");d(this,"config");this.config={failureThreshold:h(r.failureThreshold),resetTimeout:b(r.resetTimeout),halfOpenRequests:h(r.halfOpenRequests),shouldCountAsFailure:r.shouldCountAsFailure},this.state={state:"closed",failureCount:0,halfOpenCount:0}}async canExecute(){if(this.updateStateIfNeeded(),this.state.state==="open")return!1;if(this.state.state==="half-open"){if(this.state.halfOpenCount>=this.config.halfOpenRequests)return!1;this.state={...this.state,halfOpenCount:this.state.halfOpenCount+1}}return!0}async recordSuccess(){switch(this.state.state){case"closed":this.state={...this.state,failureCount:0};break;case"half-open":this.state={state:"closed",failureCount:0,halfOpenCount:0};break;case"open":break}}async recordFailure(r){var o,i,s;if(!((s=(i=(o=this.config).shouldCountAsFailure)==null?void 0:i.call(o,r))!=null?s:!0))return;let n=new Date;switch(this.state.state){case"closed":{let a=this.state.failureCount+1;a>=this.config.failureThreshold?this.state={state:"open",failureCount:a,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:a,lastFailureTime:n};break}case"half-open":this.state={state:"open",failureCount:this.state.failureCount+1,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break;case"open":this.state={...this.state,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break}}getState(){return this.updateStateIfNeeded(),{...this.state,canExecute:this.state.state!=="open"}}createOpenError(){let r=this.state.nextAttemptTime?b(Math.max(0,this.state.nextAttemptTime.getTime()-Date.now())):this.config.resetTimeout;return new F(r)}forceState(r){this.state={state:r,failureCount:0,halfOpenCount:0}}reset(){this.state={state:"closed",failureCount:0,halfOpenCount:0}}updateStateIfNeeded(){this.state.state==="open"&&this.state.nextAttemptTime&&new Date>=this.state.nextAttemptTime&&(this.state={...this.state,state:"half-open",halfOpenCount:0})}};var G=(e,r)=>t=>{for(let n of e){let o=n(t);if(o!==null)return o}return r(t)},Q=e=>r=>r instanceof f?r:r instanceof Error?new e(r.message,r):typeof r=="string"?new e(r):new e("Unknown error occurred",r);var Ce=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},ge=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},xe=e=>{var r;if(e instanceof Error){let t=e.message.toLowerCase();if(e.name==="TypeError"&&(t.includes("fetch")&&t.includes("failed")||t.includes("network"))||t.includes("fetch")&&t.includes("failed")||t.includes("network"))return!0}if(ge(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},ke=e=>typeof e=="object"&&e!==null,U=class{constructor(r){this.predicate=r}toCode(r){return new q(this.predicate,r)}toError(r){return t=>{var c;if(!this.predicate(t))return null;let n=r(t),o=n.code,i=Object.hasOwn(n,"cause")?n.cause:t,s=(c=n.meta)!=null?c:{};class a extends f{constructor(){let l=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:i,meta:s,status:n.status,retryable:n.retryable,raw:l,path:n.path});d(this,"code",o)}}return new a}}};function Oe(e,r){let t=new U(i=>i instanceof e);if(r)return t.toError(r);let o=i=>{if(!(i instanceof e))return null;if(i instanceof f)return i;let s=i,a=typeof s.code=="string"&&s.code.length>0?s.code:"UNKNOWN",c=Object.hasOwn(s,"cause"),u=Object.hasOwn(s,"raw");class y extends f{constructor(){super(s.message||a,{title:typeof s.title=="string"?s.title:void 0,cause:c?s.cause:i,meta:ke(s.meta)?s.meta:{},status:typeof s.status=="number"?s.status:void 0,retryable:typeof s.retryable=="boolean"?s.retryable:void 0,raw:u?s.raw:i,path:typeof s.path=="string"?s.path:void 0});d(this,"code",a)}}return new y};return o.toCode=t.toCode.bind(t),o.toError=t.toError.bind(t),o}var q=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){return t=>{var c;if(!this.predicate(t))return null;let n=r(t),o=Object.hasOwn(n,"cause")?n.cause:t,i=(c=n.meta)!=null?c:{},s=this.errorCode;class a extends f{constructor(){let p=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:o,meta:i,status:n.status,retryable:n.retryable,raw:p,path:n.path});d(this,"code",s)}}return new a}}},R={when:e=>new U(e),instance:Oe},g={typed:(e=>e instanceof f?e:null),abort:R.when(e=>e instanceof Error&&e.name==="AbortError").toCode("ABORTED").with(e=>({message:e.message||"Operation was aborted",cause:e,retryable:!1,raw:e})),timeout:R.when(e=>e instanceof Error&&e.name==="TimeoutError").toCode("TIMEOUT").with(e=>({message:e.message||"Operation timed out",cause:e,raw:e})),network:R.when(e=>xe(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:R.when(e=>{var n;if(!Ce(e))return!1;let r=e,t=(n=r.status)!=null?n:r.statusCode;return typeof t=="number"&&t>=400}).toCode("HTTP").with(e=>{var n;let r=(n=e.status)!=null?n:e.statusCode,t=typeof r=="number"&&(r>=500||r===429);return{message:e.message||`HTTP ${r!=null?r:"error"} error`,cause:e,status:typeof r=="number"?r:void 0,retryable:t,raw:e}}),unknown:R.when(e=>e instanceof Error&&!(e instanceof f)).toCode("UNKNOWN").with(e=>({message:e.message||"Unknown error occurred",cause:e,raw:e}))};var Ae=[g.typed,g.abort,g.timeout,g.http,g.network,g.unknown];var X={when:e=>R.when(e),instance:R.instance},Z=Ae;var ee={fixed:e=>({type:"fixed",delay:e}),exponential:(e,r=2,t)=>({type:"exponential",base:e,factor:r,maxDelay:t}),fibonacci:(e,r)=>({type:"fibonacci",base:e,maxDelay:r}),custom:e=>({type:"custom",calculate:e})},re=(e,r,t)=>{switch(e.type){case"fixed":return e.delay;case"exponential":{let n=e.base*e.factor**(Number(r)-1);return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"fibonacci":{let n=e.base*Se(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},Se=e=>{if(e<=1)return 1;let r=1,t=1;for(let n=2;n<=e;n++){let o=r+t;r=t,t=o}return t},te=e=>{switch(e.type){case"fixed":{if(e.delay<0)throw new Error("Fixed delay must be non-negative");break}case"exponential":if(e.base<=0)throw new Error("Exponential base delay must be positive");if(e.factor<=1)throw new Error("Exponential factor must be greater than 1");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Exponential max delay must be positive");break;case"fibonacci":if(e.base<=0)throw new Error("Fibonacci base delay must be positive");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Fibonacci max delay must be positive");break;case"custom":break;default:{let r=e;throw new Error(`Unknown strategy type: ${r}`)}}};var ne=(e,r)=>new Promise((t,n)=>{if(r!=null&&r.aborted){n(new DOMException("Aborted","AbortError"));return}let o=a=>{r&&a&&r.removeEventListener("abort",a)},i,s=()=>{i&&clearTimeout(i),o(s),n(new DOMException("Aborted","AbortError"))};i=setTimeout(()=>{o(s),t()},e),r==null||r.addEventListener("abort",s,{once:!0})}),oe=(e,r,t,n)=>new Promise((o,i)=>{if(t!=null&&t.aborted){i(new DOMException("Aborted","AbortError"));return}let s=!1,a=setTimeout(()=>{var y;s=!0,u(),i((y=n==null?void 0:n())!=null?y:new Error(`Operation timed out after ${r}ms`))},r),c=()=>{s||(s=!0,u(),i(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(a),t==null||t.removeEventListener("abort",c)};t==null||t.addEventListener("abort",c,{once:!0}),e.then(y=>{s||(s=!0,u(),o(y))},y=>{s||(s=!0,u(),i(y))})});var Ne=e=>{var s,a,c;if(e.toError)return e.toError;let r=(s=e.rulesMode)!=null?s:"extend",t=(a=e.rules)!=null?a:[],n=Z,o=(c=e.fallback)!=null?c:(u=>Q(B)(u)),i=r==="replace"?t:[...t,...n];return G(i,o)},Me=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":Y(e.ratio);return;case"custom":return;default:{let r=e;throw new Error(`Unsupported jitter configuration: ${r}`)}}},$=e=>{let r=e;return r.timeout!==void 0&&(r={...r,timeout:Number(b(r.timeout))}),r.concurrency!==void 0&&(r={...r,concurrency:Number.isFinite(r.concurrency)?Number(H(r.concurrency)):r.concurrency}),r.retry&&(te(r.retry.strategy),Me(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(h(r.retry.maxRetries))}}),r},W=class e{constructor(r={}){d(this,"circuitBreaker");d(this,"config");d(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:o,toError:i,mapError:s,...a}=r,c=Ne(r),u={...a,errorHandling:{normalizer:c,mapError:s}};this.config=$(u),u.circuitBreaker&&(this.circuitBreaker=new _(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var i,s,a,c,u,y;let n=$({...this.config,...t});if(this.circuitBreaker){let l=(i=this.lastCircuitState)!=null?i:this.circuitBreaker.getState().state,p=await this.circuitBreaker.canExecute(),w=this.circuitBreaker.getState().state;if(l!==w)try{(a=(s=n.hooks)==null?void 0:s.onCircuitStateChange)==null||a.call(s,l,w)}catch{}if(this.lastCircuitState=w,!p)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let o=await Ie(r,n);if(this.circuitBreaker){let l=(c=this.lastCircuitState)!=null?c:this.circuitBreaker.getState().state;o.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(o.error);let p=this.circuitBreaker.getState().state;if(l!==p)try{(y=(u=n.hooks)==null?void 0:u.onCircuitStateChange)==null||y.call(u,l,p)}catch{}this.lastCircuitState=p}return o}async runOrThrow(r,t={}){return this.orThrow(r,t)}async orThrow(r,t={}){let n=await this.run(r,t);if(n.ok)return n.data;throw n.error}async all(r,t={}){var y;let n=$({...this.config,...t}),o=(y=n.concurrency)!=null?y:Number.POSITIVE_INFINITY,i=Number.isFinite(o)?Number(H(o)):Number.POSITIVE_INFINITY;if(i===Number.POSITIVE_INFINITY)return Promise.all(r.map(l=>this.run(l,n)));let s=new Array(r.length),a=0,c=async()=>{var l;for(;a<r.length&&!((l=n.signal)!=null&&l.aborted);){let p=a++;if(p>=r.length)break;let w=r[p];w&&(s[p]=await this.run(w,n))}},u=Array.from({length:Math.min(i,r.length)},()=>c());await Promise.all(u);for(let l=0;l<r.length;l++)if(!(l in s)){let p=r[l];p&&(s[l]=await this.run(p,n))}return s}async allOrThrow(r,t={}){return(await this.all(r,t)).map(o=>{if(!o.ok)throw o.error;return o.data})}partitionAll(r){let t=[],n=[],o=[],i=[],s=[];for(let a of r){if(a.type==="success"){t.push(a);continue}switch(n.push(a),a.type){case"failure":o.push(a);break;case"aborted":i.push(a);break;case"timeout":s.push(a);break}}return{ok:t,errors:n,failure:o,aborted:i,timeout:s}}getCircuitBreakerState(){var r;return(r=this.circuitBreaker)==null?void 0:r.getState()}resetCircuitBreaker(){var r;(r=this.circuitBreaker)==null||r.reset()}getConfig(){return{...this.config}}withConfig(r){var c,u;let{errorHandling:t,...n}=this.config,{errorHandling:o,...i}=r,s=(c=o==null?void 0:o.normalizer)!=null?c:t.normalizer,a=(u=o==null?void 0:o.mapError)!=null?u:t.mapError;return new e({...n,...i,toError:s,mapError:a})}};function S(e={}){let r=new W(e);return{run:(t,n)=>r.run(t,n),orThrow:(t,n)=>r.orThrow(t,n),runOrThrow:(t,n)=>r.runOrThrow(t,n),all:(t,n)=>r.all(t,n),allOrThrow:(t,n)=>r.allOrThrow(t,n),partitionAll:t=>r.partitionAll(t),withConfig:t=>r.withConfig(t)}}async function Ie(e,r){let{signal:t,ignoreAbort:n=!0,timeout:o,retry:i,errorHandling:s,hooks:a,logger:c}=r,u=(C,...m)=>{try{C==null||C(...m)}catch{}},y,l=0,p=0,w=[],k=Date.now(),{signal:O,cleanup:de}=se(t),M=C=>({totalAttempts:l,totalRetries:l>0?Number(l)-1:0,totalDuration:Date.now()-k,lastError:C,retryHistory:w});try{if(O.aborted){u(a==null?void 0:a.onAbort,O);let m=s.normalizer(new DOMException("Aborted","AbortError")),T=s.mapError?s.mapError(m):m;return{type:"aborted",ok:!1,data:null,error:T,metrics:{totalAttempts:l,totalRetries:p,totalDuration:Date.now()-k,lastError:T,retryHistory:w}}}let C=async()=>{var I,x,K;let m=1,T=h((I=i==null?void 0:i.maxRetries)!=null?I:0);for(;;){l=m;let V=new AbortController,{signal:L,cleanup:ye}=se(O,V.signal);try{let v=Promise.resolve(e({signal:L})),A=o?await oe(v,o,L,()=>(V.abort(),new P(b(o)))):await v;return u(a==null?void 0:a.onSuccess,A,M()),u(c==null?void 0:c.info,`Task succeeded on attempt ${m}`),A}catch(v){let A=s.normalizer(v),E=s.mapError?s.mapError(A):A;if(y=E,E.code==="ABORTED"&&u(a==null?void 0:a.onAbort,L),n&&E.code==="ABORTED"||(u(a==null?void 0:a.onError,E,M(E)),u(c==null?void 0:c.error,`Task failed on attempt ${m}`,E)),E.code==="ABORTED"||E.retryable===!1)throw E;if(m<=Number(T)){let J=i==null?void 0:i.shouldRetry,pe={totalAttempts:Number(l),elapsedTime:Date.now()-k,startTime:new Date(k),lastDelay:(x=w[w.length-1])!=null&&x.delay?Number((K=w[w.length-1])==null?void 0:K.delay):void 0};if(!J||J(m,E,pe)){let me=i?re(i.strategy,m,E):0,z=ve(me,i==null?void 0:i.jitter),j=b(z);w.push({attempt:m,error:E,delay:j,timestamp:new Date}),u(a==null?void 0:a.onRetry,m,E,z),u(c==null?void 0:c.info,`Retrying in ${z}ms (attempt ${m+1})`),m+=1,await ne(j,O);continue}}throw E}finally{ye()}}};try{let m=await C(),T=M();return p=T.totalRetries,u(a==null?void 0:a.onFinally,T),{type:"success",ok:!0,data:m,error:null,metrics:T}}catch(m){let T=y!=null?y:s.normalizer(m),I=T.code==="TIMEOUT"?"timeout":T.code==="ABORTED"?"aborted":"failure",x=M(T);return p=x.totalRetries,u(a==null?void 0:a.onFinally,x),{type:I,ok:!1,data:null,error:T,metrics:x}}}finally{de()}}function se(...e){let r=new AbortController,t=e.filter(o=>o!==void 0);if(t.length===0)return{signal:r.signal,cleanup:()=>{}};if(t.some(o=>o.aborted))return r.abort(),{signal:r.signal,cleanup:()=>{}};let n=[];for(let o of t){let i=()=>r.abort();o.addEventListener("abort",i,{once:!0}),n.push({signal:o,abort:i})}return{signal:r.signal,cleanup:()=>{for(let o of n)o.signal.removeEventListener("abort",o.abort)}}}function ve(e,r){if(!r||r.type==="none"||e<=0)return e;switch(r.type){case"full":{let t=Number(r.ratio)/100,n=Math.max(0,Number(e)*(1-t)),o=Number(e);return n+Math.random()*(o-n)}case"equal":{let t=Number(r.ratio)/100,n=Number(e)*t/2;return Number(e)-n+Math.random()*n}case"custom":return r.calculate(e);default:return r}}var N=S(),ae=N.run,ie=N.runOrThrow,ue=N.orThrow,ce=N.all,le=N.allOrThrow;0&&(module.exports={RetryStrategies,TypedError,all,allOrThrow,asMilliseconds,asRetryCount,errorRule,orThrow,run,runOrThrow,tryo});
|
package/dist/index.d.cts
CHANGED
|
@@ -317,15 +317,14 @@ type CheckUniqueCodes<T extends readonly unknown[], Seen = never> = T extends re
|
|
|
317
317
|
type UniqueRulesConstraint<TRules extends readonly RuleLike[]> = CheckUniqueCodes<TRules> extends true ? unknown : {
|
|
318
318
|
__duplicate_error_codes__: CheckUniqueCodes<TRules>;
|
|
319
319
|
};
|
|
320
|
-
|
|
321
|
-
declare function tryo<const TRules extends readonly unknown[]>(options: Omit<TryoOptions<InferErrorFromRules<EnsureRuleTuple<TRules>>>, 'rules' | 'rulesMode'> & {
|
|
320
|
+
declare function tryo<const TRules extends readonly RuleLike[]>(options: Omit<TryoOptions<InferErrorFromRules<TRules>>, 'rules' | 'rulesMode'> & {
|
|
322
321
|
rules: TRules;
|
|
323
322
|
rulesMode: 'replace';
|
|
324
|
-
} & UniqueRulesConstraint<
|
|
325
|
-
declare function tryo<const TRules extends readonly
|
|
323
|
+
} & UniqueRulesConstraint<TRules>): Tryo<InferErrorFromRules<TRules>>;
|
|
324
|
+
declare function tryo<const TRules extends readonly RuleLike[]>(options: Omit<TryoOptions<InferErrorFromRules<TRules> | DefaultError>, 'rules'> & {
|
|
326
325
|
rules: TRules;
|
|
327
326
|
rulesMode?: 'extend';
|
|
328
|
-
} & UniqueRulesConstraint<
|
|
327
|
+
} & UniqueRulesConstraint<TRules>): Tryo<InferErrorFromRules<TRules> | DefaultError>;
|
|
329
328
|
declare function tryo<E extends AnyTypedError = DefaultError>(options?: TryoOptions<E>): Tryo<E>;
|
|
330
329
|
type Tryo<E extends AnyTypedError = AnyTypedError> = {
|
|
331
330
|
run: <T>(task: (ctx: {
|
|
@@ -460,10 +459,19 @@ declare class ErrorMapper<T, C extends string> {
|
|
|
460
459
|
declare const errorRule: {
|
|
461
460
|
readonly when: <T>(predicate: (err: unknown) => err is T) => ErrorRuleBuilder<T>;
|
|
462
461
|
readonly instance: {
|
|
463
|
-
<T extends abstract new (...args: never[]) => unknown>(ErrorClass: T):
|
|
462
|
+
<T extends abstract new (...args: never[]) => unknown>(ErrorClass: T): InstanceType<T> extends Error & {
|
|
463
|
+
readonly code: string;
|
|
464
|
+
readonly title?: string;
|
|
465
|
+
readonly meta?: Record<string, unknown>;
|
|
466
|
+
readonly status?: number;
|
|
467
|
+
readonly retryable?: boolean;
|
|
468
|
+
readonly raw?: unknown;
|
|
469
|
+
readonly path?: string;
|
|
470
|
+
readonly cause?: unknown;
|
|
471
|
+
} ? ErrorRule<AnyTypedError> & {
|
|
464
472
|
toCode: <const C extends string>(code: C) => ErrorMapper<InstanceType<T>, C>;
|
|
465
473
|
toError: <const Out extends ErrorResponse>(mapper: (err: InstanceType<T>) => Out & Record<Exclude<keyof Out, keyof ErrorResponse>, never>) => ErrorRule<TypedError<Out["code"], Out["meta"] extends Record<string, unknown> ? Out["meta"] : Record<string, unknown>, Out["raw"] extends undefined ? InstanceType<T> : Out["raw"]>>;
|
|
466
|
-
}
|
|
474
|
+
} : ErrorRuleBuilder<InstanceType<T>>;
|
|
467
475
|
<T extends abstract new (...args: never[]) => unknown, const Out extends ErrorResponse>(ErrorClass: T, mapper: (err: InstanceType<T>) => Out & Record<Exclude<keyof Out, keyof ErrorResponse>, never>): ErrorRule<TypedError<Out["code"], Out["meta"] extends Record<string, unknown> ? Out["meta"] : Record<string, unknown>, Out["raw"] extends undefined ? InstanceType<T> : Out["raw"]>>;
|
|
468
476
|
};
|
|
469
477
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -317,15 +317,14 @@ type CheckUniqueCodes<T extends readonly unknown[], Seen = never> = T extends re
|
|
|
317
317
|
type UniqueRulesConstraint<TRules extends readonly RuleLike[]> = CheckUniqueCodes<TRules> extends true ? unknown : {
|
|
318
318
|
__duplicate_error_codes__: CheckUniqueCodes<TRules>;
|
|
319
319
|
};
|
|
320
|
-
|
|
321
|
-
declare function tryo<const TRules extends readonly unknown[]>(options: Omit<TryoOptions<InferErrorFromRules<EnsureRuleTuple<TRules>>>, 'rules' | 'rulesMode'> & {
|
|
320
|
+
declare function tryo<const TRules extends readonly RuleLike[]>(options: Omit<TryoOptions<InferErrorFromRules<TRules>>, 'rules' | 'rulesMode'> & {
|
|
322
321
|
rules: TRules;
|
|
323
322
|
rulesMode: 'replace';
|
|
324
|
-
} & UniqueRulesConstraint<
|
|
325
|
-
declare function tryo<const TRules extends readonly
|
|
323
|
+
} & UniqueRulesConstraint<TRules>): Tryo<InferErrorFromRules<TRules>>;
|
|
324
|
+
declare function tryo<const TRules extends readonly RuleLike[]>(options: Omit<TryoOptions<InferErrorFromRules<TRules> | DefaultError>, 'rules'> & {
|
|
326
325
|
rules: TRules;
|
|
327
326
|
rulesMode?: 'extend';
|
|
328
|
-
} & UniqueRulesConstraint<
|
|
327
|
+
} & UniqueRulesConstraint<TRules>): Tryo<InferErrorFromRules<TRules> | DefaultError>;
|
|
329
328
|
declare function tryo<E extends AnyTypedError = DefaultError>(options?: TryoOptions<E>): Tryo<E>;
|
|
330
329
|
type Tryo<E extends AnyTypedError = AnyTypedError> = {
|
|
331
330
|
run: <T>(task: (ctx: {
|
|
@@ -460,10 +459,19 @@ declare class ErrorMapper<T, C extends string> {
|
|
|
460
459
|
declare const errorRule: {
|
|
461
460
|
readonly when: <T>(predicate: (err: unknown) => err is T) => ErrorRuleBuilder<T>;
|
|
462
461
|
readonly instance: {
|
|
463
|
-
<T extends abstract new (...args: never[]) => unknown>(ErrorClass: T):
|
|
462
|
+
<T extends abstract new (...args: never[]) => unknown>(ErrorClass: T): InstanceType<T> extends Error & {
|
|
463
|
+
readonly code: string;
|
|
464
|
+
readonly title?: string;
|
|
465
|
+
readonly meta?: Record<string, unknown>;
|
|
466
|
+
readonly status?: number;
|
|
467
|
+
readonly retryable?: boolean;
|
|
468
|
+
readonly raw?: unknown;
|
|
469
|
+
readonly path?: string;
|
|
470
|
+
readonly cause?: unknown;
|
|
471
|
+
} ? ErrorRule<AnyTypedError> & {
|
|
464
472
|
toCode: <const C extends string>(code: C) => ErrorMapper<InstanceType<T>, C>;
|
|
465
473
|
toError: <const Out extends ErrorResponse>(mapper: (err: InstanceType<T>) => Out & Record<Exclude<keyof Out, keyof ErrorResponse>, never>) => ErrorRule<TypedError<Out["code"], Out["meta"] extends Record<string, unknown> ? Out["meta"] : Record<string, unknown>, Out["raw"] extends undefined ? InstanceType<T> : Out["raw"]>>;
|
|
466
|
-
}
|
|
474
|
+
} : ErrorRuleBuilder<InstanceType<T>>;
|
|
467
475
|
<T extends abstract new (...args: never[]) => unknown, const Out extends ErrorResponse>(ErrorClass: T, mapper: (err: InstanceType<T>) => Out & Record<Exclude<keyof Out, keyof ErrorResponse>, never>): ErrorRule<TypedError<Out["code"], Out["meta"] extends Record<string, unknown> ? Out["meta"] : Record<string, unknown>, Out["raw"] extends undefined ? InstanceType<T> : Out["raw"]>>;
|
|
468
476
|
};
|
|
469
477
|
};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var ie=Object.defineProperty;var ue=(e,r,t)=>r in e?ie(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var d=(e,r,t)=>ue(e,typeof r!="symbol"?r+"":r,t);var E=class extends Error{constructor(t,n){var s,i;super(t);d(this,"cause");d(this,"title");d(this,"meta");d(this,"status");d(this,"raw");d(this,"path");d(this,"timestamp");d(this,"retryable");this.timestamp=Date.now(),this.retryable=(s=n.retryable)!=null?s:!0,this.name=this.constructor.name,this.cause=n.cause,this.title=n.title,this.meta=(i=n.meta)!=null?i:{},this.status=n.status,this.raw=n.raw,this.path=n.path,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}is(t){return this.code===t}withMeta(t){return Object.assign(this,{meta:t})}withStatus(t){return Object.assign(this,{status:t})}withCause(t){return Object.assign(this,{cause:t})}withPath(t){return this.path=t,this}withRaw(t){return Object.assign(this,{raw:t})}withRetryable(t){return this.retryable=t,this}toJSON(){return{name:this.name,code:this.code,title:this.title,message:this.message,timestamp:this.timestamp,retryable:this.retryable,cause:this.cause,raw:this.raw,path:this.path,stack:this.stack}}},v=class extends E{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0});d(this,"code","TIMEOUT")}};var D=class extends E{constructor(t,n){super(`Circuit breaker is open, reset after ${t}ms`,{cause:n,retryable:!1});d(this,"code","CIRCUIT_OPEN")}};var P=class extends E{constructor(t,n){super(t,{cause:n});d(this,"code","UNKNOWN")}};var b=e=>{if(e<0||!Number.isFinite(e))throw new Error(`Invalid milliseconds: must be a non-negative finite number, got ${e}`);return e},C=e=>{if(e<0||!Number.isInteger(e))throw new Error(`Invalid retry count: must be a non-negative integer, got ${e}`);return e},z=e=>{if(e<1||!Number.isInteger(e))throw new Error(`Invalid concurrency limit: must be a positive integer, got ${e}`);return e},j=e=>{if(e<0||e>100||!Number.isFinite(e))throw new Error(`Invalid percentage: must be between 0 and 100, got ${e}`);return e};var F=class{constructor(r){d(this,"state");d(this,"config");this.config={failureThreshold:C(r.failureThreshold),resetTimeout:b(r.resetTimeout),halfOpenRequests:C(r.halfOpenRequests),shouldCountAsFailure:r.shouldCountAsFailure},this.state={state:"closed",failureCount:0,halfOpenCount:0}}async canExecute(){if(this.updateStateIfNeeded(),this.state.state==="open")return!1;if(this.state.state==="half-open"){if(this.state.halfOpenCount>=this.config.halfOpenRequests)return!1;this.state={...this.state,halfOpenCount:this.state.halfOpenCount+1}}return!0}async recordSuccess(){switch(this.state.state){case"closed":this.state={...this.state,failureCount:0};break;case"half-open":this.state={state:"closed",failureCount:0,halfOpenCount:0};break;case"open":break}}async recordFailure(r){var s,i,o;if(!((o=(i=(s=this.config).shouldCountAsFailure)==null?void 0:i.call(s,r))!=null?o:!0))return;let n=new Date;switch(this.state.state){case"closed":{let a=this.state.failureCount+1;a>=this.config.failureThreshold?this.state={state:"open",failureCount:a,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:a,lastFailureTime:n};break}case"half-open":this.state={state:"open",failureCount:this.state.failureCount+1,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break;case"open":this.state={...this.state,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break}}getState(){return this.updateStateIfNeeded(),{...this.state,canExecute:this.state.state!=="open"}}createOpenError(){let r=this.state.nextAttemptTime?b(Math.max(0,this.state.nextAttemptTime.getTime()-Date.now())):this.config.resetTimeout;return new D(r)}forceState(r){this.state={state:r,failureCount:0,halfOpenCount:0}}reset(){this.state={state:"closed",failureCount:0,halfOpenCount:0}}updateStateIfNeeded(){this.state.state==="open"&&this.state.nextAttemptTime&&new Date>=this.state.nextAttemptTime&&(this.state={...this.state,state:"half-open",halfOpenCount:0})}};var Y=(e,r)=>t=>{for(let n of e){let s=n(t);if(s!==null)return s}return r(t)},G=e=>r=>r instanceof E?r:r instanceof Error?new e(r.message,r):typeof r=="string"?new e(r):new e("Unknown error occurred",r);var le=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},ce=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},de=e=>{var r;if(e instanceof Error){let t=e.message.toLowerCase();if(e.name==="TypeError"&&(t.includes("fetch")&&t.includes("failed")||t.includes("network"))||t.includes("fetch")&&t.includes("failed")||t.includes("network"))return!0}if(ce(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},ye=e=>typeof e=="object"&&e!==null,B=class{constructor(r){this.predicate=r}toCode(r){return new H(this.predicate,r)}toError(r){return t=>{var l;if(!this.predicate(t))return null;let n=r(t),s=n.code,i=Object.hasOwn(n,"cause")?n.cause:t,o=(l=n.meta)!=null?l:{};class a extends E{constructor(){let c=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:i,meta:o,status:n.status,retryable:n.retryable,raw:c,path:n.path});d(this,"code",s)}}return new a}}};function pe(e,r){let t=new B(i=>i instanceof e);if(r)return t.toError(r);let s=i=>{if(!(i instanceof e))return null;if(i instanceof E)return i;let o=i,a=typeof o.code=="string"&&o.code.length>0?o.code:"UNKNOWN",l=Object.hasOwn(o,"cause"),u=Object.hasOwn(o,"raw");class y extends E{constructor(){super(o.message||a,{title:typeof o.title=="string"?o.title:void 0,cause:l?o.cause:i,meta:ye(o.meta)?o.meta:{},status:typeof o.status=="number"?o.status:void 0,retryable:typeof o.retryable=="boolean"?o.retryable:void 0,raw:u?o.raw:i,path:typeof o.path=="string"?o.path:void 0});d(this,"code",a)}}return new y};return s.toCode=t.toCode.bind(t),s.toError=t.toError.bind(t),s}var H=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){return t=>{var l;if(!this.predicate(t))return null;let n=r(t),s=Object.hasOwn(n,"cause")?n.cause:t,i=(l=n.meta)!=null?l:{},o=this.errorCode;class a extends E{constructor(){let p=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:s,meta:i,status:n.status,retryable:n.retryable,raw:p,path:n.path});d(this,"code",o)}}return new a}}},h={when:e=>new B(e),instance:pe},x={typed:(e=>e instanceof E?e:null),abort:h.when(e=>e instanceof Error&&e.name==="AbortError").toCode("ABORTED").with(e=>({message:e.message||"Operation was aborted",cause:e,retryable:!1,raw:e})),timeout:h.when(e=>e instanceof Error&&e.name==="TimeoutError").toCode("TIMEOUT").with(e=>({message:e.message||"Operation timed out",cause:e,raw:e})),network:h.when(e=>de(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:h.when(e=>{var n;if(!le(e))return!1;let r=e,t=(n=r.status)!=null?n:r.statusCode;return typeof t=="number"&&t>=400}).toCode("HTTP").with(e=>{var n;let r=(n=e.status)!=null?n:e.statusCode,t=typeof r=="number"&&(r>=500||r===429);return{message:e.message||`HTTP ${r!=null?r:"error"} error`,cause:e,status:typeof r=="number"?r:void 0,retryable:t,raw:e}}),unknown:h.when(e=>e instanceof Error&&!(e instanceof E)).toCode("UNKNOWN").with(e=>({message:e.message||"Unknown error occurred",cause:e,raw:e}))};var me=[x.typed,x.abort,x.timeout,x.http,x.network,x.unknown];var fe={when:e=>h.when(e),instance:h.instance},Q=me;var Ee={fixed:e=>({type:"fixed",delay:e}),exponential:(e,r=2,t)=>({type:"exponential",base:e,factor:r,maxDelay:t}),fibonacci:(e,r)=>({type:"fibonacci",base:e,maxDelay:r}),custom:e=>({type:"custom",calculate:e})},X=(e,r,t)=>{switch(e.type){case"fixed":return e.delay;case"exponential":{let n=e.base*e.factor**(Number(r)-1);return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"fibonacci":{let n=e.base*Te(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},Te=e=>{if(e<=1)return 1;let r=1,t=1;for(let n=2;n<=e;n++){let s=r+t;r=t,t=s}return t},Z=e=>{switch(e.type){case"fixed":{if(e.delay<0)throw new Error("Fixed delay must be non-negative");break}case"exponential":if(e.base<=0)throw new Error("Exponential base delay must be positive");if(e.factor<=1)throw new Error("Exponential factor must be greater than 1");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Exponential max delay must be positive");break;case"fibonacci":if(e.base<=0)throw new Error("Fibonacci base delay must be positive");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Fibonacci max delay must be positive");break;case"custom":break;default:{let r=e;throw new Error(`Unknown strategy type: ${r}`)}}};var ee=(e,r)=>new Promise((t,n)=>{if(r!=null&&r.aborted){n(new DOMException("Aborted","AbortError"));return}let s=a=>{r&&a&&r.removeEventListener("abort",a)},i,o=()=>{i&&clearTimeout(i),s(o),n(new DOMException("Aborted","AbortError"))};i=setTimeout(()=>{s(o),t()},e),r==null||r.addEventListener("abort",o,{once:!0})}),re=(e,r,t,n)=>new Promise((s,i)=>{if(t!=null&&t.aborted){i(new DOMException("Aborted","AbortError"));return}let o=!1,a=setTimeout(()=>{var y;o=!0,u(),i((y=n==null?void 0:n())!=null?y:new Error(`Operation timed out after ${r}ms`))},r),l=()=>{o||(o=!0,u(),i(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(a),t==null||t.removeEventListener("abort",l)};t==null||t.addEventListener("abort",l,{once:!0}),e.then(y=>{o||(o=!0,u(),s(y))},y=>{o||(o=!0,u(),i(y))})});var we=e=>{var o,a,l;if(e.toError)return e.toError;let r=(o=e.rulesMode)!=null?o:"extend",t=(a=e.rules)!=null?a:[],n=Q,s=(l=e.fallback)!=null?l:(u=>G(P)(u)),i=r==="replace"?t:[...t,...n];return Y(i,s)},be=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":j(e.ratio);return;case"custom":return;default:{let r=e;throw new Error(`Unsupported jitter configuration: ${r}`)}}},q=e=>{let r=e;return r.timeout!==void 0&&(r={...r,timeout:Number(b(r.timeout))}),r.concurrency!==void 0&&(r={...r,concurrency:Number.isFinite(r.concurrency)?Number(z(r.concurrency)):r.concurrency}),r.retry&&(Z(r.retry.strategy),be(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(C(r.retry.maxRetries))}}),r},$=class e{constructor(r={}){d(this,"circuitBreaker");d(this,"config");d(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:s,toError:i,mapError:o,...a}=r,l=we(r),u={...a,errorHandling:{normalizer:l,mapError:o}};this.config=q(u),u.circuitBreaker&&(this.circuitBreaker=new F(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var i,o,a,l,u,y;let n=q({...this.config,...t});if(this.circuitBreaker){let c=(i=this.lastCircuitState)!=null?i:this.circuitBreaker.getState().state,p=await this.circuitBreaker.canExecute(),T=this.circuitBreaker.getState().state;if(c!==T)try{(a=(o=n.hooks)==null?void 0:o.onCircuitStateChange)==null||a.call(o,c,T)}catch{}if(this.lastCircuitState=T,!p)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let s=await he(r,n);if(this.circuitBreaker){let c=(l=this.lastCircuitState)!=null?l:this.circuitBreaker.getState().state;s.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(s.error);let p=this.circuitBreaker.getState().state;if(c!==p)try{(y=(u=n.hooks)==null?void 0:u.onCircuitStateChange)==null||y.call(u,c,p)}catch{}this.lastCircuitState=p}return s}async runOrThrow(r,t={}){return this.orThrow(r,t)}async orThrow(r,t={}){let n=await this.run(r,t);if(n.ok)return n.data;throw n.error}async all(r,t={}){var y;let n=q({...this.config,...t}),s=(y=n.concurrency)!=null?y:Number.POSITIVE_INFINITY,i=Number.isFinite(s)?Number(z(s)):Number.POSITIVE_INFINITY;if(i===Number.POSITIVE_INFINITY)return Promise.all(r.map(c=>this.run(c,n)));let o=new Array(r.length),a=0,l=async()=>{var c;for(;a<r.length&&!((c=n.signal)!=null&&c.aborted);){let p=a++;if(p>=r.length)break;let T=r[p];T&&(o[p]=await this.run(T,n))}},u=Array.from({length:Math.min(i,r.length)},()=>l());await Promise.all(u);for(let c=0;c<r.length;c++)if(!(c in o)){let p=r[c];p&&(o[c]=await this.run(p,n))}return o}async allOrThrow(r,t={}){return(await this.all(r,t)).map(s=>{if(!s.ok)throw s.error;return s.data})}partitionAll(r){let t=[],n=[],s=[],i=[],o=[];for(let a of r){if(a.type==="success"){t.push(a);continue}switch(n.push(a),a.type){case"failure":s.push(a);break;case"aborted":i.push(a);break;case"timeout":o.push(a);break}}return{ok:t,errors:n,failure:s,aborted:i,timeout:o}}getCircuitBreakerState(){var r;return(r=this.circuitBreaker)==null?void 0:r.getState()}resetCircuitBreaker(){var r;(r=this.circuitBreaker)==null||r.reset()}getConfig(){return{...this.config}}withConfig(r){var l,u;let{errorHandling:t,...n}=this.config,{errorHandling:s,...i}=r,o=(l=s==null?void 0:s.normalizer)!=null?l:t.normalizer,a=(u=s==null?void 0:s.mapError)!=null?u:t.mapError;return new e({...n,...i,toError:o,mapError:a})}};function _(e={}){let r=new $(e);return{run:(t,n)=>r.run(t,n),orThrow:(t,n)=>r.orThrow(t,n),runOrThrow:(t,n)=>r.runOrThrow(t,n),all:(t,n)=>r.all(t,n),allOrThrow:(t,n)=>r.allOrThrow(t,n),partitionAll:t=>r.partitionAll(t),withConfig:t=>r.withConfig(t)}}async function he(e,r){let{signal:t,ignoreAbort:n=!0,timeout:s,retry:i,errorHandling:o,hooks:a,logger:l}=r,u=(R,...m)=>{try{R==null||R(...m)}catch{}},y,c=0,p=0,T=[],k=Date.now(),{signal:O,cleanup:ne}=te(t),N=R=>({totalAttempts:c,totalRetries:c>0?Number(c)-1:0,totalDuration:Date.now()-k,lastError:R,retryHistory:T});try{if(O.aborted){u(a==null?void 0:a.onAbort,O);let m=o.normalizer(new DOMException("Aborted","AbortError")),w=o.mapError?o.mapError(m):m;return{type:"aborted",ok:!1,data:null,error:w,metrics:{totalAttempts:c,totalRetries:p,totalDuration:Date.now()-k,lastError:w,retryHistory:T}}}let R=async()=>{var M,g,W;let m=1,w=C((M=i==null?void 0:i.maxRetries)!=null?M:0);for(;;){c=m;let K=new AbortController,{signal:U,cleanup:oe}=te(O,K.signal);try{let I=Promise.resolve(e({signal:U})),A=s?await re(I,s,U,()=>(K.abort(),new v(b(s)))):await I;return u(a==null?void 0:a.onSuccess,A,N()),u(l==null?void 0:l.info,`Task succeeded on attempt ${m}`),A}catch(I){let A=o.normalizer(I),f=o.mapError?o.mapError(A):A;if(y=f,f.code==="ABORTED"&&u(a==null?void 0:a.onAbort,U),n&&f.code==="ABORTED"||(u(a==null?void 0:a.onError,f,N(f)),u(l==null?void 0:l.error,`Task failed on attempt ${m}`,f)),f.code==="ABORTED"||f.retryable===!1)throw f;if(m<=Number(w)){let V=i==null?void 0:i.shouldRetry,se={totalAttempts:Number(c),elapsedTime:Date.now()-k,startTime:new Date(k),lastDelay:(g=T[T.length-1])!=null&&g.delay?Number((W=T[T.length-1])==null?void 0:W.delay):void 0};if(!V||V(m,f,se)){let ae=i?X(i.strategy,m,f):0,L=Re(ae,i==null?void 0:i.jitter),J=b(L);T.push({attempt:m,error:f,delay:J,timestamp:new Date}),u(a==null?void 0:a.onRetry,m,f,L),u(l==null?void 0:l.info,`Retrying in ${L}ms (attempt ${m+1})`),m+=1,await ee(J,O);continue}}throw f}finally{oe()}}};try{let m=await R(),w=N();return p=w.totalRetries,u(a==null?void 0:a.onFinally,w),{type:"success",ok:!0,data:m,error:null,metrics:w}}catch(m){let w=y!=null?y:o.normalizer(m),M=w.code==="TIMEOUT"?"timeout":w.code==="ABORTED"?"aborted":"failure",g=N(w);return p=g.totalRetries,u(a==null?void 0:a.onFinally,g),{type:M,ok:!1,data:null,error:w,metrics:g}}}finally{ne()}}function te(...e){let r=new AbortController,t=e.filter(s=>s!==void 0);if(t.length===0)return{signal:r.signal,cleanup:()=>{}};if(t.some(s=>s.aborted))return r.abort(),{signal:r.signal,cleanup:()=>{}};let n=[];for(let s of t){let i=()=>r.abort();s.addEventListener("abort",i,{once:!0}),n.push({signal:s,abort:i})}return{signal:r.signal,cleanup:()=>{for(let s of n)s.signal.removeEventListener("abort",s.abort)}}}function Re(e,r){if(!r||r.type==="none"||e<=0)return e;switch(r.type){case"full":{let t=Number(r.ratio)/100,n=Math.max(0,Number(e)*(1-t)),s=Number(e);return n+Math.random()*(s-n)}case"equal":{let t=Number(r.ratio)/100,n=Number(e)*t/2;return Number(e)-n+Math.random()*n}case"custom":return r.calculate(e);default:return r}}var S=_(),Ce=S.run,xe=S.runOrThrow,ge=S.orThrow,ke=S.all,Oe=S.allOrThrow;export{Ee as RetryStrategies,E as TypedError,ke as all,Oe as allOrThrow,b as asMilliseconds,C as asRetryCount,_ as default,fe as errorRule,ge as orThrow,Ce as run,xe as runOrThrow,_ as tryo};
|
|
1
|
+
var ie=Object.defineProperty;var ue=(e,r,t)=>r in e?ie(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var d=(e,r,t)=>ue(e,typeof r!="symbol"?r+"":r,t);var E=class extends Error{constructor(t,n){var s,i;super(t);d(this,"cause");d(this,"title");d(this,"meta");d(this,"status");d(this,"raw");d(this,"path");d(this,"timestamp");d(this,"retryable");this.timestamp=Date.now(),this.retryable=(s=n.retryable)!=null?s:!0,this.name=this.constructor.name,this.cause=n.cause,this.title=n.title,this.meta=(i=n.meta)!=null?i:{},this.status=n.status,this.raw=n.raw,this.path=n.path,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}is(t){return this.code===t}withMeta(t){return Object.assign(this,{meta:t})}withStatus(t){return Object.assign(this,{status:t})}withCause(t){return Object.assign(this,{cause:t})}withPath(t){return this.path=t,this}withRaw(t){return Object.assign(this,{raw:t})}withRetryable(t){return this.retryable=t,this}toJSON(){return{name:this.name,code:this.code,title:this.title,message:this.message,timestamp:this.timestamp,retryable:this.retryable,cause:this.cause,raw:this.raw,path:this.path,stack:this.stack}}},v=class extends E{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0});d(this,"code","TIMEOUT")}};var D=class extends E{constructor(t,n){super(`Circuit breaker is open, reset after ${t}ms`,{cause:n,retryable:!1});d(this,"code","CIRCUIT_OPEN")}};var P=class extends E{constructor(t,n){super(t,{cause:n});d(this,"code","UNKNOWN")}};var b=e=>{if(e<0||!Number.isFinite(e))throw new Error(`Invalid milliseconds: must be a non-negative finite number, got ${e}`);return e},C=e=>{if(e<0||!Number.isInteger(e))throw new Error(`Invalid retry count: must be a non-negative integer, got ${e}`);return e},z=e=>{if(e<1||!Number.isInteger(e))throw new Error(`Invalid concurrency limit: must be a positive integer, got ${e}`);return e},j=e=>{if(e<0||e>100||!Number.isFinite(e))throw new Error(`Invalid percentage: must be between 0 and 100, got ${e}`);return e};var F=class{constructor(r){d(this,"state");d(this,"config");this.config={failureThreshold:C(r.failureThreshold),resetTimeout:b(r.resetTimeout),halfOpenRequests:C(r.halfOpenRequests),shouldCountAsFailure:r.shouldCountAsFailure},this.state={state:"closed",failureCount:0,halfOpenCount:0}}async canExecute(){if(this.updateStateIfNeeded(),this.state.state==="open")return!1;if(this.state.state==="half-open"){if(this.state.halfOpenCount>=this.config.halfOpenRequests)return!1;this.state={...this.state,halfOpenCount:this.state.halfOpenCount+1}}return!0}async recordSuccess(){switch(this.state.state){case"closed":this.state={...this.state,failureCount:0};break;case"half-open":this.state={state:"closed",failureCount:0,halfOpenCount:0};break;case"open":break}}async recordFailure(r){var s,i,o;if(!((o=(i=(s=this.config).shouldCountAsFailure)==null?void 0:i.call(s,r))!=null?o:!0))return;let n=new Date;switch(this.state.state){case"closed":{let a=this.state.failureCount+1;a>=this.config.failureThreshold?this.state={state:"open",failureCount:a,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:a,lastFailureTime:n};break}case"half-open":this.state={state:"open",failureCount:this.state.failureCount+1,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break;case"open":this.state={...this.state,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break}}getState(){return this.updateStateIfNeeded(),{...this.state,canExecute:this.state.state!=="open"}}createOpenError(){let r=this.state.nextAttemptTime?b(Math.max(0,this.state.nextAttemptTime.getTime()-Date.now())):this.config.resetTimeout;return new D(r)}forceState(r){this.state={state:r,failureCount:0,halfOpenCount:0}}reset(){this.state={state:"closed",failureCount:0,halfOpenCount:0}}updateStateIfNeeded(){this.state.state==="open"&&this.state.nextAttemptTime&&new Date>=this.state.nextAttemptTime&&(this.state={...this.state,state:"half-open",halfOpenCount:0})}};var Y=(e,r)=>t=>{for(let n of e){let s=n(t);if(s!==null)return s}return r(t)},G=e=>r=>r instanceof E?r:r instanceof Error?new e(r.message,r):typeof r=="string"?new e(r):new e("Unknown error occurred",r);var ce=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},le=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},de=e=>{var r;if(e instanceof Error){let t=e.message.toLowerCase();if(e.name==="TypeError"&&(t.includes("fetch")&&t.includes("failed")||t.includes("network"))||t.includes("fetch")&&t.includes("failed")||t.includes("network"))return!0}if(le(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},ye=e=>typeof e=="object"&&e!==null,B=class{constructor(r){this.predicate=r}toCode(r){return new H(this.predicate,r)}toError(r){return t=>{var c;if(!this.predicate(t))return null;let n=r(t),s=n.code,i=Object.hasOwn(n,"cause")?n.cause:t,o=(c=n.meta)!=null?c:{};class a extends E{constructor(){let l=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:i,meta:o,status:n.status,retryable:n.retryable,raw:l,path:n.path});d(this,"code",s)}}return new a}}};function pe(e,r){let t=new B(i=>i instanceof e);if(r)return t.toError(r);let s=i=>{if(!(i instanceof e))return null;if(i instanceof E)return i;let o=i,a=typeof o.code=="string"&&o.code.length>0?o.code:"UNKNOWN",c=Object.hasOwn(o,"cause"),u=Object.hasOwn(o,"raw");class y extends E{constructor(){super(o.message||a,{title:typeof o.title=="string"?o.title:void 0,cause:c?o.cause:i,meta:ye(o.meta)?o.meta:{},status:typeof o.status=="number"?o.status:void 0,retryable:typeof o.retryable=="boolean"?o.retryable:void 0,raw:u?o.raw:i,path:typeof o.path=="string"?o.path:void 0});d(this,"code",a)}}return new y};return s.toCode=t.toCode.bind(t),s.toError=t.toError.bind(t),s}var H=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){return t=>{var c;if(!this.predicate(t))return null;let n=r(t),s=Object.hasOwn(n,"cause")?n.cause:t,i=(c=n.meta)!=null?c:{},o=this.errorCode;class a extends E{constructor(){let p=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:s,meta:i,status:n.status,retryable:n.retryable,raw:p,path:n.path});d(this,"code",o)}}return new a}}},h={when:e=>new B(e),instance:pe},g={typed:(e=>e instanceof E?e:null),abort:h.when(e=>e instanceof Error&&e.name==="AbortError").toCode("ABORTED").with(e=>({message:e.message||"Operation was aborted",cause:e,retryable:!1,raw:e})),timeout:h.when(e=>e instanceof Error&&e.name==="TimeoutError").toCode("TIMEOUT").with(e=>({message:e.message||"Operation timed out",cause:e,raw:e})),network:h.when(e=>de(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:h.when(e=>{var n;if(!ce(e))return!1;let r=e,t=(n=r.status)!=null?n:r.statusCode;return typeof t=="number"&&t>=400}).toCode("HTTP").with(e=>{var n;let r=(n=e.status)!=null?n:e.statusCode,t=typeof r=="number"&&(r>=500||r===429);return{message:e.message||`HTTP ${r!=null?r:"error"} error`,cause:e,status:typeof r=="number"?r:void 0,retryable:t,raw:e}}),unknown:h.when(e=>e instanceof Error&&!(e instanceof E)).toCode("UNKNOWN").with(e=>({message:e.message||"Unknown error occurred",cause:e,raw:e}))};var me=[g.typed,g.abort,g.timeout,g.http,g.network,g.unknown];var fe={when:e=>h.when(e),instance:h.instance},Q=me;var Ee={fixed:e=>({type:"fixed",delay:e}),exponential:(e,r=2,t)=>({type:"exponential",base:e,factor:r,maxDelay:t}),fibonacci:(e,r)=>({type:"fibonacci",base:e,maxDelay:r}),custom:e=>({type:"custom",calculate:e})},X=(e,r,t)=>{switch(e.type){case"fixed":return e.delay;case"exponential":{let n=e.base*e.factor**(Number(r)-1);return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"fibonacci":{let n=e.base*we(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},we=e=>{if(e<=1)return 1;let r=1,t=1;for(let n=2;n<=e;n++){let s=r+t;r=t,t=s}return t},Z=e=>{switch(e.type){case"fixed":{if(e.delay<0)throw new Error("Fixed delay must be non-negative");break}case"exponential":if(e.base<=0)throw new Error("Exponential base delay must be positive");if(e.factor<=1)throw new Error("Exponential factor must be greater than 1");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Exponential max delay must be positive");break;case"fibonacci":if(e.base<=0)throw new Error("Fibonacci base delay must be positive");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Fibonacci max delay must be positive");break;case"custom":break;default:{let r=e;throw new Error(`Unknown strategy type: ${r}`)}}};var ee=(e,r)=>new Promise((t,n)=>{if(r!=null&&r.aborted){n(new DOMException("Aborted","AbortError"));return}let s=a=>{r&&a&&r.removeEventListener("abort",a)},i,o=()=>{i&&clearTimeout(i),s(o),n(new DOMException("Aborted","AbortError"))};i=setTimeout(()=>{s(o),t()},e),r==null||r.addEventListener("abort",o,{once:!0})}),re=(e,r,t,n)=>new Promise((s,i)=>{if(t!=null&&t.aborted){i(new DOMException("Aborted","AbortError"));return}let o=!1,a=setTimeout(()=>{var y;o=!0,u(),i((y=n==null?void 0:n())!=null?y:new Error(`Operation timed out after ${r}ms`))},r),c=()=>{o||(o=!0,u(),i(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(a),t==null||t.removeEventListener("abort",c)};t==null||t.addEventListener("abort",c,{once:!0}),e.then(y=>{o||(o=!0,u(),s(y))},y=>{o||(o=!0,u(),i(y))})});var Te=e=>{var o,a,c;if(e.toError)return e.toError;let r=(o=e.rulesMode)!=null?o:"extend",t=(a=e.rules)!=null?a:[],n=Q,s=(c=e.fallback)!=null?c:(u=>G(P)(u)),i=r==="replace"?t:[...t,...n];return Y(i,s)},be=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":j(e.ratio);return;case"custom":return;default:{let r=e;throw new Error(`Unsupported jitter configuration: ${r}`)}}},q=e=>{let r=e;return r.timeout!==void 0&&(r={...r,timeout:Number(b(r.timeout))}),r.concurrency!==void 0&&(r={...r,concurrency:Number.isFinite(r.concurrency)?Number(z(r.concurrency)):r.concurrency}),r.retry&&(Z(r.retry.strategy),be(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(C(r.retry.maxRetries))}}),r},$=class e{constructor(r={}){d(this,"circuitBreaker");d(this,"config");d(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:s,toError:i,mapError:o,...a}=r,c=Te(r),u={...a,errorHandling:{normalizer:c,mapError:o}};this.config=q(u),u.circuitBreaker&&(this.circuitBreaker=new F(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var i,o,a,c,u,y;let n=q({...this.config,...t});if(this.circuitBreaker){let l=(i=this.lastCircuitState)!=null?i:this.circuitBreaker.getState().state,p=await this.circuitBreaker.canExecute(),w=this.circuitBreaker.getState().state;if(l!==w)try{(a=(o=n.hooks)==null?void 0:o.onCircuitStateChange)==null||a.call(o,l,w)}catch{}if(this.lastCircuitState=w,!p)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let s=await he(r,n);if(this.circuitBreaker){let l=(c=this.lastCircuitState)!=null?c:this.circuitBreaker.getState().state;s.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(s.error);let p=this.circuitBreaker.getState().state;if(l!==p)try{(y=(u=n.hooks)==null?void 0:u.onCircuitStateChange)==null||y.call(u,l,p)}catch{}this.lastCircuitState=p}return s}async runOrThrow(r,t={}){return this.orThrow(r,t)}async orThrow(r,t={}){let n=await this.run(r,t);if(n.ok)return n.data;throw n.error}async all(r,t={}){var y;let n=q({...this.config,...t}),s=(y=n.concurrency)!=null?y:Number.POSITIVE_INFINITY,i=Number.isFinite(s)?Number(z(s)):Number.POSITIVE_INFINITY;if(i===Number.POSITIVE_INFINITY)return Promise.all(r.map(l=>this.run(l,n)));let o=new Array(r.length),a=0,c=async()=>{var l;for(;a<r.length&&!((l=n.signal)!=null&&l.aborted);){let p=a++;if(p>=r.length)break;let w=r[p];w&&(o[p]=await this.run(w,n))}},u=Array.from({length:Math.min(i,r.length)},()=>c());await Promise.all(u);for(let l=0;l<r.length;l++)if(!(l in o)){let p=r[l];p&&(o[l]=await this.run(p,n))}return o}async allOrThrow(r,t={}){return(await this.all(r,t)).map(s=>{if(!s.ok)throw s.error;return s.data})}partitionAll(r){let t=[],n=[],s=[],i=[],o=[];for(let a of r){if(a.type==="success"){t.push(a);continue}switch(n.push(a),a.type){case"failure":s.push(a);break;case"aborted":i.push(a);break;case"timeout":o.push(a);break}}return{ok:t,errors:n,failure:s,aborted:i,timeout:o}}getCircuitBreakerState(){var r;return(r=this.circuitBreaker)==null?void 0:r.getState()}resetCircuitBreaker(){var r;(r=this.circuitBreaker)==null||r.reset()}getConfig(){return{...this.config}}withConfig(r){var c,u;let{errorHandling:t,...n}=this.config,{errorHandling:s,...i}=r,o=(c=s==null?void 0:s.normalizer)!=null?c:t.normalizer,a=(u=s==null?void 0:s.mapError)!=null?u:t.mapError;return new e({...n,...i,toError:o,mapError:a})}};function _(e={}){let r=new $(e);return{run:(t,n)=>r.run(t,n),orThrow:(t,n)=>r.orThrow(t,n),runOrThrow:(t,n)=>r.runOrThrow(t,n),all:(t,n)=>r.all(t,n),allOrThrow:(t,n)=>r.allOrThrow(t,n),partitionAll:t=>r.partitionAll(t),withConfig:t=>r.withConfig(t)}}async function he(e,r){let{signal:t,ignoreAbort:n=!0,timeout:s,retry:i,errorHandling:o,hooks:a,logger:c}=r,u=(R,...m)=>{try{R==null||R(...m)}catch{}},y,l=0,p=0,w=[],k=Date.now(),{signal:O,cleanup:ne}=te(t),N=R=>({totalAttempts:l,totalRetries:l>0?Number(l)-1:0,totalDuration:Date.now()-k,lastError:R,retryHistory:w});try{if(O.aborted){u(a==null?void 0:a.onAbort,O);let m=o.normalizer(new DOMException("Aborted","AbortError")),T=o.mapError?o.mapError(m):m;return{type:"aborted",ok:!1,data:null,error:T,metrics:{totalAttempts:l,totalRetries:p,totalDuration:Date.now()-k,lastError:T,retryHistory:w}}}let R=async()=>{var M,x,W;let m=1,T=C((M=i==null?void 0:i.maxRetries)!=null?M:0);for(;;){l=m;let K=new AbortController,{signal:U,cleanup:oe}=te(O,K.signal);try{let I=Promise.resolve(e({signal:U})),A=s?await re(I,s,U,()=>(K.abort(),new v(b(s)))):await I;return u(a==null?void 0:a.onSuccess,A,N()),u(c==null?void 0:c.info,`Task succeeded on attempt ${m}`),A}catch(I){let A=o.normalizer(I),f=o.mapError?o.mapError(A):A;if(y=f,f.code==="ABORTED"&&u(a==null?void 0:a.onAbort,U),n&&f.code==="ABORTED"||(u(a==null?void 0:a.onError,f,N(f)),u(c==null?void 0:c.error,`Task failed on attempt ${m}`,f)),f.code==="ABORTED"||f.retryable===!1)throw f;if(m<=Number(T)){let V=i==null?void 0:i.shouldRetry,se={totalAttempts:Number(l),elapsedTime:Date.now()-k,startTime:new Date(k),lastDelay:(x=w[w.length-1])!=null&&x.delay?Number((W=w[w.length-1])==null?void 0:W.delay):void 0};if(!V||V(m,f,se)){let ae=i?X(i.strategy,m,f):0,L=Re(ae,i==null?void 0:i.jitter),J=b(L);w.push({attempt:m,error:f,delay:J,timestamp:new Date}),u(a==null?void 0:a.onRetry,m,f,L),u(c==null?void 0:c.info,`Retrying in ${L}ms (attempt ${m+1})`),m+=1,await ee(J,O);continue}}throw f}finally{oe()}}};try{let m=await R(),T=N();return p=T.totalRetries,u(a==null?void 0:a.onFinally,T),{type:"success",ok:!0,data:m,error:null,metrics:T}}catch(m){let T=y!=null?y:o.normalizer(m),M=T.code==="TIMEOUT"?"timeout":T.code==="ABORTED"?"aborted":"failure",x=N(T);return p=x.totalRetries,u(a==null?void 0:a.onFinally,x),{type:M,ok:!1,data:null,error:T,metrics:x}}}finally{ne()}}function te(...e){let r=new AbortController,t=e.filter(s=>s!==void 0);if(t.length===0)return{signal:r.signal,cleanup:()=>{}};if(t.some(s=>s.aborted))return r.abort(),{signal:r.signal,cleanup:()=>{}};let n=[];for(let s of t){let i=()=>r.abort();s.addEventListener("abort",i,{once:!0}),n.push({signal:s,abort:i})}return{signal:r.signal,cleanup:()=>{for(let s of n)s.signal.removeEventListener("abort",s.abort)}}}function Re(e,r){if(!r||r.type==="none"||e<=0)return e;switch(r.type){case"full":{let t=Number(r.ratio)/100,n=Math.max(0,Number(e)*(1-t)),s=Number(e);return n+Math.random()*(s-n)}case"equal":{let t=Number(r.ratio)/100,n=Number(e)*t/2;return Number(e)-n+Math.random()*n}case"custom":return r.calculate(e);default:return r}}var S=_(),Ce=S.run,ge=S.runOrThrow,xe=S.orThrow,ke=S.all,Oe=S.allOrThrow;export{Ee as RetryStrategies,E as TypedError,ke as all,Oe as allOrThrow,b as asMilliseconds,C as asRetryCount,_ as default,fe as errorRule,xe as orThrow,Ce as run,ge as runOrThrow,_ as tryo};
|