runsheet 0.4.0 → 0.6.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 +238 -47
- package/dist/index.cjs +639 -249
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +497 -243
- package/dist/index.d.ts +497 -243
- package/dist/index.js +624 -247
- package/dist/index.js.map +1 -1
- package/llms.txt +191 -36
- package/package.json +4 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* A schema that can parse/validate unknown data.
|
|
3
|
+
*
|
|
4
|
+
* This is the structural interface that Zod schemas (and other schema
|
|
5
|
+
* libraries) satisfy. runsheet does not depend on any specific schema
|
|
6
|
+
* library — any object with a `safeParse` method works.
|
|
7
|
+
*
|
|
8
|
+
* @typeParam T - The validated output type.
|
|
9
|
+
*/
|
|
10
|
+
type StepSchema<T> = {
|
|
11
|
+
safeParse(data: unknown): {
|
|
12
|
+
success: true;
|
|
13
|
+
data: T;
|
|
14
|
+
} | {
|
|
15
|
+
success: false;
|
|
16
|
+
error: {
|
|
17
|
+
issues: readonly {
|
|
18
|
+
path: readonly (string | number)[];
|
|
19
|
+
message: string;
|
|
20
|
+
}[];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
4
24
|
/**
|
|
5
25
|
* The type-erased context shape used at runtime by the pipeline engine.
|
|
6
26
|
*
|
|
@@ -34,18 +54,18 @@ type Step = {
|
|
|
34
54
|
/** Unique name identifying this step in metadata and rollback reports. */
|
|
35
55
|
readonly name: string;
|
|
36
56
|
/** Optional schema that validates the accumulated context before `run`. */
|
|
37
|
-
readonly requires:
|
|
57
|
+
readonly requires: StepSchema<StepContext> | undefined;
|
|
38
58
|
/** Optional schema that validates the step's output after `run`. */
|
|
39
|
-
readonly provides:
|
|
59
|
+
readonly provides: StepSchema<StepOutput> | undefined;
|
|
40
60
|
/**
|
|
41
61
|
* Execute the step. Receives the accumulated context and returns a
|
|
42
|
-
*
|
|
43
|
-
* `
|
|
62
|
+
* {@link StepResult} — either a success with `data` or a failure with
|
|
63
|
+
* `error`, `failedStep`, and `rollback`.
|
|
44
64
|
*
|
|
45
65
|
* Step authors never call this directly; the pipeline engine calls it
|
|
46
|
-
* after
|
|
66
|
+
* after wrapping with middleware.
|
|
47
67
|
*/
|
|
48
|
-
readonly run: (ctx: Readonly<StepContext>) => Promise<
|
|
68
|
+
readonly run: (ctx: Readonly<StepContext>) => Promise<StepResult<StepOutput>>;
|
|
49
69
|
/**
|
|
50
70
|
* Optional rollback handler, called when a later step fails.
|
|
51
71
|
*
|
|
@@ -62,6 +82,10 @@ type Step = {
|
|
|
62
82
|
* Phantom type brands for compile-time tracking of step I/O types.
|
|
63
83
|
* These symbols never exist at runtime — they only guide TypeScript's
|
|
64
84
|
* type checker through the builder's progressive type narrowing.
|
|
85
|
+
*
|
|
86
|
+
* `RequiresBrand` uses a function type for contravariance: a step that
|
|
87
|
+
* requires `StepContext` (anything) is usable where a narrower context
|
|
88
|
+
* is available. `ProvidesBrand` is covariant (a plain value brand).
|
|
65
89
|
*/
|
|
66
90
|
declare const RequiresBrand: unique symbol;
|
|
67
91
|
declare const ProvidesBrand: unique symbol;
|
|
@@ -76,13 +100,17 @@ declare const ProvidesBrand: unique symbol;
|
|
|
76
100
|
* schemas or generics. When assigned to `Step` (e.g., in a pipeline's
|
|
77
101
|
* step array), the intersection collapses to the erased signatures.
|
|
78
102
|
*
|
|
103
|
+
* The typed properties appear BEFORE the `Step` intersection so that
|
|
104
|
+
* TypeScript's overload resolution picks the concrete signatures first
|
|
105
|
+
* when calling `run()` directly on a `TypedStep`.
|
|
106
|
+
*
|
|
79
107
|
* @typeParam Requires - The context shape this step reads from.
|
|
80
108
|
* @typeParam Provides - The output shape this step produces.
|
|
81
109
|
*
|
|
82
110
|
* @example
|
|
83
111
|
* ```ts
|
|
84
112
|
* // Hover over `step.run` to see:
|
|
85
|
-
* // (ctx: Readonly<{ amount: number }>) => Promise<
|
|
113
|
+
* // (ctx: Readonly<{ amount: number }>) => Promise<StepResult<{ chargeId: string }>>
|
|
86
114
|
* const step = defineStep({
|
|
87
115
|
* name: 'charge',
|
|
88
116
|
* requires: z.object({ amount: z.number() }),
|
|
@@ -91,15 +119,15 @@ declare const ProvidesBrand: unique symbol;
|
|
|
91
119
|
* });
|
|
92
120
|
* ```
|
|
93
121
|
*/
|
|
94
|
-
type TypedStep<Requires extends StepContext = StepContext, Provides extends StepContext = StepContext> =
|
|
95
|
-
readonly [RequiresBrand]: Requires;
|
|
122
|
+
type TypedStep<Requires extends StepContext = StepContext, Provides extends StepContext = StepContext> = {
|
|
123
|
+
readonly [RequiresBrand]: (ctx: Requires) => void;
|
|
96
124
|
readonly [ProvidesBrand]: Provides;
|
|
97
125
|
/** Optional schema that validates the accumulated context before `run`. */
|
|
98
|
-
readonly requires:
|
|
126
|
+
readonly requires: StepSchema<Requires> | undefined;
|
|
99
127
|
/** Optional schema that validates the step's output after `run`. */
|
|
100
|
-
readonly provides:
|
|
128
|
+
readonly provides: StepSchema<Provides> | undefined;
|
|
101
129
|
/** Execute the step with concrete input/output types. */
|
|
102
|
-
readonly run: (ctx: Readonly<Requires>) => Promise<
|
|
130
|
+
readonly run: (ctx: Readonly<Requires>) => Promise<StepResult<Provides>>;
|
|
103
131
|
/**
|
|
104
132
|
* Optional rollback handler, called when a later step fails.
|
|
105
133
|
*
|
|
@@ -107,13 +135,30 @@ type TypedStep<Requires extends StepContext = StepContext, Provides extends Step
|
|
|
107
135
|
* @param output - The frozen output this step produced.
|
|
108
136
|
*/
|
|
109
137
|
readonly rollback: ((ctx: Readonly<Requires>, output: Readonly<Provides>) => Promise<void>) | undefined;
|
|
110
|
-
};
|
|
138
|
+
} & Step;
|
|
111
139
|
/** Convert a union type to an intersection type. */
|
|
112
140
|
type UnionToIntersection<U> = [U] extends [never] ? unknown : (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
141
|
+
/**
|
|
142
|
+
* Extract the Requires type from a step via its phantom brand.
|
|
143
|
+
* Returns `StepContext` for untyped (erased) steps.
|
|
144
|
+
*
|
|
145
|
+
* Matches the contravariant function brand directly — avoids full
|
|
146
|
+
* structural matching on `TypedStep` which would fail due to
|
|
147
|
+
* `run` parameter contravariance in conditional types.
|
|
148
|
+
*/
|
|
149
|
+
type ExtractRequires<T extends Step> = T extends {
|
|
150
|
+
readonly [RequiresBrand]: (ctx: infer R) => void;
|
|
151
|
+
} ? R : StepContext;
|
|
152
|
+
/**
|
|
153
|
+
* Extract the Provides type from a step via its phantom brand.
|
|
154
|
+
* Returns `object` for untyped (erased) steps.
|
|
155
|
+
*
|
|
156
|
+
* Matches the covariant value brand directly — avoids full structural
|
|
157
|
+
* matching which would fail for steps with non-trivial Requires types.
|
|
158
|
+
*/
|
|
159
|
+
type ExtractProvides<T extends Step> = T extends {
|
|
160
|
+
readonly [ProvidesBrand]: infer P;
|
|
161
|
+
} ? P : object;
|
|
117
162
|
/**
|
|
118
163
|
* Retry policy for a step's `run` function.
|
|
119
164
|
*
|
|
@@ -160,23 +205,23 @@ type StepConfig<Requires extends StepContext, Provides extends StepContext> = {
|
|
|
160
205
|
/**
|
|
161
206
|
* Optional Zod (or Standard Schema compatible) schema that validates
|
|
162
207
|
* the accumulated context before `run` is called. When provided, a
|
|
163
|
-
* schema validation failure produces a `
|
|
208
|
+
* schema validation failure produces a `StepResult` error — the step's
|
|
164
209
|
* `run` function is never invoked.
|
|
165
210
|
*/
|
|
166
|
-
requires?:
|
|
211
|
+
requires?: StepSchema<Requires>;
|
|
167
212
|
/**
|
|
168
213
|
* Optional Zod (or Standard Schema compatible) schema that validates
|
|
169
214
|
* the step's output after `run` returns. When provided, a schema
|
|
170
|
-
* validation failure produces a `
|
|
215
|
+
* validation failure produces a `StepResult` error even though `run`
|
|
171
216
|
* succeeded.
|
|
172
217
|
*/
|
|
173
|
-
provides?:
|
|
218
|
+
provides?: StepSchema<Provides>;
|
|
174
219
|
/**
|
|
175
220
|
* The step implementation. Receives the accumulated context (frozen)
|
|
176
221
|
* and returns the step's output. Can be sync or async.
|
|
177
222
|
*
|
|
178
223
|
* To signal failure, throw an error. The pipeline catches it and
|
|
179
|
-
* produces a `
|
|
224
|
+
* produces a `StepResult` failure — do not return failure objects.
|
|
180
225
|
*
|
|
181
226
|
* @param ctx - The frozen accumulated context up to this point.
|
|
182
227
|
* @returns The step's output, which is merged into the accumulated context.
|
|
@@ -219,7 +264,7 @@ type RollbackFailure = {
|
|
|
219
264
|
readonly error: Error;
|
|
220
265
|
};
|
|
221
266
|
/**
|
|
222
|
-
* Summary of rollback execution after a pipeline failure.
|
|
267
|
+
* Summary of rollback execution after a step or pipeline failure.
|
|
223
268
|
*
|
|
224
269
|
* Rollback is best-effort: every completed step's rollback handler is
|
|
225
270
|
* attempted in reverse order, regardless of whether earlier handlers
|
|
@@ -232,69 +277,153 @@ type RollbackReport = {
|
|
|
232
277
|
readonly failed: readonly RollbackFailure[];
|
|
233
278
|
};
|
|
234
279
|
/**
|
|
235
|
-
* Metadata about a
|
|
280
|
+
* Metadata about a step execution, present on both success and failure
|
|
236
281
|
* results. Useful for logging, debugging, and observability.
|
|
237
282
|
*/
|
|
238
|
-
type
|
|
239
|
-
/** The
|
|
240
|
-
readonly
|
|
241
|
-
/** The original arguments passed to `
|
|
283
|
+
type StepMeta = {
|
|
284
|
+
/** The step's name (or pipeline name for pipeline-steps). */
|
|
285
|
+
readonly name: string;
|
|
286
|
+
/** The original arguments/context passed to `step.run()`. */
|
|
242
287
|
readonly args: Readonly<StepContext>;
|
|
288
|
+
};
|
|
289
|
+
/**
|
|
290
|
+
* Extended metadata for orchestrator results (pipelines, parallel,
|
|
291
|
+
* choice).
|
|
292
|
+
*
|
|
293
|
+
* Includes orchestration detail — which steps ran — on top of the
|
|
294
|
+
* base {@link StepMeta}. Present on results from `pipeline()`,
|
|
295
|
+
* `parallel()`, and `choice()`.
|
|
296
|
+
*/
|
|
297
|
+
type AggregateMeta = StepMeta & {
|
|
243
298
|
/** Names of steps that executed successfully, in order. */
|
|
244
299
|
readonly stepsExecuted: readonly string[];
|
|
245
|
-
/** Names of conditional steps that were skipped (predicate returned false). */
|
|
246
|
-
readonly stepsSkipped: readonly string[];
|
|
247
300
|
};
|
|
248
301
|
/**
|
|
249
|
-
* A successful
|
|
302
|
+
* A successful step result.
|
|
250
303
|
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* (initial args merged with all step outputs).
|
|
304
|
+
* The `data` property contains the step's output (or the fully
|
|
305
|
+
* accumulated context for pipeline-steps).
|
|
254
306
|
*
|
|
255
|
-
* @typeParam T - The
|
|
307
|
+
* @typeParam T - The output type.
|
|
256
308
|
*/
|
|
257
|
-
type
|
|
258
|
-
|
|
259
|
-
|
|
309
|
+
type StepSuccess<T> = {
|
|
310
|
+
readonly success: true;
|
|
311
|
+
/** The step's output data. */
|
|
312
|
+
readonly data: T;
|
|
313
|
+
/** Step execution metadata. */
|
|
314
|
+
readonly meta: StepMeta;
|
|
260
315
|
};
|
|
261
316
|
/**
|
|
262
|
-
* A failed
|
|
263
|
-
*
|
|
264
|
-
* Extends composable-functions' `Failure` with the name of the step that
|
|
265
|
-
* failed, a rollback report, and pipeline execution metadata.
|
|
317
|
+
* A failed step result.
|
|
266
318
|
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
319
|
+
* Contains the error that caused the failure, the name of the step
|
|
320
|
+
* that failed, and a rollback report.
|
|
269
321
|
*/
|
|
270
|
-
type
|
|
271
|
-
|
|
272
|
-
|
|
322
|
+
type StepFailure = {
|
|
323
|
+
readonly success: false;
|
|
324
|
+
/** The error that caused the failure. Use `AggregateError` when multiple errors occur. */
|
|
325
|
+
readonly error: Error;
|
|
326
|
+
/** Step execution metadata. */
|
|
327
|
+
readonly meta: StepMeta;
|
|
273
328
|
/** Name of the step that failed. */
|
|
274
329
|
readonly failedStep: string;
|
|
275
330
|
/** Report of which rollback handlers succeeded and which threw. */
|
|
276
331
|
readonly rollback: RollbackReport;
|
|
277
332
|
};
|
|
278
333
|
/**
|
|
279
|
-
* The result of running a
|
|
334
|
+
* The result of running a step — either a success or a failure.
|
|
280
335
|
*
|
|
281
336
|
* Use the `success` discriminant to narrow:
|
|
282
337
|
*
|
|
283
338
|
* ```ts
|
|
284
|
-
* const result = await
|
|
339
|
+
* const result = await step.run(ctx);
|
|
285
340
|
* if (result.success) {
|
|
286
|
-
* result.data; //
|
|
341
|
+
* result.data; // the step's output
|
|
287
342
|
* result.meta; // execution metadata
|
|
288
343
|
* } else {
|
|
289
|
-
* result.
|
|
344
|
+
* result.error; // what went wrong
|
|
290
345
|
* result.failedStep; // which step failed
|
|
291
346
|
* result.rollback; // { completed: [...], failed: [...] }
|
|
292
347
|
* }
|
|
293
348
|
* ```
|
|
294
349
|
*
|
|
295
|
-
* @typeParam T - The
|
|
350
|
+
* @typeParam T - The output type on success.
|
|
296
351
|
*/
|
|
297
|
-
type
|
|
352
|
+
type StepResult<T> = StepSuccess<T> | StepFailure;
|
|
353
|
+
/**
|
|
354
|
+
* A successful orchestrator result.
|
|
355
|
+
*
|
|
356
|
+
* Identical to {@link StepSuccess} but with {@link AggregateMeta}
|
|
357
|
+
* instead of {@link StepMeta}, providing orchestration detail.
|
|
358
|
+
*
|
|
359
|
+
* @typeParam T - The accumulated output type.
|
|
360
|
+
*/
|
|
361
|
+
type AggregateSuccess<T> = {
|
|
362
|
+
readonly success: true;
|
|
363
|
+
/** The accumulated output after all inner steps. */
|
|
364
|
+
readonly data: T;
|
|
365
|
+
/** Orchestrator execution metadata including step tracking. */
|
|
366
|
+
readonly meta: AggregateMeta;
|
|
367
|
+
};
|
|
368
|
+
/**
|
|
369
|
+
* A failed orchestrator result.
|
|
370
|
+
*
|
|
371
|
+
* Identical to {@link StepFailure} but with {@link AggregateMeta}
|
|
372
|
+
* instead of {@link StepMeta}, providing orchestration detail.
|
|
373
|
+
*/
|
|
374
|
+
type AggregateFailure = {
|
|
375
|
+
readonly success: false;
|
|
376
|
+
/** The error that caused the failure. */
|
|
377
|
+
readonly error: Error;
|
|
378
|
+
/** Orchestrator execution metadata including step tracking. */
|
|
379
|
+
readonly meta: AggregateMeta;
|
|
380
|
+
/** Name of the step that failed. */
|
|
381
|
+
readonly failedStep: string;
|
|
382
|
+
/** Report of which rollback handlers succeeded and which threw. */
|
|
383
|
+
readonly rollback: RollbackReport;
|
|
384
|
+
};
|
|
385
|
+
/**
|
|
386
|
+
* The result of running an orchestrator — extends {@link StepResult}
|
|
387
|
+
* with richer metadata.
|
|
388
|
+
*
|
|
389
|
+
* `AggregateResult<T>` is assignable to `StepResult<T>`, so
|
|
390
|
+
* orchestrators (`pipeline`, `parallel`, `choice`) satisfy the `Step`
|
|
391
|
+
* interface while providing orchestration detail to callers.
|
|
392
|
+
*
|
|
393
|
+
* ```ts
|
|
394
|
+
* const checkout = pipeline({ name: 'checkout', steps: [...] });
|
|
395
|
+
* const result = await checkout.run({ orderId: '123' });
|
|
396
|
+
* if (result.success) {
|
|
397
|
+
* result.meta.stepsExecuted; // string[] — which steps ran
|
|
398
|
+
* } else {
|
|
399
|
+
* result.meta.stepsExecuted; // string[] — which steps ran
|
|
400
|
+
* result.failedStep; // which step failed
|
|
401
|
+
* result.rollback; // { completed, failed }
|
|
402
|
+
* }
|
|
403
|
+
* ```
|
|
404
|
+
*
|
|
405
|
+
* @typeParam T - The accumulated output type on success.
|
|
406
|
+
*/
|
|
407
|
+
type AggregateResult<T> = AggregateSuccess<T> | AggregateFailure;
|
|
408
|
+
/**
|
|
409
|
+
* A step that orchestrates other steps and returns rich results.
|
|
410
|
+
*
|
|
411
|
+
* Extends {@link TypedStep} with a narrower `run()` that returns
|
|
412
|
+
* {@link AggregateResult} instead of {@link StepResult}. This is the
|
|
413
|
+
* type returned by `pipeline()`, `parallel()`, and `choice()`.
|
|
414
|
+
*
|
|
415
|
+
* The `run` property uses an explicit overloaded function type:
|
|
416
|
+
* the first overload returns `AggregateResult` (matched when calling
|
|
417
|
+
* directly), the second preserves the erased `Step.run` signature
|
|
418
|
+
* (for `Step` assignability when used in pipeline arrays).
|
|
419
|
+
*
|
|
420
|
+
* @typeParam Requires - The input type.
|
|
421
|
+
* @typeParam Provides - The accumulated output type.
|
|
422
|
+
*/
|
|
423
|
+
type AggregateStep<Requires extends StepContext = StepContext, Provides extends StepContext = StepContext> = {
|
|
424
|
+
/** Execute the orchestrator and return an {@link AggregateResult}. */
|
|
425
|
+
readonly run: (ctx: Readonly<Requires>) => Promise<AggregateResult<Provides>>;
|
|
426
|
+
} & TypedStep<Requires, Provides>;
|
|
298
427
|
|
|
299
428
|
/**
|
|
300
429
|
* Define a pipeline step.
|
|
@@ -323,9 +452,8 @@ type PipelineResult<T> = PipelineSuccess<T> | PipelineFailure;
|
|
|
323
452
|
*
|
|
324
453
|
* **Invariants:**
|
|
325
454
|
* - The returned step object is always frozen (immutable).
|
|
326
|
-
* - The `run` function
|
|
327
|
-
*
|
|
328
|
-
* `Result` values. Step authors should throw to signal failure.
|
|
455
|
+
* - The `run` function catches thrown errors and produces
|
|
456
|
+
* `StepResult` values. Step authors should throw to signal failure.
|
|
329
457
|
* - This is the single type-erasure cast point in the library.
|
|
330
458
|
*
|
|
331
459
|
* @typeParam Requires - The context shape this step reads from.
|
|
@@ -338,31 +466,28 @@ declare function defineStep<Requires extends StepContext, Provides extends StepC
|
|
|
338
466
|
/**
|
|
339
467
|
* Error codes for errors produced by the runsheet library itself.
|
|
340
468
|
*
|
|
341
|
-
* Use these to distinguish library errors from application errors
|
|
342
|
-
* in a pipeline's `errors` array:
|
|
469
|
+
* Use these to distinguish library errors from application errors:
|
|
343
470
|
*
|
|
344
471
|
* ```ts
|
|
345
472
|
* if (!result.success) {
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
* console.log(error.code); // 'REQUIRES_VALIDATION', etc.
|
|
349
|
-
* }
|
|
473
|
+
* if (result.error instanceof RunsheetError) {
|
|
474
|
+
* console.log(result.error.code); // 'REQUIRES_VALIDATION', etc.
|
|
350
475
|
* }
|
|
351
476
|
* }
|
|
352
477
|
* ```
|
|
353
478
|
*/
|
|
354
|
-
type RunsheetErrorCode = 'REQUIRES_VALIDATION' | 'PROVIDES_VALIDATION' | 'ARGS_VALIDATION' | 'PREDICATE' | 'TIMEOUT' | 'RETRY_EXHAUSTED' | 'STRICT_OVERLAP';
|
|
479
|
+
type RunsheetErrorCode = 'REQUIRES_VALIDATION' | 'PROVIDES_VALIDATION' | 'ARGS_VALIDATION' | 'PREDICATE' | 'TIMEOUT' | 'RETRY_EXHAUSTED' | 'STRICT_OVERLAP' | 'CHOICE_NO_MATCH' | 'ROLLBACK' | 'UNKNOWN';
|
|
355
480
|
/**
|
|
356
481
|
* Base error class for all errors produced by the runsheet library.
|
|
357
482
|
*
|
|
358
483
|
* Application errors (thrown by step `run` or `rollback` functions)
|
|
359
484
|
* are never wrapped in `RunsheetError` — they pass through as-is.
|
|
360
|
-
* If you see a `RunsheetError`
|
|
361
|
-
*
|
|
485
|
+
* If you see a `RunsheetError` as `result.error`, the library itself
|
|
486
|
+
* produced it.
|
|
362
487
|
*
|
|
363
488
|
* Use `instanceof RunsheetError` to distinguish library errors from
|
|
364
|
-
* application errors
|
|
365
|
-
* specific
|
|
489
|
+
* application errors. Use `instanceof` on a subclass (e.g.,
|
|
490
|
+
* `TimeoutError`) or check the `code` property for specific failures.
|
|
366
491
|
*/
|
|
367
492
|
declare class RunsheetError extends Error {
|
|
368
493
|
/** Discriminant code identifying the type of library error. */
|
|
@@ -373,6 +498,58 @@ declare class RunsheetError extends Error {
|
|
|
373
498
|
*/
|
|
374
499
|
constructor(code: RunsheetErrorCode, message: string);
|
|
375
500
|
}
|
|
501
|
+
/** Schema validation failed on the accumulated context before a step ran. */
|
|
502
|
+
declare class RequiresValidationError extends RunsheetError {
|
|
503
|
+
constructor(message: string);
|
|
504
|
+
}
|
|
505
|
+
/** Schema validation failed on a step's output after it ran. */
|
|
506
|
+
declare class ProvidesValidationError extends RunsheetError {
|
|
507
|
+
constructor(message: string);
|
|
508
|
+
}
|
|
509
|
+
/** Schema validation failed on the pipeline's input arguments. */
|
|
510
|
+
declare class ArgsValidationError extends RunsheetError {
|
|
511
|
+
constructor(message: string);
|
|
512
|
+
}
|
|
513
|
+
/** A `when()` or `choice()` predicate threw an error. */
|
|
514
|
+
declare class PredicateError extends RunsheetError {
|
|
515
|
+
constructor(message: string);
|
|
516
|
+
}
|
|
517
|
+
/** A step exceeded its configured timeout. */
|
|
518
|
+
declare class TimeoutError extends RunsheetError {
|
|
519
|
+
/** The timeout duration in milliseconds that was exceeded. */
|
|
520
|
+
readonly timeoutMs: number;
|
|
521
|
+
constructor(message: string, timeoutMs: number);
|
|
522
|
+
}
|
|
523
|
+
/** A step failed after exhausting all retry attempts. */
|
|
524
|
+
declare class RetryExhaustedError extends RunsheetError {
|
|
525
|
+
/** Total number of attempts (initial + retries). */
|
|
526
|
+
readonly attempts: number;
|
|
527
|
+
constructor(message: string, attempts: number);
|
|
528
|
+
}
|
|
529
|
+
/** Two steps provide the same key (strict mode, detected at build time). */
|
|
530
|
+
declare class StrictOverlapError extends RunsheetError {
|
|
531
|
+
/** The key that is provided by multiple steps. */
|
|
532
|
+
readonly key: string;
|
|
533
|
+
/** The names of the two steps that both provide the key. */
|
|
534
|
+
readonly steps: readonly [string, string];
|
|
535
|
+
constructor(message: string, key: string, steps: readonly [string, string]);
|
|
536
|
+
}
|
|
537
|
+
/** No branch matched in a `choice()` step. */
|
|
538
|
+
declare class ChoiceNoMatchError extends RunsheetError {
|
|
539
|
+
constructor(message: string);
|
|
540
|
+
}
|
|
541
|
+
/** A non-Error value was thrown and caught by the pipeline engine. */
|
|
542
|
+
declare class UnknownError extends RunsheetError {
|
|
543
|
+
/** The original thrown value before stringification. */
|
|
544
|
+
readonly originalValue: unknown;
|
|
545
|
+
constructor(message: string, originalValue: unknown);
|
|
546
|
+
}
|
|
547
|
+
/** One or more rollback handlers failed in a combinator. */
|
|
548
|
+
declare class RollbackError extends RunsheetError {
|
|
549
|
+
/** The individual errors from each failed rollback handler. */
|
|
550
|
+
readonly causes: readonly Error[];
|
|
551
|
+
constructor(message: string, causes?: readonly Error[]);
|
|
552
|
+
}
|
|
376
553
|
|
|
377
554
|
/**
|
|
378
555
|
* Metadata about the step being executed, passed to middleware.
|
|
@@ -391,10 +568,9 @@ type StepInfo = {
|
|
|
391
568
|
/**
|
|
392
569
|
* A function that executes a step (or the next middleware in the chain).
|
|
393
570
|
*
|
|
394
|
-
* Receives the frozen accumulated context and returns a
|
|
395
|
-
* `{ success: true, data }` or `{ success: false, errors }`.
|
|
571
|
+
* Receives the frozen accumulated context and returns a {@link StepResult}.
|
|
396
572
|
*/
|
|
397
|
-
type StepExecutor = (ctx: Readonly<StepContext>) => Promise<
|
|
573
|
+
type StepExecutor = (ctx: Readonly<StepContext>) => Promise<StepResult<StepOutput>>;
|
|
398
574
|
/**
|
|
399
575
|
* Middleware that wraps the entire step lifecycle, including schema
|
|
400
576
|
* validation.
|
|
@@ -405,7 +581,7 @@ type StepExecutor = (ctx: Readonly<StepContext>) => Promise<Result<StepOutput>>;
|
|
|
405
581
|
*
|
|
406
582
|
* - **Observe**: read the context or result for logging/metrics.
|
|
407
583
|
* - **Transform**: modify the result before returning it.
|
|
408
|
-
* - **Short-circuit**: return a `
|
|
584
|
+
* - **Short-circuit**: return a `StepResult` without calling `next`.
|
|
409
585
|
*
|
|
410
586
|
* If a middleware throws, the pipeline catches it and treats it as a
|
|
411
587
|
* step failure (triggering rollback for previously completed steps).
|
|
@@ -426,11 +602,58 @@ type StepExecutor = (ctx: Readonly<StepContext>) => Promise<Result<StepOutput>>;
|
|
|
426
602
|
*/
|
|
427
603
|
type StepMiddleware = (step: StepInfo, next: StepExecutor) => StepExecutor;
|
|
428
604
|
|
|
605
|
+
/**
|
|
606
|
+
* A fluent pipeline builder that progressively narrows the accumulated
|
|
607
|
+
* context type as steps are added.
|
|
608
|
+
*
|
|
609
|
+
* Each method returns a new, frozen builder — builders are immutable.
|
|
610
|
+
*
|
|
611
|
+
* This means you can safely fork a builder to create variants:
|
|
612
|
+
*
|
|
613
|
+
* ```ts
|
|
614
|
+
* const base = pipeline({ name: 'order' }).step(validate);
|
|
615
|
+
* const withCharge = base.step(charge).build();
|
|
616
|
+
* const withoutCharge = base.build(); // unaffected by the fork
|
|
617
|
+
* ```
|
|
618
|
+
*
|
|
619
|
+
* @typeParam Args - The pipeline's initial input type.
|
|
620
|
+
* @typeParam Ctx - The accumulated context type so far (grows with each `.step()`).
|
|
621
|
+
*/
|
|
622
|
+
type PipelineBuilder<Args extends StepContext, Ctx extends StepContext> = {
|
|
623
|
+
/**
|
|
624
|
+
* Add a step to the pipeline.
|
|
625
|
+
*
|
|
626
|
+
* The step's `Requires` type must be satisfied by the current `Ctx`
|
|
627
|
+
* (checked via phantom brands — a step that requires less than `Ctx`
|
|
628
|
+
* is always accepted). The returned builder's `Ctx` expands to
|
|
629
|
+
* include the step's `Provides`.
|
|
630
|
+
*
|
|
631
|
+
* @typeParam S - The step type being added.
|
|
632
|
+
* @param step - A {@link Step} (from `defineStep`, `when`, `pipeline`, etc.).
|
|
633
|
+
* @returns A new builder with the expanded context type.
|
|
634
|
+
*/
|
|
635
|
+
readonly step: <S extends Step>(step: S & ([Ctx] extends [ExtractRequires<S>] ? unknown : never)) => PipelineBuilder<Args, Ctx & ExtractProvides<S>>;
|
|
636
|
+
/**
|
|
637
|
+
* Add middleware to the pipeline.
|
|
638
|
+
*
|
|
639
|
+
* Middleware is applied to every step. Multiple `.use()` calls
|
|
640
|
+
* accumulate — earlier middleware is outermost (executes first).
|
|
641
|
+
*
|
|
642
|
+
* @param middleware - One or more {@link StepMiddleware} functions.
|
|
643
|
+
* @returns A new builder with the middleware added.
|
|
644
|
+
*/
|
|
645
|
+
readonly use: (...middleware: StepMiddleware[]) => PipelineBuilder<Args, Ctx>;
|
|
646
|
+
/**
|
|
647
|
+
* Build the pipeline. Returns an {@link AggregateStep} — pipelines
|
|
648
|
+
* are steps whose `run()` returns {@link AggregateResult}.
|
|
649
|
+
*/
|
|
650
|
+
readonly build: () => AggregateStep<Args, Ctx>;
|
|
651
|
+
};
|
|
652
|
+
|
|
429
653
|
/**
|
|
430
654
|
* Internal configuration shape for the pipeline engine.
|
|
431
655
|
*
|
|
432
|
-
* Users typically don't construct this directly — use `
|
|
433
|
-
* or `createPipeline()` instead.
|
|
656
|
+
* Users typically don't construct this directly — use `pipeline()`.
|
|
434
657
|
*/
|
|
435
658
|
type PipelineConfig = {
|
|
436
659
|
/** Pipeline name, used in execution metadata and error messages. */
|
|
@@ -440,7 +663,7 @@ type PipelineConfig = {
|
|
|
440
663
|
/** Optional middleware applied to every step. First in array = outermost. */
|
|
441
664
|
readonly middleware?: readonly StepMiddleware[];
|
|
442
665
|
/** Optional schema that validates the pipeline's input arguments. */
|
|
443
|
-
readonly argsSchema?:
|
|
666
|
+
readonly argsSchema?: StepSchema<StepContext>;
|
|
444
667
|
/**
|
|
445
668
|
* When `true`, throws at build time if two or more steps provide the
|
|
446
669
|
* same key. Only checks steps that have a `provides` schema with an
|
|
@@ -450,89 +673,57 @@ type PipelineConfig = {
|
|
|
450
673
|
readonly strict?: boolean;
|
|
451
674
|
};
|
|
452
675
|
/**
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
* Call `run(args)` to execute the pipeline. The result is a
|
|
456
|
-
* {@link PipelineResult} — either a success with the fully accumulated
|
|
457
|
-
* context, or a failure with error details and a rollback report.
|
|
676
|
+
* Create a pipeline — either directly from steps, or via the fluent
|
|
677
|
+
* builder API.
|
|
458
678
|
*
|
|
459
|
-
*
|
|
679
|
+
* **With steps** — returns an {@link AggregateStep} immediately:
|
|
460
680
|
*
|
|
461
|
-
* @typeParam Args - The input type accepted by `run()`.
|
|
462
|
-
* @typeParam Ctx - The accumulated output type on success.
|
|
463
|
-
*/
|
|
464
|
-
type Pipeline<Args extends StepContext, Ctx> = {
|
|
465
|
-
/** The pipeline's name, as provided at build time. */
|
|
466
|
-
readonly name: string;
|
|
467
|
-
/**
|
|
468
|
-
* Execute the pipeline.
|
|
469
|
-
*
|
|
470
|
-
* @param args - The initial arguments. Merged into the context before
|
|
471
|
-
* the first step runs. Validated against `argsSchema` if one was
|
|
472
|
-
* provided.
|
|
473
|
-
* @returns A {@link PipelineResult} — discriminate on `success` to
|
|
474
|
-
* access `data` (on success) or `errors`/`rollback` (on failure).
|
|
475
|
-
*/
|
|
476
|
-
readonly run: (args: Args) => Promise<PipelineResult<Ctx>>;
|
|
477
|
-
};
|
|
478
|
-
/**
|
|
479
|
-
* Build a pipeline from an array of steps.
|
|
480
|
-
*
|
|
481
|
-
* The result type is inferred from the steps — `pipeline.run()` returns
|
|
482
|
-
* a {@link PipelineResult} whose `data` is the intersection of the
|
|
483
|
-
* initial `Args` and all step output types.
|
|
484
|
-
*
|
|
485
|
-
* @example
|
|
486
681
|
* ```ts
|
|
487
|
-
* const
|
|
488
|
-
* name: '
|
|
682
|
+
* const checkout = pipeline({
|
|
683
|
+
* name: 'checkout',
|
|
489
684
|
* steps: [validateOrder, chargePayment, sendConfirmation],
|
|
490
685
|
* middleware: [logging, timing],
|
|
491
686
|
* argsSchema: z.object({ orderId: z.string() }),
|
|
492
687
|
* });
|
|
493
|
-
*
|
|
494
|
-
* const result = await pipeline.run({ orderId: '123' });
|
|
495
|
-
* if (result.success) {
|
|
496
|
-
* result.data.chargeId; // string — fully typed
|
|
497
|
-
* }
|
|
498
688
|
* ```
|
|
499
689
|
*
|
|
500
|
-
* **
|
|
501
|
-
*
|
|
502
|
-
* - Context is frozen (`Object.freeze`) at every step boundary.
|
|
503
|
-
* - Conditional steps (wrapped with `when()`) are skipped when their
|
|
504
|
-
* predicate returns false — no snapshot, no rollback entry.
|
|
505
|
-
* - On step failure, rollback handlers for all previously completed
|
|
506
|
-
* steps execute in reverse order (best-effort).
|
|
507
|
-
* - Middleware wraps the full step lifecycle including schema validation.
|
|
690
|
+
* **Without steps** — returns a {@link PipelineBuilder} with
|
|
691
|
+
* progressive type narrowing:
|
|
508
692
|
*
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
*
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
*
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
|
|
529
|
-
|
|
693
|
+
* ```ts
|
|
694
|
+
* const checkout = pipeline({ name: 'checkout' })
|
|
695
|
+
* .step(validateOrder)
|
|
696
|
+
* .step(chargePayment)
|
|
697
|
+
* .build();
|
|
698
|
+
*
|
|
699
|
+
* // With schema (runtime validation):
|
|
700
|
+
* pipeline({
|
|
701
|
+
* name: 'checkout',
|
|
702
|
+
* argsSchema: z.object({ orderId: z.string() }),
|
|
703
|
+
* }).step(validateOrder).build();
|
|
704
|
+
*
|
|
705
|
+
* // Type-only args (no runtime validation):
|
|
706
|
+
* pipeline<{ orderId: string }>({ name: 'checkout' })
|
|
707
|
+
* .step(validateOrder)
|
|
708
|
+
* .build();
|
|
709
|
+
* ```
|
|
710
|
+
*
|
|
711
|
+
* Pipelines ARE steps — they can be used directly in another
|
|
712
|
+
* pipeline's steps array for composition.
|
|
713
|
+
*/
|
|
714
|
+
declare function pipeline<Args extends StepContext = StepContext, S extends Step = Step>(config: {
|
|
530
715
|
readonly name: string;
|
|
531
716
|
readonly steps: readonly S[];
|
|
532
717
|
readonly middleware?: readonly StepMiddleware[];
|
|
533
|
-
readonly argsSchema?:
|
|
718
|
+
readonly argsSchema?: StepSchema<Args>;
|
|
534
719
|
readonly strict?: boolean;
|
|
535
|
-
}):
|
|
720
|
+
}): AggregateStep<Args, Args & UnionToIntersection<ExtractProvides<S>>>;
|
|
721
|
+
declare function pipeline<Args extends StepContext = StepContext>(config: {
|
|
722
|
+
readonly name: string;
|
|
723
|
+
readonly middleware?: readonly StepMiddleware[];
|
|
724
|
+
readonly argsSchema?: StepSchema<Args>;
|
|
725
|
+
readonly strict?: boolean;
|
|
726
|
+
}): PipelineBuilder<Args, Args>;
|
|
536
727
|
|
|
537
728
|
/**
|
|
538
729
|
* A step with a conditional predicate attached.
|
|
@@ -552,24 +743,9 @@ type ConditionalStep = Step & {
|
|
|
552
743
|
* skipped:
|
|
553
744
|
* - No context snapshot is taken.
|
|
554
745
|
* - No rollback entry is created.
|
|
555
|
-
* - The step name is recorded in `
|
|
556
|
-
*
|
|
557
|
-
* If the predicate throws, the pipeline treats it as a step failure
|
|
558
|
-
* and triggers rollback for any previously completed steps.
|
|
746
|
+
* - The step name is not recorded in the pipeline's `meta.stepsExecuted`.
|
|
559
747
|
*
|
|
560
|
-
* @
|
|
561
|
-
* ```ts
|
|
562
|
-
* const steps = [
|
|
563
|
-
* validateOrder,
|
|
564
|
-
* when((ctx) => ctx.order.amount > 100, notifyManager),
|
|
565
|
-
* sendConfirmation,
|
|
566
|
-
* ];
|
|
567
|
-
* ```
|
|
568
|
-
*
|
|
569
|
-
* @typeParam Requires - Inferred from the step's requires type.
|
|
570
|
-
* @typeParam Provides - Inferred from the step's provides type.
|
|
571
|
-
* @param predicate - Guard function. Receives the current accumulated
|
|
572
|
-
* context (frozen). Return `true` to execute, `false` to skip.
|
|
748
|
+
* @param predicate - Guard function. Return `true` to execute, `false` to skip.
|
|
573
749
|
* @param step - The step to conditionally execute.
|
|
574
750
|
* @returns A frozen {@link TypedStep} with the predicate attached.
|
|
575
751
|
*/
|
|
@@ -577,6 +753,7 @@ declare function when<Requires extends StepContext, Provides extends StepContext
|
|
|
577
753
|
|
|
578
754
|
/** Ensure a type satisfies StepContext, falling back to StepContext. */
|
|
579
755
|
type AsContext<T> = T extends StepContext ? T : StepContext;
|
|
756
|
+
|
|
580
757
|
/**
|
|
581
758
|
* Run multiple steps concurrently and merge their outputs.
|
|
582
759
|
*
|
|
@@ -586,8 +763,8 @@ type AsContext<T> = T extends StepContext ? T : StepContext;
|
|
|
586
763
|
* steps are rolled back in reverse array order before the failure
|
|
587
764
|
* propagates.
|
|
588
765
|
*
|
|
589
|
-
*
|
|
590
|
-
*
|
|
766
|
+
* Returns an {@link AggregateStep} with orchestration metadata
|
|
767
|
+
* tracking which inner steps executed.
|
|
591
768
|
*
|
|
592
769
|
* Inner steps retain their own `requires`/`provides` validation,
|
|
593
770
|
* `retry`, and `timeout` behavior. Conditional steps (via `when()`)
|
|
@@ -595,7 +772,7 @@ type AsContext<T> = T extends StepContext ? T : StepContext;
|
|
|
595
772
|
*
|
|
596
773
|
* @example
|
|
597
774
|
* ```ts
|
|
598
|
-
* const
|
|
775
|
+
* const p = pipeline({
|
|
599
776
|
* name: 'checkout',
|
|
600
777
|
* steps: [
|
|
601
778
|
* validateOrder,
|
|
@@ -606,105 +783,182 @@ type AsContext<T> = T extends StepContext ? T : StepContext;
|
|
|
606
783
|
* ```
|
|
607
784
|
*
|
|
608
785
|
* @param steps - Two or more steps to execute concurrently.
|
|
609
|
-
* @returns A frozen {@link
|
|
786
|
+
* @returns A frozen {@link AggregateStep} whose `Requires` is the
|
|
610
787
|
* intersection of all inner steps' requires, and `Provides` is the
|
|
611
788
|
* intersection of all inner steps' provides.
|
|
612
789
|
*/
|
|
613
|
-
declare function parallel<S extends readonly
|
|
790
|
+
declare function parallel<S extends readonly Step[]>(...steps: [...S]): AggregateStep<AsContext<UnionToIntersection<ExtractRequires<S[number]>>>, AsContext<UnionToIntersection<ExtractProvides<S[number]>>>>;
|
|
614
791
|
|
|
792
|
+
/** A [predicate, step] tuple used by {@link choice}. */
|
|
793
|
+
type BranchTuple = readonly [(ctx: Readonly<StepContext>) => boolean, Step];
|
|
794
|
+
/** Extract the Requires type from a branch tuple's step. */
|
|
795
|
+
type BranchRequires<T> = T extends readonly [unknown, infer S extends Step] ? ExtractRequires<S> : T extends Step ? ExtractRequires<T> : StepContext;
|
|
796
|
+
/** Extract the Provides type from a branch tuple's step. */
|
|
797
|
+
type BranchProvides<T> = T extends readonly [unknown, infer S extends Step] ? ExtractProvides<S> : T extends Step ? ExtractProvides<T> : StepContext;
|
|
615
798
|
/**
|
|
616
|
-
*
|
|
617
|
-
* context type as steps are added.
|
|
799
|
+
* Execute the first branch whose predicate returns `true`.
|
|
618
800
|
*
|
|
619
|
-
*
|
|
620
|
-
*
|
|
801
|
+
* Similar to an AWS Step Functions Choice state — predicates are evaluated
|
|
802
|
+
* in order, and the first match wins. Exactly one branch executes. If no
|
|
803
|
+
* predicate matches, the step fails with a `CHOICE_NO_MATCH` error.
|
|
804
|
+
*
|
|
805
|
+
* A bare step (without a predicate tuple) can be passed as the last argument
|
|
806
|
+
* to serve as a default branch — it is equivalent to `[() => true, step]`.
|
|
807
|
+
*
|
|
808
|
+
* Returns an {@link AggregateStep} with orchestration metadata
|
|
809
|
+
* tracking which branch executed.
|
|
621
810
|
*
|
|
811
|
+
* All branches should provide the same output shape so that
|
|
812
|
+
* subsequent steps can rely on a consistent context type.
|
|
813
|
+
*
|
|
814
|
+
* @example
|
|
622
815
|
* ```ts
|
|
623
|
-
* const
|
|
624
|
-
*
|
|
625
|
-
*
|
|
816
|
+
* const p = pipeline({
|
|
817
|
+
* name: 'payment',
|
|
818
|
+
* steps: [
|
|
819
|
+
* validateOrder,
|
|
820
|
+
* choice(
|
|
821
|
+
* [(ctx) => ctx.method === 'card', chargeCard],
|
|
822
|
+
* [(ctx) => ctx.method === 'bank', chargeBankTransfer],
|
|
823
|
+
* chargeDefault, // default
|
|
824
|
+
* ),
|
|
825
|
+
* sendReceipt,
|
|
826
|
+
* ],
|
|
827
|
+
* });
|
|
626
828
|
* ```
|
|
627
829
|
*
|
|
628
|
-
* @
|
|
629
|
-
*
|
|
830
|
+
* @param branches - One or more `[predicate, step]` tuples, optionally
|
|
831
|
+
* followed by a bare step as the default.
|
|
832
|
+
* @returns A frozen {@link AggregateStep} that executes the first
|
|
833
|
+
* matching branch.
|
|
630
834
|
*/
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
*
|
|
635
|
-
* The step's `Requires` type must be satisfied by the current `Ctx`.
|
|
636
|
-
* The returned builder's `Ctx` expands to include the step's `Provides`.
|
|
637
|
-
*
|
|
638
|
-
* @typeParam Provides - The output type of the step being added.
|
|
639
|
-
* @param step - A {@link TypedStep} (from `defineStep` or `when`).
|
|
640
|
-
* @returns A new builder with the expanded context type.
|
|
641
|
-
*/
|
|
642
|
-
readonly step: <Provides extends StepContext>(step: TypedStep<Ctx, Provides>) => PipelineBuilder<Args, Ctx & Provides>;
|
|
643
|
-
/**
|
|
644
|
-
* Add middleware to the pipeline.
|
|
645
|
-
*
|
|
646
|
-
* Middleware is applied to every step. Multiple `.use()` calls
|
|
647
|
-
* accumulate — earlier middleware is outermost (executes first).
|
|
648
|
-
*
|
|
649
|
-
* @param middleware - One or more {@link StepMiddleware} functions.
|
|
650
|
-
* @returns A new builder with the middleware added.
|
|
651
|
-
*/
|
|
652
|
-
readonly use: (...middleware: StepMiddleware[]) => PipelineBuilder<Args, Ctx>;
|
|
653
|
-
/**
|
|
654
|
-
* Build the pipeline.
|
|
655
|
-
*
|
|
656
|
-
* @returns A frozen {@link Pipeline} ready to execute with `run()`.
|
|
657
|
-
*/
|
|
658
|
-
readonly build: () => Pipeline<Args, Ctx>;
|
|
659
|
-
};
|
|
835
|
+
declare function choice<B extends readonly BranchTuple[]>(...branches: [...B]): AggregateStep<AsContext<UnionToIntersection<BranchRequires<B[number]>>>, AsContext<UnionToIntersection<BranchProvides<B[number]>>>>;
|
|
836
|
+
declare function choice<B extends readonly BranchTuple[], D extends Step>(...args: [...B, D]): AggregateStep<AsContext<UnionToIntersection<BranchRequires<B[number]> | ExtractRequires<D>>>, AsContext<UnionToIntersection<BranchProvides<B[number]> | ExtractProvides<D>>>>;
|
|
837
|
+
|
|
660
838
|
/**
|
|
661
|
-
*
|
|
839
|
+
* Iterate over a collection and run a function or step per item, concurrently.
|
|
662
840
|
*
|
|
663
|
-
*
|
|
664
|
-
* extends the known context type, so TypeScript catches mismatches
|
|
665
|
-
* at compile time.
|
|
841
|
+
* **Function form:** `(item, ctx) => result` — items can be any type.
|
|
666
842
|
*
|
|
667
|
-
* **
|
|
668
|
-
*
|
|
669
|
-
* createPipeline<{ orderId: string }>('placeOrder')
|
|
670
|
-
* .step(validateOrder)
|
|
671
|
-
* .step(chargePayment)
|
|
672
|
-
* .build();
|
|
673
|
-
* ```
|
|
843
|
+
* **Step form:** each item must be an object whose keys are spread into
|
|
844
|
+
* the pipeline context before the step runs.
|
|
674
845
|
*
|
|
675
|
-
*
|
|
846
|
+
* The step receives `{ ...ctx, ...item }`. The step's own
|
|
847
|
+
* `requires`/`provides` validation, `retry`, and `timeout` apply
|
|
848
|
+
* per item. On partial failure, succeeded items are rolled back
|
|
849
|
+
* (if the step has a rollback handler).
|
|
850
|
+
*
|
|
851
|
+
* @example
|
|
676
852
|
* ```ts
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
*
|
|
680
|
-
*
|
|
853
|
+
* // Function form
|
|
854
|
+
* const pipeline = pipeline({
|
|
855
|
+
* name: 'notify',
|
|
856
|
+
* steps: [
|
|
857
|
+
* map('emails', (ctx) => ctx.users, async (user) => {
|
|
858
|
+
* await sendEmail(user.email);
|
|
859
|
+
* return { email: user.email, sentAt: new Date() };
|
|
860
|
+
* }),
|
|
861
|
+
* ],
|
|
862
|
+
* });
|
|
863
|
+
*
|
|
864
|
+
* // Step form
|
|
865
|
+
* const pipeline = pipeline({
|
|
866
|
+
* name: 'process',
|
|
867
|
+
* steps: [
|
|
868
|
+
* map('results', (ctx) => ctx.items, processItem),
|
|
869
|
+
* ],
|
|
870
|
+
* });
|
|
681
871
|
* ```
|
|
682
872
|
*
|
|
683
|
-
*
|
|
873
|
+
* @param key - The output key under which results are collected.
|
|
874
|
+
* @param collection - A selector that extracts the collection from context.
|
|
875
|
+
* @param fnOrStep - A per-item function or a step to execute for each item.
|
|
876
|
+
* @returns A frozen {@link TypedStep} that provides `{ [key]: Result[] }`.
|
|
877
|
+
*/
|
|
878
|
+
declare function map<K extends string, Item, Result, Ctx extends StepContext = StepContext>(key: K, collection: (ctx: Readonly<Ctx>) => Item[], fn: (item: Item, ctx: Readonly<Ctx>) => Result | Promise<Result>): TypedStep<Ctx, Record<K, Awaited<Result>[]>>;
|
|
879
|
+
declare function map<K extends string, S extends Step, Ctx extends StepContext = StepContext>(key: K, collection: (ctx: Readonly<Ctx>) => StepContext[], step: S): TypedStep<Ctx, Record<K, ExtractProvides<S>[]>>;
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* Filter a collection from context using a predicate, concurrently.
|
|
883
|
+
*
|
|
884
|
+
* Extracts a collection from the pipeline context, evaluates the
|
|
885
|
+
* predicate for each item via `Promise.allSettled`, and collects
|
|
886
|
+
* items that pass into an array under the given key.
|
|
887
|
+
*
|
|
888
|
+
* Original order is preserved.
|
|
889
|
+
*
|
|
890
|
+
* The predicate can be sync or async. If any predicate throws, the
|
|
891
|
+
* entire step fails — no partial results are returned.
|
|
892
|
+
*
|
|
893
|
+
* There is no rollback (filtering is a pure operation with nothing
|
|
894
|
+
* to undo).
|
|
895
|
+
*
|
|
896
|
+
* @example
|
|
684
897
|
* ```ts
|
|
685
|
-
*
|
|
898
|
+
* const pipeline = pipeline({
|
|
899
|
+
* name: 'notify',
|
|
900
|
+
* steps: [
|
|
901
|
+
* filter(
|
|
902
|
+
* 'eligible',
|
|
903
|
+
* (ctx) => ctx.users,
|
|
904
|
+
* (user) => user.optedIn,
|
|
905
|
+
* ),
|
|
906
|
+
* map('emails', (ctx) => ctx.eligible, sendEmail),
|
|
907
|
+
* ],
|
|
908
|
+
* });
|
|
909
|
+
*
|
|
910
|
+
* // Async predicate
|
|
911
|
+
* filter('valid', (ctx) => ctx.orders, async (order) => {
|
|
912
|
+
* const inventory = await checkInventory(order.sku);
|
|
913
|
+
* return inventory.available >= order.quantity;
|
|
914
|
+
* });
|
|
686
915
|
* ```
|
|
687
916
|
*
|
|
688
|
-
*
|
|
917
|
+
* @param key - The output key under which filtered results are collected.
|
|
918
|
+
* @param collection - A selector that extracts the collection from context.
|
|
919
|
+
* @param predicate - A per-item predicate. Return `true` to keep, `false` to discard.
|
|
920
|
+
* @returns A frozen {@link TypedStep} that provides `{ [key]: Item[] }`.
|
|
921
|
+
*/
|
|
922
|
+
declare function filter<K extends string, Item, Ctx extends StepContext = StepContext>(key: K, collection: (ctx: Readonly<Ctx>) => Item[], predicate: (item: Item, ctx: Readonly<Ctx>) => boolean | Promise<boolean>): TypedStep<Ctx, Record<K, Item[]>>;
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Map each item in a collection to an array, then flatten one level.
|
|
926
|
+
*
|
|
927
|
+
* Extracts a collection from the pipeline context, runs the callback
|
|
928
|
+
* for each item via `Promise.allSettled`, and flattens the per-item
|
|
929
|
+
* arrays into a single array under the given key.
|
|
930
|
+
*
|
|
931
|
+
* The callback can be sync or async. If any callback throws, the
|
|
932
|
+
* entire step fails — no partial results are returned.
|
|
933
|
+
*
|
|
934
|
+
* There is no rollback (pure transformation with nothing to undo).
|
|
935
|
+
*
|
|
936
|
+
* @example
|
|
689
937
|
* ```ts
|
|
690
|
-
*
|
|
938
|
+
* // Expand orders into line items
|
|
939
|
+
* const pipeline = pipeline({
|
|
940
|
+
* name: 'process',
|
|
941
|
+
* steps: [
|
|
942
|
+
* flatMap(
|
|
943
|
+
* 'lineItems',
|
|
944
|
+
* (ctx) => ctx.orders,
|
|
945
|
+
* (order) => order.items,
|
|
946
|
+
* ),
|
|
947
|
+
* ],
|
|
948
|
+
* });
|
|
949
|
+
*
|
|
950
|
+
* // Async callback
|
|
951
|
+
* flatMap('emails', (ctx) => ctx.teams, async (team) => {
|
|
952
|
+
* const members = await fetchMembers(team.id);
|
|
953
|
+
* return members.map((m) => m.email);
|
|
954
|
+
* });
|
|
691
955
|
* ```
|
|
692
956
|
*
|
|
693
|
-
* @
|
|
694
|
-
*
|
|
695
|
-
* @param
|
|
696
|
-
* @
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
* @returns A frozen {@link PipelineBuilder} ready for `.step()`,
|
|
700
|
-
* `.use()`, and `.build()`.
|
|
701
|
-
*/
|
|
702
|
-
type PipelineOptions = {
|
|
703
|
-
strict?: boolean;
|
|
704
|
-
};
|
|
705
|
-
declare function createPipeline<Args extends StepContext>(name: string): PipelineBuilder<Args, Args>;
|
|
706
|
-
declare function createPipeline<Args extends StepContext>(name: string, argsSchema: ParserSchema<Args>): PipelineBuilder<Args, Args>;
|
|
707
|
-
declare function createPipeline<Args extends StepContext>(name: string, options: PipelineOptions): PipelineBuilder<Args, Args>;
|
|
708
|
-
declare function createPipeline<Args extends StepContext>(name: string, argsSchema: ParserSchema<Args>, options: PipelineOptions): PipelineBuilder<Args, Args>;
|
|
957
|
+
* @param key - The output key under which flattened results are collected.
|
|
958
|
+
* @param collection - A selector that extracts the collection from context.
|
|
959
|
+
* @param fn - A per-item callback that returns an array (or Promise of array).
|
|
960
|
+
* @returns A frozen {@link TypedStep} that provides `{ [key]: Item[] }`.
|
|
961
|
+
*/
|
|
962
|
+
declare function flatMap<K extends string, Item, Result, Ctx extends StepContext = StepContext>(key: K, collection: (ctx: Readonly<Ctx>) => Item[], fn: (item: Item, ctx: Readonly<Ctx>) => Result[] | Promise<Result[]>): TypedStep<Ctx, Record<K, Result[]>>;
|
|
709
963
|
|
|
710
|
-
export { type
|
|
964
|
+
export { type AggregateFailure, type AggregateMeta, type AggregateResult, type AggregateStep, type AggregateSuccess, ArgsValidationError, ChoiceNoMatchError, type ConditionalStep, type ExtractProvides, type ExtractRequires, type PipelineBuilder, type PipelineConfig, PredicateError, ProvidesValidationError, RequiresValidationError, RetryExhaustedError, type RetryPolicy, RollbackError, type RollbackFailure, type RollbackReport, RunsheetError, type RunsheetErrorCode, type Step, type StepConfig, type StepContext, type StepExecutor, type StepFailure, type StepInfo, type StepMeta, type StepMiddleware, type StepOutput, type StepResult, type StepSchema, type StepSuccess, StrictOverlapError, TimeoutError, type TypedStep, UnknownError, choice, defineStep, filter, flatMap, map, parallel, pipeline, when };
|