@jagreehal/workflow 1.3.0 → 1.5.0

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 CHANGED
@@ -280,9 +280,18 @@ if (result.ok) {
280
280
  | `step(op())` | Unwrap Result or exit early |
281
281
  | `step.try(fn, { error })` | Catch throws/rejects → typed error |
282
282
  | `step.fromResult(fn, { onError })` | Map Result errors with typed onError |
283
+ | `step.retry(fn, opts)` | Retry with backoff on failure |
284
+ | `step.withTimeout(fn, { ms })` | Timeout after specified duration |
283
285
  | `ok(value)` / `err(error)` | Create Results |
284
286
  | `map`, `andThen`, `match` | Transform Results |
285
287
  | `allAsync`, `partition` | Batch operations |
288
+ | `isStepTimeoutError(e)` | Check if error is a timeout |
289
+ | `getStepTimeoutMeta(e)` | Get timeout metadata from error |
290
+ | `createCircuitBreaker(name, config)` | Create circuit breaker for step protection |
291
+ | `createSagaWorkflow(deps, opts)` | Create saga with auto-compensation |
292
+ | `createRateLimiter(name, config)` | Control step throughput |
293
+ | `createWebhookHandler(workflow, fn, config)` | Expose workflow as HTTP endpoint |
294
+ | `createWorkflowHarness(deps, opts)` | Create test harness for workflows |
286
295
 
287
296
  ### Choosing Between run() and createWorkflow()
288
297
 
@@ -347,6 +356,84 @@ const result = await workflow(async (step) => {
347
356
  });
348
357
  ```
349
358
 
359
+ ### Retry with backoff
360
+
361
+ Automatically retry failed steps with configurable backoff:
362
+
363
+ ```typescript
364
+ const result = await workflow(async (step) => {
365
+ // Retry up to 3 times with exponential backoff
366
+ const data = await step.retry(
367
+ () => fetchData(),
368
+ {
369
+ attempts: 3,
370
+ backoff: 'exponential', // 'fixed' | 'linear' | 'exponential'
371
+ initialDelay: 100, // ms
372
+ maxDelay: 5000, // cap delay at 5s
373
+ jitter: true, // add randomness to prevent thundering herd
374
+ retryOn: (error) => error !== 'FATAL', // custom retry predicate
375
+ }
376
+ );
377
+ return data;
378
+ });
379
+ ```
380
+
381
+ Or use retry options directly on `step()`:
382
+
383
+ ```typescript
384
+ const user = await step(() => fetchUser(id), {
385
+ key: 'user:1',
386
+ retry: { attempts: 3, backoff: 'exponential' },
387
+ });
388
+ ```
389
+
390
+ ### Timeout
391
+
392
+ Prevent steps from hanging with timeouts:
393
+
394
+ ```typescript
395
+ const result = await workflow(async (step) => {
396
+ // Timeout after 5 seconds
397
+ const data = await step.withTimeout(
398
+ () => slowOperation(),
399
+ { ms: 5000, name: 'slow-op' }
400
+ );
401
+ return data;
402
+ });
403
+ ```
404
+
405
+ With AbortSignal for cancellable operations:
406
+
407
+ ```typescript
408
+ const data = await step.withTimeout(
409
+ (signal) => fetch('/api/data', { signal }),
410
+ { ms: 5000, signal: true } // pass signal to operation
411
+ );
412
+ ```
413
+
414
+ Combine retry and timeout - each attempt gets its own timeout:
415
+
416
+ ```typescript
417
+ const data = await step.retry(
418
+ () => fetchData(),
419
+ {
420
+ attempts: 3,
421
+ timeout: { ms: 2000 }, // 2s timeout per attempt
422
+ }
423
+ );
424
+ ```
425
+
426
+ Detecting timeout errors:
427
+
428
+ ```typescript
429
+ import { isStepTimeoutError, getStepTimeoutMeta } from '@jagreehal/workflow';
430
+
431
+ if (!result.ok && isStepTimeoutError(result.error)) {
432
+ const meta = getStepTimeoutMeta(result.error);
433
+ console.log(`Timed out after ${meta?.timeoutMs}ms on attempt ${meta?.attempt}`);
434
+ }
435
+ ```
436
+
350
437
  ### State save & resume
351
438
 
352
439
  Save step results for workflow replay:
@@ -399,11 +486,48 @@ const workflow = createWorkflow({ fetchUser }, {
399
486
  onEvent: (event) => {
400
487
  // workflow_start | workflow_success | workflow_error
401
488
  // step_start | step_success | step_error | step_complete
489
+ // step_retry | step_timeout | step_retries_exhausted
402
490
  console.log(event.type, event.durationMs);
403
491
  }
404
492
  });
405
493
  ```
406
494
 
495
+ ### Visualization
496
+
497
+ Render workflow execution as ASCII art or Mermaid diagrams:
498
+
499
+ ```typescript
500
+ import { createIRBuilder, renderToAscii, renderToMermaid } from '@jagreehal/workflow/visualize';
501
+
502
+ const builder = createIRBuilder();
503
+ const workflow = createWorkflow({ fetchUser, fetchPosts }, {
504
+ onEvent: (event) => builder.addEvent(event),
505
+ });
506
+
507
+ await workflow(async (step) => {
508
+ const user = await step(() => fetchUser('1'), { name: 'Fetch user' });
509
+ const posts = await step(() => fetchPosts(user.id), { name: 'Fetch posts' });
510
+ return { user, posts };
511
+ });
512
+
513
+ // ASCII output
514
+ console.log(renderToAscii(builder.getIR()));
515
+ // ┌── my-workflow ──────────────────────────┐
516
+ // │ ✓ Fetch user [150ms] │
517
+ // │ ✓ Fetch posts [89ms] │
518
+ // │ Completed in 240ms │
519
+ // └─────────────────────────────────────────┘
520
+
521
+ // Mermaid output (for docs, GitHub, etc.)
522
+ console.log(renderToMermaid(builder.getIR()));
523
+ ```
524
+
525
+ Visualization includes retry and timeout indicators:
526
+
527
+ ```
528
+ ✓ Fetch data [500ms] [2 retries] [timeout 5000ms]
529
+ ```
530
+
407
531
  ### Human-in-the-loop
408
532
 
409
533
  ```typescript
@@ -431,7 +555,20 @@ if (!result.ok && isPendingApproval(result.error)) {
431
555
 
432
556
  ### More utilities
433
557
 
434
- See [docs/advanced.md](docs/advanced.md) for batch operations, transformers, and neverthrow interop.
558
+ See [docs/advanced.md](docs/advanced.md) for:
559
+ - Batch operations (`all`, `allSettled`, `partition`)
560
+ - Result transformers (`map`, `andThen`, `match`)
561
+ - Circuit breaker pattern
562
+ - Saga/compensation pattern for rollbacks
563
+ - Rate limiting and concurrency control
564
+ - Workflow versioning and migrations
565
+ - Pluggable persistence adapters
566
+ - Webhook and event trigger adapters
567
+ - Policy-driven step middleware
568
+ - Developer tools and visualization
569
+ - HITL orchestration helpers
570
+ - Deterministic testing harness
571
+ - OpenTelemetry integration
435
572
 
436
573
  ## API Reference
437
574
 
package/dist/core.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var b=Object.defineProperty;var J=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var G=Object.prototype.hasOwnProperty;var q=(e,n)=>{for(var t in n)b(e,t,{get:n[t],enumerable:!0})},B=(e,n,t,u)=>{if(n&&typeof n=="object"||typeof n=="function")for(let c of $(n))!G.call(e,c)&&c!==t&&b(e,c,{get:()=>n[c],enumerable:!(u=J(n,c))||u.enumerable});return e};var H=e=>B(b({},"__esModule",{value:!0}),e);var ge={};q(ge,{EARLY_EXIT_SYMBOL:()=>O,UnwrapError:()=>I,all:()=>de,allAsync:()=>Re,allSettled:()=>fe,allSettledAsync:()=>Ae,andThen:()=>Ee,any:()=>Ce,anyAsync:()=>xe,createEarlyExit:()=>F,err:()=>l,from:()=>se,fromNullable:()=>pe,fromPromise:()=>ue,isEarlyExit:()=>N,isErr:()=>Q,isOk:()=>z,isUnexpectedError:()=>D,map:()=>ie,mapError:()=>ce,mapErrorTry:()=>ke,mapTry:()=>Te,match:()=>le,ok:()=>f,partition:()=>me,run:()=>M,tap:()=>we,tapError:()=>ye,tryAsync:()=>ae,unwrap:()=>te,unwrapOr:()=>re,unwrapOrElse:()=>oe});module.exports=H(ge);var f=e=>({ok:!0,value:e}),l=(e,n)=>({ok:!1,error:e,...n?.cause!==void 0?{cause:n.cause}:{}}),z=e=>e.ok,Q=e=>!e.ok,D=e=>typeof e=="object"&&e!==null&&e.type==="UNEXPECTED_ERROR",O=Symbol("early-exit");function F(e,n){return{[O]:!0,error:e,meta:n}}function N(e){return typeof e=="object"&&e!==null&&e[O]===!0}var V=Symbol("mapper-exception");function Z(e){return{[V]:!0,thrown:e}}function ee(e){return typeof e=="object"&&e!==null&&e[V]===!0}function ne(e){return typeof e=="string"?{name:e}:e??{}}async function M(e,n){let{onError:t,onEvent:u,catchUnexpected:c,workflowId:C,context:A}=n&&typeof n=="object"?n:{},a=C??crypto.randomUUID(),j=!t&&!c,g=[],L=0,_=r=>r??`step_${++L}`,E=r=>{if(r.type==="step_success"){let S=r.stepId;for(let x=g.length-1;x>=0;x--){let T=g[x];if(T.type==="race"&&!T.winnerId){T.winnerId=S;break}}}u?.(r,A)},h=F,K=r=>N(r),U=(r,S)=>j?S?.origin==="result"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:r,...S.resultCause!==void 0?{cause:S.resultCause}:{}}}:S?.origin==="throw"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"throw",error:r,thrown:S.thrown}}:{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:r}}:r,X=r=>r.origin==="result"?r.resultCause:r.thrown,W=r=>({type:"UNEXPECTED_ERROR",cause:r.meta.origin==="result"?{type:"STEP_FAILURE",origin:"result",error:r.error,...r.meta.resultCause!==void 0?{cause:r.meta.resultCause}:{}}:{type:"STEP_FAILURE",origin:"throw",error:r.error,thrown:r.meta.thrown}});try{let r=(T,k)=>(async()=>{let{name:o,key:s}=ne(k),y=_(s),i=u?performance.now():0;u&&E({type:"step_start",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now()});let p;try{p=await(typeof T=="function"?T():T)}catch(R){let v=performance.now()-i;if(K(R))throw E({type:"step_aborted",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:v}),R;if(c){let P;try{P=c(R)}catch(Y){throw Z(Y)}throw E({type:"step_error",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:v,error:P}),s&&E({type:"step_complete",workflowId:a,stepKey:s,name:o,ts:Date.now(),durationMs:v,result:l(P,{cause:R}),meta:{origin:"throw",thrown:R}}),t?.(P,o),h(P,{origin:"throw",thrown:R})}else{let P={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:R}};throw E({type:"step_error",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:v,error:P}),s&&E({type:"step_complete",workflowId:a,stepKey:s,name:o,ts:Date.now(),durationMs:v,result:l(P,{cause:R}),meta:{origin:"throw",thrown:R}}),R}}let w=performance.now()-i;if(p.ok)return E({type:"step_success",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:w}),s&&E({type:"step_complete",workflowId:a,stepKey:s,name:o,ts:Date.now(),durationMs:w,result:p}),p.value;let d=U(p.error,{origin:"result",resultCause:p.cause});throw E({type:"step_error",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:w,error:d}),s&&E({type:"step_complete",workflowId:a,stepKey:s,name:o,ts:Date.now(),durationMs:w,result:p,meta:{origin:"result",resultCause:p.cause}}),t?.(p.error,o),h(p.error,{origin:"result",resultCause:p.cause})})();r.try=(T,k)=>{let o=k.name,s=k.key,y=_(s),m="error"in k?()=>k.error:k.onError,i=u;return(async()=>{let p=i?performance.now():0;u&&E({type:"step_start",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now()});try{let w=await T(),d=performance.now()-p;return E({type:"step_success",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:d}),s&&E({type:"step_complete",workflowId:a,stepKey:s,name:o,ts:Date.now(),durationMs:d,result:f(w)}),w}catch(w){let d=m(w),R=performance.now()-p,v=U(d,{origin:"throw",thrown:w});throw E({type:"step_error",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:R,error:v}),s&&E({type:"step_complete",workflowId:a,stepKey:s,name:o,ts:Date.now(),durationMs:R,result:l(d,{cause:w}),meta:{origin:"throw",thrown:w}}),t?.(d,o),h(d,{origin:"throw",thrown:w})}})()},r.fromResult=(T,k)=>{let o=k.name,s=k.key,y=_(s),m="error"in k?()=>k.error:k.onError,i=u;return(async()=>{let p=i?performance.now():0;u&&E({type:"step_start",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now()});let w=await T();if(w.ok){let d=performance.now()-p;return E({type:"step_success",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:d}),s&&E({type:"step_complete",workflowId:a,stepKey:s,name:o,ts:Date.now(),durationMs:d,result:f(w.value)}),w.value}else{let d=m(w.error),R=performance.now()-p,v=U(d,{origin:"result",resultCause:w.error});throw E({type:"step_error",workflowId:a,stepId:y,stepKey:s,name:o,ts:Date.now(),durationMs:R,error:v}),s&&E({type:"step_complete",workflowId:a,stepKey:s,name:o,ts:Date.now(),durationMs:R,result:l(d,{cause:w.error}),meta:{origin:"result",resultCause:w.error}}),t?.(d,o),h(d,{origin:"result",resultCause:w.error})}})()},r.parallel=(T,k)=>{let o=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let s=performance.now(),y=!1;g.push({scopeId:o,type:"parallel"});let m=()=>{if(y)return;y=!0;let i=g.findIndex(p=>p.scopeId===o);i!==-1&&g.splice(i,1),E({type:"scope_end",workflowId:a,scopeId:o,ts:Date.now(),durationMs:performance.now()-s})};E({type:"scope_start",workflowId:a,scopeId:o,scopeType:"parallel",name:T,ts:Date.now()});try{let i=await k();if(m(),!i.ok)throw t?.(i.error,T),h(i.error,{origin:"result",resultCause:i.cause});return i.value}catch(i){throw m(),i}})()},r.race=(T,k)=>{let o=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let s=performance.now(),y=!1,m={scopeId:o,type:"race",winnerId:void 0};g.push(m);let i=()=>{if(y)return;y=!0;let p=g.findIndex(w=>w.scopeId===o);p!==-1&&g.splice(p,1),E({type:"scope_end",workflowId:a,scopeId:o,ts:Date.now(),durationMs:performance.now()-s,winnerId:m.winnerId})};E({type:"scope_start",workflowId:a,scopeId:o,scopeType:"race",name:T,ts:Date.now()});try{let p=await k();if(i(),!p.ok)throw t?.(p.error,T),h(p.error,{origin:"result",resultCause:p.cause});return p.value}catch(p){throw i(),p}})()},r.allSettled=(T,k)=>{let o=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let s=performance.now(),y=!1;g.push({scopeId:o,type:"allSettled"});let m=()=>{if(y)return;y=!0;let i=g.findIndex(p=>p.scopeId===o);i!==-1&&g.splice(i,1),E({type:"scope_end",workflowId:a,scopeId:o,ts:Date.now(),durationMs:performance.now()-s})};E({type:"scope_start",workflowId:a,scopeId:o,scopeType:"allSettled",name:T,ts:Date.now()});try{let i=await k();if(m(),!i.ok)throw t?.(i.error,T),h(i.error,{origin:"result",resultCause:i.cause});return i.value}catch(i){throw m(),i}})()};let x=await e(r);return f(x)}catch(r){if(ee(r))throw r.thrown;if(K(r)){let x=X(r.meta);if(c||t)return l(r.error,{cause:x});if(D(r.error))return l(r.error,{cause:x});let T=W(r);return l(T,{cause:x})}if(c){let x=c(r);return t?.(x,"unexpected"),l(x,{cause:r})}let S={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:r}};return t?.(S,"unexpected"),l(S,{cause:r})}}M.strict=(e,n)=>M(e,n);var I=class extends Error{constructor(t,u){super(`Unwrap called on an error result: ${String(t)}`);this.error=t;this.cause=u;this.name="UnwrapError"}},te=e=>{if(e.ok)return e.value;throw new I(e.error,e.cause)},re=(e,n)=>e.ok?e.value:n,oe=(e,n)=>e.ok?e.value:n(e.error,e.cause);function se(e,n){try{return f(e())}catch(t){return n?l(n(t),{cause:t}):l(t)}}async function ue(e,n){try{return f(await e)}catch(t){return n?l(n(t),{cause:t}):l(t)}}async function ae(e,n){try{return f(await e())}catch(t){return n?l(n(t),{cause:t}):l(t)}}function pe(e,n){return e!=null?f(e):l(n())}function ie(e,n){return e.ok?f(n(e.value)):e}function ce(e,n){return e.ok?e:l(n(e.error),{cause:e.cause})}function le(e,n){return e.ok?n.ok(e.value):n.err(e.error,e.cause)}function Ee(e,n){return e.ok?n(e.value):e}function we(e,n){return e.ok&&n(e.value),e}function ye(e,n){return e.ok||n(e.error,e.cause),e}function Te(e,n,t){if(!e.ok)return e;try{return f(n(e.value))}catch(u){return l(t(u),{cause:u})}}function ke(e,n,t){if(e.ok)return e;try{return l(n(e.error),{cause:e.cause})}catch(u){return l(t(u),{cause:u})}}function de(e){let n=[];for(let t of e){if(!t.ok)return t;n.push(t.value)}return f(n)}async function Re(e){return e.length===0?f([]):new Promise(n=>{let t=!1,u=e.length,c=new Array(e.length);for(let C=0;C<e.length;C++){let A=C;Promise.resolve(e[A]).catch(a=>l({type:"PROMISE_REJECTED",cause:a},{cause:{type:"PROMISE_REJECTION",reason:a}})).then(a=>{if(!t){if(!a.ok){t=!0,n(a);return}c[A]=a.value,u--,u===0&&n(f(c))}})}})}function fe(e){let n=[],t=[];for(let u of e)u.ok?n.push(u.value):t.push({error:u.error,cause:u.cause});return t.length>0?l(t):f(n)}function me(e){let n=[],t=[];for(let u of e)u.ok?n.push(u.value):t.push(u.error);return{values:n,errors:t}}function Ce(e){if(e.length===0)return l({type:"EMPTY_INPUT",message:"any() requires at least one Result"});let n=null;for(let t of e){if(t.ok)return t;n||(n=t)}return n}async function xe(e){return e.length===0?l({type:"EMPTY_INPUT",message:"anyAsync() requires at least one Result"}):new Promise(n=>{let t=!1,u=e.length,c=null;for(let C of e)Promise.resolve(C).catch(A=>l({type:"PROMISE_REJECTED",cause:A},{cause:{type:"PROMISE_REJECTION",reason:A}})).then(A=>{if(!t){if(A.ok){t=!0,n(A);return}c||(c=A),u--,u===0&&n(c)}})})}async function Ae(e){let n=await Promise.all(e.map(c=>Promise.resolve(c).then(C=>({status:"result",result:C})).catch(C=>({status:"rejected",error:{type:"PROMISE_REJECTED",cause:C},cause:{type:"PROMISE_REJECTION",reason:C}})))),t=[],u=[];for(let c of n)c.status==="rejected"?u.push({error:c.error,cause:c.cause}):c.result.ok?t.push(c.result.value):u.push({error:c.result.error,cause:c.result.cause});return u.length>0?l(u):f(t)}0&&(module.exports={EARLY_EXIT_SYMBOL,UnwrapError,all,allAsync,allSettled,allSettledAsync,andThen,any,anyAsync,createEarlyExit,err,from,fromNullable,fromPromise,isEarlyExit,isErr,isOk,isUnexpectedError,map,mapError,mapErrorTry,mapTry,match,ok,partition,run,tap,tapError,tryAsync,unwrap,unwrapOr,unwrapOrElse});
1
+ "use strict";var Y=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var ce=Object.prototype.hasOwnProperty;var Ee=(e,t)=>{for(var n in t)Y(e,n,{get:t[n],enumerable:!0})},ye=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let l of le(t))!ce.call(e,l)&&l!==n&&Y(e,l,{get:()=>t[l],enumerable:!(s=pe(t,l))||s.enumerable});return e};var me=e=>ye(Y({},"__esModule",{value:!0}),e);var Xe={};Ee(Xe,{EARLY_EXIT_SYMBOL:()=>G,STEP_TIMEOUT_MARKER:()=>O,UnwrapError:()=>N,all:()=>Ke,allAsync:()=>je,allSettled:()=>Fe,allSettledAsync:()=>We,andThen:()=>Me,any:()=>Ve,anyAsync:()=>Le,createEarlyExit:()=>ne,err:()=>T,from:()=>ge,fromNullable:()=>be,fromPromise:()=>Ae,getStepTimeoutMeta:()=>te,isEarlyExit:()=>re,isErr:()=>Te,isOk:()=>we,isStepTimeoutError:()=>J,isUnexpectedError:()=>ee,map:()=>he,mapError:()=>ve,mapErrorTry:()=>De,mapTry:()=>Ue,match:()=>_e,ok:()=>A,partition:()=>Ne,run:()=>$,tap:()=>Ie,tapError:()=>Oe,tryAsync:()=>Pe,unwrap:()=>Ce,unwrapOr:()=>xe,unwrapOrElse:()=>Se});module.exports=me(Xe);var A=e=>({ok:!0,value:e}),T=(e,t)=>({ok:!1,error:e,...t?.cause!==void 0?{cause:t.cause}:{}}),we=e=>e.ok,Te=e=>!e.ok,ee=e=>typeof e=="object"&&e!==null&&e.type==="UNEXPECTED_ERROR",O=Symbol.for("step_timeout_marker");function J(e){return typeof e!="object"||e===null?!1:e.type==="STEP_TIMEOUT"?!0:O in e}function te(e){if(!(typeof e!="object"||e===null)){if(e.type==="STEP_TIMEOUT"){let t=e;return{timeoutMs:t.timeoutMs,stepName:t.stepName,stepKey:t.stepKey,attempt:t.attempt}}if(O in e)return e[O]}}var G=Symbol("early-exit");function ne(e,t){return{[G]:!0,error:e,meta:t}}function re(e){return typeof e=="object"&&e!==null&&e[G]===!0}var oe=Symbol("mapper-exception");function ke(e){return{[oe]:!0,thrown:e}}function de(e){return typeof e=="object"&&e!==null&&e[oe]===!0}function fe(e){return typeof e=="string"?{name:e}:e??{}}function B(e,t){let{backoff:n,initialDelay:s,maxDelay:l,jitter:g}=t,k;switch(n){case"fixed":k=s;break;case"linear":k=s*e;break;case"exponential":k=s*Math.pow(2,e-1);break}if(k=Math.min(k,l),g){let o=k*.25*Math.random();k=k+o}return Math.floor(k)}function q(e){return new Promise(t=>setTimeout(t,e))}var Z=Symbol("timeout");async function Re(e,t,n){let s=new AbortController,l=t.error??{type:"STEP_TIMEOUT",stepName:n.name,stepKey:n.key,timeoutMs:t.ms,attempt:n.attempt},g,k=new Promise((v,x)=>{g=setTimeout(()=>{s.abort(),x({[Z]:!0,error:l})},t.ms)}),o;t.signal?o=Promise.resolve(e(s.signal)):o=Promise.resolve(e());try{return await Promise.race([o,k])}catch(v){if(typeof v=="object"&&v!==null&&v[Z]===!0){let x=v.error;if(typeof x=="object"&&x!==null&&x.type!=="STEP_TIMEOUT"){let K={timeoutMs:t.ms,stepName:n.name,stepKey:n.key,attempt:n.attempt};O in x?x[O]=K:Object.defineProperty(x,O,{value:K,enumerable:!1,writable:!0,configurable:!1})}throw x}throw v}finally{clearTimeout(g)}}var D={backoff:"exponential",initialDelay:100,maxDelay:3e4,jitter:!0,retryOn:()=>!0,onRetry:()=>{}};async function $(e,t){let{onError:n,onEvent:s,catchUnexpected:l,workflowId:g,context:k}=t&&typeof t=="object"?t:{},o=g??crypto.randomUUID(),v=!n&&!l,x=[],K=0,V=r=>r??`step_${++K}`,c=r=>{if(r.type==="step_success"){let h=r.stepId;for(let b=x.length-1;b>=0;b--){let w=x[b];if(w.type==="race"&&!w.winnerId){w.winnerId=h;break}}}s?.(r,k)},M=ne,H=r=>re(r),L=(r,h)=>v?h?.origin==="result"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:r,...h.resultCause!==void 0?{cause:h.resultCause}:{}}}:h?.origin==="throw"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"throw",error:r,thrown:h.thrown}}:{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:r}}:r,se=r=>r.origin==="result"?r.resultCause:r.thrown,ue=r=>({type:"UNEXPECTED_ERROR",cause:r.meta.origin==="result"?{type:"STEP_FAILURE",origin:"result",error:r.error,...r.meta.resultCause!==void 0?{cause:r.meta.resultCause}:{}}:{type:"STEP_FAILURE",origin:"throw",error:r.error,thrown:r.meta.thrown}});try{let r=(w,i)=>(async()=>{let m=fe(i),{name:u,key:a,retry:d,timeout:E}=m,p=V(a),f=s,R=f?performance.now():0;if(!(typeof w=="function")){if(d&&d.attempts>1)throw new Error("step: retry options require a function operation. Direct Promise/Result values cannot be re-executed on retry. Wrap your operation in a function: step(() => yourOperation, { retry: {...} })");if(E)throw new Error("step: timeout options require a function operation. Direct Promise/Result values cannot be wrapped with timeout after they've started. Wrap your operation in a function: step(() => yourOperation, { timeout: {...} })")}let S={attempts:Math.max(1,d?.attempts??1),backoff:d?.backoff??D.backoff,initialDelay:d?.initialDelay??D.initialDelay,maxDelay:d?.maxDelay??D.maxDelay,jitter:d?.jitter??D.jitter,retryOn:d?.retryOn??D.retryOn,onRetry:d?.onRetry??D.onRetry};s&&c({type:"step_start",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now()});let z;for(let C=1;C<=S.attempts;C++){let ie=f?performance.now():0;try{let y;if(typeof w=="function"?E?y=await Re(w,E,{name:u,key:a,attempt:C}):y=await w():y=await w,y.ok){let _=performance.now()-R;return c({type:"step_success",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),durationMs:_}),a&&c({type:"step_complete",workflowId:o,stepKey:a,name:u,ts:Date.now(),durationMs:_,result:y}),y.value}if(z=y,C<S.attempts&&S.retryOn(y.error,C)){let _=B(C,S);c({type:"step_retry",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),attempt:C+1,maxAttempts:S.attempts,delayMs:_,error:y.error}),S.onRetry(y.error,C,_),await q(_);continue}S.attempts>1&&c({type:"step_retries_exhausted",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),durationMs:performance.now()-R,attempts:C,lastError:y.error});break}catch(y){let _=performance.now()-ie;if(H(y))throw c({type:"step_aborted",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),durationMs:_}),y;if(J(y)){let P=te(y),W=E?.ms??P?.timeoutMs??0;if(c({type:"step_timeout",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),timeoutMs:W,attempt:C}),C<S.attempts&&S.retryOn(y,C)){let X=B(C,S);c({type:"step_retry",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),attempt:C+1,maxAttempts:S.attempts,delayMs:X,error:y}),S.onRetry(y,C,X),await q(X);continue}S.attempts>1&&c({type:"step_retries_exhausted",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),durationMs:performance.now()-R,attempts:C,lastError:y})}if(C<S.attempts&&S.retryOn(y,C)){let P=B(C,S);c({type:"step_retry",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),attempt:C+1,maxAttempts:S.attempts,delayMs:P,error:y}),S.onRetry(y,C,P),await q(P);continue}S.attempts>1&&!J(y)&&c({type:"step_retries_exhausted",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),durationMs:performance.now()-R,attempts:C,lastError:y});let F=performance.now()-R;if(l){let P;try{P=l(y)}catch(W){throw ke(W)}throw c({type:"step_error",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),durationMs:F,error:P}),a&&c({type:"step_complete",workflowId:o,stepKey:a,name:u,ts:Date.now(),durationMs:F,result:T(P,{cause:y}),meta:{origin:"throw",thrown:y}}),n?.(P,u),M(P,{origin:"throw",thrown:y})}else{let P={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:y}};throw c({type:"step_error",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),durationMs:F,error:P}),a&&c({type:"step_complete",workflowId:o,stepKey:a,name:u,ts:Date.now(),durationMs:F,result:T(P,{cause:y}),meta:{origin:"throw",thrown:y}}),y}}}let I=z,Q=performance.now()-R,ae=L(I.error,{origin:"result",resultCause:I.cause});throw c({type:"step_error",workflowId:o,stepId:p,stepKey:a,name:u,ts:Date.now(),durationMs:Q,error:ae}),a&&c({type:"step_complete",workflowId:o,stepKey:a,name:u,ts:Date.now(),durationMs:Q,result:I,meta:{origin:"result",resultCause:I.cause}}),n?.(I.error,u),M(I.error,{origin:"result",resultCause:I.cause})})();r.try=(w,i)=>{let m=i.name,u=i.key,a=V(u),d="error"in i?()=>i.error:i.onError,E=s;return(async()=>{let p=E?performance.now():0;s&&c({type:"step_start",workflowId:o,stepId:a,stepKey:u,name:m,ts:Date.now()});try{let f=await w(),R=performance.now()-p;return c({type:"step_success",workflowId:o,stepId:a,stepKey:u,name:m,ts:Date.now(),durationMs:R}),u&&c({type:"step_complete",workflowId:o,stepKey:u,name:m,ts:Date.now(),durationMs:R,result:A(f)}),f}catch(f){let R=d(f),U=performance.now()-p,j=L(R,{origin:"throw",thrown:f});throw c({type:"step_error",workflowId:o,stepId:a,stepKey:u,name:m,ts:Date.now(),durationMs:U,error:j}),u&&c({type:"step_complete",workflowId:o,stepKey:u,name:m,ts:Date.now(),durationMs:U,result:T(R,{cause:f}),meta:{origin:"throw",thrown:f}}),n?.(R,m),M(R,{origin:"throw",thrown:f})}})()},r.fromResult=(w,i)=>{let m=i.name,u=i.key,a=V(u),d="error"in i?()=>i.error:i.onError,E=s;return(async()=>{let p=E?performance.now():0;s&&c({type:"step_start",workflowId:o,stepId:a,stepKey:u,name:m,ts:Date.now()});let f=await w();if(f.ok){let R=performance.now()-p;return c({type:"step_success",workflowId:o,stepId:a,stepKey:u,name:m,ts:Date.now(),durationMs:R}),u&&c({type:"step_complete",workflowId:o,stepKey:u,name:m,ts:Date.now(),durationMs:R,result:A(f.value)}),f.value}else{let R=d(f.error),U=performance.now()-p,j=L(R,{origin:"result",resultCause:f.error});throw c({type:"step_error",workflowId:o,stepId:a,stepKey:u,name:m,ts:Date.now(),durationMs:U,error:j}),u&&c({type:"step_complete",workflowId:o,stepKey:u,name:m,ts:Date.now(),durationMs:U,result:T(R,{cause:f.error}),meta:{origin:"result",resultCause:f.error}}),n?.(R,m),M(R,{origin:"result",resultCause:f.error})}})()},r.retry=(w,i)=>r(w,{name:i.name,key:i.key,retry:{attempts:i.attempts,backoff:i.backoff,initialDelay:i.initialDelay,maxDelay:i.maxDelay,jitter:i.jitter,retryOn:i.retryOn,onRetry:i.onRetry},timeout:i.timeout}),r.withTimeout=(w,i)=>r(w,{name:i.name,key:i.key,timeout:i}),r.parallel=(w,i)=>{let m=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let u=performance.now(),a=!1;x.push({scopeId:m,type:"parallel"});let d=()=>{if(a)return;a=!0;let E=x.findIndex(p=>p.scopeId===m);E!==-1&&x.splice(E,1),c({type:"scope_end",workflowId:o,scopeId:m,ts:Date.now(),durationMs:performance.now()-u})};c({type:"scope_start",workflowId:o,scopeId:m,scopeType:"parallel",name:w,ts:Date.now()});try{let E=await i();if(d(),!E.ok)throw n?.(E.error,w),M(E.error,{origin:"result",resultCause:E.cause});return E.value}catch(E){throw d(),E}})()},r.race=(w,i)=>{let m=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let u=performance.now(),a=!1,d={scopeId:m,type:"race",winnerId:void 0};x.push(d);let E=()=>{if(a)return;a=!0;let p=x.findIndex(f=>f.scopeId===m);p!==-1&&x.splice(p,1),c({type:"scope_end",workflowId:o,scopeId:m,ts:Date.now(),durationMs:performance.now()-u,winnerId:d.winnerId})};c({type:"scope_start",workflowId:o,scopeId:m,scopeType:"race",name:w,ts:Date.now()});try{let p=await i();if(E(),!p.ok)throw n?.(p.error,w),M(p.error,{origin:"result",resultCause:p.cause});return p.value}catch(p){throw E(),p}})()},r.allSettled=(w,i)=>{let m=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let u=performance.now(),a=!1;x.push({scopeId:m,type:"allSettled"});let d=()=>{if(a)return;a=!0;let E=x.findIndex(p=>p.scopeId===m);E!==-1&&x.splice(E,1),c({type:"scope_end",workflowId:o,scopeId:m,ts:Date.now(),durationMs:performance.now()-u})};c({type:"scope_start",workflowId:o,scopeId:m,scopeType:"allSettled",name:w,ts:Date.now()});try{let E=await i();if(d(),!E.ok)throw n?.(E.error,w),M(E.error,{origin:"result",resultCause:E.cause});return E.value}catch(E){throw d(),E}})()};let b=await e(r);return A(b)}catch(r){if(de(r))throw r.thrown;if(H(r)){let b=se(r.meta);if(l||n)return T(r.error,{cause:b});if(ee(r.error))return T(r.error,{cause:b});let w=ue(r);return T(w,{cause:b})}if(l){let b=l(r);return n?.(b,"unexpected"),T(b,{cause:r})}let h={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:r}};return n?.(h,"unexpected"),T(h,{cause:r})}}$.strict=(e,t)=>$(e,t);var N=class extends Error{constructor(n,s){super(`Unwrap called on an error result: ${String(n)}`);this.error=n;this.cause=s;this.name="UnwrapError"}},Ce=e=>{if(e.ok)return e.value;throw new N(e.error,e.cause)},xe=(e,t)=>e.ok?e.value:t,Se=(e,t)=>e.ok?e.value:t(e.error,e.cause);function ge(e,t){try{return A(e())}catch(n){return t?T(t(n),{cause:n}):T(n)}}async function Ae(e,t){try{return A(await e)}catch(n){return t?T(t(n),{cause:n}):T(n)}}async function Pe(e,t){try{return A(await e())}catch(n){return t?T(t(n),{cause:n}):T(n)}}function be(e,t){return e!=null?A(e):T(t())}function he(e,t){return e.ok?A(t(e.value)):e}function ve(e,t){return e.ok?e:T(t(e.error),{cause:e.cause})}function _e(e,t){return e.ok?t.ok(e.value):t.err(e.error,e.cause)}function Me(e,t){return e.ok?t(e.value):e}function Ie(e,t){return e.ok&&t(e.value),e}function Oe(e,t){return e.ok||t(e.error,e.cause),e}function Ue(e,t,n){if(!e.ok)return e;try{return A(t(e.value))}catch(s){return T(n(s),{cause:s})}}function De(e,t,n){if(e.ok)return e;try{return T(t(e.error),{cause:e.cause})}catch(s){return T(n(s),{cause:s})}}function Ke(e){let t=[];for(let n of e){if(!n.ok)return n;t.push(n.value)}return A(t)}async function je(e){return e.length===0?A([]):new Promise(t=>{let n=!1,s=e.length,l=new Array(e.length);for(let g=0;g<e.length;g++){let k=g;Promise.resolve(e[k]).catch(o=>T({type:"PROMISE_REJECTED",cause:o},{cause:{type:"PROMISE_REJECTION",reason:o}})).then(o=>{if(!n){if(!o.ok){n=!0,t(o);return}l[k]=o.value,s--,s===0&&t(A(l))}})}})}function Fe(e){let t=[],n=[];for(let s of e)s.ok?t.push(s.value):n.push({error:s.error,cause:s.cause});return n.length>0?T(n):A(t)}function Ne(e){let t=[],n=[];for(let s of e)s.ok?t.push(s.value):n.push(s.error);return{values:t,errors:n}}function Ve(e){if(e.length===0)return T({type:"EMPTY_INPUT",message:"any() requires at least one Result"});let t=null;for(let n of e){if(n.ok)return n;t||(t=n)}return t}async function Le(e){return e.length===0?T({type:"EMPTY_INPUT",message:"anyAsync() requires at least one Result"}):new Promise(t=>{let n=!1,s=e.length,l=null;for(let g of e)Promise.resolve(g).catch(k=>T({type:"PROMISE_REJECTED",cause:k},{cause:{type:"PROMISE_REJECTION",reason:k}})).then(k=>{if(!n){if(k.ok){n=!0,t(k);return}l||(l=k),s--,s===0&&t(l)}})})}async function We(e){let t=await Promise.all(e.map(l=>Promise.resolve(l).then(g=>({status:"result",result:g})).catch(g=>({status:"rejected",error:{type:"PROMISE_REJECTED",cause:g},cause:{type:"PROMISE_REJECTION",reason:g}})))),n=[],s=[];for(let l of t)l.status==="rejected"?s.push({error:l.error,cause:l.cause}):l.result.ok?n.push(l.result.value):s.push({error:l.result.error,cause:l.result.cause});return s.length>0?T(s):A(n)}0&&(module.exports={EARLY_EXIT_SYMBOL,STEP_TIMEOUT_MARKER,UnwrapError,all,allAsync,allSettled,allSettledAsync,andThen,any,anyAsync,createEarlyExit,err,from,fromNullable,fromPromise,getStepTimeoutMeta,isEarlyExit,isErr,isOk,isStepTimeoutError,isUnexpectedError,map,mapError,mapErrorTry,mapTry,match,ok,partition,run,tap,tapError,tryAsync,unwrap,unwrapOr,unwrapOrElse});
2
2
  //# sourceMappingURL=core.cjs.map