@jagreehal/workflow 1.6.0 → 1.8.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.
@@ -183,15 +183,45 @@ type CausesOfDeps<Deps extends Record<string, AnyResultFn>> = CauseOf<Deps[keyof
183
183
  * Returns E | UnexpectedError (safe default)
184
184
  */
185
185
  type WorkflowOptions<E, C = void> = {
186
- onError?: (error: E | UnexpectedError, stepName?: string) => void;
187
- /** Unified event stream for workflow and step lifecycle */
188
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
186
+ onError?: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;
187
+ /**
188
+ * Unified event stream for workflow and step lifecycle.
189
+ *
190
+ * Context is automatically included in `event.context` when provided via `createContext`.
191
+ * The separate `ctx` parameter is provided for convenience.
192
+ */
193
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
189
194
  /** Create per-run context for event correlation */
190
195
  createContext?: () => C;
191
196
  /** Step result cache - only steps with a `key` option are cached */
192
197
  cache?: StepCache;
193
198
  /** Pre-populate cache from saved state for workflow resume */
194
199
  resumeState?: ResumeState | (() => ResumeState | Promise<ResumeState>);
200
+ /**
201
+ * Hook called before workflow execution starts.
202
+ * Return `false` to skip workflow execution (useful for distributed locking, queue checking).
203
+ * @param workflowId - Unique ID for this workflow run
204
+ * @param context - Context object from createContext (or void if not provided)
205
+ * @returns `true` to proceed, `false` to skip workflow execution
206
+ */
207
+ onBeforeStart?: (workflowId: string, context: C) => boolean | Promise<boolean>;
208
+ /**
209
+ * Hook called after each step completes (only for steps with a `key`).
210
+ * Useful for checkpointing to external systems (queues, streams, databases).
211
+ * @param stepKey - The key of the completed step
212
+ * @param result - The step's result (success or error)
213
+ * @param workflowId - Unique ID for this workflow run
214
+ * @param context - Context object from createContext (or void if not provided)
215
+ */
216
+ onAfterStep?: (stepKey: string, result: Result<unknown, unknown, unknown>, workflowId: string, context: C) => void | Promise<void>;
217
+ /**
218
+ * Hook to check if workflow should run (concurrency control).
219
+ * Called before onBeforeStart. Return `false` to skip workflow execution.
220
+ * @param workflowId - Unique ID for this workflow run
221
+ * @param context - Context object from createContext (or void if not provided)
222
+ * @returns `true` to proceed, `false` to skip workflow execution
223
+ */
224
+ shouldRun?: (workflowId: string, context: C) => boolean | Promise<boolean>;
195
225
  catchUnexpected?: never;
196
226
  strict?: false;
197
227
  };
@@ -202,15 +232,65 @@ type WorkflowOptions<E, C = void> = {
202
232
  type WorkflowOptionsStrict<E, U, C = void> = {
203
233
  strict: true;
204
234
  catchUnexpected: (cause: unknown) => U;
205
- onError?: (error: E | U, stepName?: string) => void;
206
- /** Unified event stream for workflow and step lifecycle */
207
- onEvent?: (event: WorkflowEvent<E | U>, ctx: C) => void;
235
+ onError?: (error: E | U, stepName?: string, ctx?: C) => void;
236
+ /**
237
+ * Unified event stream for workflow and step lifecycle.
238
+ *
239
+ * Context is automatically included in `event.context` when provided via `createContext`.
240
+ * The separate `ctx` parameter is provided for convenience.
241
+ */
242
+ onEvent?: (event: WorkflowEvent<E | U, C>, ctx: C) => void;
208
243
  /** Create per-run context for event correlation */
209
244
  createContext?: () => C;
210
245
  /** Step result cache - only steps with a `key` option are cached */
211
246
  cache?: StepCache;
212
247
  /** Pre-populate cache from saved state for workflow resume */
213
248
  resumeState?: ResumeState | (() => ResumeState | Promise<ResumeState>);
249
+ /**
250
+ * Hook called before workflow execution starts.
251
+ * Return `false` to skip workflow execution (useful for distributed locking, queue checking).
252
+ * @param workflowId - Unique ID for this workflow run
253
+ * @param context - Context object from createContext (or void if not provided)
254
+ * @returns `true` to proceed, `false` to skip workflow execution
255
+ */
256
+ onBeforeStart?: (workflowId: string, context: C) => boolean | Promise<boolean>;
257
+ /**
258
+ * Hook called after each step completes (only for steps with a `key`).
259
+ * Useful for checkpointing to external systems (queues, streams, databases).
260
+ * @param stepKey - The key of the completed step
261
+ * @param result - The step's result (success or error)
262
+ * @param workflowId - Unique ID for this workflow run
263
+ * @param context - Context object from createContext (or void if not provided)
264
+ */
265
+ onAfterStep?: (stepKey: string, result: Result<unknown, unknown, unknown>, workflowId: string, context: C) => void | Promise<void>;
266
+ /**
267
+ * Hook to check if workflow should run (concurrency control).
268
+ * Called before onBeforeStart. Return `false` to skip workflow execution.
269
+ * @param workflowId - Unique ID for this workflow run
270
+ * @param context - Context object from createContext (or void if not provided)
271
+ * @returns `true` to proceed, `false` to skip workflow execution
272
+ */
273
+ shouldRun?: (workflowId: string, context: C) => boolean | Promise<boolean>;
274
+ };
275
+ /**
276
+ * Workflow context provided to callbacks, containing workflow metadata.
277
+ * This allows conditional helpers and other utilities to access workflowId, onEvent, and context.
278
+ */
279
+ type WorkflowContext<C = void> = {
280
+ /**
281
+ * Unique ID for this workflow run.
282
+ */
283
+ workflowId: string;
284
+ /**
285
+ * Event emitter function for workflow events.
286
+ * Can be used with conditional helpers to emit step_skipped events.
287
+ */
288
+ onEvent?: (event: WorkflowEvent<unknown, C>) => void;
289
+ /**
290
+ * Per-run context created by createContext (or undefined if not provided).
291
+ * Automatically included in all workflow events.
292
+ */
293
+ context?: C;
214
294
  };
215
295
  /**
216
296
  * Workflow return type (non-strict)
@@ -222,17 +302,18 @@ type WorkflowOptionsStrict<E, U, C = void> = {
222
302
  * - Different steps may have different cause types
223
303
  * The cause IS preserved at runtime; narrow based on error type if needed.
224
304
  */
225
- interface Workflow<E, Deps> {
305
+ interface Workflow<E, Deps, C = void> {
226
306
  /**
227
307
  * Execute workflow without arguments (original API)
308
+ * @param fn - Callback receives (step, deps, ctx) where ctx is workflow context (always provided)
228
309
  */
229
- <T>(fn: (step: RunStep<E>, deps: Deps) => T | Promise<T>): AsyncResult<T, E | UnexpectedError, unknown>;
310
+ <T>(fn: (step: RunStep<E>, deps: Deps, ctx: WorkflowContext<C>) => T | Promise<T>): AsyncResult<T, E | UnexpectedError, unknown>;
230
311
  /**
231
312
  * Execute workflow with typed arguments
232
313
  * @param args - Typed arguments passed to the callback (type inferred at call site)
233
- * @param fn - Callback receives (step, deps, args)
314
+ * @param fn - Callback receives (step, deps, args, ctx) where ctx is workflow context (always provided)
234
315
  */
235
- <T, Args>(args: Args, fn: (step: RunStep<E>, deps: Deps, args: Args) => T | Promise<T>): AsyncResult<T, E | UnexpectedError, unknown>;
316
+ <T, Args>(args: Args, fn: (step: RunStep<E>, deps: Deps, args: Args, ctx: WorkflowContext<C>) => T | Promise<T>): AsyncResult<T, E | UnexpectedError, unknown>;
236
317
  }
237
318
  /**
238
319
  * Workflow return type (strict)
@@ -241,17 +322,18 @@ interface Workflow<E, Deps> {
241
322
  * Note: Cause type is `unknown` because catchUnexpected receives thrown
242
323
  * values which have unknown type.
243
324
  */
244
- interface WorkflowStrict<E, U, Deps> {
325
+ interface WorkflowStrict<E, U, Deps, C = void> {
245
326
  /**
246
327
  * Execute workflow without arguments (original API)
328
+ * @param fn - Callback receives (step, deps, ctx) where ctx is workflow context (always provided)
247
329
  */
248
- <T>(fn: (step: RunStep<E>, deps: Deps) => T | Promise<T>): AsyncResult<T, E | U, unknown>;
330
+ <T>(fn: (step: RunStep<E>, deps: Deps, ctx: WorkflowContext<C>) => T | Promise<T>): AsyncResult<T, E | U, unknown>;
249
331
  /**
250
332
  * Execute workflow with typed arguments
251
333
  * @param args - Typed arguments passed to the callback (type inferred at call site)
252
- * @param fn - Callback receives (step, deps, args)
334
+ * @param fn - Callback receives (step, deps, args, ctx) where ctx is workflow context (always provided)
253
335
  */
254
- <T, Args>(args: Args, fn: (step: RunStep<E>, deps: Deps, args: Args) => T | Promise<T>): AsyncResult<T, E | U, unknown>;
336
+ <T, Args>(args: Args, fn: (step: RunStep<E>, deps: Deps, args: Args, ctx: WorkflowContext<C>) => T | Promise<T>): AsyncResult<T, E | U, unknown>;
255
337
  }
256
338
  /**
257
339
  * Create a typed workflow with automatic error inference.
@@ -774,4 +856,4 @@ declare function createHITLCollector(): {
774
856
  injectApproval: <T>(stepKey: string, value: T) => ResumeState;
775
857
  };
776
858
 
777
- export { type AnyResultFn, type ApprovalRejected, type ApprovalStepOptions, AsyncResult, type CausesOfDeps, type ErrorsOfDeps, type PendingApproval, Result, type ResumeState, type ResumeStateEntry, RunStep, type StepCache, UnexpectedError, type Workflow, WorkflowEvent, type WorkflowOptions, type WorkflowOptionsStrict, type WorkflowStrict, clearStep, createApprovalStep, createHITLCollector, createStepCollector, createWorkflow, getPendingApprovals, hasPendingApproval, injectApproval, isApprovalRejected, isPendingApproval, isStepComplete, pendingApproval };
859
+ export { type AnyResultFn, type ApprovalRejected, type ApprovalStepOptions, AsyncResult, type CausesOfDeps, type ErrorsOfDeps, type PendingApproval, Result, type ResumeState, type ResumeStateEntry, RunStep, type StepCache, UnexpectedError, type Workflow, type WorkflowContext, WorkflowEvent, type WorkflowOptions, type WorkflowOptionsStrict, type WorkflowStrict, clearStep, createApprovalStep, createHITLCollector, createStepCollector, createWorkflow, getPendingApprovals, hasPendingApproval, injectApproval, isApprovalRejected, isPendingApproval, isStepComplete, pendingApproval };
@@ -183,15 +183,45 @@ type CausesOfDeps<Deps extends Record<string, AnyResultFn>> = CauseOf<Deps[keyof
183
183
  * Returns E | UnexpectedError (safe default)
184
184
  */
185
185
  type WorkflowOptions<E, C = void> = {
186
- onError?: (error: E | UnexpectedError, stepName?: string) => void;
187
- /** Unified event stream for workflow and step lifecycle */
188
- onEvent?: (event: WorkflowEvent<E | UnexpectedError>, ctx: C) => void;
186
+ onError?: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;
187
+ /**
188
+ * Unified event stream for workflow and step lifecycle.
189
+ *
190
+ * Context is automatically included in `event.context` when provided via `createContext`.
191
+ * The separate `ctx` parameter is provided for convenience.
192
+ */
193
+ onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;
189
194
  /** Create per-run context for event correlation */
190
195
  createContext?: () => C;
191
196
  /** Step result cache - only steps with a `key` option are cached */
192
197
  cache?: StepCache;
193
198
  /** Pre-populate cache from saved state for workflow resume */
194
199
  resumeState?: ResumeState | (() => ResumeState | Promise<ResumeState>);
200
+ /**
201
+ * Hook called before workflow execution starts.
202
+ * Return `false` to skip workflow execution (useful for distributed locking, queue checking).
203
+ * @param workflowId - Unique ID for this workflow run
204
+ * @param context - Context object from createContext (or void if not provided)
205
+ * @returns `true` to proceed, `false` to skip workflow execution
206
+ */
207
+ onBeforeStart?: (workflowId: string, context: C) => boolean | Promise<boolean>;
208
+ /**
209
+ * Hook called after each step completes (only for steps with a `key`).
210
+ * Useful for checkpointing to external systems (queues, streams, databases).
211
+ * @param stepKey - The key of the completed step
212
+ * @param result - The step's result (success or error)
213
+ * @param workflowId - Unique ID for this workflow run
214
+ * @param context - Context object from createContext (or void if not provided)
215
+ */
216
+ onAfterStep?: (stepKey: string, result: Result<unknown, unknown, unknown>, workflowId: string, context: C) => void | Promise<void>;
217
+ /**
218
+ * Hook to check if workflow should run (concurrency control).
219
+ * Called before onBeforeStart. Return `false` to skip workflow execution.
220
+ * @param workflowId - Unique ID for this workflow run
221
+ * @param context - Context object from createContext (or void if not provided)
222
+ * @returns `true` to proceed, `false` to skip workflow execution
223
+ */
224
+ shouldRun?: (workflowId: string, context: C) => boolean | Promise<boolean>;
195
225
  catchUnexpected?: never;
196
226
  strict?: false;
197
227
  };
@@ -202,15 +232,65 @@ type WorkflowOptions<E, C = void> = {
202
232
  type WorkflowOptionsStrict<E, U, C = void> = {
203
233
  strict: true;
204
234
  catchUnexpected: (cause: unknown) => U;
205
- onError?: (error: E | U, stepName?: string) => void;
206
- /** Unified event stream for workflow and step lifecycle */
207
- onEvent?: (event: WorkflowEvent<E | U>, ctx: C) => void;
235
+ onError?: (error: E | U, stepName?: string, ctx?: C) => void;
236
+ /**
237
+ * Unified event stream for workflow and step lifecycle.
238
+ *
239
+ * Context is automatically included in `event.context` when provided via `createContext`.
240
+ * The separate `ctx` parameter is provided for convenience.
241
+ */
242
+ onEvent?: (event: WorkflowEvent<E | U, C>, ctx: C) => void;
208
243
  /** Create per-run context for event correlation */
209
244
  createContext?: () => C;
210
245
  /** Step result cache - only steps with a `key` option are cached */
211
246
  cache?: StepCache;
212
247
  /** Pre-populate cache from saved state for workflow resume */
213
248
  resumeState?: ResumeState | (() => ResumeState | Promise<ResumeState>);
249
+ /**
250
+ * Hook called before workflow execution starts.
251
+ * Return `false` to skip workflow execution (useful for distributed locking, queue checking).
252
+ * @param workflowId - Unique ID for this workflow run
253
+ * @param context - Context object from createContext (or void if not provided)
254
+ * @returns `true` to proceed, `false` to skip workflow execution
255
+ */
256
+ onBeforeStart?: (workflowId: string, context: C) => boolean | Promise<boolean>;
257
+ /**
258
+ * Hook called after each step completes (only for steps with a `key`).
259
+ * Useful for checkpointing to external systems (queues, streams, databases).
260
+ * @param stepKey - The key of the completed step
261
+ * @param result - The step's result (success or error)
262
+ * @param workflowId - Unique ID for this workflow run
263
+ * @param context - Context object from createContext (or void if not provided)
264
+ */
265
+ onAfterStep?: (stepKey: string, result: Result<unknown, unknown, unknown>, workflowId: string, context: C) => void | Promise<void>;
266
+ /**
267
+ * Hook to check if workflow should run (concurrency control).
268
+ * Called before onBeforeStart. Return `false` to skip workflow execution.
269
+ * @param workflowId - Unique ID for this workflow run
270
+ * @param context - Context object from createContext (or void if not provided)
271
+ * @returns `true` to proceed, `false` to skip workflow execution
272
+ */
273
+ shouldRun?: (workflowId: string, context: C) => boolean | Promise<boolean>;
274
+ };
275
+ /**
276
+ * Workflow context provided to callbacks, containing workflow metadata.
277
+ * This allows conditional helpers and other utilities to access workflowId, onEvent, and context.
278
+ */
279
+ type WorkflowContext<C = void> = {
280
+ /**
281
+ * Unique ID for this workflow run.
282
+ */
283
+ workflowId: string;
284
+ /**
285
+ * Event emitter function for workflow events.
286
+ * Can be used with conditional helpers to emit step_skipped events.
287
+ */
288
+ onEvent?: (event: WorkflowEvent<unknown, C>) => void;
289
+ /**
290
+ * Per-run context created by createContext (or undefined if not provided).
291
+ * Automatically included in all workflow events.
292
+ */
293
+ context?: C;
214
294
  };
215
295
  /**
216
296
  * Workflow return type (non-strict)
@@ -222,17 +302,18 @@ type WorkflowOptionsStrict<E, U, C = void> = {
222
302
  * - Different steps may have different cause types
223
303
  * The cause IS preserved at runtime; narrow based on error type if needed.
224
304
  */
225
- interface Workflow<E, Deps> {
305
+ interface Workflow<E, Deps, C = void> {
226
306
  /**
227
307
  * Execute workflow without arguments (original API)
308
+ * @param fn - Callback receives (step, deps, ctx) where ctx is workflow context (always provided)
228
309
  */
229
- <T>(fn: (step: RunStep<E>, deps: Deps) => T | Promise<T>): AsyncResult<T, E | UnexpectedError, unknown>;
310
+ <T>(fn: (step: RunStep<E>, deps: Deps, ctx: WorkflowContext<C>) => T | Promise<T>): AsyncResult<T, E | UnexpectedError, unknown>;
230
311
  /**
231
312
  * Execute workflow with typed arguments
232
313
  * @param args - Typed arguments passed to the callback (type inferred at call site)
233
- * @param fn - Callback receives (step, deps, args)
314
+ * @param fn - Callback receives (step, deps, args, ctx) where ctx is workflow context (always provided)
234
315
  */
235
- <T, Args>(args: Args, fn: (step: RunStep<E>, deps: Deps, args: Args) => T | Promise<T>): AsyncResult<T, E | UnexpectedError, unknown>;
316
+ <T, Args>(args: Args, fn: (step: RunStep<E>, deps: Deps, args: Args, ctx: WorkflowContext<C>) => T | Promise<T>): AsyncResult<T, E | UnexpectedError, unknown>;
236
317
  }
237
318
  /**
238
319
  * Workflow return type (strict)
@@ -241,17 +322,18 @@ interface Workflow<E, Deps> {
241
322
  * Note: Cause type is `unknown` because catchUnexpected receives thrown
242
323
  * values which have unknown type.
243
324
  */
244
- interface WorkflowStrict<E, U, Deps> {
325
+ interface WorkflowStrict<E, U, Deps, C = void> {
245
326
  /**
246
327
  * Execute workflow without arguments (original API)
328
+ * @param fn - Callback receives (step, deps, ctx) where ctx is workflow context (always provided)
247
329
  */
248
- <T>(fn: (step: RunStep<E>, deps: Deps) => T | Promise<T>): AsyncResult<T, E | U, unknown>;
330
+ <T>(fn: (step: RunStep<E>, deps: Deps, ctx: WorkflowContext<C>) => T | Promise<T>): AsyncResult<T, E | U, unknown>;
249
331
  /**
250
332
  * Execute workflow with typed arguments
251
333
  * @param args - Typed arguments passed to the callback (type inferred at call site)
252
- * @param fn - Callback receives (step, deps, args)
334
+ * @param fn - Callback receives (step, deps, args, ctx) where ctx is workflow context (always provided)
253
335
  */
254
- <T, Args>(args: Args, fn: (step: RunStep<E>, deps: Deps, args: Args) => T | Promise<T>): AsyncResult<T, E | U, unknown>;
336
+ <T, Args>(args: Args, fn: (step: RunStep<E>, deps: Deps, args: Args, ctx: WorkflowContext<C>) => T | Promise<T>): AsyncResult<T, E | U, unknown>;
255
337
  }
256
338
  /**
257
339
  * Create a typed workflow with automatic error inference.
@@ -774,4 +856,4 @@ declare function createHITLCollector(): {
774
856
  injectApproval: <T>(stepKey: string, value: T) => ResumeState;
775
857
  };
776
858
 
777
- export { type AnyResultFn, type ApprovalRejected, type ApprovalStepOptions, AsyncResult, type CausesOfDeps, type ErrorsOfDeps, type PendingApproval, Result, type ResumeState, type ResumeStateEntry, RunStep, type StepCache, UnexpectedError, type Workflow, WorkflowEvent, type WorkflowOptions, type WorkflowOptionsStrict, type WorkflowStrict, clearStep, createApprovalStep, createHITLCollector, createStepCollector, createWorkflow, getPendingApprovals, hasPendingApproval, injectApproval, isApprovalRejected, isPendingApproval, isStepComplete, pendingApproval };
859
+ export { type AnyResultFn, type ApprovalRejected, type ApprovalStepOptions, AsyncResult, type CausesOfDeps, type ErrorsOfDeps, type PendingApproval, Result, type ResumeState, type ResumeStateEntry, RunStep, type StepCache, UnexpectedError, type Workflow, type WorkflowContext, WorkflowEvent, type WorkflowOptions, type WorkflowOptionsStrict, type WorkflowStrict, clearStep, createApprovalStep, createHITLCollector, createStepCollector, createWorkflow, getPendingApprovals, hasPendingApproval, injectApproval, isApprovalRejected, isPendingApproval, isStepComplete, pendingApproval };
package/dist/workflow.js CHANGED
@@ -1,2 +1,2 @@
1
- var O=e=>({ok:!0,value:e}),h=(e,n)=>({ok:!1,error:e,...n?.cause!==void 0?{cause:n.cause}:{}});var ie=e=>typeof e=="object"&&e!==null&&e.type==="UNEXPECTED_ERROR",j=Symbol.for("step_timeout_marker");function ne(e){return typeof e!="object"||e===null?!1:e.type==="STEP_TIMEOUT"?!0:j in e}function ce(e){if(!(typeof e!="object"||e===null)){if(e.type==="STEP_TIMEOUT"){let n=e;return{timeoutMs:n.timeoutMs,stepName:n.stepName,stepKey:n.stepKey,attempt:n.attempt}}if(j in e)return e[j]}}var se=Symbol("early-exit");function V(e,n){return{[se]:!0,error:e,meta:n}}function L(e){return typeof e=="object"&&e!==null&&e[se]===!0}var oe=Symbol("mapper-exception");function le(e){return{[oe]:!0,thrown:e}}function Ee(e){return typeof e=="object"&&e!==null&&e[oe]===!0}function ye(e){return typeof e=="string"?{name:e}:e??{}}function z(e,n){let{backoff:E,initialDelay:d,maxDelay:_,jitter:b}=n,g;switch(E){case"fixed":g=d;break;case"linear":g=d*e;break;case"exponential":g=d*Math.pow(2,e-1);break}if(g=Math.min(g,_),b){let c=g*.25*Math.random();g=g+c}return Math.floor(g)}function Q(e){return new Promise(n=>setTimeout(n,e))}var re=Symbol("timeout");async function me(e,n,E){let d=new AbortController,_=n.error??{type:"STEP_TIMEOUT",stepName:E.name,stepKey:E.key,timeoutMs:n.ms,attempt:E.attempt},b,g=new Promise((S,T)=>{b=setTimeout(()=>{d.abort(),T({[re]:!0,error:_})},n.ms)}),c;n.signal?c=Promise.resolve(e(d.signal)):c=Promise.resolve(e());try{return await Promise.race([c,g])}catch(S){if(typeof S=="object"&&S!==null&&S[re]===!0){let T=S.error;if(typeof T=="object"&&T!==null&&T.type!=="STEP_TIMEOUT"){let A={timeoutMs:n.ms,stepName:E.name,stepKey:E.key,attempt:E.attempt};j in T?T[j]=A:Object.defineProperty(T,j,{value:A,enumerable:!1,writable:!0,configurable:!1})}throw T}throw S}finally{clearTimeout(b)}}var K={backoff:"exponential",initialDelay:100,maxDelay:3e4,jitter:!0,retryOn:()=>!0,onRetry:()=>{}};async function W(e,n){let{onError:E,onEvent:d,catchUnexpected:_,workflowId:b,context:g}=n&&typeof n=="object"?n:{},c=b??crypto.randomUUID(),S=!E&&!_,T=[],A=0,F=u=>u??`step_${++A}`,m=u=>{if(u.type==="step_success"){let v=u.stepId;for(let y=T.length-1;y>=0;y--){let l=T[y];if(l.type==="race"&&!l.winnerId){l.winnerId=v;break}}}d?.(u,g)},D=V,C=u=>L(u),N=(u,v)=>S?v?.origin==="result"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:u,...v.resultCause!==void 0?{cause:v.resultCause}:{}}}:v?.origin==="throw"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"throw",error:u,thrown:v.thrown}}:{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:u}}:u,X=u=>u.origin==="result"?u.resultCause:u.thrown,G=u=>({type:"UNEXPECTED_ERROR",cause:u.meta.origin==="result"?{type:"STEP_FAILURE",origin:"result",error:u.error,...u.meta.resultCause!==void 0?{cause:u.meta.resultCause}:{}}:{type:"STEP_FAILURE",origin:"throw",error:u.error,thrown:u.meta.thrown}});try{let u=(l,a)=>(async()=>{let s=ye(a),{name:o,key:t,retry:p,timeout:r}=s,i=F(t),f=d,k=f?performance.now():0;if(!(typeof l=="function")){if(p&&p.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(r)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 x={attempts:Math.max(1,p?.attempts??1),backoff:p?.backoff??K.backoff,initialDelay:p?.initialDelay??K.initialDelay,maxDelay:p?.maxDelay??K.maxDelay,jitter:p?.jitter??K.jitter,retryOn:p?.retryOn??K.retryOn,onRetry:p?.onRetry??K.onRetry};d&&m({type:"step_start",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now()});let ee;for(let R=1;R<=x.attempts;R++){let pe=f?performance.now():0;try{let w;if(typeof l=="function"?r?w=await me(l,r,{name:o,key:t,attempt:R}):w=await l():w=await l,w.ok){let M=performance.now()-k;return m({type:"step_success",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),durationMs:M}),t&&m({type:"step_complete",workflowId:c,stepKey:t,name:o,ts:Date.now(),durationMs:M,result:w}),w.value}if(ee=w,R<x.attempts&&x.retryOn(w.error,R)){let M=z(R,x);m({type:"step_retry",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),attempt:R+1,maxAttempts:x.attempts,delayMs:M,error:w.error}),x.onRetry(w.error,R,M),await Q(M);continue}x.attempts>1&&m({type:"step_retries_exhausted",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),durationMs:performance.now()-k,attempts:R,lastError:w.error});break}catch(w){let M=performance.now()-pe;if(C(w))throw m({type:"step_aborted",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),durationMs:M}),w;if(ne(w)){let P=ce(w),$=r?.ms??P?.timeoutMs??0;if(m({type:"step_timeout",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),timeoutMs:$,attempt:R}),R<x.attempts&&x.retryOn(w,R)){let H=z(R,x);m({type:"step_retry",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),attempt:R+1,maxAttempts:x.attempts,delayMs:H,error:w}),x.onRetry(w,R,H),await Q(H);continue}x.attempts>1&&m({type:"step_retries_exhausted",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),durationMs:performance.now()-k,attempts:R,lastError:w})}if(R<x.attempts&&x.retryOn(w,R)){let P=z(R,x);m({type:"step_retry",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),attempt:R+1,maxAttempts:x.attempts,delayMs:P,error:w}),x.onRetry(w,R,P),await Q(P);continue}x.attempts>1&&!ne(w)&&m({type:"step_retries_exhausted",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),durationMs:performance.now()-k,attempts:R,lastError:w});let Y=performance.now()-k;if(_){let P;try{P=_(w)}catch($){throw le($)}throw m({type:"step_error",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),durationMs:Y,error:P}),t&&m({type:"step_complete",workflowId:c,stepKey:t,name:o,ts:Date.now(),durationMs:Y,result:h(P,{cause:w}),meta:{origin:"throw",thrown:w}}),E?.(P,o),D(P,{origin:"throw",thrown:w})}else{let P={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:w}};throw m({type:"step_error",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),durationMs:Y,error:P}),t&&m({type:"step_complete",workflowId:c,stepKey:t,name:o,ts:Date.now(),durationMs:Y,result:h(P,{cause:w}),meta:{origin:"throw",thrown:w}}),w}}}let U=ee,te=performance.now()-k,ae=N(U.error,{origin:"result",resultCause:U.cause});throw m({type:"step_error",workflowId:c,stepId:i,stepKey:t,name:o,ts:Date.now(),durationMs:te,error:ae}),t&&m({type:"step_complete",workflowId:c,stepKey:t,name:o,ts:Date.now(),durationMs:te,result:U,meta:{origin:"result",resultCause:U.cause}}),E?.(U.error,o),D(U.error,{origin:"result",resultCause:U.cause})})();u.try=(l,a)=>{let s=a.name,o=a.key,t=F(o),p="error"in a?()=>a.error:a.onError,r=d;return(async()=>{let i=r?performance.now():0;d&&m({type:"step_start",workflowId:c,stepId:t,stepKey:o,name:s,ts:Date.now()});try{let f=await l(),k=performance.now()-i;return m({type:"step_success",workflowId:c,stepId:t,stepKey:o,name:s,ts:Date.now(),durationMs:k}),o&&m({type:"step_complete",workflowId:c,stepKey:o,name:s,ts:Date.now(),durationMs:k,result:O(f)}),f}catch(f){let k=p(f),I=performance.now()-i,J=N(k,{origin:"throw",thrown:f});throw m({type:"step_error",workflowId:c,stepId:t,stepKey:o,name:s,ts:Date.now(),durationMs:I,error:J}),o&&m({type:"step_complete",workflowId:c,stepKey:o,name:s,ts:Date.now(),durationMs:I,result:h(k,{cause:f}),meta:{origin:"throw",thrown:f}}),E?.(k,s),D(k,{origin:"throw",thrown:f})}})()},u.fromResult=(l,a)=>{let s=a.name,o=a.key,t=F(o),p="error"in a?()=>a.error:a.onError,r=d;return(async()=>{let i=r?performance.now():0;d&&m({type:"step_start",workflowId:c,stepId:t,stepKey:o,name:s,ts:Date.now()});let f=await l();if(f.ok){let k=performance.now()-i;return m({type:"step_success",workflowId:c,stepId:t,stepKey:o,name:s,ts:Date.now(),durationMs:k}),o&&m({type:"step_complete",workflowId:c,stepKey:o,name:s,ts:Date.now(),durationMs:k,result:O(f.value)}),f.value}else{let k=p(f.error),I=performance.now()-i,J=N(k,{origin:"result",resultCause:f.error});throw m({type:"step_error",workflowId:c,stepId:t,stepKey:o,name:s,ts:Date.now(),durationMs:I,error:J}),o&&m({type:"step_complete",workflowId:c,stepKey:o,name:s,ts:Date.now(),durationMs:I,result:h(k,{cause:f.error}),meta:{origin:"result",resultCause:f.error}}),E?.(k,s),D(k,{origin:"result",resultCause:f.error})}})()},u.retry=(l,a)=>u(l,{name:a.name,key:a.key,retry:{attempts:a.attempts,backoff:a.backoff,initialDelay:a.initialDelay,maxDelay:a.maxDelay,jitter:a.jitter,retryOn:a.retryOn,onRetry:a.onRetry},timeout:a.timeout}),u.withTimeout=(l,a)=>u(l,{name:a.name,key:a.key,timeout:a}),u.parallel=(l,a)=>{let s=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let o=performance.now(),t=!1;T.push({scopeId:s,type:"parallel"});let p=()=>{if(t)return;t=!0;let r=T.findIndex(i=>i.scopeId===s);r!==-1&&T.splice(r,1),m({type:"scope_end",workflowId:c,scopeId:s,ts:Date.now(),durationMs:performance.now()-o})};m({type:"scope_start",workflowId:c,scopeId:s,scopeType:"parallel",name:l,ts:Date.now()});try{let r=await a();if(p(),!r.ok)throw E?.(r.error,l),D(r.error,{origin:"result",resultCause:r.cause});return r.value}catch(r){throw p(),r}})()},u.race=(l,a)=>{let s=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let o=performance.now(),t=!1,p={scopeId:s,type:"race",winnerId:void 0};T.push(p);let r=()=>{if(t)return;t=!0;let i=T.findIndex(f=>f.scopeId===s);i!==-1&&T.splice(i,1),m({type:"scope_end",workflowId:c,scopeId:s,ts:Date.now(),durationMs:performance.now()-o,winnerId:p.winnerId})};m({type:"scope_start",workflowId:c,scopeId:s,scopeType:"race",name:l,ts:Date.now()});try{let i=await a();if(r(),!i.ok)throw E?.(i.error,l),D(i.error,{origin:"result",resultCause:i.cause});return i.value}catch(i){throw r(),i}})()},u.allSettled=(l,a)=>{let s=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let o=performance.now(),t=!1;T.push({scopeId:s,type:"allSettled"});let p=()=>{if(t)return;t=!0;let r=T.findIndex(i=>i.scopeId===s);r!==-1&&T.splice(r,1),m({type:"scope_end",workflowId:c,scopeId:s,ts:Date.now(),durationMs:performance.now()-o})};m({type:"scope_start",workflowId:c,scopeId:s,scopeType:"allSettled",name:l,ts:Date.now()});try{let r=await a();if(p(),!r.ok)throw E?.(r.error,l),D(r.error,{origin:"result",resultCause:r.cause});return r.value}catch(r){throw p(),r}})()};let y=await e(u);return O(y)}catch(u){if(Ee(u))throw u.thrown;if(C(u)){let y=X(u.meta);if(_||E)return h(u.error,{cause:y});if(ie(u.error))return h(u.error,{cause:y});let l=G(u);return h(l,{cause:y})}if(_){let y=_(u);return E?.(y,"unexpected"),h(y,{cause:u})}let v={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:u}};return E?.(v,"unexpected"),h(v,{cause:u})}}W.strict=(e,n)=>W(e,n);function fe(){let e=new Map;return{handleEvent:n=>{ue(n)&&e.set(n.stepKey,{result:n.result,meta:n.meta})},getState:()=>({steps:new Map(e)}),clear:()=>e.clear()}}function we(e){return typeof e=="object"&&e!==null&&e.__cachedMeta===!0}function B(e,n,E){return h(e,{cause:{__cachedMeta:!0,originalCause:E,meta:n}})}function Z(e){return we(e)?e.meta:{origin:"result",resultCause:e}}function ke(e,n){async function E(d,_){let b=typeof _=="function",g=b?d:void 0,c=b?_:d,S=crypto.randomUUID(),T=n?.createContext?.(),A=y=>{n?.onEvent?.(y,T)},F=Date.now(),m=performance.now();A({type:"workflow_start",workflowId:S,ts:F});let D=n?.resumeState,C=n?.cache;if(D&&!C&&(C=new Map),D&&C){let y=typeof D=="function"?await D():D;for(let[l,a]of y.steps){let{result:s,meta:o}=a;if(s.ok)C.set(l,s);else{let t=o??{origin:"result",resultCause:s.cause};C.set(l,B(s.error,t,s.cause))}}}let N=y=>typeof y=="string"?{name:y}:y??{},X=y=>{if(!C)return y;let l=async(a,s)=>{let{name:o,key:t}=N(s);if(t&&C.has(t)){A({type:"step_cache_hit",workflowId:S,stepKey:t,name:o,ts:Date.now()});let r=C.get(t);if(r.ok)return r.value;let i=Z(r.cause);throw V(r.error,i)}t&&A({type:"step_cache_miss",workflowId:S,stepKey:t,name:o,ts:Date.now()});let p=typeof a=="function"?a:()=>a;try{let r=await y(p,s);return t&&C.set(t,O(r)),r}catch(r){if(t&&L(r)){let i=r,f=i.meta.origin==="result"?i.meta.resultCause:i.meta.thrown;C.set(t,B(i.error,i.meta,f))}throw r}};return l.try=async(a,s)=>{let{name:o,key:t}=s;if(t&&C.has(t)){A({type:"step_cache_hit",workflowId:S,stepKey:t,name:o,ts:Date.now()});let p=C.get(t);if(p.ok)return p.value;let r=Z(p.cause);throw V(p.error,r)}t&&A({type:"step_cache_miss",workflowId:S,stepKey:t,name:o,ts:Date.now()});try{let p=await y.try(a,s);return t&&C.set(t,O(p)),p}catch(p){if(t&&L(p)){let r=p,i=r.meta.origin==="result"?r.meta.resultCause:r.meta.thrown;C.set(t,B(r.error,r.meta,i))}throw p}},l.fromResult=async(a,s)=>{let{name:o,key:t}=s;if(t&&C.has(t)){A({type:"step_cache_hit",workflowId:S,stepKey:t,name:o,ts:Date.now()});let p=C.get(t);if(p.ok)return p.value;let r=Z(p.cause);throw V(p.error,r)}t&&A({type:"step_cache_miss",workflowId:S,stepKey:t,name:o,ts:Date.now()});try{let p=await y.fromResult(a,s);return t&&C.set(t,O(p)),p}catch(p){if(t&&L(p)){let r=p,i=r.meta.origin==="result"?r.meta.resultCause:r.meta.thrown;C.set(t,B(r.error,r.meta,i))}throw p}},l.parallel=y.parallel,l.race=y.race,l.allSettled=y.allSettled,l.retry=(a,s)=>l(a,{name:s.name,key:s.key,retry:{attempts:s.attempts,backoff:s.backoff,initialDelay:s.initialDelay,maxDelay:s.maxDelay,jitter:s.jitter,retryOn:s.retryOn,onRetry:s.onRetry},timeout:s.timeout}),l.withTimeout=(a,s)=>l(a,{name:s.name,key:s.key,timeout:s}),l},G=b?y=>c(X(y),e,g):y=>c(X(y),e),u;if(n?.strict===!0){let y=n;u=await W.strict(G,{onError:y.onError,onEvent:y.onEvent,catchUnexpected:y.catchUnexpected,workflowId:S,context:T})}else{let y=n;u=await W(G,{onError:y?.onError??(()=>{}),onEvent:y?.onEvent,workflowId:S,context:T})}let v=performance.now()-m;return u.ok?A({type:"workflow_success",workflowId:S,ts:Date.now(),durationMs:v}):A({type:"workflow_error",workflowId:S,ts:Date.now(),durationMs:v,error:u.error}),u}return E}function ue(e){return e.type==="step_complete"}function q(e){return typeof e=="object"&&e!==null&&e.type==="PENDING_APPROVAL"}function Re(e){return typeof e=="object"&&e!==null&&e.type==="APPROVAL_REJECTED"}function Se(e,n){return h({type:"PENDING_APPROVAL",stepKey:e,reason:n?.reason,metadata:n?.metadata})}function Ce(e){return async()=>{let n=await e.checkApproval();switch(n.status){case"pending":return h({type:"PENDING_APPROVAL",stepKey:e.key,reason:e.pendingReason,metadata:e.metadata});case"rejected":return h({type:"APPROVAL_REJECTED",stepKey:e.key,reason:n.reason});case"approved":return O(n.value)}}}function xe(e,n){let E=new Map(e.steps);return E.set(n.stepKey,{result:O(n.value)}),{steps:E}}function ge(e,n){let E=new Map(e.steps);return E.delete(n),{steps:E}}function Ae(e,n){let E=e.steps.get(n);return!E||E.result.ok?!1:q(E.result.error)}function ve(e){let n=[];for(let[E,d]of e.steps)!d.result.ok&&q(d.result.error)&&n.push(E);return n}function Pe(){let e=new Map;return{handleEvent:n=>{ue(n)&&e.set(n.stepKey,{result:n.result,meta:n.meta})},getState:()=>({steps:new Map(e)}),clear:()=>e.clear(),hasPendingApprovals:()=>{for(let n of e.values())if(!n.result.ok&&q(n.result.error))return!0;return!1},getPendingApprovals:()=>{let n=[];for(let[E,d]of e)!d.result.ok&&q(d.result.error)&&n.push({stepKey:E,error:d.result.error});return n},injectApproval:(n,E)=>(e.set(n,{result:O(E)}),{steps:new Map(e)})}}export{ge as clearStep,Ce as createApprovalStep,Pe as createHITLCollector,fe as createStepCollector,ke as createWorkflow,ve as getPendingApprovals,Ae as hasPendingApproval,xe as injectApproval,Re as isApprovalRejected,q as isPendingApproval,ue as isStepComplete,Se as pendingApproval};
1
+ var M=e=>({ok:!0,value:e}),S=(e,o)=>({ok:!1,error:e,...o?.cause!==void 0?{cause:o.cause}:{}});var ye=e=>typeof e=="object"&&e!==null&&e.type==="UNEXPECTED_ERROR",X=Symbol.for("step_timeout_marker");function ae(e){return typeof e!="object"||e===null?!1:e.type==="STEP_TIMEOUT"?!0:X in e}function we(e){if(!(typeof e!="object"||e===null)){if(e.type==="STEP_TIMEOUT"){let o=e;return{timeoutMs:o.timeoutMs,stepName:o.stepName,stepKey:o.stepKey,attempt:o.attempt}}if(X in e)return e[X]}}var pe=Symbol("early-exit");function Y(e,o){return{[pe]:!0,error:e,meta:o}}function $(e){return typeof e=="object"&&e!==null&&e[pe]===!0}var ce=Symbol("mapper-exception");function me(e){return{[ce]:!0,thrown:e}}function ke(e){return typeof e=="object"&&e!==null&&e[ce]===!0}function de(e){return typeof e=="string"?{name:e}:e??{}}function re(e,o){let{backoff:E,initialDelay:x,maxDelay:D,jitter:K}=o,C;switch(E){case"fixed":C=x;break;case"linear":C=x*e;break;case"exponential":C=x*Math.pow(2,e-1);break}if(C=Math.min(C,D),K){let c=C*.25*Math.random();C=C+c}return Math.floor(C)}function oe(e){return new Promise(o=>setTimeout(o,e))}var ie=Symbol("timeout");async function fe(e,o,E){let x=new AbortController,D=o.error??{type:"STEP_TIMEOUT",stepName:E.name,stepKey:E.key,timeoutMs:o.ms,attempt:E.attempt},K,C=new Promise((f,m)=>{K=setTimeout(()=>{x.abort(),m({[ie]:!0,error:D})},o.ms)}),c;o.signal?c=Promise.resolve(e(x.signal)):c=Promise.resolve(e());try{return await Promise.race([c,C])}catch(f){if(typeof f=="object"&&f!==null&&f[ie]===!0){let m=f.error;if(typeof m=="object"&&m!==null&&m.type!=="STEP_TIMEOUT"){let j={timeoutMs:o.ms,stepName:E.name,stepKey:E.key,attempt:E.attempt};X in m?m[X]=j:Object.defineProperty(m,X,{value:j,enumerable:!1,writable:!0,configurable:!1})}throw m}throw f}finally{clearTimeout(K)}}var L={backoff:"exponential",initialDelay:100,maxDelay:3e4,jitter:!0,retryOn:()=>!0,onRetry:()=>{}};async function H(e,o){let{onError:E,onEvent:x,catchUnexpected:D,workflowId:K,context:C}=o&&typeof o=="object"?o:{},c=K??crypto.randomUUID(),f=!E&&!D,m=[],j=0,v=p=>p??`step_${++j}`,w=p=>{let g=p.context!==void 0||C===void 0?p:{...p,context:C};if(g.type==="step_success"){let b=g.stepId;for(let W=m.length-1;W>=0;W--){let I=m[W];if(I.type==="race"&&!I.winnerId){I.winnerId=b;break}}}x?.(g,C)},P=Y,G=p=>$(p),B=(p,g)=>f?g?.origin==="result"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:p,...g.resultCause!==void 0?{cause:g.resultCause}:{}}}:g?.origin==="throw"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"throw",error:p,thrown:g.thrown}}:{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:p}}:p,Z=p=>p.origin==="result"?p.resultCause:p.thrown,F=p=>({type:"UNEXPECTED_ERROR",cause:p.meta.origin==="result"?{type:"STEP_FAILURE",origin:"result",error:p.error,...p.meta.resultCause!==void 0?{cause:p.meta.resultCause}:{}}:{type:"STEP_FAILURE",origin:"throw",error:p.error,thrown:p.meta.thrown}});try{let g=function(k,r){let s=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let u=performance.now(),t=!1;m.push({scopeId:s,type:"parallel"});let l=()=>{if(t)return;t=!0;let n=m.findIndex(a=>a.scopeId===s);n!==-1&&m.splice(n,1),w({type:"scope_end",workflowId:c,scopeId:s,ts:Date.now(),durationMs:performance.now()-u})};w({type:"scope_start",workflowId:c,scopeId:s,scopeType:"parallel",name:k,ts:Date.now()});try{let n=await r();if(l(),!n.ok)throw E?.(n.error,k,C),P(n.error,{origin:"result",resultCause:n.cause});return n.value}catch(n){throw l(),n}})()},b=function(k,r){let s=Object.keys(k),u=r.name??`Parallel(${s.join(", ")})`,t=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let l=performance.now(),n=!1;m.push({scopeId:t,type:"parallel"});let a=()=>{if(n)return;n=!0;let i=m.findIndex(y=>y.scopeId===t);i!==-1&&m.splice(i,1),w({type:"scope_end",workflowId:c,scopeId:t,ts:Date.now(),durationMs:performance.now()-l})};w({type:"scope_start",workflowId:c,scopeId:t,scopeType:"parallel",name:u,ts:Date.now()});try{let i=await new Promise(h=>{if(s.length===0){h([]);return}let _=!1,A=s.length,J=new Array(s.length);for(let O=0;O<s.length;O++){let V=s[O],ee=O;Promise.resolve(k[V]()).catch(R=>S({type:"PROMISE_REJECTED",cause:R},{cause:{type:"PROMISE_REJECTION",reason:R}})).then(R=>{if(!_){if(!R.ok){_=!0,h([{key:V,result:R}]);return}J[ee]={key:V,result:R},A--,A===0&&h(J)}})}});a();let y={};for(let{key:h,result:_}of i){if(!_.ok)throw E?.(_.error,h,C),P(_.error,{origin:"result",resultCause:_.cause});y[h]=_.value}return y}catch(i){throw a(),i}})()};var T=g,ue=b;let p=(k,r)=>(async()=>{let s=de(r),{name:u,key:t,retry:l,timeout:n}=s,a=v(t),i=x,y=i?performance.now():0;if(!(typeof k=="function")){if(l&&l.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(n)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 A={attempts:Math.max(1,l?.attempts??1),backoff:l?.backoff??L.backoff,initialDelay:l?.initialDelay??L.initialDelay,maxDelay:l?.maxDelay??L.maxDelay,jitter:l?.jitter??L.jitter,retryOn:l?.retryOn??L.retryOn,onRetry:l?.onRetry??L.onRetry};x&&w({type:"step_start",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now()});let J;for(let R=1;R<=A.attempts;R++){let Ee=i?performance.now():0;try{let d;if(typeof k=="function"?n?d=await fe(k,n,{name:u,key:t,attempt:R}):d=await k():d=await k,d.ok){let N=performance.now()-y;return w({type:"step_success",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),durationMs:N}),t&&w({type:"step_complete",workflowId:c,stepKey:t,name:u,ts:Date.now(),durationMs:N,result:d}),d.value}if(J=d,R<A.attempts&&A.retryOn(d.error,R)){let N=re(R,A);w({type:"step_retry",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),attempt:R+1,maxAttempts:A.attempts,delayMs:N,error:d.error}),A.onRetry(d.error,R,N),await oe(N);continue}A.attempts>1&&w({type:"step_retries_exhausted",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),durationMs:performance.now()-y,attempts:R,lastError:d.error});break}catch(d){let N=performance.now()-Ee;if(G(d))throw w({type:"step_aborted",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),durationMs:N}),d;if(ae(d)){let U=we(d),te=n?.ms??U?.timeoutMs??0;if(w({type:"step_timeout",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),timeoutMs:te,attempt:R}),R<A.attempts&&A.retryOn(d,R)){let ne=re(R,A);w({type:"step_retry",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),attempt:R+1,maxAttempts:A.attempts,delayMs:ne,error:d}),A.onRetry(d,R,ne),await oe(ne);continue}A.attempts>1&&w({type:"step_retries_exhausted",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),durationMs:performance.now()-y,attempts:R,lastError:d})}if(R<A.attempts&&A.retryOn(d,R)){let U=re(R,A);w({type:"step_retry",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),attempt:R+1,maxAttempts:A.attempts,delayMs:U,error:d}),A.onRetry(d,R,U),await oe(U);continue}A.attempts>1&&!ae(d)&&w({type:"step_retries_exhausted",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),durationMs:performance.now()-y,attempts:R,lastError:d});let q=performance.now()-y;if(D){let U;try{U=D(d)}catch(te){throw me(te)}throw w({type:"step_error",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),durationMs:q,error:U}),t&&w({type:"step_complete",workflowId:c,stepKey:t,name:u,ts:Date.now(),durationMs:q,result:S(U,{cause:d}),meta:{origin:"throw",thrown:d}}),E?.(U,u,C),P(U,{origin:"throw",thrown:d})}else{let U={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:d}};throw w({type:"step_error",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),durationMs:q,error:U}),t&&w({type:"step_complete",workflowId:c,stepKey:t,name:u,ts:Date.now(),durationMs:q,result:S(U,{cause:d}),meta:{origin:"throw",thrown:d}}),d}}}let O=J,V=performance.now()-y,ee=B(O.error,{origin:"result",resultCause:O.cause});throw w({type:"step_error",workflowId:c,stepId:a,stepKey:t,name:u,ts:Date.now(),durationMs:V,error:ee}),t&&w({type:"step_complete",workflowId:c,stepKey:t,name:u,ts:Date.now(),durationMs:V,result:O,meta:{origin:"result",resultCause:O.cause}}),E?.(O.error,u,C),P(O.error,{origin:"result",resultCause:O.cause})})();p.try=(k,r)=>{let s=r.name,u=r.key,t=v(u),l="error"in r?()=>r.error:r.onError,n=x;return(async()=>{let a=n?performance.now():0;x&&w({type:"step_start",workflowId:c,stepId:t,stepKey:u,name:s,ts:Date.now()});try{let i=await k(),y=performance.now()-a;return w({type:"step_success",workflowId:c,stepId:t,stepKey:u,name:s,ts:Date.now(),durationMs:y}),u&&w({type:"step_complete",workflowId:c,stepKey:u,name:s,ts:Date.now(),durationMs:y,result:M(i)}),i}catch(i){let y=l(i),h=performance.now()-a,_=B(y,{origin:"throw",thrown:i});throw w({type:"step_error",workflowId:c,stepId:t,stepKey:u,name:s,ts:Date.now(),durationMs:h,error:_}),u&&w({type:"step_complete",workflowId:c,stepKey:u,name:s,ts:Date.now(),durationMs:h,result:S(y,{cause:i}),meta:{origin:"throw",thrown:i}}),E?.(y,s,C),P(y,{origin:"throw",thrown:i})}})()},p.fromResult=(k,r)=>{let s=r.name,u=r.key,t=v(u),l="error"in r?()=>r.error:r.onError,n=x;return(async()=>{let a=n?performance.now():0;x&&w({type:"step_start",workflowId:c,stepId:t,stepKey:u,name:s,ts:Date.now()});let i=await k();if(i.ok){let y=performance.now()-a;return w({type:"step_success",workflowId:c,stepId:t,stepKey:u,name:s,ts:Date.now(),durationMs:y}),u&&w({type:"step_complete",workflowId:c,stepKey:u,name:s,ts:Date.now(),durationMs:y,result:M(i.value)}),i.value}else{let y=l(i.error),h=performance.now()-a,_=B(y,{origin:"result",resultCause:i.error});throw w({type:"step_error",workflowId:c,stepId:t,stepKey:u,name:s,ts:Date.now(),durationMs:h,error:_}),u&&w({type:"step_complete",workflowId:c,stepKey:u,name:s,ts:Date.now(),durationMs:h,result:S(y,{cause:i.error}),meta:{origin:"result",resultCause:i.error}}),E?.(y,s,C),P(y,{origin:"result",resultCause:i.error})}})()},p.retry=(k,r)=>p(k,{name:r.name,key:r.key,retry:{attempts:r.attempts,backoff:r.backoff,initialDelay:r.initialDelay,maxDelay:r.maxDelay,jitter:r.jitter,retryOn:r.retryOn,onRetry:r.onRetry},timeout:r.timeout}),p.withTimeout=(k,r)=>p(k,{name:r.name,key:r.key,timeout:r}),p.parallel=((...k)=>{if(typeof k[0]=="string"){let r=k[0],s=k[1];return g(r,s)}else{let r=k[0],s=k[1]??{};return b(r,s)}}),p.race=(k,r)=>{let s=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let u=performance.now(),t=!1,l={scopeId:s,type:"race",winnerId:void 0};m.push(l);let n=()=>{if(t)return;t=!0;let a=m.findIndex(i=>i.scopeId===s);a!==-1&&m.splice(a,1),w({type:"scope_end",workflowId:c,scopeId:s,ts:Date.now(),durationMs:performance.now()-u,winnerId:l.winnerId})};w({type:"scope_start",workflowId:c,scopeId:s,scopeType:"race",name:k,ts:Date.now()});try{let a=await r();if(n(),!a.ok)throw E?.(a.error,k,C),P(a.error,{origin:"result",resultCause:a.cause});return a.value}catch(a){throw n(),a}})()},p.allSettled=(k,r)=>{let s=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let u=performance.now(),t=!1;m.push({scopeId:s,type:"allSettled"});let l=()=>{if(t)return;t=!0;let n=m.findIndex(a=>a.scopeId===s);n!==-1&&m.splice(n,1),w({type:"scope_end",workflowId:c,scopeId:s,ts:Date.now(),durationMs:performance.now()-u})};w({type:"scope_start",workflowId:c,scopeId:s,scopeType:"allSettled",name:k,ts:Date.now()});try{let n=await r();if(l(),!n.ok)throw E?.(n.error,k,C),P(n.error,{origin:"result",resultCause:n.cause});return n.value}catch(n){throw l(),n}})()};let I=await e(p);return M(I)}catch(p){if(ke(p))throw p.thrown;if(G(p)){let b=Z(p.meta);if(D||E)return S(p.error,{cause:b});if(ye(p.error))return S(p.error,{cause:b});let W=F(p);return S(W,{cause:b})}if(D){let b=D(p);return E?.(b,"unexpected",C),S(b,{cause:p})}let g={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:p}};return E?.(g,"unexpected",C),S(g,{cause:p})}}H.strict=(e,o)=>H(e,o);function xe(){let e=new Map;return{handleEvent:o=>{le(o)&&e.set(o.stepKey,{result:o.result,meta:o.meta})},getState:()=>({steps:new Map(e)}),clear:()=>e.clear()}}function Te(e){return typeof e=="object"&&e!==null&&e.__cachedMeta===!0}function z(e,o,E){return S(e,{cause:{__cachedMeta:!0,originalCause:E,meta:o}})}function se(e){return Te(e)?e.meta:{origin:"result",resultCause:e}}function Se(e,o){async function E(x,D){let K=typeof D=="function",C=K?x:void 0,c=K?D:x,f=crypto.randomUUID(),m=o?.createContext?.(),j={workflowId:f,onEvent:o?.onEvent,context:m!==void 0?m:void 0},v=r=>{let s=r.context!==void 0||m===void 0?r:{...r,context:m};o?.onEvent?.(s,m)},w=o?.shouldRun,P=o?.catchUnexpected;if(w){let r=performance.now();try{let s=await w(f,m),u=performance.now()-r;if(v({type:"hook_should_run",workflowId:f,ts:Date.now(),durationMs:u,result:s,skipped:!s}),!s){let t=new Error("Workflow skipped by shouldRun hook");if(P){let n=P(t);return S(n)}return S({type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:t}})}}catch(s){let u=performance.now()-r;if(v({type:"hook_should_run_error",workflowId:f,ts:Date.now(),durationMs:u,error:s}),P){let l=P(s);return S(l)}return S({type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:s}})}}let G=o?.onBeforeStart;if(G){let r=performance.now();try{let s=await G(f,m),u=performance.now()-r;if(v({type:"hook_before_start",workflowId:f,ts:Date.now(),durationMs:u,result:s,skipped:!s}),!s){let t=new Error("Workflow skipped by onBeforeStart hook");if(P){let n=P(t);return S(n)}return S({type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:t}})}}catch(s){let u=performance.now()-r;if(v({type:"hook_before_start_error",workflowId:f,ts:Date.now(),durationMs:u,error:s}),P){let l=P(s);return S(l)}return S({type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:s}})}}let B=Date.now(),Z=performance.now();v({type:"workflow_start",workflowId:f,ts:B});let F=o?.resumeState,T=o?.cache;if(F&&!T&&(T=new Map),F&&T){let r=typeof F=="function"?await F():F;for(let[s,u]of r.steps){let{result:t,meta:l}=u;if(t.ok)T.set(s,t);else{let n=l??{origin:"result",resultCause:t.cause};T.set(s,z(t.error,n,t.cause))}}}let ue=r=>typeof r=="string"?{name:r}:r??{},p=o?.onAfterStep,g=async(r,s)=>{if(!p)return;let u=performance.now();try{await p(r,s,f,m);let t=performance.now()-u;v({type:"hook_after_step",workflowId:f,stepKey:r,ts:Date.now(),durationMs:t})}catch(t){let l=performance.now()-u;throw v({type:"hook_after_step_error",workflowId:f,stepKey:r,ts:Date.now(),durationMs:l,error:t}),t}},b=r=>{if(!T&&!p)return r;let s=async(u,t)=>{let{name:l,key:n}=ue(t);if(n&&T&&T.has(n)){v({type:"step_cache_hit",workflowId:f,stepKey:n,name:l,ts:Date.now()});let i=T.get(n);if(i.ok)return i.value;let y=se(i.cause);throw Y(i.error,y)}n&&T&&v({type:"step_cache_miss",workflowId:f,stepKey:n,name:l,ts:Date.now()});let a=typeof u=="function"?u:()=>u;try{let i=await r(a,t);return n&&(T&&T.set(n,M(i)),await g(n,M(i))),i}catch(i){if(n&&$(i)){let y=i,h=y.meta.origin==="result"?y.meta.resultCause:y.meta.thrown,_=z(y.error,y.meta,h);T&&T.set(n,_),await g(n,_)}throw i}};return s.try=async(u,t)=>{let{name:l,key:n}=t;if(n&&T&&T.has(n)){v({type:"step_cache_hit",workflowId:f,stepKey:n,name:l,ts:Date.now()});let a=T.get(n);if(a.ok)return a.value;let i=se(a.cause);throw Y(a.error,i)}n&&T&&v({type:"step_cache_miss",workflowId:f,stepKey:n,name:l,ts:Date.now()});try{let a=await r.try(u,t);return n&&(T&&T.set(n,M(a)),await g(n,M(a))),a}catch(a){if(n&&$(a)){let i=a,y=i.meta.origin==="result"?i.meta.resultCause:i.meta.thrown,h=z(i.error,i.meta,y);T&&T.set(n,h),await g(n,h)}throw a}},s.fromResult=async(u,t)=>{let{name:l,key:n}=t;if(n&&T&&T.has(n)){v({type:"step_cache_hit",workflowId:f,stepKey:n,name:l,ts:Date.now()});let a=T.get(n);if(a.ok)return a.value;let i=se(a.cause);throw Y(a.error,i)}n&&T&&v({type:"step_cache_miss",workflowId:f,stepKey:n,name:l,ts:Date.now()});try{let a=await r.fromResult(u,t);return n&&(T&&T.set(n,M(a)),await g(n,M(a))),a}catch(a){if(n&&$(a)){let i=a,y=i.meta.origin==="result"?i.meta.resultCause:i.meta.thrown,h=z(i.error,i.meta,y);T&&T.set(n,h),await g(n,h)}throw a}},s.parallel=r.parallel,s.race=r.race,s.allSettled=r.allSettled,s.retry=(u,t)=>s(u,{name:t.name,key:t.key,retry:{attempts:t.attempts,backoff:t.backoff,initialDelay:t.initialDelay,maxDelay:t.maxDelay,jitter:t.jitter,retryOn:t.retryOn,onRetry:t.onRetry},timeout:t.timeout}),s.withTimeout=(u,t)=>s(u,{name:t.name,key:t.key,timeout:t}),s},W=K?r=>c(b(r),e,C,j):r=>c(b(r),e,j),I;if(o?.strict===!0){let r=o;I=await H.strict(W,{onError:r.onError,onEvent:r.onEvent,catchUnexpected:r.catchUnexpected,workflowId:f,context:m})}else{let r=o;I=await H(W,{onError:r?.onError??(()=>{}),onEvent:r?.onEvent,workflowId:f,context:m})}let k=performance.now()-Z;return I.ok?v({type:"workflow_success",workflowId:f,ts:Date.now(),durationMs:k}):v({type:"workflow_error",workflowId:f,ts:Date.now(),durationMs:k,error:I.error}),I}return E}function le(e){return e.type==="step_complete"}function Q(e){return typeof e=="object"&&e!==null&&e.type==="PENDING_APPROVAL"}function ge(e){return typeof e=="object"&&e!==null&&e.type==="APPROVAL_REJECTED"}function Ae(e,o){return S({type:"PENDING_APPROVAL",stepKey:e,reason:o?.reason,metadata:o?.metadata})}function he(e){return async()=>{let o=await e.checkApproval();switch(o.status){case"pending":return S({type:"PENDING_APPROVAL",stepKey:e.key,reason:e.pendingReason,metadata:e.metadata});case"rejected":return S({type:"APPROVAL_REJECTED",stepKey:e.key,reason:o.reason});case"approved":return M(o.value)}}}function ve(e,o){let E=new Map(e.steps);return E.set(o.stepKey,{result:M(o.value)}),{steps:E}}function Pe(e,o){let E=new Map(e.steps);return E.delete(o),{steps:E}}function _e(e,o){let E=e.steps.get(o);return!E||E.result.ok?!1:Q(E.result.error)}function be(e){let o=[];for(let[E,x]of e.steps)!x.result.ok&&Q(x.result.error)&&o.push(E);return o}function Ue(){let e=new Map;return{handleEvent:o=>{le(o)&&e.set(o.stepKey,{result:o.result,meta:o.meta})},getState:()=>({steps:new Map(e)}),clear:()=>e.clear(),hasPendingApprovals:()=>{for(let o of e.values())if(!o.result.ok&&Q(o.result.error))return!0;return!1},getPendingApprovals:()=>{let o=[];for(let[E,x]of e)!x.result.ok&&Q(x.result.error)&&o.push({stepKey:E,error:x.result.error});return o},injectApproval:(o,E)=>(e.set(o,{result:M(E)}),{steps:new Map(e)})}}export{Pe as clearStep,he as createApprovalStep,Ue as createHITLCollector,xe as createStepCollector,Se as createWorkflow,be as getPendingApprovals,_e as hasPendingApproval,ve as injectApproval,ge as isApprovalRejected,Q as isPendingApproval,le as isStepComplete,Ae as pendingApproval};
2
2
  //# sourceMappingURL=workflow.js.map