tryo 0.13.3 → 0.13.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var I=Object.defineProperty;var fe=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var be=(e,r,t)=>r in e?I(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var we=(e,r)=>{for(var t in r)I(e,t,{get:r[t],enumerable:!0})},he=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of Ee(r))!Te.call(e,o)&&o!==t&&I(e,o,{get:()=>r[o],enumerable:!(n=fe(r,o))||n.enumerable});return e};var Ce=e=>he(I({},"__esModule",{value:!0}),e);var y=(e,r,t)=>be(e,typeof r!="symbol"?r+"":r,t);var ve={};we(ve,{RetryStrategies:()=>ee,TypedError:()=>T,all:()=>le,allOrThrow:()=>ce,asMilliseconds:()=>w,asRetryCount:()=>h,default:()=>S,errorRule:()=>Z,orThrow:()=>ue,run:()=>ae,runOrThrow:()=>ie,tryo:()=>S});module.exports=Ce(ve);var T=class extends Error{constructor(t,n){var o,a;super(t);y(this,"cause");y(this,"meta");y(this,"status");y(this,"raw");y(this,"path");y(this,"timestamp");y(this,"retryable");this.timestamp=Date.now(),this.retryable=(o=n.retryable)!=null?o:!0,this.name=this.constructor.name,this.cause=n.cause,this.meta=(a=n.meta)!=null?a:{},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,message:this.message,timestamp:this.timestamp,retryable:this.retryable,cause:this.cause,raw:this.raw,path:this.path,stack:this.stack}}},P=class extends T{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0,raw:n});y(this,"code","TIMEOUT")}};var F=class extends T{constructor(t,n){super(`Circuit breaker is open, reset after ${t}ms`,{cause:n,retryable:!1,raw:n});y(this,"code","CIRCUIT_OPEN")}};var _=class extends T{constructor(t,n){super(t,{cause:n,raw:n});y(this,"code","UNKNOWN")}};var w=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},G=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 B=class{constructor(r){y(this,"state");y(this,"config");this.config={failureThreshold:h(r.failureThreshold),resetTimeout:w(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,a,i;if(!((i=(a=(o=this.config).shouldCountAsFailure)==null?void 0:a.call(o,r))!=null?i:!0))return;let n=new Date;switch(this.state.state){case"closed":{let s=this.state.failureCount+1;s>=this.config.failureThreshold?this.state={state:"open",failureCount:s,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:s,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?w(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 Q=(e,r)=>t=>{for(let n of e){let o=n(t);if(o!==null)return o}return r(t)},X=e=>r=>r instanceof T?r:r instanceof Error?new e(r.message,r):typeof r=="string"?new e(r):new e("Unknown error occurred",r);var Re=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},xe=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},ge=e=>{var r;if(e instanceof Error){let t=e.message.toLowerCase();if(e.name==="TypeError"&&(t.includes("fetch")&&t.includes("failed")||t.includes("network"))||t.includes("fetch")&&t.includes("failed")||t.includes("network"))return!0}if(xe(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},U=class{constructor(r){this.predicate=r}toCode(r){return new $(this.predicate,r)}toError(r){return t=>{if(!this.predicate(t))return null;let n=r(t),o=n.code;class a extends T{constructor(){var l,u,d;super(n.message,{cause:(l=n.cause)!=null?l:t,meta:(u=n.meta)!=null?u:{},status:n.status,retryable:n.retryable,raw:(d=n.raw)!=null?d:t,path:n.path});y(this,"code",o)}}return new a}}},$=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){return t=>{if(!this.predicate(t))return null;let n=r(t),o=this.errorCode;class a extends T{constructor(){var u;let l=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{cause:n.cause,meta:(u=n.meta)!=null?u:{},status:n.status,retryable:n.retryable,raw:l,path:n.path});y(this,"code",o)}}return new a}}},C={when:e=>new U(e),instance:e=>new U(r=>r instanceof e)},x={typed:(e=>e instanceof T?e:null),abort:C.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:C.when(e=>e instanceof Error&&e.name==="TimeoutError").toCode("TIMEOUT").with(e=>({message:e.message||"Operation timed out",cause:e,raw:e})),network:C.when(e=>ge(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:C.when(e=>{var n;if(!Re(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:C.when(e=>e instanceof Error&&!(e instanceof T)).toCode("UNKNOWN").with(e=>({message:e.message||"Unknown error occurred",cause:e,raw:e}))};var ke=[x.typed,x.abort,x.timeout,x.http,x.network,x.unknown];var Z={when:e=>C.when(e),instance:e=>C.instance(e)},j=ke;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*Ae(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},Ae=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=s=>{r&&s&&r.removeEventListener("abort",s)},a,i=()=>{a&&clearTimeout(a),o(i),n(new DOMException("Aborted","AbortError"))};a=setTimeout(()=>{o(i),t()},e),r==null||r.addEventListener("abort",i,{once:!0})}),oe=(e,r,t,n)=>new Promise((o,a)=>{if(t!=null&&t.aborted){a(new DOMException("Aborted","AbortError"));return}let i=!1,s=setTimeout(()=>{var d;i=!0,u(),a((d=n==null?void 0:n())!=null?d:new Error(`Operation timed out after ${r}ms`))},r),l=()=>{i||(i=!0,u(),a(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(s),t==null||t.removeEventListener("abort",l)};t==null||t.addEventListener("abort",l,{once:!0}),e.then(d=>{i||(i=!0,u(),o(d))},d=>{i||(i=!0,u(),a(d))})});var Oe=e=>{var i,s,l;if(e.toError)return e.toError;let r=(i=e.rulesMode)!=null?i:"extend",t=(s=e.rules)!=null?s:[],n=j,o=(l=e.fallback)!=null?l:(u=>X(_)(u)),a=r==="replace"?t:[...t,...n];return Q(a,o)},Se=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":G(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(w(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),Se(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(h(r.retry.maxRetries))}}),r},V=class e{constructor(r={}){y(this,"circuitBreaker");y(this,"config");y(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:o,toError:a,mapError:i,...s}=r,l=Oe(r),u={...s,errorHandling:{normalizer:l,mapError:i}};this.config=q(u),u.circuitBreaker&&(this.circuitBreaker=new B(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var a,i,s,l,u,d;let n=q({...this.config,...t});if(this.circuitBreaker){let c=(a=this.lastCircuitState)!=null?a:this.circuitBreaker.getState().state,m=await this.circuitBreaker.canExecute(),E=this.circuitBreaker.getState().state;if(c!==E)try{(s=(i=n.hooks)==null?void 0:i.onCircuitStateChange)==null||s.call(i,c,E)}catch{}if(this.lastCircuitState=E,!m)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let o=await Ne(r,n);if(this.circuitBreaker){let c=(l=this.lastCircuitState)!=null?l:this.circuitBreaker.getState().state;o.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(o.error);let m=this.circuitBreaker.getState().state;if(c!==m)try{(d=(u=n.hooks)==null?void 0:u.onCircuitStateChange)==null||d.call(u,c,m)}catch{}this.lastCircuitState=m}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 d;let n=q({...this.config,...t}),o=(d=n.concurrency)!=null?d:Number.POSITIVE_INFINITY,a=Number.isFinite(o)?Number(H(o)):Number.POSITIVE_INFINITY;if(a===Number.POSITIVE_INFINITY)return Promise.all(r.map(c=>this.run(c,n)));let i=new Array(r.length),s=0,l=async()=>{var c;for(;s<r.length&&!((c=n.signal)!=null&&c.aborted);){let m=s++;if(m>=r.length)break;let E=r[m];E&&(i[m]=await this.run(E,n))}},u=Array.from({length:Math.min(a,r.length)},()=>l());await Promise.all(u);for(let c=0;c<r.length;c++)if(!(c in i)){let m=r[c];m&&(i[c]=await this.run(m,n))}return i}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=[],a=[],i=[];for(let s of r){if(s.type==="success"){t.push(s);continue}switch(n.push(s),s.type){case"failure":o.push(s);break;case"aborted":a.push(s);break;case"timeout":i.push(s);break}}return{ok:t,errors:n,failure:o,aborted:a,timeout:i}}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,...a}=r,i=(l=o==null?void 0:o.normalizer)!=null?l:t.normalizer,s=(u=o==null?void 0:o.mapError)!=null?u:t.mapError;return new e({...n,...a,toError:i,mapError:s})}};function S(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 Ne(e,r){let{signal:t,ignoreAbort:n=!0,timeout:o,retry:a,errorHandling:i,hooks:s,logger:l}=r,u=(R,...p)=>{try{R==null||R(...p)}catch{}},d,c=0,m=0,E=[],k=Date.now(),{signal:A,cleanup:ye}=se(t),M=R=>({totalAttempts:c,totalRetries:c>0?Number(c)-1:0,totalDuration:Date.now()-k,lastError:R,retryHistory:E});try{if(A.aborted){u(s==null?void 0:s.onAbort,A);let p=i.normalizer(new DOMException("Aborted","AbortError")),b=i.mapError?i.mapError(p):p;return{type:"aborted",ok:!1,data:null,error:b,metrics:{totalAttempts:c,totalRetries:m,totalDuration:Date.now()-k,lastError:b,retryHistory:E}}}let R=async()=>{var v,g,W;let p=1,b=h((v=a==null?void 0:a.maxRetries)!=null?v:0);for(;;){c=p;let K=new AbortController,{signal:z,cleanup:de}=se(A,K.signal);try{let D=Promise.resolve(e({signal:z})),O=o?await oe(D,o,z,()=>(K.abort(),new P(w(o)))):await D;return u(s==null?void 0:s.onSuccess,O,M()),u(l==null?void 0:l.info,`Task succeeded on attempt ${p}`),O}catch(D){let O=i.normalizer(D),f=i.mapError?i.mapError(O):O;if(d=f,f.code==="ABORTED"&&u(s==null?void 0:s.onAbort,z),n&&f.code==="ABORTED"||(u(s==null?void 0:s.onError,f,M(f)),u(l==null?void 0:l.error,`Task failed on attempt ${p}`,f)),f.code==="ABORTED"||f.retryable===!1)throw f;if(p<=Number(b)){let J=a==null?void 0:a.shouldRetry,pe={totalAttempts:Number(c),elapsedTime:Date.now()-k,startTime:new Date(k),lastDelay:(g=E[E.length-1])!=null&&g.delay?Number((W=E[E.length-1])==null?void 0:W.delay):void 0};if(!J||J(p,f,pe)){let me=a?re(a.strategy,p,f):0,L=Me(me,a==null?void 0:a.jitter),Y=w(L);E.push({attempt:p,error:f,delay:Y,timestamp:new Date}),u(s==null?void 0:s.onRetry,p,f,L),u(l==null?void 0:l.info,`Retrying in ${L}ms (attempt ${p+1})`),p+=1,await ne(Y,A);continue}}throw f}finally{de()}}};try{let p=await R(),b=M();return m=b.totalRetries,u(s==null?void 0:s.onFinally,b),{type:"success",ok:!0,data:p,error:null,metrics:b}}catch(p){let b=d!=null?d:i.normalizer(p),v=b.code==="TIMEOUT"?"timeout":b.code==="ABORTED"?"aborted":"failure",g=M(b);return m=g.totalRetries,u(s==null?void 0:s.onFinally,g),{type:v,ok:!1,data:null,error:b,metrics:g}}}finally{ye()}}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 a=()=>r.abort();o.addEventListener("abort",a,{once:!0}),n.push({signal:o,abort:a})}return{signal:r.signal,cleanup:()=>{for(let o of n)o.signal.removeEventListener("abort",o.abort)}}}function Me(e,r){if(!r||r.type==="none"||e<=0)return e;switch(r.type){case"full":{let t=Number(r.ratio)/100,n=Math.max(0,Number(e)*(1-t)),o=Number(e);return n+Math.random()*(o-n)}case"equal":{let t=Number(r.ratio)/100,n=Number(e)*t/2;return Number(e)-n+Math.random()*n}case"custom":return r.calculate(e);default:return r}}var N=S(),ae=N.run,ie=N.runOrThrow,ue=N.orThrow,le=N.all,ce=N.allOrThrow;0&&(module.exports={RetryStrategies,TypedError,all,allOrThrow,asMilliseconds,asRetryCount,errorRule,orThrow,run,runOrThrow,tryo});
1
+ "use strict";var D=Object.defineProperty;var fe=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var we=(e,r,t)=>r in e?D(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var be=(e,r)=>{for(var t in r)D(e,t,{get:r[t],enumerable:!0})},he=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of Ee(r))!Te.call(e,o)&&o!==t&&D(e,o,{get:()=>r[o],enumerable:!(n=fe(r,o))||n.enumerable});return e};var Re=e=>he(D({},"__esModule",{value:!0}),e);var d=(e,r,t)=>we(e,typeof r!="symbol"?r+"":r,t);var De={};be(De,{RetryStrategies:()=>ee,TypedError:()=>f,all:()=>le,allOrThrow:()=>ce,asMilliseconds:()=>b,asRetryCount:()=>h,default:()=>S,errorRule:()=>X,orThrow:()=>ue,run:()=>ae,runOrThrow:()=>ie,tryo:()=>S});module.exports=Re(De);var f=class extends Error{constructor(t,n){var o,i;super(t);d(this,"cause");d(this,"title");d(this,"meta");d(this,"status");d(this,"raw");d(this,"path");d(this,"timestamp");d(this,"retryable");this.timestamp=Date.now(),this.retryable=(o=n.retryable)!=null?o:!0,this.name=this.constructor.name,this.cause=n.cause,this.title=n.title,this.meta=(i=n.meta)!=null?i:{},this.status=n.status,this.raw=n.raw,this.path=n.path,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}is(t){return this.code===t}withMeta(t){return Object.assign(this,{meta:t})}withStatus(t){return Object.assign(this,{status:t})}withCause(t){return Object.assign(this,{cause:t})}withPath(t){return this.path=t,this}withRaw(t){return Object.assign(this,{raw:t})}withRetryable(t){return this.retryable=t,this}toJSON(){return{name:this.name,code:this.code,title:this.title,message:this.message,timestamp:this.timestamp,retryable:this.retryable,cause:this.cause,raw:this.raw,path:this.path,stack:this.stack}}},P=class extends f{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0});d(this,"code","TIMEOUT")}};var F=class extends f{constructor(t,n){super(`Circuit breaker is open, reset after ${t}ms`,{cause:n,retryable:!1});d(this,"code","CIRCUIT_OPEN")}};var B=class extends f{constructor(t,n){super(t,{cause:n});d(this,"code","UNKNOWN")}};var b=e=>{if(e<0||!Number.isFinite(e))throw new Error(`Invalid milliseconds: must be a non-negative finite number, got ${e}`);return e},h=e=>{if(e<0||!Number.isInteger(e))throw new Error(`Invalid retry count: must be a non-negative integer, got ${e}`);return e},H=e=>{if(e<1||!Number.isInteger(e))throw new Error(`Invalid concurrency limit: must be a positive integer, got ${e}`);return e},Y=e=>{if(e<0||e>100||!Number.isFinite(e))throw new Error(`Invalid percentage: must be between 0 and 100, got ${e}`);return e};var _=class{constructor(r){d(this,"state");d(this,"config");this.config={failureThreshold:h(r.failureThreshold),resetTimeout:b(r.resetTimeout),halfOpenRequests:h(r.halfOpenRequests),shouldCountAsFailure:r.shouldCountAsFailure},this.state={state:"closed",failureCount:0,halfOpenCount:0}}async canExecute(){if(this.updateStateIfNeeded(),this.state.state==="open")return!1;if(this.state.state==="half-open"){if(this.state.halfOpenCount>=this.config.halfOpenRequests)return!1;this.state={...this.state,halfOpenCount:this.state.halfOpenCount+1}}return!0}async recordSuccess(){switch(this.state.state){case"closed":this.state={...this.state,failureCount:0};break;case"half-open":this.state={state:"closed",failureCount:0,halfOpenCount:0};break;case"open":break}}async recordFailure(r){var o,i,s;if(!((s=(i=(o=this.config).shouldCountAsFailure)==null?void 0:i.call(o,r))!=null?s:!0))return;let n=new Date;switch(this.state.state){case"closed":{let a=this.state.failureCount+1;a>=this.config.failureThreshold?this.state={state:"open",failureCount:a,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:a,lastFailureTime:n};break}case"half-open":this.state={state:"open",failureCount:this.state.failureCount+1,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break;case"open":this.state={...this.state,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break}}getState(){return this.updateStateIfNeeded(),{...this.state,canExecute:this.state.state!=="open"}}createOpenError(){let r=this.state.nextAttemptTime?b(Math.max(0,this.state.nextAttemptTime.getTime()-Date.now())):this.config.resetTimeout;return new F(r)}forceState(r){this.state={state:r,failureCount:0,halfOpenCount:0}}reset(){this.state={state:"closed",failureCount:0,halfOpenCount:0}}updateStateIfNeeded(){this.state.state==="open"&&this.state.nextAttemptTime&&new Date>=this.state.nextAttemptTime&&(this.state={...this.state,state:"half-open",halfOpenCount:0})}};var G=(e,r)=>t=>{for(let n of e){let o=n(t);if(o!==null)return o}return r(t)},Q=e=>r=>r instanceof f?r:r instanceof Error?new e(r.message,r):typeof r=="string"?new e(r):new e("Unknown error occurred",r);var Ce=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},xe=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},ge=e=>{var r;if(e instanceof Error){let t=e.message.toLowerCase();if(e.name==="TypeError"&&(t.includes("fetch")&&t.includes("failed")||t.includes("network"))||t.includes("fetch")&&t.includes("failed")||t.includes("network"))return!0}if(xe(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},ke=e=>typeof e=="object"&&e!==null,U=class{constructor(r){this.predicate=r}toCode(r){return new q(this.predicate,r)}toError(r){return t=>{var l;if(!this.predicate(t))return null;let n=r(t),o=n.code,i=Object.hasOwn(n,"cause")?n.cause:t,s=(l=n.meta)!=null?l:{};class a extends f{constructor(){let c=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:i,meta:s,status:n.status,retryable:n.retryable,raw:c,path:n.path});d(this,"code",o)}}return new a}}};function Oe(e,r){let t=new U(i=>i instanceof e);if(r)return t.toError(r);let o=i=>{if(!(i instanceof e))return null;if(i instanceof f)return i;let s=i,a=typeof s.code=="string"&&s.code.length>0?s.code:"UNKNOWN",l=Object.hasOwn(s,"cause"),u=Object.hasOwn(s,"raw");class y extends f{constructor(){super(s.message||a,{title:typeof s.title=="string"?s.title:void 0,cause:l?s.cause:i,meta:ke(s.meta)?s.meta:{},status:typeof s.status=="number"?s.status:void 0,retryable:typeof s.retryable=="boolean"?s.retryable:void 0,raw:u?s.raw:i,path:typeof s.path=="string"?s.path:void 0});d(this,"code",a)}}return new y};return o.toCode=t.toCode.bind(t),o.toError=t.toError.bind(t),o}var q=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){return t=>{var l;if(!this.predicate(t))return null;let n=r(t),o=Object.hasOwn(n,"cause")?n.cause:t,i=(l=n.meta)!=null?l:{},s=this.errorCode;class a extends f{constructor(){let p=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:o,meta:i,status:n.status,retryable:n.retryable,raw:p,path:n.path});d(this,"code",s)}}return new a}}},R={when:e=>new U(e),instance:Oe},x={typed:(e=>e instanceof f?e:null),abort:R.when(e=>e instanceof Error&&e.name==="AbortError").toCode("ABORTED").with(e=>({message:e.message||"Operation was aborted",cause:e,retryable:!1,raw:e})),timeout:R.when(e=>e instanceof Error&&e.name==="TimeoutError").toCode("TIMEOUT").with(e=>({message:e.message||"Operation timed out",cause:e,raw:e})),network:R.when(e=>ge(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:R.when(e=>{var n;if(!Ce(e))return!1;let r=e,t=(n=r.status)!=null?n:r.statusCode;return typeof t=="number"&&t>=400}).toCode("HTTP").with(e=>{var n;let r=(n=e.status)!=null?n:e.statusCode,t=typeof r=="number"&&(r>=500||r===429);return{message:e.message||`HTTP ${r!=null?r:"error"} error`,cause:e,status:typeof r=="number"?r:void 0,retryable:t,raw:e}}),unknown:R.when(e=>e instanceof Error&&!(e instanceof f)).toCode("UNKNOWN").with(e=>({message:e.message||"Unknown error occurred",cause:e,raw:e}))};var Ae=[x.typed,x.abort,x.timeout,x.http,x.network,x.unknown];var X={when:e=>R.when(e),instance:R.instance},Z=Ae;var ee={fixed:e=>({type:"fixed",delay:e}),exponential:(e,r=2,t)=>({type:"exponential",base:e,factor:r,maxDelay:t}),fibonacci:(e,r)=>({type:"fibonacci",base:e,maxDelay:r}),custom:e=>({type:"custom",calculate:e})},re=(e,r,t)=>{switch(e.type){case"fixed":return e.delay;case"exponential":{let n=e.base*e.factor**(Number(r)-1);return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"fibonacci":{let n=e.base*Se(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},Se=e=>{if(e<=1)return 1;let r=1,t=1;for(let n=2;n<=e;n++){let o=r+t;r=t,t=o}return t},te=e=>{switch(e.type){case"fixed":{if(e.delay<0)throw new Error("Fixed delay must be non-negative");break}case"exponential":if(e.base<=0)throw new Error("Exponential base delay must be positive");if(e.factor<=1)throw new Error("Exponential factor must be greater than 1");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Exponential max delay must be positive");break;case"fibonacci":if(e.base<=0)throw new Error("Fibonacci base delay must be positive");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Fibonacci max delay must be positive");break;case"custom":break;default:{let r=e;throw new Error(`Unknown strategy type: ${r}`)}}};var ne=(e,r)=>new Promise((t,n)=>{if(r!=null&&r.aborted){n(new DOMException("Aborted","AbortError"));return}let o=a=>{r&&a&&r.removeEventListener("abort",a)},i,s=()=>{i&&clearTimeout(i),o(s),n(new DOMException("Aborted","AbortError"))};i=setTimeout(()=>{o(s),t()},e),r==null||r.addEventListener("abort",s,{once:!0})}),oe=(e,r,t,n)=>new Promise((o,i)=>{if(t!=null&&t.aborted){i(new DOMException("Aborted","AbortError"));return}let s=!1,a=setTimeout(()=>{var y;s=!0,u(),i((y=n==null?void 0:n())!=null?y:new Error(`Operation timed out after ${r}ms`))},r),l=()=>{s||(s=!0,u(),i(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(a),t==null||t.removeEventListener("abort",l)};t==null||t.addEventListener("abort",l,{once:!0}),e.then(y=>{s||(s=!0,u(),o(y))},y=>{s||(s=!0,u(),i(y))})});var Ne=e=>{var s,a,l;if(e.toError)return e.toError;let r=(s=e.rulesMode)!=null?s:"extend",t=(a=e.rules)!=null?a:[],n=Z,o=(l=e.fallback)!=null?l:(u=>Q(B)(u)),i=r==="replace"?t:[...t,...n];return G(i,o)},Me=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":Y(e.ratio);return;case"custom":return;default:{let r=e;throw new Error(`Unsupported jitter configuration: ${r}`)}}},$=e=>{let r=e;return r.timeout!==void 0&&(r={...r,timeout:Number(b(r.timeout))}),r.concurrency!==void 0&&(r={...r,concurrency:Number.isFinite(r.concurrency)?Number(H(r.concurrency)):r.concurrency}),r.retry&&(te(r.retry.strategy),Me(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(h(r.retry.maxRetries))}}),r},W=class e{constructor(r={}){d(this,"circuitBreaker");d(this,"config");d(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:o,toError:i,mapError:s,...a}=r,l=Ne(r),u={...a,errorHandling:{normalizer:l,mapError:s}};this.config=$(u),u.circuitBreaker&&(this.circuitBreaker=new _(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var i,s,a,l,u,y;let n=$({...this.config,...t});if(this.circuitBreaker){let c=(i=this.lastCircuitState)!=null?i:this.circuitBreaker.getState().state,p=await this.circuitBreaker.canExecute(),T=this.circuitBreaker.getState().state;if(c!==T)try{(a=(s=n.hooks)==null?void 0:s.onCircuitStateChange)==null||a.call(s,c,T)}catch{}if(this.lastCircuitState=T,!p)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let o=await Ie(r,n);if(this.circuitBreaker){let c=(l=this.lastCircuitState)!=null?l:this.circuitBreaker.getState().state;o.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(o.error);let p=this.circuitBreaker.getState().state;if(c!==p)try{(y=(u=n.hooks)==null?void 0:u.onCircuitStateChange)==null||y.call(u,c,p)}catch{}this.lastCircuitState=p}return o}async runOrThrow(r,t={}){return this.orThrow(r,t)}async orThrow(r,t={}){let n=await this.run(r,t);if(n.ok)return n.data;throw n.error}async all(r,t={}){var y;let n=$({...this.config,...t}),o=(y=n.concurrency)!=null?y:Number.POSITIVE_INFINITY,i=Number.isFinite(o)?Number(H(o)):Number.POSITIVE_INFINITY;if(i===Number.POSITIVE_INFINITY)return Promise.all(r.map(c=>this.run(c,n)));let s=new Array(r.length),a=0,l=async()=>{var c;for(;a<r.length&&!((c=n.signal)!=null&&c.aborted);){let p=a++;if(p>=r.length)break;let T=r[p];T&&(s[p]=await this.run(T,n))}},u=Array.from({length:Math.min(i,r.length)},()=>l());await Promise.all(u);for(let c=0;c<r.length;c++)if(!(c in s)){let p=r[c];p&&(s[c]=await this.run(p,n))}return s}async allOrThrow(r,t={}){return(await this.all(r,t)).map(o=>{if(!o.ok)throw o.error;return o.data})}partitionAll(r){let t=[],n=[],o=[],i=[],s=[];for(let a of r){if(a.type==="success"){t.push(a);continue}switch(n.push(a),a.type){case"failure":o.push(a);break;case"aborted":i.push(a);break;case"timeout":s.push(a);break}}return{ok:t,errors:n,failure:o,aborted:i,timeout:s}}getCircuitBreakerState(){var r;return(r=this.circuitBreaker)==null?void 0:r.getState()}resetCircuitBreaker(){var r;(r=this.circuitBreaker)==null||r.reset()}getConfig(){return{...this.config}}withConfig(r){var l,u;let{errorHandling:t,...n}=this.config,{errorHandling:o,...i}=r,s=(l=o==null?void 0:o.normalizer)!=null?l:t.normalizer,a=(u=o==null?void 0:o.mapError)!=null?u:t.mapError;return new e({...n,...i,toError:s,mapError:a})}};function S(e={}){let r=new W(e);return{run:(t,n)=>r.run(t,n),orThrow:(t,n)=>r.orThrow(t,n),runOrThrow:(t,n)=>r.runOrThrow(t,n),all:(t,n)=>r.all(t,n),allOrThrow:(t,n)=>r.allOrThrow(t,n),partitionAll:t=>r.partitionAll(t),withConfig:t=>r.withConfig(t)}}async function Ie(e,r){let{signal:t,ignoreAbort:n=!0,timeout:o,retry:i,errorHandling:s,hooks:a,logger:l}=r,u=(C,...m)=>{try{C==null||C(...m)}catch{}},y,c=0,p=0,T=[],k=Date.now(),{signal:O,cleanup:de}=se(t),M=C=>({totalAttempts:c,totalRetries:c>0?Number(c)-1:0,totalDuration:Date.now()-k,lastError:C,retryHistory:T});try{if(O.aborted){u(a==null?void 0:a.onAbort,O);let m=s.normalizer(new DOMException("Aborted","AbortError")),w=s.mapError?s.mapError(m):m;return{type:"aborted",ok:!1,data:null,error:w,metrics:{totalAttempts:c,totalRetries:p,totalDuration:Date.now()-k,lastError:w,retryHistory:T}}}let C=async()=>{var I,g,K;let m=1,w=h((I=i==null?void 0:i.maxRetries)!=null?I:0);for(;;){c=m;let V=new AbortController,{signal:L,cleanup:ye}=se(O,V.signal);try{let v=Promise.resolve(e({signal:L})),A=o?await oe(v,o,L,()=>(V.abort(),new P(b(o)))):await v;return u(a==null?void 0:a.onSuccess,A,M()),u(l==null?void 0:l.info,`Task succeeded on attempt ${m}`),A}catch(v){let A=s.normalizer(v),E=s.mapError?s.mapError(A):A;if(y=E,E.code==="ABORTED"&&u(a==null?void 0:a.onAbort,L),n&&E.code==="ABORTED"||(u(a==null?void 0:a.onError,E,M(E)),u(l==null?void 0:l.error,`Task failed on attempt ${m}`,E)),E.code==="ABORTED"||E.retryable===!1)throw E;if(m<=Number(w)){let J=i==null?void 0:i.shouldRetry,pe={totalAttempts:Number(c),elapsedTime:Date.now()-k,startTime:new Date(k),lastDelay:(g=T[T.length-1])!=null&&g.delay?Number((K=T[T.length-1])==null?void 0:K.delay):void 0};if(!J||J(m,E,pe)){let me=i?re(i.strategy,m,E):0,z=ve(me,i==null?void 0:i.jitter),j=b(z);T.push({attempt:m,error:E,delay:j,timestamp:new Date}),u(a==null?void 0:a.onRetry,m,E,z),u(l==null?void 0:l.info,`Retrying in ${z}ms (attempt ${m+1})`),m+=1,await ne(j,O);continue}}throw E}finally{ye()}}};try{let m=await C(),w=M();return p=w.totalRetries,u(a==null?void 0:a.onFinally,w),{type:"success",ok:!0,data:m,error:null,metrics:w}}catch(m){let w=y!=null?y:s.normalizer(m),I=w.code==="TIMEOUT"?"timeout":w.code==="ABORTED"?"aborted":"failure",g=M(w);return p=g.totalRetries,u(a==null?void 0:a.onFinally,g),{type:I,ok:!1,data:null,error:w,metrics:g}}}finally{de()}}function se(...e){let r=new AbortController,t=e.filter(o=>o!==void 0);if(t.length===0)return{signal:r.signal,cleanup:()=>{}};if(t.some(o=>o.aborted))return r.abort(),{signal:r.signal,cleanup:()=>{}};let n=[];for(let o of t){let i=()=>r.abort();o.addEventListener("abort",i,{once:!0}),n.push({signal:o,abort:i})}return{signal:r.signal,cleanup:()=>{for(let o of n)o.signal.removeEventListener("abort",o.abort)}}}function ve(e,r){if(!r||r.type==="none"||e<=0)return e;switch(r.type){case"full":{let t=Number(r.ratio)/100,n=Math.max(0,Number(e)*(1-t)),o=Number(e);return n+Math.random()*(o-n)}case"equal":{let t=Number(r.ratio)/100,n=Number(e)*t/2;return Number(e)-n+Math.random()*n}case"custom":return r.calculate(e);default:return r}}var N=S(),ae=N.run,ie=N.runOrThrow,ue=N.orThrow,le=N.all,ce=N.allOrThrow;0&&(module.exports={RetryStrategies,TypedError,all,allOrThrow,asMilliseconds,asRetryCount,errorRule,orThrow,run,runOrThrow,tryo});
package/dist/index.d.cts CHANGED
@@ -19,18 +19,20 @@ declare const asRetryCount: (n: number) => RetryCount;
19
19
  declare abstract class TypedError<Code extends string = string, Meta extends Record<string, unknown> = Record<string, unknown>, Raw = unknown> extends Error {
20
20
  abstract readonly code: Code;
21
21
  readonly cause?: unknown;
22
+ readonly title?: string;
22
23
  readonly meta: Meta;
23
24
  readonly status?: number;
24
- readonly raw: Raw;
25
+ readonly raw?: Raw;
25
26
  readonly path?: string;
26
27
  readonly timestamp: number;
27
28
  readonly retryable: boolean;
28
29
  constructor(message: string, opts: {
30
+ title?: string;
29
31
  cause?: unknown;
30
32
  meta?: Meta;
31
33
  status?: number;
32
34
  retryable?: boolean;
33
- raw: Raw;
35
+ raw?: Raw;
34
36
  path?: string;
35
37
  });
36
38
  is<C extends string>(code: C): this is TypedError<C> & {
@@ -294,9 +296,10 @@ type AllOptions<E extends AnyTypedError> = Omit<Partial<TryoConfig<E> & {
294
296
  concurrency?: number;
295
297
  }>, 'circuitBreaker'>;
296
298
  type MaybePromise<T> = T | Promise<T>;
299
+ type RuleLike = (error: unknown) => AnyTypedError | null;
297
300
  type NonNull<T> = T extends null ? never : T;
298
301
  type RuleReturn<R> = R extends (err: unknown) => infer Out ? NonNull<Out> : never;
299
- type InferErrorFromRules<TRules extends readonly ErrorRule<AnyTypedError>[]> = TRules extends readonly [] ? TypedError : RuleReturn<TRules[number]> | UnknownError;
302
+ type InferErrorFromRules<TRules extends readonly RuleLike[]> = TRules extends readonly [] ? TypedError : RuleReturn<TRules[number]> | UnknownError;
300
303
  type TryoOptions<E extends AnyTypedError = AnyTypedError> = Omit<Partial<TryoConfig<E>>, 'errorHandling' | 'signal'> & {
301
304
  rules?: Array<ErrorRule<E>>;
302
305
  rulesMode?: RulesMode;
@@ -304,19 +307,25 @@ type TryoOptions<E extends AnyTypedError = AnyTypedError> = Omit<Partial<TryoCon
304
307
  toError?: (err: unknown) => E;
305
308
  mapError?: (error: E) => E;
306
309
  };
307
- type ExtractCode<R> = R extends (...args: any[]) => infer E ? E extends TypedError<any, any, any> | null ? E extends null ? never : E extends TypedError<infer C, any, any> ? string extends C ? never : C : never : never : never;
308
- type CheckUniqueCodes<T extends readonly any[], Seen = never> = T extends readonly [infer Head, ...infer Tail] ? ExtractCode<Head> extends infer C ? [C] extends [never] ? CheckUniqueCodes<Tail, Seen> : [C] extends [Seen] ? {
310
+ type ExtractCode<R> = R extends (...args: unknown[]) => unknown ? Exclude<ReturnType<R>, null> extends {
311
+ readonly code: infer C extends string;
312
+ } ? string extends C ? never : C : never : never;
313
+ type CheckUniqueCodes<T extends readonly unknown[], Seen = never> = T extends readonly [infer Head, ...infer Tail] ? ExtractCode<Head> extends infer C ? [C] extends [never] ? CheckUniqueCodes<Tail, Seen> : [C] extends [Seen] ? {
309
314
  error: '❌ ERROR: Código duplicado detectado';
310
315
  code: C;
311
316
  } : CheckUniqueCodes<Tail, Seen | C> : never : true;
312
- declare function tryo<const TRules extends readonly ErrorRule<AnyTypedError>[]>(options: Omit<TryoOptions<InferErrorFromRules<TRules>>, 'rules' | 'rulesMode'> & {
313
- rules: TRules & (CheckUniqueCodes<TRules> extends true ? unknown : CheckUniqueCodes<TRules>);
317
+ type UniqueRulesConstraint<TRules extends readonly RuleLike[]> = CheckUniqueCodes<TRules> extends true ? unknown : {
318
+ __duplicate_error_codes__: CheckUniqueCodes<TRules>;
319
+ };
320
+ type EnsureRuleTuple<TRules extends readonly unknown[]> = TRules extends readonly RuleLike[] ? TRules : never;
321
+ declare function tryo<const TRules extends readonly unknown[]>(options: Omit<TryoOptions<InferErrorFromRules<EnsureRuleTuple<TRules>>>, 'rules' | 'rulesMode'> & {
322
+ rules: TRules;
314
323
  rulesMode: 'replace';
315
- }): Tryo<InferErrorFromRules<TRules>>;
316
- declare function tryo<const TRules extends readonly ErrorRule<AnyTypedError>[]>(options: Omit<TryoOptions<InferErrorFromRules<TRules> | DefaultError>, 'rules'> & {
317
- rules: TRules & (CheckUniqueCodes<TRules> extends true ? unknown : CheckUniqueCodes<TRules>);
324
+ } & UniqueRulesConstraint<EnsureRuleTuple<TRules>>): Tryo<InferErrorFromRules<EnsureRuleTuple<TRules>>>;
325
+ declare function tryo<const TRules extends readonly unknown[]>(options: Omit<TryoOptions<InferErrorFromRules<EnsureRuleTuple<TRules>> | DefaultError>, 'rules'> & {
326
+ rules: TRules;
318
327
  rulesMode?: 'extend';
319
- }): Tryo<InferErrorFromRules<TRules> | DefaultError>;
328
+ } & UniqueRulesConstraint<EnsureRuleTuple<TRules>>): Tryo<InferErrorFromRules<EnsureRuleTuple<TRules>> | DefaultError>;
320
329
  declare function tryo<E extends AnyTypedError = DefaultError>(options?: TryoOptions<E>): Tryo<E>;
321
330
  type Tryo<E extends AnyTypedError = AnyTypedError> = {
322
331
  run: <T>(task: (ctx: {
@@ -410,39 +419,53 @@ declare const allOrThrow: <T>(tasks: ((ctx: {
410
419
  * Provides type-safe error rule creation with enhanced ergonomics
411
420
  */
412
421
 
422
+ /** Standard error response properties allowed in rules */
423
+ interface ErrorResponse {
424
+ code: string;
425
+ message: string;
426
+ title?: string;
427
+ meta?: Record<string, unknown>;
428
+ status?: number;
429
+ cause?: unknown;
430
+ retryable?: boolean;
431
+ raw?: unknown;
432
+ path?: string;
433
+ }
434
+ /** Standard mapper properties allowed in .with() */
435
+ interface MapperResponse {
436
+ message: string;
437
+ title?: string;
438
+ cause?: unknown;
439
+ meta?: Record<string, unknown>;
440
+ status?: number;
441
+ retryable?: boolean;
442
+ raw?: unknown;
443
+ path?: string;
444
+ }
445
+ type Strict<T, Shape> = T & Record<Exclude<keyof T, keyof Shape>, never>;
446
+ type MappedTypedError<Out extends ErrorResponse, Input> = TypedError<Out['code'], Out['meta'] extends Record<string, unknown> ? Out['meta'] : Record<string, unknown>, Out['raw'] extends undefined ? Input : Out['raw']>;
413
447
  declare class ErrorRuleBuilder<T> {
414
448
  private readonly predicate;
415
449
  constructor(predicate: (err: unknown) => err is T);
416
450
  toCode<const C extends string>(code: C): ErrorMapper<T, C>;
417
- toError<const Out extends {
418
- code: string;
419
- message: string;
420
- meta?: Record<string, unknown>;
421
- status?: number;
422
- cause?: unknown;
423
- retryable?: boolean;
424
- raw?: any;
425
- path?: string;
426
- }>(mapper: (err: T) => Out): ErrorRule<TypedError<Out['code'], Out['meta'] extends Record<string, unknown> ? Out['meta'] : Record<string, unknown>, unknown extends Out['raw'] ? T : Out['raw']>>;
451
+ toError<const Out extends ErrorResponse>(mapper: (err: T) => Strict<Out, ErrorResponse>): ErrorRule<MappedTypedError<Out, T>>;
427
452
  }
428
453
  declare class ErrorMapper<T, C extends string> {
429
454
  private readonly predicate;
430
455
  private readonly errorCode;
431
456
  constructor(predicate: (err: unknown) => err is T, errorCode: C);
432
- with<const M extends Record<string, unknown> = Record<string, unknown>, const R = '__NOT_SET__'>(mapper: (err: T) => {
433
- message: string;
434
- cause?: unknown;
435
- meta?: M;
436
- status?: number;
437
- retryable?: boolean;
438
- raw?: R;
439
- path?: string;
440
- }): ErrorRule<TypedError<C, M, R extends '__NOT_SET__' ? T : R>>;
457
+ with<const Out extends MapperResponse>(mapper: (err: T) => Strict<Out, ErrorResponse>): ErrorRule<TypedError<C, Out['meta'] extends Record<string, unknown> ? Out['meta'] : Record<string, unknown>, Out['raw'] extends undefined ? T : Out['raw']>>;
441
458
  }
442
459
 
443
460
  declare const errorRule: {
444
461
  readonly when: <T>(predicate: (err: unknown) => err is T) => ErrorRuleBuilder<T>;
445
- readonly instance: <T extends new (...args: unknown[]) => unknown>(ErrorClass: T) => ErrorRuleBuilder<InstanceType<T>>;
462
+ readonly instance: {
463
+ <T extends abstract new (...args: never[]) => unknown>(ErrorClass: T): ErrorRule<AnyTypedError> & {
464
+ toCode: <const C extends string>(code: C) => ErrorMapper<InstanceType<T>, C>;
465
+ toError: <const Out extends ErrorResponse>(mapper: (err: InstanceType<T>) => Out & Record<Exclude<keyof Out, keyof ErrorResponse>, never>) => ErrorRule<TypedError<Out["code"], Out["meta"] extends Record<string, unknown> ? Out["meta"] : Record<string, unknown>, Out["raw"] extends undefined ? InstanceType<T> : Out["raw"]>>;
466
+ };
467
+ <T extends abstract new (...args: never[]) => unknown, const Out extends ErrorResponse>(ErrorClass: T, mapper: (err: InstanceType<T>) => Out & Record<Exclude<keyof Out, keyof ErrorResponse>, never>): ErrorRule<TypedError<Out["code"], Out["meta"] extends Record<string, unknown> ? Out["meta"] : Record<string, unknown>, Out["raw"] extends undefined ? InstanceType<T> : Out["raw"]>>;
468
+ };
446
469
  };
447
470
 
448
471
  export { type AbortedResult, type FailureResult, type Milliseconds, type RetryCount, RetryStrategies, type RulesMode, type SuccessResult, type TimeoutResult, type TryoConfig, type TryoMetrics$1 as TryoMetrics, type TryoOptions, type TryoResult, TypedError, all, allOrThrow, asMilliseconds, asRetryCount, tryo as default, errorRule, orThrow, run, runOrThrow, tryo };
package/dist/index.d.ts CHANGED
@@ -19,18 +19,20 @@ declare const asRetryCount: (n: number) => RetryCount;
19
19
  declare abstract class TypedError<Code extends string = string, Meta extends Record<string, unknown> = Record<string, unknown>, Raw = unknown> extends Error {
20
20
  abstract readonly code: Code;
21
21
  readonly cause?: unknown;
22
+ readonly title?: string;
22
23
  readonly meta: Meta;
23
24
  readonly status?: number;
24
- readonly raw: Raw;
25
+ readonly raw?: Raw;
25
26
  readonly path?: string;
26
27
  readonly timestamp: number;
27
28
  readonly retryable: boolean;
28
29
  constructor(message: string, opts: {
30
+ title?: string;
29
31
  cause?: unknown;
30
32
  meta?: Meta;
31
33
  status?: number;
32
34
  retryable?: boolean;
33
- raw: Raw;
35
+ raw?: Raw;
34
36
  path?: string;
35
37
  });
36
38
  is<C extends string>(code: C): this is TypedError<C> & {
@@ -294,9 +296,10 @@ type AllOptions<E extends AnyTypedError> = Omit<Partial<TryoConfig<E> & {
294
296
  concurrency?: number;
295
297
  }>, 'circuitBreaker'>;
296
298
  type MaybePromise<T> = T | Promise<T>;
299
+ type RuleLike = (error: unknown) => AnyTypedError | null;
297
300
  type NonNull<T> = T extends null ? never : T;
298
301
  type RuleReturn<R> = R extends (err: unknown) => infer Out ? NonNull<Out> : never;
299
- type InferErrorFromRules<TRules extends readonly ErrorRule<AnyTypedError>[]> = TRules extends readonly [] ? TypedError : RuleReturn<TRules[number]> | UnknownError;
302
+ type InferErrorFromRules<TRules extends readonly RuleLike[]> = TRules extends readonly [] ? TypedError : RuleReturn<TRules[number]> | UnknownError;
300
303
  type TryoOptions<E extends AnyTypedError = AnyTypedError> = Omit<Partial<TryoConfig<E>>, 'errorHandling' | 'signal'> & {
301
304
  rules?: Array<ErrorRule<E>>;
302
305
  rulesMode?: RulesMode;
@@ -304,19 +307,25 @@ type TryoOptions<E extends AnyTypedError = AnyTypedError> = Omit<Partial<TryoCon
304
307
  toError?: (err: unknown) => E;
305
308
  mapError?: (error: E) => E;
306
309
  };
307
- type ExtractCode<R> = R extends (...args: any[]) => infer E ? E extends TypedError<any, any, any> | null ? E extends null ? never : E extends TypedError<infer C, any, any> ? string extends C ? never : C : never : never : never;
308
- type CheckUniqueCodes<T extends readonly any[], Seen = never> = T extends readonly [infer Head, ...infer Tail] ? ExtractCode<Head> extends infer C ? [C] extends [never] ? CheckUniqueCodes<Tail, Seen> : [C] extends [Seen] ? {
310
+ type ExtractCode<R> = R extends (...args: unknown[]) => unknown ? Exclude<ReturnType<R>, null> extends {
311
+ readonly code: infer C extends string;
312
+ } ? string extends C ? never : C : never : never;
313
+ type CheckUniqueCodes<T extends readonly unknown[], Seen = never> = T extends readonly [infer Head, ...infer Tail] ? ExtractCode<Head> extends infer C ? [C] extends [never] ? CheckUniqueCodes<Tail, Seen> : [C] extends [Seen] ? {
309
314
  error: '❌ ERROR: Código duplicado detectado';
310
315
  code: C;
311
316
  } : CheckUniqueCodes<Tail, Seen | C> : never : true;
312
- declare function tryo<const TRules extends readonly ErrorRule<AnyTypedError>[]>(options: Omit<TryoOptions<InferErrorFromRules<TRules>>, 'rules' | 'rulesMode'> & {
313
- rules: TRules & (CheckUniqueCodes<TRules> extends true ? unknown : CheckUniqueCodes<TRules>);
317
+ type UniqueRulesConstraint<TRules extends readonly RuleLike[]> = CheckUniqueCodes<TRules> extends true ? unknown : {
318
+ __duplicate_error_codes__: CheckUniqueCodes<TRules>;
319
+ };
320
+ type EnsureRuleTuple<TRules extends readonly unknown[]> = TRules extends readonly RuleLike[] ? TRules : never;
321
+ declare function tryo<const TRules extends readonly unknown[]>(options: Omit<TryoOptions<InferErrorFromRules<EnsureRuleTuple<TRules>>>, 'rules' | 'rulesMode'> & {
322
+ rules: TRules;
314
323
  rulesMode: 'replace';
315
- }): Tryo<InferErrorFromRules<TRules>>;
316
- declare function tryo<const TRules extends readonly ErrorRule<AnyTypedError>[]>(options: Omit<TryoOptions<InferErrorFromRules<TRules> | DefaultError>, 'rules'> & {
317
- rules: TRules & (CheckUniqueCodes<TRules> extends true ? unknown : CheckUniqueCodes<TRules>);
324
+ } & UniqueRulesConstraint<EnsureRuleTuple<TRules>>): Tryo<InferErrorFromRules<EnsureRuleTuple<TRules>>>;
325
+ declare function tryo<const TRules extends readonly unknown[]>(options: Omit<TryoOptions<InferErrorFromRules<EnsureRuleTuple<TRules>> | DefaultError>, 'rules'> & {
326
+ rules: TRules;
318
327
  rulesMode?: 'extend';
319
- }): Tryo<InferErrorFromRules<TRules> | DefaultError>;
328
+ } & UniqueRulesConstraint<EnsureRuleTuple<TRules>>): Tryo<InferErrorFromRules<EnsureRuleTuple<TRules>> | DefaultError>;
320
329
  declare function tryo<E extends AnyTypedError = DefaultError>(options?: TryoOptions<E>): Tryo<E>;
321
330
  type Tryo<E extends AnyTypedError = AnyTypedError> = {
322
331
  run: <T>(task: (ctx: {
@@ -410,39 +419,53 @@ declare const allOrThrow: <T>(tasks: ((ctx: {
410
419
  * Provides type-safe error rule creation with enhanced ergonomics
411
420
  */
412
421
 
422
+ /** Standard error response properties allowed in rules */
423
+ interface ErrorResponse {
424
+ code: string;
425
+ message: string;
426
+ title?: string;
427
+ meta?: Record<string, unknown>;
428
+ status?: number;
429
+ cause?: unknown;
430
+ retryable?: boolean;
431
+ raw?: unknown;
432
+ path?: string;
433
+ }
434
+ /** Standard mapper properties allowed in .with() */
435
+ interface MapperResponse {
436
+ message: string;
437
+ title?: string;
438
+ cause?: unknown;
439
+ meta?: Record<string, unknown>;
440
+ status?: number;
441
+ retryable?: boolean;
442
+ raw?: unknown;
443
+ path?: string;
444
+ }
445
+ type Strict<T, Shape> = T & Record<Exclude<keyof T, keyof Shape>, never>;
446
+ type MappedTypedError<Out extends ErrorResponse, Input> = TypedError<Out['code'], Out['meta'] extends Record<string, unknown> ? Out['meta'] : Record<string, unknown>, Out['raw'] extends undefined ? Input : Out['raw']>;
413
447
  declare class ErrorRuleBuilder<T> {
414
448
  private readonly predicate;
415
449
  constructor(predicate: (err: unknown) => err is T);
416
450
  toCode<const C extends string>(code: C): ErrorMapper<T, C>;
417
- toError<const Out extends {
418
- code: string;
419
- message: string;
420
- meta?: Record<string, unknown>;
421
- status?: number;
422
- cause?: unknown;
423
- retryable?: boolean;
424
- raw?: any;
425
- path?: string;
426
- }>(mapper: (err: T) => Out): ErrorRule<TypedError<Out['code'], Out['meta'] extends Record<string, unknown> ? Out['meta'] : Record<string, unknown>, unknown extends Out['raw'] ? T : Out['raw']>>;
451
+ toError<const Out extends ErrorResponse>(mapper: (err: T) => Strict<Out, ErrorResponse>): ErrorRule<MappedTypedError<Out, T>>;
427
452
  }
428
453
  declare class ErrorMapper<T, C extends string> {
429
454
  private readonly predicate;
430
455
  private readonly errorCode;
431
456
  constructor(predicate: (err: unknown) => err is T, errorCode: C);
432
- with<const M extends Record<string, unknown> = Record<string, unknown>, const R = '__NOT_SET__'>(mapper: (err: T) => {
433
- message: string;
434
- cause?: unknown;
435
- meta?: M;
436
- status?: number;
437
- retryable?: boolean;
438
- raw?: R;
439
- path?: string;
440
- }): ErrorRule<TypedError<C, M, R extends '__NOT_SET__' ? T : R>>;
457
+ with<const Out extends MapperResponse>(mapper: (err: T) => Strict<Out, ErrorResponse>): ErrorRule<TypedError<C, Out['meta'] extends Record<string, unknown> ? Out['meta'] : Record<string, unknown>, Out['raw'] extends undefined ? T : Out['raw']>>;
441
458
  }
442
459
 
443
460
  declare const errorRule: {
444
461
  readonly when: <T>(predicate: (err: unknown) => err is T) => ErrorRuleBuilder<T>;
445
- readonly instance: <T extends new (...args: unknown[]) => unknown>(ErrorClass: T) => ErrorRuleBuilder<InstanceType<T>>;
462
+ readonly instance: {
463
+ <T extends abstract new (...args: never[]) => unknown>(ErrorClass: T): ErrorRule<AnyTypedError> & {
464
+ toCode: <const C extends string>(code: C) => ErrorMapper<InstanceType<T>, C>;
465
+ toError: <const Out extends ErrorResponse>(mapper: (err: InstanceType<T>) => Out & Record<Exclude<keyof Out, keyof ErrorResponse>, never>) => ErrorRule<TypedError<Out["code"], Out["meta"] extends Record<string, unknown> ? Out["meta"] : Record<string, unknown>, Out["raw"] extends undefined ? InstanceType<T> : Out["raw"]>>;
466
+ };
467
+ <T extends abstract new (...args: never[]) => unknown, const Out extends ErrorResponse>(ErrorClass: T, mapper: (err: InstanceType<T>) => Out & Record<Exclude<keyof Out, keyof ErrorResponse>, never>): ErrorRule<TypedError<Out["code"], Out["meta"] extends Record<string, unknown> ? Out["meta"] : Record<string, unknown>, Out["raw"] extends undefined ? InstanceType<T> : Out["raw"]>>;
468
+ };
446
469
  };
447
470
 
448
471
  export { type AbortedResult, type FailureResult, type Milliseconds, type RetryCount, RetryStrategies, type RulesMode, type SuccessResult, type TimeoutResult, type TryoConfig, type TryoMetrics$1 as 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 y=(e,r,t)=>ue(e,typeof r!="symbol"?r+"":r,t);var b=class extends Error{constructor(t,n){var o,a;super(t);y(this,"cause");y(this,"meta");y(this,"status");y(this,"raw");y(this,"path");y(this,"timestamp");y(this,"retryable");this.timestamp=Date.now(),this.retryable=(o=n.retryable)!=null?o:!0,this.name=this.constructor.name,this.cause=n.cause,this.meta=(a=n.meta)!=null?a:{},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,message:this.message,timestamp:this.timestamp,retryable:this.retryable,cause:this.cause,raw:this.raw,path:this.path,stack:this.stack}}},D=class extends b{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0,raw:n});y(this,"code","TIMEOUT")}};var I=class extends b{constructor(t,n){super(`Circuit breaker is open, reset after ${t}ms`,{cause:n,retryable:!1,raw:n});y(this,"code","CIRCUIT_OPEN")}};var P=class extends b{constructor(t,n){super(t,{cause:n,raw:n});y(this,"code","UNKNOWN")}};var w=e=>{if(e<0||!Number.isFinite(e))throw new Error(`Invalid milliseconds: must be a non-negative finite number, got ${e}`);return e},R=e=>{if(e<0||!Number.isInteger(e))throw new Error(`Invalid retry count: must be a non-negative integer, got ${e}`);return e},L=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 F=class{constructor(r){y(this,"state");y(this,"config");this.config={failureThreshold:R(r.failureThreshold),resetTimeout:w(r.resetTimeout),halfOpenRequests:R(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,a,i;if(!((i=(a=(o=this.config).shouldCountAsFailure)==null?void 0:a.call(o,r))!=null?i:!0))return;let n=new Date;switch(this.state.state){case"closed":{let s=this.state.failureCount+1;s>=this.config.failureThreshold?this.state={state:"open",failureCount:s,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:s,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?w(Math.max(0,this.state.nextAttemptTime.getTime()-Date.now())):this.config.resetTimeout;return new I(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 b?r:r instanceof Error?new e(r.message,r):typeof r=="string"?new e(r):new e("Unknown error occurred",r);var le=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},ce=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},ye=e=>{var r;if(e instanceof Error){let t=e.message.toLowerCase();if(e.name==="TypeError"&&(t.includes("fetch")&&t.includes("failed")||t.includes("network"))||t.includes("fetch")&&t.includes("failed")||t.includes("network"))return!0}if(ce(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},_=class{constructor(r){this.predicate=r}toCode(r){return new H(this.predicate,r)}toError(r){return t=>{if(!this.predicate(t))return null;let n=r(t),o=n.code;class a extends b{constructor(){var l,u,d;super(n.message,{cause:(l=n.cause)!=null?l:t,meta:(u=n.meta)!=null?u:{},status:n.status,retryable:n.retryable,raw:(d=n.raw)!=null?d:t,path:n.path});y(this,"code",o)}}return new a}}},H=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){return t=>{if(!this.predicate(t))return null;let n=r(t),o=this.errorCode;class a extends b{constructor(){var u;let l=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{cause:n.cause,meta:(u=n.meta)!=null?u:{},status:n.status,retryable:n.retryable,raw:l,path:n.path});y(this,"code",o)}}return new a}}},h={when:e=>new _(e),instance:e=>new _(r=>r instanceof e)},x={typed:(e=>e instanceof b?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=>ye(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:h.when(e=>{var n;if(!le(e))return!1;let r=e,t=(n=r.status)!=null?n:r.statusCode;return typeof t=="number"&&t>=400}).toCode("HTTP").with(e=>{var n;let r=(n=e.status)!=null?n:e.statusCode,t=typeof r=="number"&&(r>=500||r===429);return{message:e.message||`HTTP ${r!=null?r:"error"} error`,cause:e,status:typeof r=="number"?r:void 0,retryable:t,raw:e}}),unknown:h.when(e=>e instanceof Error&&!(e instanceof b)).toCode("UNKNOWN").with(e=>({message:e.message||"Unknown error occurred",cause:e,raw:e}))};var de=[x.typed,x.abort,x.timeout,x.http,x.network,x.unknown];var pe={when:e=>h.when(e),instance:e=>h.instance(e)},X=de;var me={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})},Z=(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*fe(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},fe=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},j=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 o=s=>{r&&s&&r.removeEventListener("abort",s)},a,i=()=>{a&&clearTimeout(a),o(i),n(new DOMException("Aborted","AbortError"))};a=setTimeout(()=>{o(i),t()},e),r==null||r.addEventListener("abort",i,{once:!0})}),re=(e,r,t,n)=>new Promise((o,a)=>{if(t!=null&&t.aborted){a(new DOMException("Aborted","AbortError"));return}let i=!1,s=setTimeout(()=>{var d;i=!0,u(),a((d=n==null?void 0:n())!=null?d:new Error(`Operation timed out after ${r}ms`))},r),l=()=>{i||(i=!0,u(),a(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(s),t==null||t.removeEventListener("abort",l)};t==null||t.addEventListener("abort",l,{once:!0}),e.then(d=>{i||(i=!0,u(),o(d))},d=>{i||(i=!0,u(),a(d))})});var Ee=e=>{var i,s,l;if(e.toError)return e.toError;let r=(i=e.rulesMode)!=null?i:"extend",t=(s=e.rules)!=null?s:[],n=X,o=(l=e.fallback)!=null?l:(u=>Q(P)(u)),a=r==="replace"?t:[...t,...n];return G(a,o)},Te=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(w(r.timeout))}),r.concurrency!==void 0&&(r={...r,concurrency:Number.isFinite(r.concurrency)?Number(L(r.concurrency)):r.concurrency}),r.retry&&(j(r.retry.strategy),Te(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(R(r.retry.maxRetries))}}),r},q=class e{constructor(r={}){y(this,"circuitBreaker");y(this,"config");y(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:o,toError:a,mapError:i,...s}=r,l=Ee(r),u={...s,errorHandling:{normalizer:l,mapError:i}};this.config=$(u),u.circuitBreaker&&(this.circuitBreaker=new F(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var a,i,s,l,u,d;let n=$({...this.config,...t});if(this.circuitBreaker){let c=(a=this.lastCircuitState)!=null?a:this.circuitBreaker.getState().state,m=await this.circuitBreaker.canExecute(),E=this.circuitBreaker.getState().state;if(c!==E)try{(s=(i=n.hooks)==null?void 0:i.onCircuitStateChange)==null||s.call(i,c,E)}catch{}if(this.lastCircuitState=E,!m)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 c=(l=this.lastCircuitState)!=null?l:this.circuitBreaker.getState().state;o.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(o.error);let m=this.circuitBreaker.getState().state;if(c!==m)try{(d=(u=n.hooks)==null?void 0:u.onCircuitStateChange)==null||d.call(u,c,m)}catch{}this.lastCircuitState=m}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 d;let n=$({...this.config,...t}),o=(d=n.concurrency)!=null?d:Number.POSITIVE_INFINITY,a=Number.isFinite(o)?Number(L(o)):Number.POSITIVE_INFINITY;if(a===Number.POSITIVE_INFINITY)return Promise.all(r.map(c=>this.run(c,n)));let i=new Array(r.length),s=0,l=async()=>{var c;for(;s<r.length&&!((c=n.signal)!=null&&c.aborted);){let m=s++;if(m>=r.length)break;let E=r[m];E&&(i[m]=await this.run(E,n))}},u=Array.from({length:Math.min(a,r.length)},()=>l());await Promise.all(u);for(let c=0;c<r.length;c++)if(!(c in i)){let m=r[c];m&&(i[c]=await this.run(m,n))}return i}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=[],a=[],i=[];for(let s of r){if(s.type==="success"){t.push(s);continue}switch(n.push(s),s.type){case"failure":o.push(s);break;case"aborted":a.push(s);break;case"timeout":i.push(s);break}}return{ok:t,errors:n,failure:o,aborted:a,timeout:i}}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,...a}=r,i=(l=o==null?void 0:o.normalizer)!=null?l:t.normalizer,s=(u=o==null?void 0:o.mapError)!=null?u:t.mapError;return new e({...n,...a,toError:i,mapError:s})}};function B(e={}){let r=new q(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:a,errorHandling:i,hooks:s,logger:l}=r,u=(C,...p)=>{try{C==null||C(...p)}catch{}},d,c=0,m=0,E=[],k=Date.now(),{signal:A,cleanup:ne}=te(t),N=C=>({totalAttempts:c,totalRetries:c>0?Number(c)-1:0,totalDuration:Date.now()-k,lastError:C,retryHistory:E});try{if(A.aborted){u(s==null?void 0:s.onAbort,A);let p=i.normalizer(new DOMException("Aborted","AbortError")),T=i.mapError?i.mapError(p):p;return{type:"aborted",ok:!1,data:null,error:T,metrics:{totalAttempts:c,totalRetries:m,totalDuration:Date.now()-k,lastError:T,retryHistory:E}}}let C=async()=>{var M,g,V;let p=1,T=R((M=a==null?void 0:a.maxRetries)!=null?M:0);for(;;){c=p;let W=new AbortController,{signal:U,cleanup:oe}=te(A,W.signal);try{let v=Promise.resolve(e({signal:U})),O=o?await re(v,o,U,()=>(W.abort(),new D(w(o)))):await v;return u(s==null?void 0:s.onSuccess,O,N()),u(l==null?void 0:l.info,`Task succeeded on attempt ${p}`),O}catch(v){let O=i.normalizer(v),f=i.mapError?i.mapError(O):O;if(d=f,f.code==="ABORTED"&&u(s==null?void 0:s.onAbort,U),n&&f.code==="ABORTED"||(u(s==null?void 0:s.onError,f,N(f)),u(l==null?void 0:l.error,`Task failed on attempt ${p}`,f)),f.code==="ABORTED"||f.retryable===!1)throw f;if(p<=Number(T)){let K=a==null?void 0:a.shouldRetry,se={totalAttempts:Number(c),elapsedTime:Date.now()-k,startTime:new Date(k),lastDelay:(g=E[E.length-1])!=null&&g.delay?Number((V=E[E.length-1])==null?void 0:V.delay):void 0};if(!K||K(p,f,se)){let ae=a?Z(a.strategy,p,f):0,z=we(ae,a==null?void 0:a.jitter),J=w(z);E.push({attempt:p,error:f,delay:J,timestamp:new Date}),u(s==null?void 0:s.onRetry,p,f,z),u(l==null?void 0:l.info,`Retrying in ${z}ms (attempt ${p+1})`),p+=1,await ee(J,A);continue}}throw f}finally{oe()}}};try{let p=await C(),T=N();return m=T.totalRetries,u(s==null?void 0:s.onFinally,T),{type:"success",ok:!0,data:p,error:null,metrics:T}}catch(p){let T=d!=null?d:i.normalizer(p),M=T.code==="TIMEOUT"?"timeout":T.code==="ABORTED"?"aborted":"failure",g=N(T);return m=g.totalRetries,u(s==null?void 0:s.onFinally,g),{type:M,ok:!1,data:null,error:T,metrics:g}}}finally{ne()}}function te(...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 a=()=>r.abort();o.addEventListener("abort",a,{once:!0}),n.push({signal:o,abort:a})}return{signal:r.signal,cleanup:()=>{for(let o of n)o.signal.removeEventListener("abort",o.abort)}}}function we(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 S=B(),he=S.run,Ce=S.runOrThrow,Re=S.orThrow,xe=S.all,ge=S.allOrThrow;export{me as RetryStrategies,b as TypedError,xe as all,ge as allOrThrow,w as asMilliseconds,R as asRetryCount,B as default,pe as errorRule,Re as orThrow,he as run,Ce as runOrThrow,B as tryo};
1
+ var ie=Object.defineProperty;var ue=(e,r,t)=>r in e?ie(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var d=(e,r,t)=>ue(e,typeof r!="symbol"?r+"":r,t);var E=class extends Error{constructor(t,n){var s,i;super(t);d(this,"cause");d(this,"title");d(this,"meta");d(this,"status");d(this,"raw");d(this,"path");d(this,"timestamp");d(this,"retryable");this.timestamp=Date.now(),this.retryable=(s=n.retryable)!=null?s:!0,this.name=this.constructor.name,this.cause=n.cause,this.title=n.title,this.meta=(i=n.meta)!=null?i:{},this.status=n.status,this.raw=n.raw,this.path=n.path,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}is(t){return this.code===t}withMeta(t){return Object.assign(this,{meta:t})}withStatus(t){return Object.assign(this,{status:t})}withCause(t){return Object.assign(this,{cause:t})}withPath(t){return this.path=t,this}withRaw(t){return Object.assign(this,{raw:t})}withRetryable(t){return this.retryable=t,this}toJSON(){return{name:this.name,code:this.code,title:this.title,message:this.message,timestamp:this.timestamp,retryable:this.retryable,cause:this.cause,raw:this.raw,path:this.path,stack:this.stack}}},v=class extends E{constructor(t,n){super(`Operation timed out after ${t}ms`,{cause:n,retryable:!0});d(this,"code","TIMEOUT")}};var D=class extends E{constructor(t,n){super(`Circuit breaker is open, reset after ${t}ms`,{cause:n,retryable:!1});d(this,"code","CIRCUIT_OPEN")}};var P=class extends E{constructor(t,n){super(t,{cause:n});d(this,"code","UNKNOWN")}};var b=e=>{if(e<0||!Number.isFinite(e))throw new Error(`Invalid milliseconds: must be a non-negative finite number, got ${e}`);return e},C=e=>{if(e<0||!Number.isInteger(e))throw new Error(`Invalid retry count: must be a non-negative integer, got ${e}`);return e},z=e=>{if(e<1||!Number.isInteger(e))throw new Error(`Invalid concurrency limit: must be a positive integer, got ${e}`);return e},j=e=>{if(e<0||e>100||!Number.isFinite(e))throw new Error(`Invalid percentage: must be between 0 and 100, got ${e}`);return e};var F=class{constructor(r){d(this,"state");d(this,"config");this.config={failureThreshold:C(r.failureThreshold),resetTimeout:b(r.resetTimeout),halfOpenRequests:C(r.halfOpenRequests),shouldCountAsFailure:r.shouldCountAsFailure},this.state={state:"closed",failureCount:0,halfOpenCount:0}}async canExecute(){if(this.updateStateIfNeeded(),this.state.state==="open")return!1;if(this.state.state==="half-open"){if(this.state.halfOpenCount>=this.config.halfOpenRequests)return!1;this.state={...this.state,halfOpenCount:this.state.halfOpenCount+1}}return!0}async recordSuccess(){switch(this.state.state){case"closed":this.state={...this.state,failureCount:0};break;case"half-open":this.state={state:"closed",failureCount:0,halfOpenCount:0};break;case"open":break}}async recordFailure(r){var s,i,o;if(!((o=(i=(s=this.config).shouldCountAsFailure)==null?void 0:i.call(s,r))!=null?o:!0))return;let n=new Date;switch(this.state.state){case"closed":{let a=this.state.failureCount+1;a>=this.config.failureThreshold?this.state={state:"open",failureCount:a,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)}:this.state={...this.state,failureCount:a,lastFailureTime:n};break}case"half-open":this.state={state:"open",failureCount:this.state.failureCount+1,halfOpenCount:0,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break;case"open":this.state={...this.state,lastFailureTime:n,nextAttemptTime:new Date(n.getTime()+this.config.resetTimeout)};break}}getState(){return this.updateStateIfNeeded(),{...this.state,canExecute:this.state.state!=="open"}}createOpenError(){let r=this.state.nextAttemptTime?b(Math.max(0,this.state.nextAttemptTime.getTime()-Date.now())):this.config.resetTimeout;return new D(r)}forceState(r){this.state={state:r,failureCount:0,halfOpenCount:0}}reset(){this.state={state:"closed",failureCount:0,halfOpenCount:0}}updateStateIfNeeded(){this.state.state==="open"&&this.state.nextAttemptTime&&new Date>=this.state.nextAttemptTime&&(this.state={...this.state,state:"half-open",halfOpenCount:0})}};var Y=(e,r)=>t=>{for(let n of e){let s=n(t);if(s!==null)return s}return r(t)},G=e=>r=>r instanceof E?r:r instanceof Error?new e(r.message,r):typeof r=="string"?new e(r):new e("Unknown error occurred",r);var le=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.status=="number"||typeof r.statusCode=="number"},ce=e=>{if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.code=="string"&&r.code.length>0},de=e=>{var r;if(e instanceof Error){let t=e.message.toLowerCase();if(e.name==="TypeError"&&(t.includes("fetch")&&t.includes("failed")||t.includes("network"))||t.includes("fetch")&&t.includes("failed")||t.includes("network"))return!0}if(ce(e)){let t=((r=e.code)!=null?r:"").toUpperCase();return t==="ECONNRESET"||t==="ECONNREFUSED"||t==="ETIMEDOUT"||t==="ENOTFOUND"||t==="EAI_AGAIN"}return!1},ye=e=>typeof e=="object"&&e!==null,B=class{constructor(r){this.predicate=r}toCode(r){return new H(this.predicate,r)}toError(r){return t=>{var l;if(!this.predicate(t))return null;let n=r(t),s=n.code,i=Object.hasOwn(n,"cause")?n.cause:t,o=(l=n.meta)!=null?l:{};class a extends E{constructor(){let c=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:i,meta:o,status:n.status,retryable:n.retryable,raw:c,path:n.path});d(this,"code",s)}}return new a}}};function pe(e,r){let t=new B(i=>i instanceof e);if(r)return t.toError(r);let s=i=>{if(!(i instanceof e))return null;if(i instanceof E)return i;let o=i,a=typeof o.code=="string"&&o.code.length>0?o.code:"UNKNOWN",l=Object.hasOwn(o,"cause"),u=Object.hasOwn(o,"raw");class y extends E{constructor(){super(o.message||a,{title:typeof o.title=="string"?o.title:void 0,cause:l?o.cause:i,meta:ye(o.meta)?o.meta:{},status:typeof o.status=="number"?o.status:void 0,retryable:typeof o.retryable=="boolean"?o.retryable:void 0,raw:u?o.raw:i,path:typeof o.path=="string"?o.path:void 0});d(this,"code",a)}}return new y};return s.toCode=t.toCode.bind(t),s.toError=t.toError.bind(t),s}var H=class{constructor(r,t){this.predicate=r;this.errorCode=t}with(r){return t=>{var l;if(!this.predicate(t))return null;let n=r(t),s=Object.hasOwn(n,"cause")?n.cause:t,i=(l=n.meta)!=null?l:{},o=this.errorCode;class a extends E{constructor(){let p=Object.hasOwn(n,"raw")?n.raw:t;super(n.message,{title:n.title,cause:s,meta:i,status:n.status,retryable:n.retryable,raw:p,path:n.path});d(this,"code",o)}}return new a}}},h={when:e=>new B(e),instance:pe},x={typed:(e=>e instanceof E?e:null),abort:h.when(e=>e instanceof Error&&e.name==="AbortError").toCode("ABORTED").with(e=>({message:e.message||"Operation was aborted",cause:e,retryable:!1,raw:e})),timeout:h.when(e=>e instanceof Error&&e.name==="TimeoutError").toCode("TIMEOUT").with(e=>({message:e.message||"Operation timed out",cause:e,raw:e})),network:h.when(e=>de(e)).toCode("NETWORK").with(e=>({message:(e instanceof Error,e.message||"Network error"),cause:e,raw:e})),http:h.when(e=>{var n;if(!le(e))return!1;let r=e,t=(n=r.status)!=null?n:r.statusCode;return typeof t=="number"&&t>=400}).toCode("HTTP").with(e=>{var n;let r=(n=e.status)!=null?n:e.statusCode,t=typeof r=="number"&&(r>=500||r===429);return{message:e.message||`HTTP ${r!=null?r:"error"} error`,cause:e,status:typeof r=="number"?r:void 0,retryable:t,raw:e}}),unknown:h.when(e=>e instanceof Error&&!(e instanceof E)).toCode("UNKNOWN").with(e=>({message:e.message||"Unknown error occurred",cause:e,raw:e}))};var me=[x.typed,x.abort,x.timeout,x.http,x.network,x.unknown];var fe={when:e=>h.when(e),instance:h.instance},Q=me;var Ee={fixed:e=>({type:"fixed",delay:e}),exponential:(e,r=2,t)=>({type:"exponential",base:e,factor:r,maxDelay:t}),fibonacci:(e,r)=>({type:"fibonacci",base:e,maxDelay:r}),custom:e=>({type:"custom",calculate:e})},X=(e,r,t)=>{switch(e.type){case"fixed":return e.delay;case"exponential":{let n=e.base*e.factor**(Number(r)-1);return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"fibonacci":{let n=e.base*Te(Number(r));return e.maxDelay!==void 0?Math.min(n,e.maxDelay):n}case"custom":return e.calculate(r,t);default:return e}},Te=e=>{if(e<=1)return 1;let r=1,t=1;for(let n=2;n<=e;n++){let s=r+t;r=t,t=s}return t},Z=e=>{switch(e.type){case"fixed":{if(e.delay<0)throw new Error("Fixed delay must be non-negative");break}case"exponential":if(e.base<=0)throw new Error("Exponential base delay must be positive");if(e.factor<=1)throw new Error("Exponential factor must be greater than 1");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Exponential max delay must be positive");break;case"fibonacci":if(e.base<=0)throw new Error("Fibonacci base delay must be positive");if(e.maxDelay!==void 0&&e.maxDelay<=0)throw new Error("Fibonacci max delay must be positive");break;case"custom":break;default:{let r=e;throw new Error(`Unknown strategy type: ${r}`)}}};var ee=(e,r)=>new Promise((t,n)=>{if(r!=null&&r.aborted){n(new DOMException("Aborted","AbortError"));return}let s=a=>{r&&a&&r.removeEventListener("abort",a)},i,o=()=>{i&&clearTimeout(i),s(o),n(new DOMException("Aborted","AbortError"))};i=setTimeout(()=>{s(o),t()},e),r==null||r.addEventListener("abort",o,{once:!0})}),re=(e,r,t,n)=>new Promise((s,i)=>{if(t!=null&&t.aborted){i(new DOMException("Aborted","AbortError"));return}let o=!1,a=setTimeout(()=>{var y;o=!0,u(),i((y=n==null?void 0:n())!=null?y:new Error(`Operation timed out after ${r}ms`))},r),l=()=>{o||(o=!0,u(),i(new DOMException("Aborted","AbortError")))},u=()=>{clearTimeout(a),t==null||t.removeEventListener("abort",l)};t==null||t.addEventListener("abort",l,{once:!0}),e.then(y=>{o||(o=!0,u(),s(y))},y=>{o||(o=!0,u(),i(y))})});var we=e=>{var o,a,l;if(e.toError)return e.toError;let r=(o=e.rulesMode)!=null?o:"extend",t=(a=e.rules)!=null?a:[],n=Q,s=(l=e.fallback)!=null?l:(u=>G(P)(u)),i=r==="replace"?t:[...t,...n];return Y(i,s)},be=e=>{if(e)switch(e.type){case"none":return;case"full":case"equal":j(e.ratio);return;case"custom":return;default:{let r=e;throw new Error(`Unsupported jitter configuration: ${r}`)}}},q=e=>{let r=e;return r.timeout!==void 0&&(r={...r,timeout:Number(b(r.timeout))}),r.concurrency!==void 0&&(r={...r,concurrency:Number.isFinite(r.concurrency)?Number(z(r.concurrency)):r.concurrency}),r.retry&&(Z(r.retry.strategy),be(r.retry.jitter),r={...r,retry:{...r.retry,maxRetries:Number(C(r.retry.maxRetries))}}),r},$=class e{constructor(r={}){d(this,"circuitBreaker");d(this,"config");d(this,"lastCircuitState");let{rules:t,rulesMode:n,fallback:s,toError:i,mapError:o,...a}=r,l=we(r),u={...a,errorHandling:{normalizer:l,mapError:o}};this.config=q(u),u.circuitBreaker&&(this.circuitBreaker=new F(u.circuitBreaker),this.lastCircuitState=this.circuitBreaker.getState().state)}async run(r,t={}){var i,o,a,l,u,y;let n=q({...this.config,...t});if(this.circuitBreaker){let c=(i=this.lastCircuitState)!=null?i:this.circuitBreaker.getState().state,p=await this.circuitBreaker.canExecute(),T=this.circuitBreaker.getState().state;if(c!==T)try{(a=(o=n.hooks)==null?void 0:o.onCircuitStateChange)==null||a.call(o,c,T)}catch{}if(this.lastCircuitState=T,!p)return{type:"failure",ok:!1,data:null,error:this.circuitBreaker.createOpenError(),metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,retryHistory:[]}}}let s=await he(r,n);if(this.circuitBreaker){let c=(l=this.lastCircuitState)!=null?l:this.circuitBreaker.getState().state;s.ok?await this.circuitBreaker.recordSuccess():await this.circuitBreaker.recordFailure(s.error);let p=this.circuitBreaker.getState().state;if(c!==p)try{(y=(u=n.hooks)==null?void 0:u.onCircuitStateChange)==null||y.call(u,c,p)}catch{}this.lastCircuitState=p}return s}async runOrThrow(r,t={}){return this.orThrow(r,t)}async orThrow(r,t={}){let n=await this.run(r,t);if(n.ok)return n.data;throw n.error}async all(r,t={}){var y;let n=q({...this.config,...t}),s=(y=n.concurrency)!=null?y:Number.POSITIVE_INFINITY,i=Number.isFinite(s)?Number(z(s)):Number.POSITIVE_INFINITY;if(i===Number.POSITIVE_INFINITY)return Promise.all(r.map(c=>this.run(c,n)));let o=new Array(r.length),a=0,l=async()=>{var c;for(;a<r.length&&!((c=n.signal)!=null&&c.aborted);){let p=a++;if(p>=r.length)break;let T=r[p];T&&(o[p]=await this.run(T,n))}},u=Array.from({length:Math.min(i,r.length)},()=>l());await Promise.all(u);for(let c=0;c<r.length;c++)if(!(c in o)){let p=r[c];p&&(o[c]=await this.run(p,n))}return o}async allOrThrow(r,t={}){return(await this.all(r,t)).map(s=>{if(!s.ok)throw s.error;return s.data})}partitionAll(r){let t=[],n=[],s=[],i=[],o=[];for(let a of r){if(a.type==="success"){t.push(a);continue}switch(n.push(a),a.type){case"failure":s.push(a);break;case"aborted":i.push(a);break;case"timeout":o.push(a);break}}return{ok:t,errors:n,failure:s,aborted:i,timeout:o}}getCircuitBreakerState(){var r;return(r=this.circuitBreaker)==null?void 0:r.getState()}resetCircuitBreaker(){var r;(r=this.circuitBreaker)==null||r.reset()}getConfig(){return{...this.config}}withConfig(r){var l,u;let{errorHandling:t,...n}=this.config,{errorHandling:s,...i}=r,o=(l=s==null?void 0:s.normalizer)!=null?l:t.normalizer,a=(u=s==null?void 0:s.mapError)!=null?u:t.mapError;return new e({...n,...i,toError:o,mapError:a})}};function _(e={}){let r=new $(e);return{run:(t,n)=>r.run(t,n),orThrow:(t,n)=>r.orThrow(t,n),runOrThrow:(t,n)=>r.runOrThrow(t,n),all:(t,n)=>r.all(t,n),allOrThrow:(t,n)=>r.allOrThrow(t,n),partitionAll:t=>r.partitionAll(t),withConfig:t=>r.withConfig(t)}}async function he(e,r){let{signal:t,ignoreAbort:n=!0,timeout:s,retry:i,errorHandling:o,hooks:a,logger:l}=r,u=(R,...m)=>{try{R==null||R(...m)}catch{}},y,c=0,p=0,T=[],k=Date.now(),{signal:O,cleanup:ne}=te(t),N=R=>({totalAttempts:c,totalRetries:c>0?Number(c)-1:0,totalDuration:Date.now()-k,lastError:R,retryHistory:T});try{if(O.aborted){u(a==null?void 0:a.onAbort,O);let m=o.normalizer(new DOMException("Aborted","AbortError")),w=o.mapError?o.mapError(m):m;return{type:"aborted",ok:!1,data:null,error:w,metrics:{totalAttempts:c,totalRetries:p,totalDuration:Date.now()-k,lastError:w,retryHistory:T}}}let R=async()=>{var M,g,W;let m=1,w=C((M=i==null?void 0:i.maxRetries)!=null?M:0);for(;;){c=m;let K=new AbortController,{signal:U,cleanup:oe}=te(O,K.signal);try{let I=Promise.resolve(e({signal:U})),A=s?await re(I,s,U,()=>(K.abort(),new v(b(s)))):await I;return u(a==null?void 0:a.onSuccess,A,N()),u(l==null?void 0:l.info,`Task succeeded on attempt ${m}`),A}catch(I){let A=o.normalizer(I),f=o.mapError?o.mapError(A):A;if(y=f,f.code==="ABORTED"&&u(a==null?void 0:a.onAbort,U),n&&f.code==="ABORTED"||(u(a==null?void 0:a.onError,f,N(f)),u(l==null?void 0:l.error,`Task failed on attempt ${m}`,f)),f.code==="ABORTED"||f.retryable===!1)throw f;if(m<=Number(w)){let V=i==null?void 0:i.shouldRetry,se={totalAttempts:Number(c),elapsedTime:Date.now()-k,startTime:new Date(k),lastDelay:(g=T[T.length-1])!=null&&g.delay?Number((W=T[T.length-1])==null?void 0:W.delay):void 0};if(!V||V(m,f,se)){let ae=i?X(i.strategy,m,f):0,L=Re(ae,i==null?void 0:i.jitter),J=b(L);T.push({attempt:m,error:f,delay:J,timestamp:new Date}),u(a==null?void 0:a.onRetry,m,f,L),u(l==null?void 0:l.info,`Retrying in ${L}ms (attempt ${m+1})`),m+=1,await ee(J,O);continue}}throw f}finally{oe()}}};try{let m=await R(),w=N();return p=w.totalRetries,u(a==null?void 0:a.onFinally,w),{type:"success",ok:!0,data:m,error:null,metrics:w}}catch(m){let w=y!=null?y:o.normalizer(m),M=w.code==="TIMEOUT"?"timeout":w.code==="ABORTED"?"aborted":"failure",g=N(w);return p=g.totalRetries,u(a==null?void 0:a.onFinally,g),{type:M,ok:!1,data:null,error:w,metrics:g}}}finally{ne()}}function te(...e){let r=new AbortController,t=e.filter(s=>s!==void 0);if(t.length===0)return{signal:r.signal,cleanup:()=>{}};if(t.some(s=>s.aborted))return r.abort(),{signal:r.signal,cleanup:()=>{}};let n=[];for(let s of t){let i=()=>r.abort();s.addEventListener("abort",i,{once:!0}),n.push({signal:s,abort:i})}return{signal:r.signal,cleanup:()=>{for(let s of n)s.signal.removeEventListener("abort",s.abort)}}}function Re(e,r){if(!r||r.type==="none"||e<=0)return e;switch(r.type){case"full":{let t=Number(r.ratio)/100,n=Math.max(0,Number(e)*(1-t)),s=Number(e);return n+Math.random()*(s-n)}case"equal":{let t=Number(r.ratio)/100,n=Number(e)*t/2;return Number(e)-n+Math.random()*n}case"custom":return r.calculate(e);default:return r}}var S=_(),Ce=S.run,xe=S.runOrThrow,ge=S.orThrow,ke=S.all,Oe=S.allOrThrow;export{Ee as RetryStrategies,E as TypedError,ke as all,Oe as allOrThrow,b as asMilliseconds,C as asRetryCount,_ as default,fe as errorRule,ge as orThrow,Ce as run,xe as runOrThrow,_ as tryo};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tryo",
3
- "version": "0.13.3",
3
+ "version": "0.13.5",
4
4
  "author": {
5
5
  "name": "sebasxsala",
6
6
  "url": "https://github.com/sebasxsala"
@@ -50,8 +50,7 @@
50
50
  "lint": "biome lint",
51
51
  "lint:fix": "biome lint --fix",
52
52
  "check": "biome check",
53
- "check:fix": "biome check --write",
54
- "prepare": ""
53
+ "check:fix": "biome check --write"
55
54
  },
56
55
  "sideEffects": false,
57
56
  "type": "module",