tryo 0.13.7 → 0.13.9
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/README.md +3 -5
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +97 -131
- package/dist/index.d.ts +97 -131
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -169,11 +169,9 @@ Add hooks for logging or monitoring:
|
|
|
169
169
|
|
|
170
170
|
```typescript
|
|
171
171
|
const ex = tryo({
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
console.log(`Breaker moved: ${from} -> ${to}`),
|
|
176
|
-
},
|
|
172
|
+
onRetry: (attempt, error, delay) => console.log(`Retry ${attempt}...`),
|
|
173
|
+
onCircuitStateChange: (from, to) =>
|
|
174
|
+
console.log(`Breaker moved: ${from} -> ${to}`),
|
|
177
175
|
})
|
|
178
176
|
```
|
|
179
177
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
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});
|
|
1
|
+
"use strict";var F=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var he=Object.prototype.hasOwnProperty;var Re=(e,r,t)=>r in e?F(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var Ce=(e,r)=>{for(var t in r)F(e,t,{get:r[t],enumerable:!0})},xe=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of be(r))!he.call(e,o)&&o!==t&&F(e,o,{get:()=>r[o],enumerable:!(n=we(r,o))||n.enumerable});return e};var ge=e=>xe(F({},"__esModule",{value:!0}),e);var d=(e,r,t)=>Re(e,typeof r!="symbol"?r+"":r,t);var Ue={};Ce(Ue,{RetryStrategies:()=>ne,TypedError:()=>f,all:()=>ye,allOrThrow:()=>pe,asMilliseconds:()=>b,asRetryCount:()=>h,default:()=>N,errorRule:()=>re,orThrow:()=>de,run:()=>ce,runOrThrow:()=>le,tryo:()=>N});module.exports=ge(Ue);var f=class extends Error{constructor(t,n){var o,s;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=(s=n.meta)!=null?s:{},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}}},B=class extends f{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0});d(this,"code","TIMEOUT")}};var _=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 U=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},W=e=>{if(e<1||!Number.isInteger(e))throw new Error(`Invalid concurrency limit: must be a positive integer, got ${e}`);return e},X=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 L=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,s,a;if(!((a=(s=(o=this.config).shouldCountAsFailure)==null?void 0:s.call(o,r))!=null?a:!0))return;let n=new Date;switch(this.state.state){case"closed":{let i=this.state.failureCount+1;i>=this.config.failureThreshold?this.state={state:"open",failureCount:i,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:i,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 _(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 Z=(e,r)=>t=>{for(let n of e){let o=n(t);if(o!==null)return o}return r(t)},ee=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 ke=e=>{let t=e.toString().match(/\bcode\s*:\s*['"`]([^'"`]+)['"`]/);return t==null?void 0:t[1]},Oe=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},Ae=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},Se=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(Ae(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},Ne=e=>typeof e=="object"&&e!==null,z=class{constructor(r){this.predicate=r}toCode(r){return new K(this.predicate,r)}toError(r){let t=o=>{var c;if(!this.predicate(o))return null;let s=r(o),a=s.code,i=Object.hasOwn(s,"cause")?s.cause:o,l=(c=s.meta)!=null?c:{};class u extends f{constructor(){let m=Object.hasOwn(s,"raw")?s.raw:o;super(s.message,{title:s.title,cause:i,meta:l,status:s.status,retryable:s.retryable,raw:m,path:s.path});d(this,"code",a)}}return new u},n=ke(r);return n&&(t.__tryoCode=n),t}};function Me(e,r){let t=new z(s=>s instanceof e);if(r)return t.toError(r);let o=s=>{if(!(s instanceof e))return null;if(s instanceof f)return s;let a=s,i=typeof a.code=="string"&&a.code.length>0?a.code:"UNKNOWN",l=Object.hasOwn(a,"cause"),u=Object.hasOwn(a,"raw");class c extends f{constructor(){super(a.message||i,{title:typeof a.title=="string"?a.title:void 0,cause:l?a.cause:s,meta:Ne(a.meta)?a.meta:{},status:typeof a.status=="number"?a.status:void 0,retryable:typeof a.retryable=="boolean"?a.retryable:void 0,raw:u?a.raw:s,path:typeof a.path=="string"?a.path:void 0});d(this,"code",i)}}return new c};return o.toCode=t.toCode.bind(t),o.toError=t.toError.bind(t),o}var K=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){let t=n=>{var u;if(!this.predicate(n))return null;let o=r(n),s=Object.hasOwn(o,"cause")?o.cause:n,a=(u=o.meta)!=null?u:{},i=this.errorCode;class l extends f{constructor(){let m=Object.hasOwn(o,"raw")?o.raw:n;super(o.message,{title:o.title,cause:s,meta:a,status:o.status,retryable:o.retryable,raw:m,path:o.path});d(this,"code",i)}}return new l};return t.__tryoCode=this.errorCode,t}},R={when:e=>new z(e),instance:Me},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=>Se(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:R.when(e=>{var n;if(!Oe(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 Ie=[x.typed,x.abort,x.timeout,x.http,x.network,x.unknown];var re={when:e=>R.when(e),instance:R.instance},te=Ie;var ne={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})},oe=(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*ve(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},ve=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},se=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 ae=(e,r)=>new Promise((t,n)=>{if(r!=null&&r.aborted){n(new DOMException("Aborted","AbortError"));return}let o=i=>{r&&i&&r.removeEventListener("abort",i)},s,a=()=>{s&&clearTimeout(s),o(a),n(new DOMException("Aborted","AbortError"))};s=setTimeout(()=>{o(a),t()},e),r==null||r.addEventListener("abort",a,{once:!0})}),ie=(e,r,t,n)=>new Promise((o,s)=>{if(t!=null&&t.aborted){s(new DOMException("Aborted","AbortError"));return}let a=!1,i=setTimeout(()=>{var c;a=!0,u(),s((c=n==null?void 0:n())!=null?c:new Error(`Operation timed out after ${r}ms`))},r),l=()=>{a||(a=!0,u(),s(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(i),t==null||t.removeEventListener("abort",l)};t==null||t.addEventListener("abort",l,{once:!0}),e.then(c=>{a||(a=!0,u(),o(c))},c=>{a||(a=!0,u(),s(c))})});var De=e=>{var a,i,l;if(e.toError)return e.toError;let r=(a=e.rulesMode)!=null?a:"extend",t=(i=e.rules)!=null?i:[];Pe(t);let n=te,o=(l=e.fallback)!=null?l:(u=>ee(U)(u)),s=r==="replace"?t:[...t,...n];return Z(s,o)},Pe=e=>{let r=new Set;for(let t of e){let n=t.__tryoCode;if(n){if(r.has(n))throw new Error(`Duplicate rule code detected: ${n}`);r.add(n)}}},Fe=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":X(e.ratio);return;case"custom":return;default:{let r=e;throw new Error(`Unsupported jitter configuration: ${r}`)}}},V=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(W(r.concurrency)):r.concurrency}),r.retry&&(se(r.retry.strategy),Fe(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(h(r.retry.maxRetries))}}),r},J=class e{constructor(r={}){d(this,"circuitBreaker");d(this,"config");d(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:o,toError:s,mapError:a,...i}=r,l=De(r),u={...i,errorHandling:{normalizer:l,mapError:a}};this.config=V(u),u.circuitBreaker&&(this.circuitBreaker=new L(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var s,a,i,l;let n=V({...this.config,...t});if(this.circuitBreaker){let u=(s=this.lastCircuitState)!=null?s:this.circuitBreaker.getState().state,c=await this.circuitBreaker.canExecute(),y=this.circuitBreaker.getState().state;if(u!==y)try{(a=n.onCircuitStateChange)==null||a.call(n,u,y)}catch{}if(this.lastCircuitState=y,!c)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let o=await Be(r,n);if(this.circuitBreaker){let u=(i=this.lastCircuitState)!=null?i:this.circuitBreaker.getState().state;o.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(o.error);let c=this.circuitBreaker.getState().state;if(u!==c)try{(l=n.onCircuitStateChange)==null||l.call(n,u,c)}catch{}this.lastCircuitState=c}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 c;let n=V({...this.config,...t}),o=(c=n.concurrency)!=null?c:Number.POSITIVE_INFINITY,s=Number.isFinite(o)?Number(W(o)):Number.POSITIVE_INFINITY;if(s===Number.POSITIVE_INFINITY)return Promise.all(r.map(y=>this.run(y,n)));let a=new Array(r.length),i=0,l=async()=>{var y;for(;i<r.length&&!((y=n.signal)!=null&&y.aborted);){let T=i++;if(T>=r.length)break;let m=r[T];m&&(a[T]=await this.run(m,n))}},u=Array.from({length:Math.min(s,r.length)},()=>l());await Promise.all(u);for(let y=0;y<r.length;y++)if(!(y in a)){let T=r[y];T&&(a[y]=await this.run(T,n))}return a}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=[],s=[],a=[];for(let i of r){if(i.type==="success"){t.push(i);continue}switch(n.push(i),i.type){case"failure":o.push(i);break;case"aborted":s.push(i);break;case"timeout":a.push(i);break}}return{ok:t,errors:n,failure:o,aborted:s,timeout:a}}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,...s}=r,a=(l=o==null?void 0:o.normalizer)!=null?l:t.normalizer,i=(u=o==null?void 0:o.mapError)!=null?u:t.mapError;return new e({...n,...s,toError:a,mapError:i})}};function N(e={}){let r=new J(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 Be(e,r){let{signal:t,ignoreAbort:n=!0,timeout:o,retry:s,errorHandling:a,logger:i,onSuccess:l,onError:u,onFinally:c,onAbort:y,onRetry:T}=r,m=(C,...p)=>{try{C==null||C(...p)}catch{}},I,k=0,g=[],H=Date.now(),{signal:v,cleanup:me}=ue(t),O=C=>({totalAttempts:k,totalRetries:k>0?Number(k)-1:0,totalDuration:Date.now()-H,lastError:C,retryHistory:g});try{if(v.aborted){m(y,v);let p=a.normalizer(new DOMException("Aborted","AbortError")),w=a.mapError?a.mapError(p):p;return{type:"aborted",ok:!1,data:null,error:w,metrics:O(w)}}let C=async()=>{var D,A,j;let p=1,w=h((D=s==null?void 0:s.maxRetries)!=null?D:0);for(;;){k=p;let Y=new AbortController,{signal:$,cleanup:fe}=ue(v,Y.signal);try{let P=Promise.resolve(e({signal:$})),S=o?await ie(P,o,$,()=>(Y.abort(),new B(b(o)))):await P;return m(l,S,O()),m(i==null?void 0:i.info,`Task succeeded on attempt ${p}`),S}catch(P){let S=a.normalizer(P),E=a.mapError?a.mapError(S):S;if(I=E,E.code==="ABORTED"&&m(y,$),n&&E.code==="ABORTED"||(m(u,E,O(E)),m(i==null?void 0:i.error,`Task failed on attempt ${p}`,E)),E.code==="ABORTED"||E.retryable===!1)throw E;if(p<=Number(w)){let G=s==null?void 0:s.shouldRetry,Ee={totalAttempts:Number(k),elapsedTime:Date.now()-H,startTime:new Date(H),lastDelay:(A=g[g.length-1])!=null&&A.delay?Number((j=g[g.length-1])==null?void 0:j.delay):void 0};if(!G||G(p,E,Ee)){let Te=s?oe(s.strategy,p,E):0,q=_e(Te,s==null?void 0:s.jitter),Q=b(q);g.push({attempt:p,error:E,delay:Q,timestamp:new Date}),m(T,p,E,q),m(i==null?void 0:i.info,`Retrying in ${q}ms (attempt ${p+1})`),p+=1,await ae(Q,v);continue}}throw E}finally{fe()}}};try{let p=await C(),w=O();return m(c,w),{type:"success",ok:!0,data:p,error:null,metrics:w}}catch(p){let w=I!=null?I:a.normalizer(p),D=w.code==="TIMEOUT"?"timeout":w.code==="ABORTED"?"aborted":"failure",A=O(w);return m(c,A),{type:D,ok:!1,data:null,error:w,metrics:A}}}finally{me()}}function ue(...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 s=()=>r.abort();o.addEventListener("abort",s,{once:!0}),n.push({signal:o,abort:s})}return{signal:r.signal,cleanup:()=>{for(let o of n)o.signal.removeEventListener("abort",o.abort)}}}function _e(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 M=N(),ce=M.run,le=M.runOrThrow,de=M.orThrow,ye=M.all,pe=M.allOrThrow;0&&(module.exports={RetryStrategies,TypedError,all,allOrThrow,asMilliseconds,asRetryCount,errorRule,orThrow,run,runOrThrow,tryo});
|
package/dist/index.d.cts
CHANGED
|
@@ -94,53 +94,6 @@ declare class UnknownError extends TypedError<'UNKNOWN', Record<string, unknown>
|
|
|
94
94
|
constructor(message: string, cause?: unknown);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
/**
|
|
98
|
-
* Modern result types with enhanced discriminated unions
|
|
99
|
-
* Provides better type safety and more granular result categorization
|
|
100
|
-
*/
|
|
101
|
-
|
|
102
|
-
type TryoResult<T, E extends AnyTypedError = AnyTypedError> = SuccessResult<T, E> | FailureResult<E> | AbortedResult<E> | TimeoutResult<E>;
|
|
103
|
-
interface SuccessResult<T, E extends AnyTypedError> {
|
|
104
|
-
readonly type: 'success';
|
|
105
|
-
readonly ok: true;
|
|
106
|
-
readonly data: T;
|
|
107
|
-
readonly error: null;
|
|
108
|
-
readonly metrics: TryoMetrics$1<E>;
|
|
109
|
-
}
|
|
110
|
-
interface FailureResult<E extends AnyTypedError> {
|
|
111
|
-
readonly type: 'failure';
|
|
112
|
-
readonly ok: false;
|
|
113
|
-
readonly data: null;
|
|
114
|
-
readonly error: E;
|
|
115
|
-
readonly metrics: TryoMetrics$1<E>;
|
|
116
|
-
}
|
|
117
|
-
interface AbortedResult<E extends AnyTypedError> {
|
|
118
|
-
readonly type: 'aborted';
|
|
119
|
-
readonly ok: false;
|
|
120
|
-
readonly data: null;
|
|
121
|
-
readonly error: E;
|
|
122
|
-
readonly metrics: TryoMetrics$1<E>;
|
|
123
|
-
}
|
|
124
|
-
interface TimeoutResult<E extends AnyTypedError> {
|
|
125
|
-
readonly type: 'timeout';
|
|
126
|
-
readonly ok: false;
|
|
127
|
-
readonly data: null;
|
|
128
|
-
readonly error: E;
|
|
129
|
-
readonly metrics: TryoMetrics$1<E>;
|
|
130
|
-
}
|
|
131
|
-
interface TryoMetrics$1<E extends AnyTypedError> {
|
|
132
|
-
readonly totalAttempts: RetryCount;
|
|
133
|
-
readonly totalRetries: RetryCount;
|
|
134
|
-
readonly totalDuration: Milliseconds;
|
|
135
|
-
readonly lastError?: E;
|
|
136
|
-
readonly retryHistory: Array<{
|
|
137
|
-
readonly attempt: RetryCount;
|
|
138
|
-
readonly error: E;
|
|
139
|
-
readonly delay: Milliseconds;
|
|
140
|
-
readonly timestamp: Date;
|
|
141
|
-
}>;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
97
|
/**
|
|
145
98
|
* Modern circuit breaker implementation with enhanced state management
|
|
146
99
|
* Provides circuit breaker pattern with type safety and observability
|
|
@@ -198,6 +151,58 @@ declare const RetryStrategies: {
|
|
|
198
151
|
readonly custom: (calculate: (attempt: RetryCount, error: unknown) => number) => CustomDelayStrategy;
|
|
199
152
|
};
|
|
200
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Modern result types with enhanced discriminated unions
|
|
156
|
+
* Provides better type safety and more granular result categorization
|
|
157
|
+
*/
|
|
158
|
+
|
|
159
|
+
type TryoResult<T, E extends AnyTypedError = AnyTypedError> = SuccessResult<T, E> | FailureResult<E> | AbortedResult<E> | TimeoutResult<E>;
|
|
160
|
+
interface SuccessResult<T, E extends AnyTypedError> {
|
|
161
|
+
readonly type: 'success';
|
|
162
|
+
readonly ok: true;
|
|
163
|
+
readonly data: T;
|
|
164
|
+
readonly error: null;
|
|
165
|
+
readonly metrics: TryoMetrics<E>;
|
|
166
|
+
}
|
|
167
|
+
interface FailureResult<E extends AnyTypedError> {
|
|
168
|
+
readonly type: 'failure';
|
|
169
|
+
readonly ok: false;
|
|
170
|
+
readonly data: null;
|
|
171
|
+
readonly error: E;
|
|
172
|
+
readonly metrics: TryoMetrics<E>;
|
|
173
|
+
}
|
|
174
|
+
interface AbortedResult<E extends AnyTypedError> {
|
|
175
|
+
readonly type: 'aborted';
|
|
176
|
+
readonly ok: false;
|
|
177
|
+
readonly data: null;
|
|
178
|
+
readonly error: E;
|
|
179
|
+
readonly metrics: TryoMetrics<E>;
|
|
180
|
+
}
|
|
181
|
+
interface TimeoutResult<E extends AnyTypedError> {
|
|
182
|
+
readonly type: 'timeout';
|
|
183
|
+
readonly ok: false;
|
|
184
|
+
readonly data: null;
|
|
185
|
+
readonly error: E;
|
|
186
|
+
readonly metrics: TryoMetrics<E>;
|
|
187
|
+
}
|
|
188
|
+
interface TryoMetrics<E extends AnyTypedError> {
|
|
189
|
+
readonly totalAttempts: RetryCount;
|
|
190
|
+
readonly totalRetries: RetryCount;
|
|
191
|
+
readonly totalDuration: Milliseconds;
|
|
192
|
+
readonly lastError?: E;
|
|
193
|
+
readonly retryHistory: Array<{
|
|
194
|
+
readonly attempt: RetryCount;
|
|
195
|
+
readonly error: E;
|
|
196
|
+
readonly delay: Milliseconds;
|
|
197
|
+
readonly timestamp: Date;
|
|
198
|
+
}>;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Configuration types for modern execution engine
|
|
203
|
+
* Provides comprehensive configuration with type safety
|
|
204
|
+
*/
|
|
205
|
+
|
|
201
206
|
interface TryoConfig<E extends AnyTypedError = AnyTypedError> {
|
|
202
207
|
/** Abort signal passed to tasks */
|
|
203
208
|
readonly signal?: AbortSignal;
|
|
@@ -215,8 +220,18 @@ interface TryoConfig<E extends AnyTypedError = AnyTypedError> {
|
|
|
215
220
|
readonly concurrency?: number;
|
|
216
221
|
/** Logging configuration */
|
|
217
222
|
readonly logger?: LoggerConfig<E>;
|
|
218
|
-
/**
|
|
219
|
-
readonly
|
|
223
|
+
/** Called on successful execution */
|
|
224
|
+
readonly onSuccess?: <T>(data: T, metrics?: TryoMetrics<E>) => void;
|
|
225
|
+
/** Called on failed execution */
|
|
226
|
+
readonly onError?: (error: E, metrics?: TryoMetrics<E>) => void;
|
|
227
|
+
/** Called always, success or failure */
|
|
228
|
+
readonly onFinally?: (metrics?: TryoMetrics<E>) => void;
|
|
229
|
+
/** Called on abort */
|
|
230
|
+
readonly onAbort?: (signal: AbortSignal) => void;
|
|
231
|
+
/** Called before retry attempt */
|
|
232
|
+
readonly onRetry?: (attempt: number, error: E, delay: number) => void;
|
|
233
|
+
/** Called when circuit breaker state changes */
|
|
234
|
+
readonly onCircuitStateChange?: (from: CircuitState, to: CircuitState) => void;
|
|
220
235
|
}
|
|
221
236
|
interface RetryConfig<E extends AnyTypedError> {
|
|
222
237
|
/** Maximum number of retry attempts */
|
|
@@ -255,21 +270,6 @@ interface LoggerConfig<E extends AnyTypedError> {
|
|
|
255
270
|
/** Warning logging function */
|
|
256
271
|
readonly warn?: (message: string, meta?: unknown) => void;
|
|
257
272
|
}
|
|
258
|
-
interface HookConfig<E extends AnyTypedError> {
|
|
259
|
-
/** Called on successful execution */
|
|
260
|
-
readonly onSuccess?: <T>(data: T, metrics?: TryoMetrics<E>) => void;
|
|
261
|
-
/** Called on failed execution */
|
|
262
|
-
readonly onError?: (error: E, metrics?: TryoMetrics<E>) => void;
|
|
263
|
-
/** Called always, success or failure */
|
|
264
|
-
readonly onFinally?: (metrics?: TryoMetrics<E>) => void;
|
|
265
|
-
/** Called on abort */
|
|
266
|
-
readonly onAbort?: (signal: AbortSignal) => void;
|
|
267
|
-
/** Called before retry attempt */
|
|
268
|
-
readonly onRetry?: (attempt: number, error: E, delay: number) => void;
|
|
269
|
-
/** Called when circuit breaker state changes */
|
|
270
|
-
readonly onCircuitStateChange?: (from: CircuitState, to: CircuitState) => void;
|
|
271
|
-
}
|
|
272
|
-
type TryoMetrics<E extends AnyTypedError> = TryoMetrics$1<E>;
|
|
273
273
|
type JitterConfig = {
|
|
274
274
|
type: 'none';
|
|
275
275
|
} | {
|
|
@@ -291,10 +291,17 @@ declare const JitterConfig: {
|
|
|
291
291
|
|
|
292
292
|
type RulesMode = 'extend' | 'replace';
|
|
293
293
|
type DefaultError = AbortedError | TimeoutError | NetworkError | HttpError | CircuitOpenError | ValidationError | UnknownError;
|
|
294
|
-
type RunOptions<E extends AnyTypedError> = Omit<Partial<TryoConfig<E>>, 'circuitBreaker'
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
294
|
+
type RunOptions<E extends AnyTypedError, TData = unknown> = Omit<Partial<TryoConfig<E>>, 'circuitBreaker' | 'onSuccess'> & {
|
|
295
|
+
onSuccess?: (data: TData, metrics?: TryoMetrics<E>) => void;
|
|
296
|
+
};
|
|
297
|
+
type AllOptions<E extends AnyTypedError, TData = unknown> = RunOptions<E, TData>;
|
|
298
|
+
type PartitionedResults<T, E extends AnyTypedError> = {
|
|
299
|
+
ok: Array<SuccessResult<T, E>>;
|
|
300
|
+
errors: Array<FailureResult<E> | AbortedResult<E> | TimeoutResult<E>>;
|
|
301
|
+
failure: Array<FailureResult<E>>;
|
|
302
|
+
aborted: Array<AbortedResult<E>>;
|
|
303
|
+
timeout: Array<TimeoutResult<E>>;
|
|
304
|
+
};
|
|
298
305
|
type MaybePromise<T> = T | Promise<T>;
|
|
299
306
|
type RuleLike = (error: unknown) => AnyTypedError | null;
|
|
300
307
|
type NonNull<T> = T extends null ? never : T;
|
|
@@ -329,89 +336,48 @@ declare function tryo<E extends AnyTypedError = DefaultError>(options?: TryoOpti
|
|
|
329
336
|
type Tryo<E extends AnyTypedError = AnyTypedError> = {
|
|
330
337
|
run: <T>(task: (ctx: {
|
|
331
338
|
signal: AbortSignal;
|
|
332
|
-
}) => MaybePromise<T>, options?: RunOptions<E>) => Promise<TryoResult<T, E>>;
|
|
339
|
+
}) => MaybePromise<T>, options?: RunOptions<E, T>) => Promise<TryoResult<T, E>>;
|
|
333
340
|
runOrThrow: <T>(task: (ctx: {
|
|
334
341
|
signal: AbortSignal;
|
|
335
|
-
}) => MaybePromise<T>, options?: RunOptions<E>) => Promise<T>;
|
|
342
|
+
}) => MaybePromise<T>, options?: RunOptions<E, T>) => Promise<T>;
|
|
336
343
|
orThrow: <T>(task: (ctx: {
|
|
337
344
|
signal: AbortSignal;
|
|
338
|
-
}) => MaybePromise<T>, options?: RunOptions<E>) => Promise<T>;
|
|
345
|
+
}) => MaybePromise<T>, options?: RunOptions<E, T>) => Promise<T>;
|
|
339
346
|
all: <T>(tasks: Array<(ctx: {
|
|
340
347
|
signal: AbortSignal;
|
|
341
|
-
}) => MaybePromise<T>>, options?: AllOptions<E>) => Promise<Array<TryoResult<T, E>>>;
|
|
348
|
+
}) => MaybePromise<T>>, options?: AllOptions<E, T>) => Promise<Array<TryoResult<T, E>>>;
|
|
342
349
|
allOrThrow: <T>(tasks: Array<(ctx: {
|
|
343
350
|
signal: AbortSignal;
|
|
344
|
-
}) => MaybePromise<T>>, options?: AllOptions<E>) => Promise<T[]>;
|
|
345
|
-
partitionAll: <T>(results: Array<TryoResult<T, E>>) =>
|
|
346
|
-
ok: Array<SuccessResult<T, E>>;
|
|
347
|
-
errors: Array<FailureResult<E> | AbortedResult<E> | TimeoutResult<E>>;
|
|
348
|
-
failure: Array<FailureResult<E>>;
|
|
349
|
-
aborted: Array<AbortedResult<E>>;
|
|
350
|
-
timeout: Array<TimeoutResult<E>>;
|
|
351
|
-
};
|
|
351
|
+
}) => MaybePromise<T>>, options?: AllOptions<E, T>) => Promise<T[]>;
|
|
352
|
+
partitionAll: <T>(results: Array<TryoResult<T, E>>) => PartitionedResults<T, E>;
|
|
352
353
|
withConfig: (additionalConfig: Omit<Partial<TryoConfig<E>>, 'signal'>) => Tryo<E>;
|
|
353
354
|
};
|
|
354
355
|
|
|
355
356
|
declare const run: <T>(task: (ctx: {
|
|
356
357
|
signal: AbortSignal;
|
|
357
|
-
}) => T | Promise<T>, options?: {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
361
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
362
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
363
|
-
readonly concurrency?: number | undefined;
|
|
364
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
365
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
366
|
-
} | undefined) => Promise<TryoResult<T, DefaultError>>;
|
|
358
|
+
}) => T | Promise<T>, options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
359
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
360
|
+
}) | undefined) => Promise<TryoResult<T, DefaultError>>;
|
|
367
361
|
declare const runOrThrow: <T>(task: (ctx: {
|
|
368
362
|
signal: AbortSignal;
|
|
369
|
-
}) => T | Promise<T>, options?: {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
373
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
374
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
375
|
-
readonly concurrency?: number | undefined;
|
|
376
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
377
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
378
|
-
} | undefined) => Promise<T>;
|
|
363
|
+
}) => T | Promise<T>, options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
364
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
365
|
+
}) | undefined) => Promise<T>;
|
|
379
366
|
declare const orThrow: <T>(task: (ctx: {
|
|
380
367
|
signal: AbortSignal;
|
|
381
|
-
}) => T | Promise<T>, options?: {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
385
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
386
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
387
|
-
readonly concurrency?: number | undefined;
|
|
388
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
389
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
390
|
-
} | undefined) => Promise<T>;
|
|
368
|
+
}) => T | Promise<T>, options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
369
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
370
|
+
}) | undefined) => Promise<T>;
|
|
391
371
|
declare const all: <T>(tasks: ((ctx: {
|
|
392
372
|
signal: AbortSignal;
|
|
393
|
-
}) => T | Promise<T>)[], options?: {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
397
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
398
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
399
|
-
concurrency?: number | undefined;
|
|
400
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
401
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
402
|
-
} | undefined) => Promise<TryoResult<T, DefaultError>[]>;
|
|
373
|
+
}) => T | Promise<T>)[], options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
374
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
375
|
+
}) | undefined) => Promise<TryoResult<T, DefaultError>[]>;
|
|
403
376
|
declare const allOrThrow: <T>(tasks: ((ctx: {
|
|
404
377
|
signal: AbortSignal;
|
|
405
|
-
}) => T | Promise<T>)[], options?: {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
409
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
410
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
411
|
-
concurrency?: number | undefined;
|
|
412
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
413
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
414
|
-
} | undefined) => Promise<T[]>;
|
|
378
|
+
}) => T | Promise<T>)[], options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
379
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
380
|
+
}) | undefined) => Promise<T[]>;
|
|
415
381
|
|
|
416
382
|
/**
|
|
417
383
|
* Modern fluent error rule builder
|
|
@@ -476,4 +442,4 @@ declare const errorRule: {
|
|
|
476
442
|
};
|
|
477
443
|
};
|
|
478
444
|
|
|
479
|
-
export { type AbortedResult, type FailureResult, type Milliseconds, type RetryCount, RetryStrategies, type RulesMode, type SuccessResult, type TimeoutResult, type TryoConfig, type TryoMetrics
|
|
445
|
+
export { type AbortedResult, type FailureResult, type Milliseconds, type RetryCount, RetryStrategies, type RulesMode, type SuccessResult, type TimeoutResult, type TryoConfig, type TryoMetrics, type TryoOptions, type TryoResult, TypedError, all, allOrThrow, asMilliseconds, asRetryCount, tryo as default, errorRule, orThrow, run, runOrThrow, tryo };
|
package/dist/index.d.ts
CHANGED
|
@@ -94,53 +94,6 @@ declare class UnknownError extends TypedError<'UNKNOWN', Record<string, unknown>
|
|
|
94
94
|
constructor(message: string, cause?: unknown);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
/**
|
|
98
|
-
* Modern result types with enhanced discriminated unions
|
|
99
|
-
* Provides better type safety and more granular result categorization
|
|
100
|
-
*/
|
|
101
|
-
|
|
102
|
-
type TryoResult<T, E extends AnyTypedError = AnyTypedError> = SuccessResult<T, E> | FailureResult<E> | AbortedResult<E> | TimeoutResult<E>;
|
|
103
|
-
interface SuccessResult<T, E extends AnyTypedError> {
|
|
104
|
-
readonly type: 'success';
|
|
105
|
-
readonly ok: true;
|
|
106
|
-
readonly data: T;
|
|
107
|
-
readonly error: null;
|
|
108
|
-
readonly metrics: TryoMetrics$1<E>;
|
|
109
|
-
}
|
|
110
|
-
interface FailureResult<E extends AnyTypedError> {
|
|
111
|
-
readonly type: 'failure';
|
|
112
|
-
readonly ok: false;
|
|
113
|
-
readonly data: null;
|
|
114
|
-
readonly error: E;
|
|
115
|
-
readonly metrics: TryoMetrics$1<E>;
|
|
116
|
-
}
|
|
117
|
-
interface AbortedResult<E extends AnyTypedError> {
|
|
118
|
-
readonly type: 'aborted';
|
|
119
|
-
readonly ok: false;
|
|
120
|
-
readonly data: null;
|
|
121
|
-
readonly error: E;
|
|
122
|
-
readonly metrics: TryoMetrics$1<E>;
|
|
123
|
-
}
|
|
124
|
-
interface TimeoutResult<E extends AnyTypedError> {
|
|
125
|
-
readonly type: 'timeout';
|
|
126
|
-
readonly ok: false;
|
|
127
|
-
readonly data: null;
|
|
128
|
-
readonly error: E;
|
|
129
|
-
readonly metrics: TryoMetrics$1<E>;
|
|
130
|
-
}
|
|
131
|
-
interface TryoMetrics$1<E extends AnyTypedError> {
|
|
132
|
-
readonly totalAttempts: RetryCount;
|
|
133
|
-
readonly totalRetries: RetryCount;
|
|
134
|
-
readonly totalDuration: Milliseconds;
|
|
135
|
-
readonly lastError?: E;
|
|
136
|
-
readonly retryHistory: Array<{
|
|
137
|
-
readonly attempt: RetryCount;
|
|
138
|
-
readonly error: E;
|
|
139
|
-
readonly delay: Milliseconds;
|
|
140
|
-
readonly timestamp: Date;
|
|
141
|
-
}>;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
97
|
/**
|
|
145
98
|
* Modern circuit breaker implementation with enhanced state management
|
|
146
99
|
* Provides circuit breaker pattern with type safety and observability
|
|
@@ -198,6 +151,58 @@ declare const RetryStrategies: {
|
|
|
198
151
|
readonly custom: (calculate: (attempt: RetryCount, error: unknown) => number) => CustomDelayStrategy;
|
|
199
152
|
};
|
|
200
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Modern result types with enhanced discriminated unions
|
|
156
|
+
* Provides better type safety and more granular result categorization
|
|
157
|
+
*/
|
|
158
|
+
|
|
159
|
+
type TryoResult<T, E extends AnyTypedError = AnyTypedError> = SuccessResult<T, E> | FailureResult<E> | AbortedResult<E> | TimeoutResult<E>;
|
|
160
|
+
interface SuccessResult<T, E extends AnyTypedError> {
|
|
161
|
+
readonly type: 'success';
|
|
162
|
+
readonly ok: true;
|
|
163
|
+
readonly data: T;
|
|
164
|
+
readonly error: null;
|
|
165
|
+
readonly metrics: TryoMetrics<E>;
|
|
166
|
+
}
|
|
167
|
+
interface FailureResult<E extends AnyTypedError> {
|
|
168
|
+
readonly type: 'failure';
|
|
169
|
+
readonly ok: false;
|
|
170
|
+
readonly data: null;
|
|
171
|
+
readonly error: E;
|
|
172
|
+
readonly metrics: TryoMetrics<E>;
|
|
173
|
+
}
|
|
174
|
+
interface AbortedResult<E extends AnyTypedError> {
|
|
175
|
+
readonly type: 'aborted';
|
|
176
|
+
readonly ok: false;
|
|
177
|
+
readonly data: null;
|
|
178
|
+
readonly error: E;
|
|
179
|
+
readonly metrics: TryoMetrics<E>;
|
|
180
|
+
}
|
|
181
|
+
interface TimeoutResult<E extends AnyTypedError> {
|
|
182
|
+
readonly type: 'timeout';
|
|
183
|
+
readonly ok: false;
|
|
184
|
+
readonly data: null;
|
|
185
|
+
readonly error: E;
|
|
186
|
+
readonly metrics: TryoMetrics<E>;
|
|
187
|
+
}
|
|
188
|
+
interface TryoMetrics<E extends AnyTypedError> {
|
|
189
|
+
readonly totalAttempts: RetryCount;
|
|
190
|
+
readonly totalRetries: RetryCount;
|
|
191
|
+
readonly totalDuration: Milliseconds;
|
|
192
|
+
readonly lastError?: E;
|
|
193
|
+
readonly retryHistory: Array<{
|
|
194
|
+
readonly attempt: RetryCount;
|
|
195
|
+
readonly error: E;
|
|
196
|
+
readonly delay: Milliseconds;
|
|
197
|
+
readonly timestamp: Date;
|
|
198
|
+
}>;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Configuration types for modern execution engine
|
|
203
|
+
* Provides comprehensive configuration with type safety
|
|
204
|
+
*/
|
|
205
|
+
|
|
201
206
|
interface TryoConfig<E extends AnyTypedError = AnyTypedError> {
|
|
202
207
|
/** Abort signal passed to tasks */
|
|
203
208
|
readonly signal?: AbortSignal;
|
|
@@ -215,8 +220,18 @@ interface TryoConfig<E extends AnyTypedError = AnyTypedError> {
|
|
|
215
220
|
readonly concurrency?: number;
|
|
216
221
|
/** Logging configuration */
|
|
217
222
|
readonly logger?: LoggerConfig<E>;
|
|
218
|
-
/**
|
|
219
|
-
readonly
|
|
223
|
+
/** Called on successful execution */
|
|
224
|
+
readonly onSuccess?: <T>(data: T, metrics?: TryoMetrics<E>) => void;
|
|
225
|
+
/** Called on failed execution */
|
|
226
|
+
readonly onError?: (error: E, metrics?: TryoMetrics<E>) => void;
|
|
227
|
+
/** Called always, success or failure */
|
|
228
|
+
readonly onFinally?: (metrics?: TryoMetrics<E>) => void;
|
|
229
|
+
/** Called on abort */
|
|
230
|
+
readonly onAbort?: (signal: AbortSignal) => void;
|
|
231
|
+
/** Called before retry attempt */
|
|
232
|
+
readonly onRetry?: (attempt: number, error: E, delay: number) => void;
|
|
233
|
+
/** Called when circuit breaker state changes */
|
|
234
|
+
readonly onCircuitStateChange?: (from: CircuitState, to: CircuitState) => void;
|
|
220
235
|
}
|
|
221
236
|
interface RetryConfig<E extends AnyTypedError> {
|
|
222
237
|
/** Maximum number of retry attempts */
|
|
@@ -255,21 +270,6 @@ interface LoggerConfig<E extends AnyTypedError> {
|
|
|
255
270
|
/** Warning logging function */
|
|
256
271
|
readonly warn?: (message: string, meta?: unknown) => void;
|
|
257
272
|
}
|
|
258
|
-
interface HookConfig<E extends AnyTypedError> {
|
|
259
|
-
/** Called on successful execution */
|
|
260
|
-
readonly onSuccess?: <T>(data: T, metrics?: TryoMetrics<E>) => void;
|
|
261
|
-
/** Called on failed execution */
|
|
262
|
-
readonly onError?: (error: E, metrics?: TryoMetrics<E>) => void;
|
|
263
|
-
/** Called always, success or failure */
|
|
264
|
-
readonly onFinally?: (metrics?: TryoMetrics<E>) => void;
|
|
265
|
-
/** Called on abort */
|
|
266
|
-
readonly onAbort?: (signal: AbortSignal) => void;
|
|
267
|
-
/** Called before retry attempt */
|
|
268
|
-
readonly onRetry?: (attempt: number, error: E, delay: number) => void;
|
|
269
|
-
/** Called when circuit breaker state changes */
|
|
270
|
-
readonly onCircuitStateChange?: (from: CircuitState, to: CircuitState) => void;
|
|
271
|
-
}
|
|
272
|
-
type TryoMetrics<E extends AnyTypedError> = TryoMetrics$1<E>;
|
|
273
273
|
type JitterConfig = {
|
|
274
274
|
type: 'none';
|
|
275
275
|
} | {
|
|
@@ -291,10 +291,17 @@ declare const JitterConfig: {
|
|
|
291
291
|
|
|
292
292
|
type RulesMode = 'extend' | 'replace';
|
|
293
293
|
type DefaultError = AbortedError | TimeoutError | NetworkError | HttpError | CircuitOpenError | ValidationError | UnknownError;
|
|
294
|
-
type RunOptions<E extends AnyTypedError> = Omit<Partial<TryoConfig<E>>, 'circuitBreaker'
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
294
|
+
type RunOptions<E extends AnyTypedError, TData = unknown> = Omit<Partial<TryoConfig<E>>, 'circuitBreaker' | 'onSuccess'> & {
|
|
295
|
+
onSuccess?: (data: TData, metrics?: TryoMetrics<E>) => void;
|
|
296
|
+
};
|
|
297
|
+
type AllOptions<E extends AnyTypedError, TData = unknown> = RunOptions<E, TData>;
|
|
298
|
+
type PartitionedResults<T, E extends AnyTypedError> = {
|
|
299
|
+
ok: Array<SuccessResult<T, E>>;
|
|
300
|
+
errors: Array<FailureResult<E> | AbortedResult<E> | TimeoutResult<E>>;
|
|
301
|
+
failure: Array<FailureResult<E>>;
|
|
302
|
+
aborted: Array<AbortedResult<E>>;
|
|
303
|
+
timeout: Array<TimeoutResult<E>>;
|
|
304
|
+
};
|
|
298
305
|
type MaybePromise<T> = T | Promise<T>;
|
|
299
306
|
type RuleLike = (error: unknown) => AnyTypedError | null;
|
|
300
307
|
type NonNull<T> = T extends null ? never : T;
|
|
@@ -329,89 +336,48 @@ declare function tryo<E extends AnyTypedError = DefaultError>(options?: TryoOpti
|
|
|
329
336
|
type Tryo<E extends AnyTypedError = AnyTypedError> = {
|
|
330
337
|
run: <T>(task: (ctx: {
|
|
331
338
|
signal: AbortSignal;
|
|
332
|
-
}) => MaybePromise<T>, options?: RunOptions<E>) => Promise<TryoResult<T, E>>;
|
|
339
|
+
}) => MaybePromise<T>, options?: RunOptions<E, T>) => Promise<TryoResult<T, E>>;
|
|
333
340
|
runOrThrow: <T>(task: (ctx: {
|
|
334
341
|
signal: AbortSignal;
|
|
335
|
-
}) => MaybePromise<T>, options?: RunOptions<E>) => Promise<T>;
|
|
342
|
+
}) => MaybePromise<T>, options?: RunOptions<E, T>) => Promise<T>;
|
|
336
343
|
orThrow: <T>(task: (ctx: {
|
|
337
344
|
signal: AbortSignal;
|
|
338
|
-
}) => MaybePromise<T>, options?: RunOptions<E>) => Promise<T>;
|
|
345
|
+
}) => MaybePromise<T>, options?: RunOptions<E, T>) => Promise<T>;
|
|
339
346
|
all: <T>(tasks: Array<(ctx: {
|
|
340
347
|
signal: AbortSignal;
|
|
341
|
-
}) => MaybePromise<T>>, options?: AllOptions<E>) => Promise<Array<TryoResult<T, E>>>;
|
|
348
|
+
}) => MaybePromise<T>>, options?: AllOptions<E, T>) => Promise<Array<TryoResult<T, E>>>;
|
|
342
349
|
allOrThrow: <T>(tasks: Array<(ctx: {
|
|
343
350
|
signal: AbortSignal;
|
|
344
|
-
}) => MaybePromise<T>>, options?: AllOptions<E>) => Promise<T[]>;
|
|
345
|
-
partitionAll: <T>(results: Array<TryoResult<T, E>>) =>
|
|
346
|
-
ok: Array<SuccessResult<T, E>>;
|
|
347
|
-
errors: Array<FailureResult<E> | AbortedResult<E> | TimeoutResult<E>>;
|
|
348
|
-
failure: Array<FailureResult<E>>;
|
|
349
|
-
aborted: Array<AbortedResult<E>>;
|
|
350
|
-
timeout: Array<TimeoutResult<E>>;
|
|
351
|
-
};
|
|
351
|
+
}) => MaybePromise<T>>, options?: AllOptions<E, T>) => Promise<T[]>;
|
|
352
|
+
partitionAll: <T>(results: Array<TryoResult<T, E>>) => PartitionedResults<T, E>;
|
|
352
353
|
withConfig: (additionalConfig: Omit<Partial<TryoConfig<E>>, 'signal'>) => Tryo<E>;
|
|
353
354
|
};
|
|
354
355
|
|
|
355
356
|
declare const run: <T>(task: (ctx: {
|
|
356
357
|
signal: AbortSignal;
|
|
357
|
-
}) => T | Promise<T>, options?: {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
361
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
362
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
363
|
-
readonly concurrency?: number | undefined;
|
|
364
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
365
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
366
|
-
} | undefined) => Promise<TryoResult<T, DefaultError>>;
|
|
358
|
+
}) => T | Promise<T>, options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
359
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
360
|
+
}) | undefined) => Promise<TryoResult<T, DefaultError>>;
|
|
367
361
|
declare const runOrThrow: <T>(task: (ctx: {
|
|
368
362
|
signal: AbortSignal;
|
|
369
|
-
}) => T | Promise<T>, options?: {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
373
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
374
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
375
|
-
readonly concurrency?: number | undefined;
|
|
376
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
377
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
378
|
-
} | undefined) => Promise<T>;
|
|
363
|
+
}) => T | Promise<T>, options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
364
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
365
|
+
}) | undefined) => Promise<T>;
|
|
379
366
|
declare const orThrow: <T>(task: (ctx: {
|
|
380
367
|
signal: AbortSignal;
|
|
381
|
-
}) => T | Promise<T>, options?: {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
385
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
386
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
387
|
-
readonly concurrency?: number | undefined;
|
|
388
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
389
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
390
|
-
} | undefined) => Promise<T>;
|
|
368
|
+
}) => T | Promise<T>, options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
369
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
370
|
+
}) | undefined) => Promise<T>;
|
|
391
371
|
declare const all: <T>(tasks: ((ctx: {
|
|
392
372
|
signal: AbortSignal;
|
|
393
|
-
}) => T | Promise<T>)[], options?: {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
397
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
398
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
399
|
-
concurrency?: number | undefined;
|
|
400
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
401
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
402
|
-
} | undefined) => Promise<TryoResult<T, DefaultError>[]>;
|
|
373
|
+
}) => T | Promise<T>)[], options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
374
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
375
|
+
}) | undefined) => Promise<TryoResult<T, DefaultError>[]>;
|
|
403
376
|
declare const allOrThrow: <T>(tasks: ((ctx: {
|
|
404
377
|
signal: AbortSignal;
|
|
405
|
-
}) => T | Promise<T>)[], options?: {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
readonly ignoreAbort?: boolean | undefined;
|
|
409
|
-
readonly retry?: RetryConfig<DefaultError> | undefined;
|
|
410
|
-
readonly errorHandling?: ErrorHandlingConfig<DefaultError> | undefined;
|
|
411
|
-
concurrency?: number | undefined;
|
|
412
|
-
readonly logger?: LoggerConfig<DefaultError> | undefined;
|
|
413
|
-
readonly hooks?: HookConfig<DefaultError> | undefined;
|
|
414
|
-
} | undefined) => Promise<T[]>;
|
|
378
|
+
}) => T | Promise<T>)[], options?: (Omit<Partial<TryoConfig<DefaultError>>, "circuitBreaker" | "onSuccess"> & {
|
|
379
|
+
onSuccess?: ((data: T, metrics?: TryoMetrics<DefaultError> | undefined) => void) | undefined;
|
|
380
|
+
}) | undefined) => Promise<T[]>;
|
|
415
381
|
|
|
416
382
|
/**
|
|
417
383
|
* Modern fluent error rule builder
|
|
@@ -476,4 +442,4 @@ declare const errorRule: {
|
|
|
476
442
|
};
|
|
477
443
|
};
|
|
478
444
|
|
|
479
|
-
export { type AbortedResult, type FailureResult, type Milliseconds, type RetryCount, RetryStrategies, type RulesMode, type SuccessResult, type TimeoutResult, type TryoConfig, type TryoMetrics
|
|
445
|
+
export { type AbortedResult, type FailureResult, type Milliseconds, type RetryCount, RetryStrategies, type RulesMode, type SuccessResult, type TimeoutResult, type TryoConfig, type TryoMetrics, type TryoOptions, type TryoResult, TypedError, all, allOrThrow, asMilliseconds, asRetryCount, tryo as default, errorRule, orThrow, run, runOrThrow, tryo };
|
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 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};
|
|
1
|
+
var le=Object.defineProperty;var de=(e,r,t)=>r in e?le(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var d=(e,r,t)=>de(e,typeof r!="symbol"?r+"":r,t);var E=class extends Error{constructor(t,n){var o,s;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=(s=n.meta)!=null?s:{},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 E{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0});d(this,"code","TIMEOUT")}};var F=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 B=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},q=e=>{if(e<1||!Number.isInteger(e))throw new Error(`Invalid concurrency limit: must be a positive integer, got ${e}`);return e},Q=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: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 o,s,a;if(!((a=(s=(o=this.config).shouldCountAsFailure)==null?void 0:s.call(o,r))!=null?a:!0))return;let n=new Date;switch(this.state.state){case"closed":{let i=this.state.failureCount+1;i>=this.config.failureThreshold?this.state={state:"open",failureCount:i,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:i,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 X=(e,r)=>t=>{for(let n of e){let o=n(t);if(o!==null)return o}return r(t)},Z=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 ye=e=>{let t=e.toString().match(/\bcode\s*:\s*['"`]([^'"`]+)['"`]/);return t==null?void 0:t[1]},pe=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},me=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},fe=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(me(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},Ee=e=>typeof e=="object"&&e!==null,U=class{constructor(r){this.predicate=r}toCode(r){return new W(this.predicate,r)}toError(r){let t=o=>{var c;if(!this.predicate(o))return null;let s=r(o),a=s.code,i=Object.hasOwn(s,"cause")?s.cause:o,l=(c=s.meta)!=null?c:{};class u extends E{constructor(){let m=Object.hasOwn(s,"raw")?s.raw:o;super(s.message,{title:s.title,cause:i,meta:l,status:s.status,retryable:s.retryable,raw:m,path:s.path});d(this,"code",a)}}return new u},n=ye(r);return n&&(t.__tryoCode=n),t}};function Te(e,r){let t=new U(s=>s instanceof e);if(r)return t.toError(r);let o=s=>{if(!(s instanceof e))return null;if(s instanceof E)return s;let a=s,i=typeof a.code=="string"&&a.code.length>0?a.code:"UNKNOWN",l=Object.hasOwn(a,"cause"),u=Object.hasOwn(a,"raw");class c extends E{constructor(){super(a.message||i,{title:typeof a.title=="string"?a.title:void 0,cause:l?a.cause:s,meta:Ee(a.meta)?a.meta:{},status:typeof a.status=="number"?a.status:void 0,retryable:typeof a.retryable=="boolean"?a.retryable:void 0,raw:u?a.raw:s,path:typeof a.path=="string"?a.path:void 0});d(this,"code",i)}}return new c};return o.toCode=t.toCode.bind(t),o.toError=t.toError.bind(t),o}var W=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){let t=n=>{var u;if(!this.predicate(n))return null;let o=r(n),s=Object.hasOwn(o,"cause")?o.cause:n,a=(u=o.meta)!=null?u:{},i=this.errorCode;class l extends E{constructor(){let m=Object.hasOwn(o,"raw")?o.raw:n;super(o.message,{title:o.title,cause:s,meta:a,status:o.status,retryable:o.retryable,raw:m,path:o.path});d(this,"code",i)}}return new l};return t.__tryoCode=this.errorCode,t}},h={when:e=>new U(e),instance:Te},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=>fe(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:h.when(e=>{var n;if(!pe(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 we=[x.typed,x.abort,x.timeout,x.http,x.network,x.unknown];var be={when:e=>h.when(e),instance:h.instance},ee=we;var he={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*Re(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},Re=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=i=>{r&&i&&r.removeEventListener("abort",i)},s,a=()=>{s&&clearTimeout(s),o(a),n(new DOMException("Aborted","AbortError"))};s=setTimeout(()=>{o(a),t()},e),r==null||r.addEventListener("abort",a,{once:!0})}),oe=(e,r,t,n)=>new Promise((o,s)=>{if(t!=null&&t.aborted){s(new DOMException("Aborted","AbortError"));return}let a=!1,i=setTimeout(()=>{var c;a=!0,u(),s((c=n==null?void 0:n())!=null?c:new Error(`Operation timed out after ${r}ms`))},r),l=()=>{a||(a=!0,u(),s(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(i),t==null||t.removeEventListener("abort",l)};t==null||t.addEventListener("abort",l,{once:!0}),e.then(c=>{a||(a=!0,u(),o(c))},c=>{a||(a=!0,u(),s(c))})});var Ce=e=>{var a,i,l;if(e.toError)return e.toError;let r=(a=e.rulesMode)!=null?a:"extend",t=(i=e.rules)!=null?i:[];xe(t);let n=ee,o=(l=e.fallback)!=null?l:(u=>Z(B)(u)),s=r==="replace"?t:[...t,...n];return X(s,o)},xe=e=>{let r=new Set;for(let t of e){let n=t.__tryoCode;if(n){if(r.has(n))throw new Error(`Duplicate rule code detected: ${n}`);r.add(n)}}},ge=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":Q(e.ratio);return;case"custom":return;default:{let r=e;throw new Error(`Unsupported jitter configuration: ${r}`)}}},K=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(q(r.concurrency)):r.concurrency}),r.retry&&(te(r.retry.strategy),ge(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(C(r.retry.maxRetries))}}),r},V=class e{constructor(r={}){d(this,"circuitBreaker");d(this,"config");d(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:o,toError:s,mapError:a,...i}=r,l=Ce(r),u={...i,errorHandling:{normalizer:l,mapError:a}};this.config=K(u),u.circuitBreaker&&(this.circuitBreaker=new _(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var s,a,i,l;let n=K({...this.config,...t});if(this.circuitBreaker){let u=(s=this.lastCircuitState)!=null?s:this.circuitBreaker.getState().state,c=await this.circuitBreaker.canExecute(),y=this.circuitBreaker.getState().state;if(u!==y)try{(a=n.onCircuitStateChange)==null||a.call(n,u,y)}catch{}if(this.lastCircuitState=y,!c)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let o=await ke(r,n);if(this.circuitBreaker){let u=(i=this.lastCircuitState)!=null?i:this.circuitBreaker.getState().state;o.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(o.error);let c=this.circuitBreaker.getState().state;if(u!==c)try{(l=n.onCircuitStateChange)==null||l.call(n,u,c)}catch{}this.lastCircuitState=c}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 c;let n=K({...this.config,...t}),o=(c=n.concurrency)!=null?c:Number.POSITIVE_INFINITY,s=Number.isFinite(o)?Number(q(o)):Number.POSITIVE_INFINITY;if(s===Number.POSITIVE_INFINITY)return Promise.all(r.map(y=>this.run(y,n)));let a=new Array(r.length),i=0,l=async()=>{var y;for(;i<r.length&&!((y=n.signal)!=null&&y.aborted);){let T=i++;if(T>=r.length)break;let m=r[T];m&&(a[T]=await this.run(m,n))}},u=Array.from({length:Math.min(s,r.length)},()=>l());await Promise.all(u);for(let y=0;y<r.length;y++)if(!(y in a)){let T=r[y];T&&(a[y]=await this.run(T,n))}return a}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=[],s=[],a=[];for(let i of r){if(i.type==="success"){t.push(i);continue}switch(n.push(i),i.type){case"failure":o.push(i);break;case"aborted":s.push(i);break;case"timeout":a.push(i);break}}return{ok:t,errors:n,failure:o,aborted:s,timeout:a}}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,...s}=r,a=(l=o==null?void 0:o.normalizer)!=null?l:t.normalizer,i=(u=o==null?void 0:o.mapError)!=null?u:t.mapError;return new e({...n,...s,toError:a,mapError:i})}};function L(e={}){let r=new V(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 ke(e,r){let{signal:t,ignoreAbort:n=!0,timeout:o,retry:s,errorHandling:a,logger:i,onSuccess:l,onError:u,onFinally:c,onAbort:y,onRetry:T}=r,m=(R,...p)=>{try{R==null||R(...p)}catch{}},M,k=0,g=[],z=Date.now(),{signal:I,cleanup:ae}=se(t),O=R=>({totalAttempts:k,totalRetries:k>0?Number(k)-1:0,totalDuration:Date.now()-z,lastError:R,retryHistory:g});try{if(I.aborted){m(y,I);let p=a.normalizer(new DOMException("Aborted","AbortError")),w=a.mapError?a.mapError(p):p;return{type:"aborted",ok:!1,data:null,error:w,metrics:O(w)}}let R=async()=>{var v,A,J;let p=1,w=C((v=s==null?void 0:s.maxRetries)!=null?v:0);for(;;){k=p;let j=new AbortController,{signal:H,cleanup:ie}=se(I,j.signal);try{let D=Promise.resolve(e({signal:H})),S=o?await oe(D,o,H,()=>(j.abort(),new P(b(o)))):await D;return m(l,S,O()),m(i==null?void 0:i.info,`Task succeeded on attempt ${p}`),S}catch(D){let S=a.normalizer(D),f=a.mapError?a.mapError(S):S;if(M=f,f.code==="ABORTED"&&m(y,H),n&&f.code==="ABORTED"||(m(u,f,O(f)),m(i==null?void 0:i.error,`Task failed on attempt ${p}`,f)),f.code==="ABORTED"||f.retryable===!1)throw f;if(p<=Number(w)){let Y=s==null?void 0:s.shouldRetry,ue={totalAttempts:Number(k),elapsedTime:Date.now()-z,startTime:new Date(z),lastDelay:(A=g[g.length-1])!=null&&A.delay?Number((J=g[g.length-1])==null?void 0:J.delay):void 0};if(!Y||Y(p,f,ue)){let ce=s?re(s.strategy,p,f):0,$=Oe(ce,s==null?void 0:s.jitter),G=b($);g.push({attempt:p,error:f,delay:G,timestamp:new Date}),m(T,p,f,$),m(i==null?void 0:i.info,`Retrying in ${$}ms (attempt ${p+1})`),p+=1,await ne(G,I);continue}}throw f}finally{ie()}}};try{let p=await R(),w=O();return m(c,w),{type:"success",ok:!0,data:p,error:null,metrics:w}}catch(p){let w=M!=null?M:a.normalizer(p),v=w.code==="TIMEOUT"?"timeout":w.code==="ABORTED"?"aborted":"failure",A=O(w);return m(c,A),{type:v,ok:!1,data:null,error:w,metrics:A}}}finally{ae()}}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 s=()=>r.abort();o.addEventListener("abort",s,{once:!0}),n.push({signal:o,abort:s})}return{signal:r.signal,cleanup:()=>{for(let o of n)o.signal.removeEventListener("abort",o.abort)}}}function Oe(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=L(),Ae=N.run,Se=N.runOrThrow,Ne=N.orThrow,Me=N.all,Ie=N.allOrThrow;export{he as RetryStrategies,E as TypedError,Me as all,Ie as allOrThrow,b as asMilliseconds,C as asRetryCount,L as default,be as errorRule,Ne as orThrow,Ae as run,Se as runOrThrow,L as tryo};
|