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/llms.txt
CHANGED
|
@@ -7,8 +7,8 @@ focused steps with explicit inputs and outputs, then compose them into pipelines
|
|
|
7
7
|
that handle context passing, rollback on failure, and schema validation at every
|
|
8
8
|
boundary.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
schema validation but is optional — TypeScript generics alone provide
|
|
10
|
+
Uses its own `StepResult` type for result semantics. Zod is supported for
|
|
11
|
+
runtime schema validation but is optional — TypeScript generics alone provide
|
|
12
12
|
compile-time safety.
|
|
13
13
|
|
|
14
14
|
## Core concepts
|
|
@@ -20,7 +20,9 @@ compile-time safety.
|
|
|
20
20
|
context).
|
|
21
21
|
- Pipelines run steps sequentially. On failure, rollback handlers execute in
|
|
22
22
|
reverse order with snapshot-based context.
|
|
23
|
-
- Results use `
|
|
23
|
+
- Results use `StepResult<T>` — a discriminated union: `StepSuccess<T>`
|
|
24
|
+
(`success`, `data`, `meta`) or `StepFailure` (`success`, `error`, `meta`,
|
|
25
|
+
`failedStep`, `rollback`). Never throws.
|
|
24
26
|
|
|
25
27
|
## Quick reference
|
|
26
28
|
|
|
@@ -117,25 +119,25 @@ RetryPolicy type:
|
|
|
117
119
|
- backoff?: 'linear' | 'exponential' (default 'linear')
|
|
118
120
|
- retryIf?: (errors: Error[]) => boolean — return false to stop retrying
|
|
119
121
|
|
|
120
|
-
###
|
|
122
|
+
### pipeline
|
|
121
123
|
|
|
122
124
|
Build a pipeline from an array of steps. The result type is inferred from the
|
|
123
125
|
steps.
|
|
124
126
|
|
|
125
127
|
```typescript
|
|
126
|
-
import {
|
|
128
|
+
import { pipeline } from 'runsheet';
|
|
127
129
|
|
|
128
|
-
const
|
|
130
|
+
const p = pipeline({
|
|
129
131
|
name: 'checkout',
|
|
130
132
|
steps: [fetchUser, chargePayment, sendEmail],
|
|
131
133
|
});
|
|
132
134
|
|
|
133
|
-
const result = await
|
|
135
|
+
const result = await p.run({ userId: '123', amount: 50 });
|
|
134
136
|
|
|
135
137
|
if (result.success) {
|
|
136
138
|
result.data.chargeId; // string — fully typed
|
|
137
139
|
} else {
|
|
138
|
-
result.
|
|
140
|
+
result.error; // what went wrong (single Error)
|
|
139
141
|
result.rollback; // { completed: string[], failed: RollbackFailure[] }
|
|
140
142
|
}
|
|
141
143
|
```
|
|
@@ -143,7 +145,7 @@ if (result.success) {
|
|
|
143
145
|
Optional argsSchema validates pipeline input:
|
|
144
146
|
|
|
145
147
|
```typescript
|
|
146
|
-
const
|
|
148
|
+
const p = pipeline({
|
|
147
149
|
name: 'checkout',
|
|
148
150
|
steps: [fetchUser, chargePayment],
|
|
149
151
|
argsSchema: z.object({ userId: z.string(), amount: z.number() }),
|
|
@@ -154,21 +156,37 @@ Use `strict: true` to detect provides key collisions at build time. Throws a
|
|
|
154
156
|
RunsheetError with code 'STRICT_OVERLAP' if two steps provide the same key:
|
|
155
157
|
|
|
156
158
|
```typescript
|
|
157
|
-
const
|
|
159
|
+
const p = pipeline({
|
|
158
160
|
name: 'checkout',
|
|
159
161
|
steps: [fetchUser, chargePayment],
|
|
160
162
|
strict: true,
|
|
161
163
|
});
|
|
162
164
|
```
|
|
163
165
|
|
|
164
|
-
###
|
|
166
|
+
### Pipeline composition
|
|
165
167
|
|
|
166
|
-
|
|
168
|
+
Pipelines are steps — pipeline returns an AggregateStep. A pipeline can be used
|
|
169
|
+
directly as a step in another pipeline's steps array:
|
|
167
170
|
|
|
168
171
|
```typescript
|
|
169
|
-
|
|
172
|
+
const inner = pipeline({ name: 'inner', steps: [a, b] });
|
|
173
|
+
const outer = pipeline({ name: 'outer', steps: [inner, c, d] });
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
If a later outer step fails, the inner pipeline's steps are rolled back.
|
|
177
|
+
|
|
178
|
+
### Builder API
|
|
170
179
|
|
|
171
|
-
|
|
180
|
+
Omit `steps` from the config to get a fluent builder with progressive type
|
|
181
|
+
narrowing.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { pipeline } from 'runsheet';
|
|
185
|
+
|
|
186
|
+
const checkout = pipeline({
|
|
187
|
+
name: 'checkout',
|
|
188
|
+
argsSchema: z.object({ userId: z.string() }),
|
|
189
|
+
})
|
|
172
190
|
.step(fetchUser)
|
|
173
191
|
.step(chargePayment)
|
|
174
192
|
.step(sendEmail)
|
|
@@ -178,7 +196,7 @@ const pipeline = createPipeline('checkout', z.object({ userId: z.string() }))
|
|
|
178
196
|
Type-only args (no runtime validation of pipeline input):
|
|
179
197
|
|
|
180
198
|
```typescript
|
|
181
|
-
const
|
|
199
|
+
const checkout = pipeline<{ userId: string }>({ name: 'checkout' })
|
|
182
200
|
.step(fetchUser)
|
|
183
201
|
.build();
|
|
184
202
|
```
|
|
@@ -186,13 +204,17 @@ const pipeline = createPipeline<{ userId: string }>('checkout')
|
|
|
186
204
|
Strict mode via the builder:
|
|
187
205
|
|
|
188
206
|
```typescript
|
|
189
|
-
|
|
207
|
+
pipeline({ name: 'checkout', strict: true })
|
|
190
208
|
.step(fetchUser)
|
|
191
209
|
.step(chargePayment)
|
|
192
210
|
.build();
|
|
193
211
|
|
|
194
212
|
// Or with a schema:
|
|
195
|
-
|
|
213
|
+
pipeline({
|
|
214
|
+
name: 'checkout',
|
|
215
|
+
argsSchema: z.object({ userId: z.string() }),
|
|
216
|
+
strict: true,
|
|
217
|
+
})
|
|
196
218
|
.step(fetchUser)
|
|
197
219
|
.step(chargePayment)
|
|
198
220
|
.build();
|
|
@@ -203,7 +225,7 @@ createPipeline('checkout', z.object({ userId: z.string() }), { strict: true })
|
|
|
203
225
|
```typescript
|
|
204
226
|
import { parallel } from 'runsheet';
|
|
205
227
|
|
|
206
|
-
const
|
|
228
|
+
const p = pipeline({
|
|
207
229
|
name: 'checkout',
|
|
208
230
|
steps: [
|
|
209
231
|
validateOrder,
|
|
@@ -224,7 +246,7 @@ their own requires/provides validation, retry, and timeout. Conditional steps
|
|
|
224
246
|
```typescript
|
|
225
247
|
import { choice } from 'runsheet';
|
|
226
248
|
|
|
227
|
-
const
|
|
249
|
+
const p = pipeline({
|
|
228
250
|
name: 'checkout',
|
|
229
251
|
steps: [
|
|
230
252
|
validateOrder,
|
|
@@ -249,7 +271,7 @@ code 'CHOICE_NO_MATCH'. Only the matched branch participates in rollback.
|
|
|
249
271
|
import { map } from 'runsheet';
|
|
250
272
|
|
|
251
273
|
// Function form — items can be any type
|
|
252
|
-
const
|
|
274
|
+
const p = pipeline({
|
|
253
275
|
name: 'notify',
|
|
254
276
|
steps: [
|
|
255
277
|
map(
|
|
@@ -264,7 +286,7 @@ const pipeline = buildPipeline({
|
|
|
264
286
|
});
|
|
265
287
|
|
|
266
288
|
// Step form — reuse existing steps, item spread into context
|
|
267
|
-
const
|
|
289
|
+
const p = pipeline({
|
|
268
290
|
name: 'process',
|
|
269
291
|
steps: [map('results', (ctx) => ctx.items, processItem)],
|
|
270
292
|
});
|
|
@@ -280,7 +302,7 @@ On partial failure, succeeded items are rolled back (step form only).
|
|
|
280
302
|
```typescript
|
|
281
303
|
import { filter, map } from 'runsheet';
|
|
282
304
|
|
|
283
|
-
const
|
|
305
|
+
const p = pipeline({
|
|
284
306
|
name: 'notify',
|
|
285
307
|
steps: [
|
|
286
308
|
filter(
|
|
@@ -303,7 +325,7 @@ operation).
|
|
|
303
325
|
```typescript
|
|
304
326
|
import { flatMap } from 'runsheet';
|
|
305
327
|
|
|
306
|
-
const
|
|
328
|
+
const p = pipeline({
|
|
307
329
|
name: 'process',
|
|
308
330
|
steps: [
|
|
309
331
|
flatMap(
|
|
@@ -325,16 +347,16 @@ Pass dependencies as pipeline args — they're available to every step through t
|
|
|
325
347
|
accumulated context without any step needing to provides them:
|
|
326
348
|
|
|
327
349
|
```typescript
|
|
328
|
-
const
|
|
350
|
+
const placeOrder = pipeline<{
|
|
329
351
|
orderId: string;
|
|
330
352
|
stripe: Stripe;
|
|
331
353
|
db: Database;
|
|
332
|
-
}>('placeOrder')
|
|
354
|
+
}>({ name: 'placeOrder' })
|
|
333
355
|
.step(validateOrder)
|
|
334
356
|
.step(chargePayment)
|
|
335
357
|
.build();
|
|
336
358
|
|
|
337
|
-
await
|
|
359
|
+
await placeOrder.run({
|
|
338
360
|
orderId: '123',
|
|
339
361
|
stripe: stripeClient,
|
|
340
362
|
db: dbClient,
|
|
@@ -349,7 +371,7 @@ testing, swap in mocks at the call site.
|
|
|
349
371
|
```typescript
|
|
350
372
|
import { when } from 'runsheet';
|
|
351
373
|
|
|
352
|
-
const
|
|
374
|
+
const p = pipeline({
|
|
353
375
|
name: 'checkout',
|
|
354
376
|
steps: [
|
|
355
377
|
fetchUser,
|
|
@@ -376,43 +398,41 @@ const timing: StepMiddleware = (step, next) => async (ctx) => {
|
|
|
376
398
|
return result;
|
|
377
399
|
};
|
|
378
400
|
|
|
379
|
-
const
|
|
401
|
+
const p = pipeline({
|
|
380
402
|
name: 'checkout',
|
|
381
403
|
steps: [fetchUser, chargePayment],
|
|
382
404
|
middleware: [timing],
|
|
383
405
|
});
|
|
384
406
|
|
|
385
407
|
// Or with the builder:
|
|
386
|
-
|
|
408
|
+
pipeline({ name: 'checkout' })
|
|
387
409
|
.use(timing)
|
|
388
410
|
.step(fetchUser)
|
|
389
411
|
.step(chargePayment)
|
|
390
412
|
.build();
|
|
391
413
|
```
|
|
392
414
|
|
|
393
|
-
###
|
|
415
|
+
### StepResult
|
|
394
416
|
|
|
395
|
-
Every
|
|
417
|
+
Every run() returns a StepResult (never throws):
|
|
396
418
|
|
|
397
419
|
```typescript
|
|
398
420
|
// Success
|
|
399
421
|
{
|
|
400
422
|
success: true,
|
|
401
423
|
data: { /* accumulated context */ },
|
|
402
|
-
errors: [],
|
|
403
424
|
meta: {
|
|
404
|
-
|
|
425
|
+
name: 'checkout',
|
|
405
426
|
args: { userId: '123' },
|
|
406
427
|
stepsExecuted: ['fetchUser', 'chargePayment'],
|
|
407
|
-
stepsSkipped: [],
|
|
408
428
|
},
|
|
409
429
|
}
|
|
410
430
|
|
|
411
431
|
// Failure
|
|
412
432
|
{
|
|
413
433
|
success: false,
|
|
414
|
-
|
|
415
|
-
meta: {
|
|
434
|
+
error: Error,
|
|
435
|
+
meta: { name, args, stepsExecuted },
|
|
416
436
|
failedStep: 'chargePayment',
|
|
417
437
|
rollback: { completed: ['fetchUser'], failed: [] },
|
|
418
438
|
}
|
|
@@ -438,15 +458,16 @@ Application errors (thrown from step run functions) pass through as-is.
|
|
|
438
458
|
|
|
439
459
|
## Key exports
|
|
440
460
|
|
|
441
|
-
Functions: defineStep,
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
461
|
+
Functions: defineStep, pipeline, when, parallel, choice, map, flatMap, filter
|
|
462
|
+
Classes: RunsheetError, RequiresValidationError, ProvidesValidationError,
|
|
463
|
+
ArgsValidationError, PredicateError, TimeoutError, RetryExhaustedError,
|
|
464
|
+
StrictOverlapError, ChoiceNoMatchError, RollbackError, UnknownError Types: Step,
|
|
465
|
+
TypedStep, AggregateStep, StepConfig, StepContext, StepOutput, StepSchema,
|
|
466
|
+
RetryPolicy, StepResult, StepSuccess, StepFailure, StepMeta, AggregateResult,
|
|
467
|
+
AggregateSuccess, AggregateFailure, AggregateMeta, RollbackReport,
|
|
468
|
+
RollbackFailure, PipelineBuilder, PipelineConfig, StepMiddleware, StepInfo,
|
|
469
|
+
StepExecutor, ConditionalStep, RunsheetErrorCode, ExtractRequires,
|
|
470
|
+
ExtractProvides
|
|
450
471
|
|
|
451
472
|
## Important patterns
|
|
452
473
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "runsheet",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Type-safe, composable business logic pipelines for TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"lint:fix": "./scripts/lint.sh --fix",
|
|
36
36
|
"format": "prettier --check .",
|
|
37
37
|
"format:fix": "prettier --write .",
|
|
38
|
-
"typecheck": "tsc --noEmit",
|
|
38
|
+
"typecheck": "tsc --noEmit -p tsconfig.check.json",
|
|
39
39
|
"prepare": "husky",
|
|
40
40
|
"prepublishOnly": "pnpm run build"
|
|
41
41
|
},
|
|
@@ -81,9 +81,6 @@
|
|
|
81
81
|
"engines": {
|
|
82
82
|
"node": ">=20"
|
|
83
83
|
},
|
|
84
|
-
"dependencies": {
|
|
85
|
-
"composable-functions": "^4.0.0"
|
|
86
|
-
},
|
|
87
84
|
"peerDependencies": {
|
|
88
85
|
"zod": "^3.22.0"
|
|
89
86
|
},
|