runsheet 0.5.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 +53 -57
- package/dist/index.cjs +357 -349
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +331 -290
- package/dist/index.d.ts +331 -290
- package/dist/index.js +356 -347
- package/dist/index.js.map +1 -1
- package/llms.txt +66 -45
- package/package.json +2 -5
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.
|
|
351
|
+
*/
|
|
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.
|
|
296
422
|
*/
|
|
297
|
-
type
|
|
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,15 +466,12 @@ 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
|
* ```
|
|
@@ -357,8 +482,8 @@ type RunsheetErrorCode = 'REQUIRES_VALIDATION' | 'PROVIDES_VALIDATION' | 'ARGS_V
|
|
|
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
489
|
* application errors. Use `instanceof` on a subclass (e.g.,
|
|
@@ -421,7 +546,9 @@ declare class UnknownError extends RunsheetError {
|
|
|
421
546
|
}
|
|
422
547
|
/** One or more rollback handlers failed in a combinator. */
|
|
423
548
|
declare class RollbackError extends RunsheetError {
|
|
424
|
-
|
|
549
|
+
/** The individual errors from each failed rollback handler. */
|
|
550
|
+
readonly causes: readonly Error[];
|
|
551
|
+
constructor(message: string, causes?: readonly Error[]);
|
|
425
552
|
}
|
|
426
553
|
|
|
427
554
|
/**
|
|
@@ -441,10 +568,9 @@ type StepInfo = {
|
|
|
441
568
|
/**
|
|
442
569
|
* A function that executes a step (or the next middleware in the chain).
|
|
443
570
|
*
|
|
444
|
-
* Receives the frozen accumulated context and returns a
|
|
445
|
-
* `{ success: true, data }` or `{ success: false, errors }`.
|
|
571
|
+
* Receives the frozen accumulated context and returns a {@link StepResult}.
|
|
446
572
|
*/
|
|
447
|
-
type StepExecutor = (ctx: Readonly<StepContext>) => Promise<
|
|
573
|
+
type StepExecutor = (ctx: Readonly<StepContext>) => Promise<StepResult<StepOutput>>;
|
|
448
574
|
/**
|
|
449
575
|
* Middleware that wraps the entire step lifecycle, including schema
|
|
450
576
|
* validation.
|
|
@@ -455,7 +581,7 @@ type StepExecutor = (ctx: Readonly<StepContext>) => Promise<Result<StepOutput>>;
|
|
|
455
581
|
*
|
|
456
582
|
* - **Observe**: read the context or result for logging/metrics.
|
|
457
583
|
* - **Transform**: modify the result before returning it.
|
|
458
|
-
* - **Short-circuit**: return a `
|
|
584
|
+
* - **Short-circuit**: return a `StepResult` without calling `next`.
|
|
459
585
|
*
|
|
460
586
|
* If a middleware throws, the pipeline catches it and treats it as a
|
|
461
587
|
* step failure (triggering rollback for previously completed steps).
|
|
@@ -476,11 +602,58 @@ type StepExecutor = (ctx: Readonly<StepContext>) => Promise<Result<StepOutput>>;
|
|
|
476
602
|
*/
|
|
477
603
|
type StepMiddleware = (step: StepInfo, next: StepExecutor) => StepExecutor;
|
|
478
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
|
+
|
|
479
653
|
/**
|
|
480
654
|
* Internal configuration shape for the pipeline engine.
|
|
481
655
|
*
|
|
482
|
-
* Users typically don't construct this directly — use `
|
|
483
|
-
* or `createPipeline()` instead.
|
|
656
|
+
* Users typically don't construct this directly — use `pipeline()`.
|
|
484
657
|
*/
|
|
485
658
|
type PipelineConfig = {
|
|
486
659
|
/** Pipeline name, used in execution metadata and error messages. */
|
|
@@ -490,7 +663,7 @@ type PipelineConfig = {
|
|
|
490
663
|
/** Optional middleware applied to every step. First in array = outermost. */
|
|
491
664
|
readonly middleware?: readonly StepMiddleware[];
|
|
492
665
|
/** Optional schema that validates the pipeline's input arguments. */
|
|
493
|
-
readonly argsSchema?:
|
|
666
|
+
readonly argsSchema?: StepSchema<StepContext>;
|
|
494
667
|
/**
|
|
495
668
|
* When `true`, throws at build time if two or more steps provide the
|
|
496
669
|
* same key. Only checks steps that have a `provides` schema with an
|
|
@@ -500,89 +673,57 @@ type PipelineConfig = {
|
|
|
500
673
|
readonly strict?: boolean;
|
|
501
674
|
};
|
|
502
675
|
/**
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
* Call `run(args)` to execute the pipeline. The result is a
|
|
506
|
-
* {@link PipelineResult} — either a success with the fully accumulated
|
|
507
|
-
* 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.
|
|
508
678
|
*
|
|
509
|
-
*
|
|
679
|
+
* **With steps** — returns an {@link AggregateStep} immediately:
|
|
510
680
|
*
|
|
511
|
-
* @typeParam Args - The input type accepted by `run()`.
|
|
512
|
-
* @typeParam Ctx - The accumulated output type on success.
|
|
513
|
-
*/
|
|
514
|
-
type Pipeline<Args extends StepContext, Ctx> = {
|
|
515
|
-
/** The pipeline's name, as provided at build time. */
|
|
516
|
-
readonly name: string;
|
|
517
|
-
/**
|
|
518
|
-
* Execute the pipeline.
|
|
519
|
-
*
|
|
520
|
-
* @param args - The initial arguments. Merged into the context before
|
|
521
|
-
* the first step runs. Validated against `argsSchema` if one was
|
|
522
|
-
* provided.
|
|
523
|
-
* @returns A {@link PipelineResult} — discriminate on `success` to
|
|
524
|
-
* access `data` (on success) or `errors`/`rollback` (on failure).
|
|
525
|
-
*/
|
|
526
|
-
readonly run: (args: Args) => Promise<PipelineResult<Ctx>>;
|
|
527
|
-
};
|
|
528
|
-
/**
|
|
529
|
-
* Build a pipeline from an array of steps.
|
|
530
|
-
*
|
|
531
|
-
* The result type is inferred from the steps — `pipeline.run()` returns
|
|
532
|
-
* a {@link PipelineResult} whose `data` is the intersection of the
|
|
533
|
-
* initial `Args` and all step output types.
|
|
534
|
-
*
|
|
535
|
-
* @example
|
|
536
681
|
* ```ts
|
|
537
|
-
* const
|
|
538
|
-
* name: '
|
|
682
|
+
* const checkout = pipeline({
|
|
683
|
+
* name: 'checkout',
|
|
539
684
|
* steps: [validateOrder, chargePayment, sendConfirmation],
|
|
540
685
|
* middleware: [logging, timing],
|
|
541
686
|
* argsSchema: z.object({ orderId: z.string() }),
|
|
542
687
|
* });
|
|
543
|
-
*
|
|
544
|
-
* const result = await pipeline.run({ orderId: '123' });
|
|
545
|
-
* if (result.success) {
|
|
546
|
-
* result.data.chargeId; // string — fully typed
|
|
547
|
-
* }
|
|
548
688
|
* ```
|
|
549
689
|
*
|
|
550
|
-
* **
|
|
551
|
-
*
|
|
552
|
-
* - Context is frozen (`Object.freeze`) at every step boundary.
|
|
553
|
-
* - Conditional steps (wrapped with `when()`) are skipped when their
|
|
554
|
-
* predicate returns false — no snapshot, no rollback entry.
|
|
555
|
-
* - On step failure, rollback handlers for all previously completed
|
|
556
|
-
* steps execute in reverse order (best-effort).
|
|
557
|
-
* - Middleware wraps the full step lifecycle including schema validation.
|
|
690
|
+
* **Without steps** — returns a {@link PipelineBuilder} with
|
|
691
|
+
* progressive type narrowing:
|
|
558
692
|
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
577
|
-
*
|
|
578
|
-
|
|
579
|
-
|
|
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: {
|
|
580
715
|
readonly name: string;
|
|
581
716
|
readonly steps: readonly S[];
|
|
582
717
|
readonly middleware?: readonly StepMiddleware[];
|
|
583
|
-
readonly argsSchema?:
|
|
718
|
+
readonly argsSchema?: StepSchema<Args>;
|
|
719
|
+
readonly strict?: boolean;
|
|
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>;
|
|
584
725
|
readonly strict?: boolean;
|
|
585
|
-
}):
|
|
726
|
+
}): PipelineBuilder<Args, Args>;
|
|
586
727
|
|
|
587
728
|
/**
|
|
588
729
|
* A step with a conditional predicate attached.
|
|
@@ -602,24 +743,9 @@ type ConditionalStep = Step & {
|
|
|
602
743
|
* skipped:
|
|
603
744
|
* - No context snapshot is taken.
|
|
604
745
|
* - No rollback entry is created.
|
|
605
|
-
* - The step name is recorded in `
|
|
606
|
-
*
|
|
607
|
-
* If the predicate throws, the pipeline treats it as a step failure
|
|
608
|
-
* and triggers rollback for any previously completed steps.
|
|
609
|
-
*
|
|
610
|
-
* @example
|
|
611
|
-
* ```ts
|
|
612
|
-
* const steps = [
|
|
613
|
-
* validateOrder,
|
|
614
|
-
* when((ctx) => ctx.order.amount > 100, notifyManager),
|
|
615
|
-
* sendConfirmation,
|
|
616
|
-
* ];
|
|
617
|
-
* ```
|
|
746
|
+
* - The step name is not recorded in the pipeline's `meta.stepsExecuted`.
|
|
618
747
|
*
|
|
619
|
-
* @
|
|
620
|
-
* @typeParam Provides - Inferred from the step's provides type.
|
|
621
|
-
* @param predicate - Guard function. Receives the current accumulated
|
|
622
|
-
* context (frozen). Return `true` to execute, `false` to skip.
|
|
748
|
+
* @param predicate - Guard function. Return `true` to execute, `false` to skip.
|
|
623
749
|
* @param step - The step to conditionally execute.
|
|
624
750
|
* @returns A frozen {@link TypedStep} with the predicate attached.
|
|
625
751
|
*/
|
|
@@ -637,8 +763,8 @@ type AsContext<T> = T extends StepContext ? T : StepContext;
|
|
|
637
763
|
* steps are rolled back in reverse array order before the failure
|
|
638
764
|
* propagates.
|
|
639
765
|
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
766
|
+
* Returns an {@link AggregateStep} with orchestration metadata
|
|
767
|
+
* tracking which inner steps executed.
|
|
642
768
|
*
|
|
643
769
|
* Inner steps retain their own `requires`/`provides` validation,
|
|
644
770
|
* `retry`, and `timeout` behavior. Conditional steps (via `when()`)
|
|
@@ -646,7 +772,7 @@ type AsContext<T> = T extends StepContext ? T : StepContext;
|
|
|
646
772
|
*
|
|
647
773
|
* @example
|
|
648
774
|
* ```ts
|
|
649
|
-
* const
|
|
775
|
+
* const p = pipeline({
|
|
650
776
|
* name: 'checkout',
|
|
651
777
|
* steps: [
|
|
652
778
|
* validateOrder,
|
|
@@ -657,14 +783,14 @@ type AsContext<T> = T extends StepContext ? T : StepContext;
|
|
|
657
783
|
* ```
|
|
658
784
|
*
|
|
659
785
|
* @param steps - Two or more steps to execute concurrently.
|
|
660
|
-
* @returns A frozen {@link
|
|
786
|
+
* @returns A frozen {@link AggregateStep} whose `Requires` is the
|
|
661
787
|
* intersection of all inner steps' requires, and `Provides` is the
|
|
662
788
|
* intersection of all inner steps' provides.
|
|
663
789
|
*/
|
|
664
|
-
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]>>>>;
|
|
665
791
|
|
|
666
792
|
/** A [predicate, step] tuple used by {@link choice}. */
|
|
667
|
-
type BranchTuple = readonly [(ctx: Readonly<StepContext>) => boolean,
|
|
793
|
+
type BranchTuple = readonly [(ctx: Readonly<StepContext>) => boolean, Step];
|
|
668
794
|
/** Extract the Requires type from a branch tuple's step. */
|
|
669
795
|
type BranchRequires<T> = T extends readonly [unknown, infer S extends Step] ? ExtractRequires<S> : T extends Step ? ExtractRequires<T> : StepContext;
|
|
670
796
|
/** Extract the Provides type from a branch tuple's step. */
|
|
@@ -679,12 +805,15 @@ type BranchProvides<T> = T extends readonly [unknown, infer S extends Step] ? Ex
|
|
|
679
805
|
* A bare step (without a predicate tuple) can be passed as the last argument
|
|
680
806
|
* to serve as a default branch — it is equivalent to `[() => true, step]`.
|
|
681
807
|
*
|
|
682
|
-
*
|
|
683
|
-
*
|
|
808
|
+
* Returns an {@link AggregateStep} with orchestration metadata
|
|
809
|
+
* tracking which branch executed.
|
|
810
|
+
*
|
|
811
|
+
* All branches should provide the same output shape so that
|
|
812
|
+
* subsequent steps can rely on a consistent context type.
|
|
684
813
|
*
|
|
685
814
|
* @example
|
|
686
815
|
* ```ts
|
|
687
|
-
* const
|
|
816
|
+
* const p = pipeline({
|
|
688
817
|
* name: 'payment',
|
|
689
818
|
* steps: [
|
|
690
819
|
* validateOrder,
|
|
@@ -700,31 +829,29 @@ type BranchProvides<T> = T extends readonly [unknown, infer S extends Step] ? Ex
|
|
|
700
829
|
*
|
|
701
830
|
* @param branches - One or more `[predicate, step]` tuples, optionally
|
|
702
831
|
* followed by a bare step as the default.
|
|
703
|
-
* @returns A frozen {@link
|
|
832
|
+
* @returns A frozen {@link AggregateStep} that executes the first
|
|
833
|
+
* matching branch.
|
|
704
834
|
*/
|
|
705
|
-
declare function choice<B extends readonly BranchTuple[]>(...branches: [...B]):
|
|
706
|
-
declare function choice<B extends readonly BranchTuple[], D extends
|
|
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>>>>;
|
|
707
837
|
|
|
708
838
|
/**
|
|
709
839
|
* Iterate over a collection and run a function or step per item, concurrently.
|
|
710
840
|
*
|
|
711
|
-
* Similar to an AWS Step Functions Map state — extracts a collection from
|
|
712
|
-
* the pipeline context, runs the callback for each item via
|
|
713
|
-
* `Promise.allSettled`, and collects results into an array under the
|
|
714
|
-
* given key.
|
|
715
|
-
*
|
|
716
841
|
* **Function form:** `(item, ctx) => result` — items can be any type.
|
|
717
842
|
*
|
|
718
843
|
* **Step form:** each item must be an object whose keys are spread into
|
|
719
|
-
* the pipeline context before the step runs
|
|
720
|
-
*
|
|
721
|
-
*
|
|
722
|
-
*
|
|
844
|
+
* the pipeline context before the step runs.
|
|
845
|
+
*
|
|
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).
|
|
723
850
|
*
|
|
724
851
|
* @example
|
|
725
852
|
* ```ts
|
|
726
853
|
* // Function form
|
|
727
|
-
* const pipeline =
|
|
854
|
+
* const pipeline = pipeline({
|
|
728
855
|
* name: 'notify',
|
|
729
856
|
* steps: [
|
|
730
857
|
* map('emails', (ctx) => ctx.users, async (user) => {
|
|
@@ -735,7 +862,7 @@ declare function choice<B extends readonly BranchTuple[], D extends TypedStep>(.
|
|
|
735
862
|
* });
|
|
736
863
|
*
|
|
737
864
|
* // Step form
|
|
738
|
-
* const pipeline =
|
|
865
|
+
* const pipeline = pipeline({
|
|
739
866
|
* name: 'process',
|
|
740
867
|
* steps: [
|
|
741
868
|
* map('results', (ctx) => ctx.items, processItem),
|
|
@@ -748,16 +875,17 @@ declare function choice<B extends readonly BranchTuple[], D extends TypedStep>(.
|
|
|
748
875
|
* @param fnOrStep - A per-item function or a step to execute for each item.
|
|
749
876
|
* @returns A frozen {@link TypedStep} that provides `{ [key]: Result[] }`.
|
|
750
877
|
*/
|
|
751
|
-
declare function map<K extends string, Item, Result>(key: K, collection: (ctx: Readonly<
|
|
752
|
-
declare function map<K extends string, S extends
|
|
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>[]>>;
|
|
753
880
|
|
|
754
881
|
/**
|
|
755
882
|
* Filter a collection from context using a predicate, concurrently.
|
|
756
883
|
*
|
|
757
884
|
* Extracts a collection from the pipeline context, evaluates the
|
|
758
885
|
* predicate for each item via `Promise.allSettled`, and collects
|
|
759
|
-
* items that pass into an array under the given key.
|
|
760
|
-
*
|
|
886
|
+
* items that pass into an array under the given key.
|
|
887
|
+
*
|
|
888
|
+
* Original order is preserved.
|
|
761
889
|
*
|
|
762
890
|
* The predicate can be sync or async. If any predicate throws, the
|
|
763
891
|
* entire step fails — no partial results are returned.
|
|
@@ -767,10 +895,14 @@ declare function map<K extends string, S extends TypedStep>(key: K, collection:
|
|
|
767
895
|
*
|
|
768
896
|
* @example
|
|
769
897
|
* ```ts
|
|
770
|
-
* const pipeline =
|
|
898
|
+
* const pipeline = pipeline({
|
|
771
899
|
* name: 'notify',
|
|
772
900
|
* steps: [
|
|
773
|
-
* filter(
|
|
901
|
+
* filter(
|
|
902
|
+
* 'eligible',
|
|
903
|
+
* (ctx) => ctx.users,
|
|
904
|
+
* (user) => user.optedIn,
|
|
905
|
+
* ),
|
|
774
906
|
* map('emails', (ctx) => ctx.eligible, sendEmail),
|
|
775
907
|
* ],
|
|
776
908
|
* });
|
|
@@ -787,7 +919,7 @@ declare function map<K extends string, S extends TypedStep>(key: K, collection:
|
|
|
787
919
|
* @param predicate - A per-item predicate. Return `true` to keep, `false` to discard.
|
|
788
920
|
* @returns A frozen {@link TypedStep} that provides `{ [key]: Item[] }`.
|
|
789
921
|
*/
|
|
790
|
-
declare function filter<K extends string, Item>(key: K, collection: (ctx: Readonly<
|
|
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[]>>;
|
|
791
923
|
|
|
792
924
|
/**
|
|
793
925
|
* Map each item in a collection to an array, then flatten one level.
|
|
@@ -804,10 +936,14 @@ declare function filter<K extends string, Item>(key: K, collection: (ctx: Readon
|
|
|
804
936
|
* @example
|
|
805
937
|
* ```ts
|
|
806
938
|
* // Expand orders into line items
|
|
807
|
-
* const pipeline =
|
|
939
|
+
* const pipeline = pipeline({
|
|
808
940
|
* name: 'process',
|
|
809
941
|
* steps: [
|
|
810
|
-
* flatMap(
|
|
942
|
+
* flatMap(
|
|
943
|
+
* 'lineItems',
|
|
944
|
+
* (ctx) => ctx.orders,
|
|
945
|
+
* (order) => order.items,
|
|
946
|
+
* ),
|
|
811
947
|
* ],
|
|
812
948
|
* });
|
|
813
949
|
*
|
|
@@ -823,101 +959,6 @@ declare function filter<K extends string, Item>(key: K, collection: (ctx: Readon
|
|
|
823
959
|
* @param fn - A per-item callback that returns an array (or Promise of array).
|
|
824
960
|
* @returns A frozen {@link TypedStep} that provides `{ [key]: Item[] }`.
|
|
825
961
|
*/
|
|
826
|
-
declare function flatMap<K extends string, Item, Result>(key: K, collection: (ctx: Readonly<
|
|
827
|
-
|
|
828
|
-
/**
|
|
829
|
-
* A fluent pipeline builder that progressively narrows the accumulated
|
|
830
|
-
* context type as steps are added.
|
|
831
|
-
*
|
|
832
|
-
* Each method returns a new, frozen builder — builders are immutable.
|
|
833
|
-
* This means you can safely fork a builder to create variants:
|
|
834
|
-
*
|
|
835
|
-
* ```ts
|
|
836
|
-
* const base = createPipeline('order').step(validate);
|
|
837
|
-
* const withCharge = base.step(charge).build();
|
|
838
|
-
* const withoutCharge = base.build(); // unaffected by the fork
|
|
839
|
-
* ```
|
|
840
|
-
*
|
|
841
|
-
* @typeParam Args - The pipeline's initial input type.
|
|
842
|
-
* @typeParam Ctx - The accumulated context type so far (grows with each `.step()`).
|
|
843
|
-
*/
|
|
844
|
-
type PipelineBuilder<Args extends StepContext, Ctx extends StepContext> = {
|
|
845
|
-
/**
|
|
846
|
-
* Add a step to the pipeline.
|
|
847
|
-
*
|
|
848
|
-
* The step's `Requires` type must be satisfied by the current `Ctx`.
|
|
849
|
-
* The returned builder's `Ctx` expands to include the step's `Provides`.
|
|
850
|
-
*
|
|
851
|
-
* @typeParam Provides - The output type of the step being added.
|
|
852
|
-
* @param step - A {@link TypedStep} (from `defineStep` or `when`).
|
|
853
|
-
* @returns A new builder with the expanded context type.
|
|
854
|
-
*/
|
|
855
|
-
readonly step: <Provides extends StepContext>(step: TypedStep<Ctx, Provides>) => PipelineBuilder<Args, Ctx & Provides>;
|
|
856
|
-
/**
|
|
857
|
-
* Add middleware to the pipeline.
|
|
858
|
-
*
|
|
859
|
-
* Middleware is applied to every step. Multiple `.use()` calls
|
|
860
|
-
* accumulate — earlier middleware is outermost (executes first).
|
|
861
|
-
*
|
|
862
|
-
* @param middleware - One or more {@link StepMiddleware} functions.
|
|
863
|
-
* @returns A new builder with the middleware added.
|
|
864
|
-
*/
|
|
865
|
-
readonly use: (...middleware: StepMiddleware[]) => PipelineBuilder<Args, Ctx>;
|
|
866
|
-
/**
|
|
867
|
-
* Build the pipeline.
|
|
868
|
-
*
|
|
869
|
-
* @returns A frozen {@link Pipeline} ready to execute with `run()`.
|
|
870
|
-
*/
|
|
871
|
-
readonly build: () => Pipeline<Args, Ctx>;
|
|
872
|
-
};
|
|
873
|
-
/**
|
|
874
|
-
* Start building a pipeline with the fluent builder API.
|
|
875
|
-
*
|
|
876
|
-
* The builder gives progressive type narrowing — each `.step()` call
|
|
877
|
-
* extends the known context type, so TypeScript catches mismatches
|
|
878
|
-
* at compile time.
|
|
879
|
-
*
|
|
880
|
-
* **Type-only args** (no runtime validation):
|
|
881
|
-
* ```ts
|
|
882
|
-
* createPipeline<{ orderId: string }>('placeOrder')
|
|
883
|
-
* .step(validateOrder)
|
|
884
|
-
* .step(chargePayment)
|
|
885
|
-
* .build();
|
|
886
|
-
* ```
|
|
887
|
-
*
|
|
888
|
-
* **Schema args** (runtime validation + type inference):
|
|
889
|
-
* ```ts
|
|
890
|
-
* createPipeline('placeOrder', z.object({ orderId: z.string() }))
|
|
891
|
-
* .step(validateOrder)
|
|
892
|
-
* .step(chargePayment)
|
|
893
|
-
* .build();
|
|
894
|
-
* ```
|
|
895
|
-
*
|
|
896
|
-
* **Strict mode** (no schema):
|
|
897
|
-
* ```ts
|
|
898
|
-
* createPipeline('placeOrder', { strict: true })
|
|
899
|
-
* ```
|
|
900
|
-
*
|
|
901
|
-
* **Schema + strict mode:**
|
|
902
|
-
* ```ts
|
|
903
|
-
* createPipeline('placeOrder', z.object({ orderId: z.string() }), { strict: true })
|
|
904
|
-
* ```
|
|
905
|
-
*
|
|
906
|
-
* @typeParam Args - The pipeline's input type. Inferred from `argsSchema`
|
|
907
|
-
* if provided, otherwise specify via generic parameter.
|
|
908
|
-
* @param name - Pipeline name, used in metadata and error messages.
|
|
909
|
-
* @param schemaOrOptions - A schema for runtime args validation, or a
|
|
910
|
-
* {@link PipelineOptions} object.
|
|
911
|
-
* @param options - When the second argument is a schema, pass options here.
|
|
912
|
-
* @returns A frozen {@link PipelineBuilder} ready for `.step()`,
|
|
913
|
-
* `.use()`, and `.build()`.
|
|
914
|
-
*/
|
|
915
|
-
type PipelineOptions = {
|
|
916
|
-
strict?: boolean;
|
|
917
|
-
};
|
|
918
|
-
declare function createPipeline<Args extends StepContext>(name: string): PipelineBuilder<Args, Args>;
|
|
919
|
-
declare function createPipeline<Args extends StepContext>(name: string, argsSchema: ParserSchema<Args>): PipelineBuilder<Args, Args>;
|
|
920
|
-
declare function createPipeline<Args extends StepContext>(name: string, options: PipelineOptions): PipelineBuilder<Args, Args>;
|
|
921
|
-
declare function createPipeline<Args extends StepContext>(name: string, argsSchema: ParserSchema<Args>, options: PipelineOptions): PipelineBuilder<Args, Args>;
|
|
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[]>>;
|
|
922
963
|
|
|
923
|
-
export {
|
|
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 };
|