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/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
- Built on composable-functions for Result semantics. Zod is supported for runtime
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 `{ success, data, errors }` — never throws.
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
- ### buildPipeline
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 { buildPipeline } from 'runsheet';
128
+ import { pipeline } from 'runsheet';
127
129
 
128
- const pipeline = buildPipeline({
130
+ const p = pipeline({
129
131
  name: 'checkout',
130
132
  steps: [fetchUser, chargePayment, sendEmail],
131
133
  });
132
134
 
133
- const result = await pipeline.run({ userId: '123', amount: 50 });
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.errors; // what went wrong
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 pipeline = buildPipeline({
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 pipeline = buildPipeline({
159
+ const p = pipeline({
158
160
  name: 'checkout',
159
161
  steps: [fetchUser, chargePayment],
160
162
  strict: true,
161
163
  });
162
164
  ```
163
165
 
164
- ### createPipeline (builder API)
166
+ ### Pipeline composition
165
167
 
166
- Fluent builder with progressive type narrowing.
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
- import { createPipeline } from 'runsheet';
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
- const pipeline = createPipeline('checkout', z.object({ userId: z.string() }))
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 pipeline = createPipeline<{ userId: string }>('checkout')
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
- createPipeline('checkout', { strict: true })
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
- createPipeline('checkout', z.object({ userId: z.string() }), { strict: true })
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 pipeline = buildPipeline({
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 pipeline = buildPipeline({
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 pipeline = buildPipeline({
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 pipeline = buildPipeline({
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 pipeline = buildPipeline({
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 pipeline = buildPipeline({
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 pipeline = createPipeline<{
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 pipeline.run({
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 pipeline = buildPipeline({
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 pipeline = buildPipeline({
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
- createPipeline('checkout')
408
+ pipeline({ name: 'checkout' })
387
409
  .use(timing)
388
410
  .step(fetchUser)
389
411
  .step(chargePayment)
390
412
  .build();
391
413
  ```
392
414
 
393
- ### PipelineResult
415
+ ### StepResult
394
416
 
395
- Every pipeline.run() returns a PipelineResult (never throws):
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
- pipeline: 'checkout',
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
- errors: [Error],
415
- meta: { pipeline, args, stepsExecuted, stepsSkipped },
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, buildPipeline, createPipeline, when, parallel, choice,
442
- map, flatMap, filter Classes: RunsheetError, RequiresValidationError,
443
- ProvidesValidationError, ArgsValidationError, PredicateError, TimeoutError,
444
- RetryExhaustedError, StrictOverlapError, ChoiceNoMatchError, RollbackError,
445
- UnknownError Types: Step, TypedStep, StepConfig, RetryPolicy, Pipeline,
446
- PipelineBuilder, PipelineResult, PipelineSuccess, PipelineFailure,
447
- PipelineExecutionMeta, RollbackReport, RollbackFailure, StepMiddleware,
448
- StepInfo, StepExecutor, ConditionalStep, RunsheetErrorCode, Result, Success,
449
- Failure
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.5.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
  },