@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.
- package/README.md +499 -19
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +158 -19
- package/dist/core.d.ts +158 -19
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +282 -17
- package/dist/index.d.ts +282 -17
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/visualize.cjs +1188 -6
- package/dist/visualize.cjs.map +1 -1
- package/dist/visualize.d.cts +467 -1
- package/dist/visualize.d.ts +467 -1
- package/dist/visualize.js +1188 -6
- package/dist/visualize.js.map +1 -1
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +97 -15
- package/dist/workflow.d.ts +97 -15
- package/dist/workflow.js +1 -1
- package/dist/workflow.js.map +1 -1
- package/docs/advanced.md +425 -7
- package/docs/api.md +37 -6
- package/package.json +1 -1
package/dist/workflow.d.cts
CHANGED
|
@@ -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
|
-
/**
|
|
188
|
-
|
|
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
|
-
/**
|
|
207
|
-
|
|
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.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
188
|
-
|
|
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
|
-
/**
|
|
207
|
-
|
|
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
|