@celom/prose 0.1.3 → 0.2.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.
@@ -0,0 +1,2 @@
1
+ export * from './lib/index.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,634 @@
1
+ class k extends Error {
2
+ constructor(e, t, r, o) {
3
+ super(e), this.flowName = t, this.stepName = r, this.timeoutMs = o, this.name = "TimeoutError";
4
+ }
5
+ }
6
+ class b extends Error {
7
+ issues;
8
+ constructor(e, t) {
9
+ super(e), this.name = "ValidationError", typeof t == "string" ? this.issues = [{ field: t, message: e }] : Array.isArray(t) ? this.issues = t : this.issues = [{ field: "unknown", message: e }];
10
+ }
11
+ /**
12
+ * Create a validation error for a single field
13
+ */
14
+ static single(e, t, r) {
15
+ return new b(t, [{ field: e, message: t, value: r }]);
16
+ }
17
+ /**
18
+ * Create a validation error for multiple fields
19
+ */
20
+ static multiple(e) {
21
+ const t = `Validation failed: ${e.map((r) => r.field).join(", ")}`;
22
+ return new b(t, e);
23
+ }
24
+ /**
25
+ * Convert to JSON for serialization
26
+ */
27
+ toJSON() {
28
+ return {
29
+ name: this.name,
30
+ message: this.message,
31
+ issues: this.issues
32
+ };
33
+ }
34
+ /**
35
+ * Get a single field error (for backward compatibility)
36
+ */
37
+ get field() {
38
+ return this.issues[0]?.field;
39
+ }
40
+ }
41
+ class d extends Error {
42
+ constructor(e, t, r, o) {
43
+ super(e), this.flowName = t, this.stepName = r, this.originalError = o, this.name = "FlowExecutionError";
44
+ }
45
+ }
46
+ function $(u) {
47
+ if (u.aborted)
48
+ throw u.reason instanceof Error ? u.reason : new Error("Flow execution was aborted");
49
+ }
50
+ function F(u, e) {
51
+ return e.aborted ? Promise.reject(
52
+ e.reason instanceof Error ? e.reason : new Error("Aborted")
53
+ ) : new Promise((t, r) => {
54
+ function o() {
55
+ r(e.reason instanceof Error ? e.reason : new Error("Aborted"));
56
+ }
57
+ e.addEventListener("abort", o, { once: !0 }), u.then(
58
+ (n) => {
59
+ e.removeEventListener("abort", o), t(n);
60
+ },
61
+ (n) => {
62
+ e.removeEventListener("abort", o), r(n);
63
+ }
64
+ );
65
+ });
66
+ }
67
+ function N(u, e) {
68
+ return new Promise((t, r) => {
69
+ if (e.aborted) {
70
+ r(e.reason instanceof Error ? e.reason : new Error("Aborted"));
71
+ return;
72
+ }
73
+ const o = setTimeout(() => {
74
+ e.removeEventListener("abort", n), t();
75
+ }, u);
76
+ function n() {
77
+ clearTimeout(o), r(e.reason instanceof Error ? e.reason : new Error("Aborted"));
78
+ }
79
+ e.addEventListener("abort", n, { once: !0 });
80
+ });
81
+ }
82
+ class T {
83
+ /**
84
+ * Execute a complete flow from configuration
85
+ * @returns FlowExecutionResult containing the result value and whether flow was short-circuited
86
+ */
87
+ async execute(e, t, r, o) {
88
+ const n = Date.now(), i = {
89
+ flowName: e.name,
90
+ startedAt: new Date(n),
91
+ correlationId: o?.correlationId
92
+ }, s = o?.observer, a = new AbortController(), h = o?.signal ? AbortSignal.any([o.signal, a.signal]) : a.signal;
93
+ let p;
94
+ o?.timeout && (p = setTimeout(
95
+ () => a.abort(
96
+ new k(
97
+ `Flow execution timeout after ${o.timeout}ms`,
98
+ e.name,
99
+ void 0,
100
+ o.timeout
101
+ )
102
+ ),
103
+ o.timeout
104
+ ));
105
+ let l = {
106
+ input: Object.freeze(t),
107
+ state: {},
108
+ deps: r,
109
+ meta: i,
110
+ signal: h
111
+ };
112
+ s?.onFlowStart?.(e.name, t);
113
+ try {
114
+ for (const c of e.steps) {
115
+ if ($(h), l.meta.currentStep = c.name, c.condition && !c.condition(l)) {
116
+ s?.onStepSkipped?.(c.name, l);
117
+ continue;
118
+ }
119
+ if (c.type === "break") {
120
+ const g = c, E = Date.now();
121
+ if (s?.onStepStart?.(c.name, l), g.breakCondition(l)) {
122
+ const y = g.breakReturnValue ? g.breakReturnValue(l) : l.state, M = Date.now() - E, x = Date.now() - n;
123
+ return s?.onStepComplete?.(c.name, y, M, l), s?.onFlowBreak?.(
124
+ e.name,
125
+ c.name,
126
+ y,
127
+ x
128
+ ), { value: y, didBreak: !0 };
129
+ }
130
+ const A = Date.now() - E;
131
+ s?.onStepComplete?.(
132
+ c.name,
133
+ { __breakConditionMet: !1 },
134
+ A,
135
+ l
136
+ );
137
+ continue;
138
+ }
139
+ const w = await this.executeStep(c, l, r, o, h);
140
+ w && typeof w == "object" && c.type !== "event" && (l = {
141
+ ...l,
142
+ state: { ...l.state, ...w }
143
+ });
144
+ }
145
+ const m = Date.now() - n;
146
+ return s?.onFlowComplete?.(e.name, l.state, m), { value: l.state, didBreak: !1 };
147
+ } catch (m) {
148
+ const c = Date.now() - n;
149
+ if (s?.onFlowError?.(e.name, m, c), o?.throwOnError === !1)
150
+ return { value: l.state, didBreak: !1 };
151
+ throw m;
152
+ } finally {
153
+ p !== void 0 && clearTimeout(p), a.abort();
154
+ }
155
+ }
156
+ /**
157
+ * Execute a single step with retry logic
158
+ */
159
+ async executeStep(e, t, r, o, n) {
160
+ const i = e.retryOptions;
161
+ return i ? this.executeWithRetry(e, t, r, i, o, n) : this.executeSingleStep(e, t, r, o, n);
162
+ }
163
+ /**
164
+ * Execute a step with retry logic
165
+ */
166
+ async executeWithRetry(e, t, r, o, n, i) {
167
+ const s = n?.observer;
168
+ let a, h = o.delayMs;
169
+ for (let p = 1; p <= o.maxAttempts; p++) {
170
+ $(i);
171
+ try {
172
+ return await this.executeSingleStep(e, t, r, n, i);
173
+ } catch (l) {
174
+ if (a = l instanceof Error ? l : new Error(String(l)), o.shouldRetry && !o.shouldRetry(a) || a instanceof b || p === o.maxAttempts)
175
+ throw a;
176
+ s?.onStepRetry?.(
177
+ e.name,
178
+ p,
179
+ o.maxAttempts,
180
+ a
181
+ ), await N(h, i), o.backoffMultiplier && (h = Math.min(
182
+ h * o.backoffMultiplier,
183
+ o.maxDelayMs || Number.MAX_SAFE_INTEGER
184
+ ));
185
+ }
186
+ }
187
+ throw a;
188
+ }
189
+ /**
190
+ * Execute a single step without retry
191
+ */
192
+ async executeSingleStep(e, t, r, o, n) {
193
+ const i = o?.observer, s = Date.now(), a = e.retryOptions?.stepTimeout ?? o?.stepTimeout;
194
+ i?.onStepStart?.(e.name, t);
195
+ let h, p, l = t;
196
+ if (a) {
197
+ h = new AbortController();
198
+ const m = AbortSignal.any([n, h.signal]);
199
+ l = { ...t, signal: m }, p = setTimeout(
200
+ () => h.abort(
201
+ new k(
202
+ `Step '${e.name}' timed out after ${a}ms`,
203
+ t.meta.flowName,
204
+ e.name,
205
+ a
206
+ )
207
+ ),
208
+ a
209
+ );
210
+ }
211
+ try {
212
+ const c = await F((async () => {
213
+ switch (e.type) {
214
+ case "validate": {
215
+ await e.handler(l);
216
+ return;
217
+ }
218
+ case "step":
219
+ return await e.handler(l);
220
+ case "transaction":
221
+ return await this.executeTransaction(e, l, r, o);
222
+ case "event":
223
+ return await this.executeEvent(e, l, o);
224
+ default:
225
+ throw new d(
226
+ "Unknown step type",
227
+ t.meta.flowName
228
+ );
229
+ }
230
+ })(), l.signal), w = Date.now() - s;
231
+ return i?.onStepComplete?.(e.name, c, w, t), c;
232
+ } catch (m) {
233
+ const c = Date.now() - s;
234
+ throw i?.onStepError?.(e.name, m, c, t), m;
235
+ } finally {
236
+ p !== void 0 && clearTimeout(p);
237
+ }
238
+ }
239
+ /**
240
+ * Execute a transaction step
241
+ */
242
+ async executeTransaction(e, t, r, o) {
243
+ const n = r.db;
244
+ if (!n) {
245
+ const i = o?.errorHandling?.throwOnMissingDatabase ?? !0, s = "No database found in dependencies for transaction";
246
+ if (i)
247
+ throw new d(s, t.meta.flowName, e.name);
248
+ console.warn(`[Workflow:${t.meta.flowName}] ${s}`);
249
+ return;
250
+ }
251
+ return await n.transaction(async (i) => await e.handler(t, i));
252
+ }
253
+ /**
254
+ * Execute an event publishing step
255
+ */
256
+ async executeEvent(e, t, r) {
257
+ const o = t.deps.eventPublisher;
258
+ if (!o) {
259
+ const s = r?.errorHandling?.throwOnMissingEventPublisher ?? !0, a = "No event publisher found in dependencies";
260
+ if (s)
261
+ throw new d(a, t.meta.flowName, e.name);
262
+ console.warn(`[Workflow:${t.meta.flowName}] ${a}`);
263
+ return;
264
+ }
265
+ if (typeof o.publish != "function")
266
+ throw new d(
267
+ "Event publisher must have publish() method",
268
+ t.meta.flowName,
269
+ e.name
270
+ );
271
+ const n = await e.handler(t);
272
+ if (!n)
273
+ return;
274
+ const i = Array.isArray(n) ? n : [n];
275
+ for (const s of i)
276
+ s && s.eventType && await this.publishEvent(o, s, e.channel, t);
277
+ }
278
+ /**
279
+ * Publish a single event to a specific channel
280
+ */
281
+ async publishEvent(e, t, r, o) {
282
+ const n = {
283
+ ...t,
284
+ correlationId: o.meta.correlationId
285
+ };
286
+ await e.publish(r, n);
287
+ }
288
+ }
289
+ function S(u) {
290
+ if (u === null || typeof u != "object") return !1;
291
+ const e = Object.getPrototypeOf(u);
292
+ return e === Object.prototype || e === null;
293
+ }
294
+ function v(...u) {
295
+ const e = {};
296
+ for (const t of u)
297
+ if (S(t))
298
+ for (const r in t) {
299
+ if (!Object.prototype.hasOwnProperty.call(t, r)) continue;
300
+ const o = e[r], n = t[r];
301
+ Array.isArray(n) ? Array.isArray(o) ? e[r] = [...o, ...n] : e[r] = [...n] : S(n) ? S(o) ? e[r] = v(o, n) : e[r] = v({}, n) : e[r] = n;
302
+ }
303
+ return e;
304
+ }
305
+ function D(u) {
306
+ return new f(u);
307
+ }
308
+ class f {
309
+ // Requires "any" for proper output inference
310
+ constructor(e, t = null, r = 0, o) {
311
+ this.name = e, this.steps = t, this.length = r, o && (this.outputMapper = o);
312
+ }
313
+ steps;
314
+ length;
315
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
316
+ outputMapper;
317
+ // Convert linked list of steps to an array for easier processing
318
+ toArray() {
319
+ const e = new Array(this.length);
320
+ let t = this.steps;
321
+ for (let r = this.length - 1; r >= 0; r--)
322
+ e[r] = t.head, t = t.tail;
323
+ return e;
324
+ }
325
+ /**
326
+ * Add a validation step
327
+ */
328
+ validate(e, t) {
329
+ return new f(
330
+ this.name,
331
+ { head: { name: e, type: "validate", handler: t }, tail: this.steps },
332
+ this.length + 1,
333
+ this.outputMapper
334
+ );
335
+ }
336
+ /**
337
+ * Add a regular step that can return state to merge
338
+ */
339
+ step(e, t, r) {
340
+ return new f(
341
+ this.name,
342
+ { head: { name: e, type: "step", handler: t, retryOptions: r }, tail: this.steps },
343
+ this.length + 1,
344
+ this.outputMapper
345
+ );
346
+ }
347
+ /**
348
+ * Add a conditional step that only executes if condition is met
349
+ */
350
+ stepIf(e, t, r, o) {
351
+ return new f(
352
+ this.name,
353
+ { head: { name: e, type: "step", handler: r, condition: t, retryOptions: o }, tail: this.steps },
354
+ this.length + 1,
355
+ this.outputMapper
356
+ );
357
+ }
358
+ /**
359
+ * Add a transaction step for database operations
360
+ */
361
+ transaction(e, t) {
362
+ return new f(
363
+ this.name,
364
+ {
365
+ // Safe assertion: at runtime the executor passes the actual ORM tx object,
366
+ // which matches the inferred type. The step definition uses `unknown` for
367
+ // storage but contravariance prevents direct assignment.
368
+ head: { name: e, type: "transaction", handler: t },
369
+ tail: this.steps
370
+ },
371
+ this.length + 1,
372
+ this.outputMapper
373
+ );
374
+ }
375
+ /**
376
+ * Add an event publishing step with explicit channel
377
+ */
378
+ event(e, t, r = "publishEvent") {
379
+ return new f(
380
+ this.name,
381
+ { head: { name: r, type: "event", channel: e, handler: t }, tail: this.steps },
382
+ this.length + 1,
383
+ this.outputMapper
384
+ );
385
+ }
386
+ /**
387
+ * Add multiple events to publish to the same channel
388
+ */
389
+ events(e, t, r = "publishEvents") {
390
+ const o = async (n) => {
391
+ const i = [];
392
+ for (const s of t) {
393
+ const a = await s(n);
394
+ a && (Array.isArray(a) ? i.push(...a) : i.push(a));
395
+ }
396
+ return i.length > 0 ? i : void 0;
397
+ };
398
+ return new f(
399
+ this.name,
400
+ { head: { name: r, type: "event", channel: e, handler: o }, tail: this.steps },
401
+ this.length + 1,
402
+ this.outputMapper
403
+ );
404
+ }
405
+ breakIf(e, t) {
406
+ const r = `break_${this.length}`;
407
+ return new f(
408
+ this.name,
409
+ { head: { name: r, type: "break", breakCondition: e, breakReturnValue: t }, tail: this.steps },
410
+ this.length + 1,
411
+ this.outputMapper
412
+ );
413
+ }
414
+ /**
415
+ * Add a retry configuration to the last step
416
+ */
417
+ withRetry(e) {
418
+ return this.steps === null ? this : new f(
419
+ this.name,
420
+ { head: { ...this.steps.head, retryOptions: e }, tail: this.steps.tail },
421
+ this.length,
422
+ this.outputMapper
423
+ );
424
+ }
425
+ /**
426
+ * Add a parallel execution step that runs multiple handlers concurrently
427
+ * and merges their results into the flow state.
428
+ *
429
+ * @example
430
+ * .parallel('fetchAll', 'shallow',
431
+ * (ctx) => ({ users: fetchUsers(ctx.input.orgId) }),
432
+ * (ctx) => ({ posts: fetchPosts(ctx.input.orgId) }),
433
+ * )
434
+ */
435
+ parallel(e, t, ...r) {
436
+ const o = async (n) => {
437
+ const i = await Promise.all(
438
+ r.map((s) => s(n))
439
+ );
440
+ if (t === "error-on-conflict") {
441
+ const s = /* @__PURE__ */ new Set();
442
+ for (const a of i)
443
+ if (a && typeof a == "object")
444
+ for (const h in a) {
445
+ if (s.has(h))
446
+ throw new Error(
447
+ `[Workflow:${e}] Key conflict detected in parallel merge: '${h}'`
448
+ );
449
+ s.add(h);
450
+ }
451
+ return Object.assign({}, ...i);
452
+ }
453
+ return t === "deep" ? v(
454
+ {},
455
+ ...i
456
+ ) : Object.assign({}, ...i);
457
+ };
458
+ return new f(
459
+ this.name,
460
+ {
461
+ head: { name: e, type: "step", handler: o },
462
+ tail: this.steps
463
+ },
464
+ this.length + 1,
465
+ this.outputMapper
466
+ );
467
+ }
468
+ /**
469
+ * Apply a builder-to-builder transformation, enabling reusable sub-flows.
470
+ *
471
+ * @example
472
+ * function withAuth(builder) {
473
+ * return builder
474
+ * .step('validateToken', ...)
475
+ * .step('loadUser', ...);
476
+ * }
477
+ *
478
+ * createFlow('order')
479
+ * .pipe(withAuth)
480
+ * .step('createOrder', ...)
481
+ * .build();
482
+ */
483
+ pipe(e) {
484
+ return e(this);
485
+ }
486
+ /**
487
+ * Transform the accumulated state into the final output
488
+ */
489
+ map(e) {
490
+ return new f(
491
+ this.name,
492
+ this.steps,
493
+ this.length,
494
+ e
495
+ );
496
+ }
497
+ /**
498
+ * Build the flow definition
499
+ */
500
+ build() {
501
+ const e = this.toArray(), t = /* @__PURE__ */ new Set(), r = [];
502
+ for (const s of e)
503
+ t.has(s.name) && r.push(s.name), t.add(s.name);
504
+ if (r.length > 0)
505
+ throw new Error(
506
+ `Flow '${this.name}' has duplicate step names: ${r.join(", ")}. Each step must have a unique name for proper debugging and observability.`
507
+ );
508
+ const o = new T(), n = {
509
+ name: this.name,
510
+ steps: e
511
+ }, i = this.outputMapper;
512
+ return {
513
+ name: n.name,
514
+ steps: n.steps,
515
+ execute: async (s, a, h) => {
516
+ const p = await o.execute(n, s, a, h);
517
+ return p.didBreak ? p.value : i ? i(s, p.value) : p.value;
518
+ }
519
+ };
520
+ }
521
+ }
522
+ class C {
523
+ constructor(e) {
524
+ this.logger = e;
525
+ }
526
+ onFlowStart(e, t) {
527
+ this.logger?.debug?.(
528
+ `[Workflow] Flow ${e} started. Input: ${t}`
529
+ );
530
+ }
531
+ onFlowComplete(e, t, r) {
532
+ this.logger?.debug?.(
533
+ `[Workflow] Flow ${e} completed. Output: ${t} - (${r}ms)`
534
+ );
535
+ }
536
+ onFlowError(e, t, r) {
537
+ this.logger?.error?.(
538
+ `[Workflow] Flow failed: ${e} (${r}ms)`,
539
+ t
540
+ );
541
+ }
542
+ onStepStart(e) {
543
+ this.logger?.debug?.(`[Workflow] Step started: ${e}`);
544
+ }
545
+ onStepComplete(e, t, r) {
546
+ this.logger?.debug?.(
547
+ `[Workflow] Step completed: ${e} (${r}ms)`
548
+ );
549
+ }
550
+ onStepError(e, t, r) {
551
+ this.logger?.error?.(
552
+ `[Workflow] Step failed: ${e} (${r}ms)`,
553
+ t
554
+ );
555
+ }
556
+ onStepRetry(e, t, r, o) {
557
+ this.logger?.warn?.(
558
+ `[Workflow] Step retry: ${e} (attempt ${t}/${r}) - ${o.message}`
559
+ );
560
+ }
561
+ onStepSkipped(e) {
562
+ this.logger?.debug?.(`[Workflow] Step skipped: ${e}`);
563
+ }
564
+ onFlowBreak(e, t, r, o) {
565
+ this.logger?.debug?.(
566
+ `[Workflow] Flow ${e} short-circuited at '${t}' (${o}ms)`
567
+ );
568
+ }
569
+ }
570
+ class O {
571
+ // All methods intentionally left empty
572
+ }
573
+ class W {
574
+ logger;
575
+ constructor(e) {
576
+ this.logger = e.child({ component: "workflow" });
577
+ }
578
+ onFlowStart(e, t) {
579
+ this.logger.info({ flow: e }, "Flow started");
580
+ }
581
+ onFlowComplete(e, t, r) {
582
+ this.logger.info(
583
+ { flow: e, durationMs: r },
584
+ "Flow completed"
585
+ );
586
+ }
587
+ onFlowError(e, t, r) {
588
+ this.logger.error(
589
+ { flow: e, durationMs: r, err: t },
590
+ "Flow failed"
591
+ );
592
+ }
593
+ onStepStart(e, t) {
594
+ this.logger.debug({ step: e }, "Step started");
595
+ }
596
+ onStepComplete(e, t, r, o) {
597
+ const n = {
598
+ step: e,
599
+ durationMs: r
600
+ };
601
+ t && typeof t == "object" && (n.resultKeys = Object.keys(t)), this.logger.info(n, "Step completed");
602
+ }
603
+ onStepError(e, t, r, o) {
604
+ this.logger.error(
605
+ { step: e, durationMs: r, err: t },
606
+ "Step failed"
607
+ );
608
+ }
609
+ onStepRetry(e, t, r, o) {
610
+ this.logger.warn(
611
+ { step: e, attempt: t, maxAttempts: r, err: o },
612
+ "Step retrying"
613
+ );
614
+ }
615
+ onStepSkipped(e, t) {
616
+ this.logger.debug({ step: e }, "Step skipped");
617
+ }
618
+ onFlowBreak(e, t, r, o) {
619
+ this.logger.info(
620
+ { flow: e, breakStep: t, durationMs: o },
621
+ "Flow short-circuited"
622
+ );
623
+ }
624
+ }
625
+ export {
626
+ C as DefaultObserver,
627
+ f as FlowBuilder,
628
+ d as FlowExecutionError,
629
+ O as NoOpObserver,
630
+ W as PinoFlowObserver,
631
+ k as TimeoutError,
632
+ b as ValidationError,
633
+ D as createFlow
634
+ };
@@ -0,0 +1,120 @@
1
+ import { FlowContext, FlowDefinition, StepDefinition, StepCondition, RetryOptions, FlowState, BaseFlowDependencies, FlowEvent, MergeStrategy } from './types.js';
2
+ type StepNode<T> = {
3
+ readonly head: T;
4
+ readonly tail: StepNode<T> | null;
5
+ };
6
+ /**
7
+ * Infer the transaction client type from the deps' db.transaction signature.
8
+ * Falls back to `unknown` when TDeps is `never` or db is absent/untyped.
9
+ */
10
+ type InferTransactionClient<TDeps> = [TDeps] extends [never] ? unknown : TDeps extends {
11
+ db: {
12
+ transaction(fn: (tx: infer Tx) => any): any;
13
+ };
14
+ } ? Tx : unknown;
15
+ /**
16
+ * Converts a union type to an intersection type.
17
+ * Used to merge return types from parallel/sequence handlers.
18
+ */
19
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
20
+ /**
21
+ * Create a new flow with the given name
22
+ */
23
+ export declare function createFlow<TInput, TDeps extends BaseFlowDependencies = never>(name: string): FlowBuilder<TInput, TDeps, Record<string, never>, never, never>;
24
+ /**
25
+ * FlowBuilder provides a fluent API for creating declarative workflows
26
+ */
27
+ export declare class FlowBuilder<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState, TMapperOutput = never, TBreakOutputs = never> {
28
+ private name;
29
+ private steps;
30
+ private length;
31
+ private outputMapper?;
32
+ constructor(name: string, steps?: StepNode<StepDefinition<TInput, TDeps, TState>> | null, length?: number, mapper?: (input: TInput, state: TState) => TMapperOutput);
33
+ private toArray;
34
+ /**
35
+ * Add a validation step
36
+ */
37
+ validate(name: string, handler: (ctx: FlowContext<TInput, TDeps, TState>) => void | Promise<void>): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
38
+ /**
39
+ * Add a regular step that can return state to merge
40
+ */
41
+ step<TResult extends object>(name: string, handler: (ctx: FlowContext<TInput, TDeps, TState>) => TResult | void | undefined | Promise<TResult | void | undefined>, retryOptions?: RetryOptions): FlowBuilder<TInput, TDeps, TResult & TState, TMapperOutput, TBreakOutputs>;
42
+ /**
43
+ * Add a conditional step that only executes if condition is met
44
+ */
45
+ stepIf<TResult extends object>(name: string, condition: StepCondition<TInput, TDeps, TState>, handler: (ctx: FlowContext<TInput, TDeps, TState>) => TResult | void | undefined | Promise<TResult | void | undefined>, retryOptions?: RetryOptions): FlowBuilder<TInput, TDeps, TResult & TState, TMapperOutput, TBreakOutputs>;
46
+ /**
47
+ * Add a transaction step for database operations
48
+ */
49
+ transaction<TResult extends object>(name: string, handler: (ctx: FlowContext<TInput, TDeps, TState>, tx: InferTransactionClient<TDeps>) => TResult | Promise<TResult>): FlowBuilder<TInput, TDeps, TResult & TState, TMapperOutput, TBreakOutputs>;
50
+ /**
51
+ * Add an event publishing step with explicit channel
52
+ */
53
+ event(channel: string, builder: (ctx: FlowContext<TInput, TDeps, TState>) => FlowEvent | FlowEvent[] | void | Promise<FlowEvent | FlowEvent[] | void>, name?: string): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
54
+ /**
55
+ * Add multiple events to publish to the same channel
56
+ */
57
+ events(channel: string, builders: Array<(ctx: FlowContext<TInput, TDeps, TState>) => FlowEvent | FlowEvent[] | void | Promise<FlowEvent | FlowEvent[] | void>>, name?: string): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
58
+ /**
59
+ * Add a break condition that short-circuits the flow if met.
60
+ * When the condition returns true, the flow stops and returns the value
61
+ * from the returnValue function (or the accumulated state if not provided).
62
+ *
63
+ * @param condition - Function that returns true to break the flow
64
+ * @param returnValue - Optional function to compute the return value when breaking
65
+ * @returns New FlowBuilder with break step added
66
+ *
67
+ * @example
68
+ * .step('validateToken', validateVerificationTokenStep)
69
+ * .breakIf(
70
+ * (ctx) => ctx.state.alreadyVerified,
71
+ * (ctx) => ({ success: true, alreadyVerified: true })
72
+ * )
73
+ * .step('getAccount', getAccountStep) // Only runs if not already verified
74
+ */
75
+ breakIf(condition: (ctx: FlowContext<TInput, TDeps, TState>) => boolean): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs | TState>;
76
+ breakIf<TBreakOutput>(condition: (ctx: FlowContext<TInput, TDeps, TState>) => boolean, returnValue: (ctx: FlowContext<TInput, TDeps, TState>) => TBreakOutput): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs | TBreakOutput>;
77
+ /**
78
+ * Add a retry configuration to the last step
79
+ */
80
+ withRetry(options: RetryOptions): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
81
+ /**
82
+ * Add a parallel execution step that runs multiple handlers concurrently
83
+ * and merges their results into the flow state.
84
+ *
85
+ * @example
86
+ * .parallel('fetchAll', 'shallow',
87
+ * (ctx) => ({ users: fetchUsers(ctx.input.orgId) }),
88
+ * (ctx) => ({ posts: fetchPosts(ctx.input.orgId) }),
89
+ * )
90
+ */
91
+ parallel<TResults extends object[]>(name: string, strategy: MergeStrategy, ...handlers: {
92
+ [K in keyof TResults]: (ctx: FlowContext<TInput, TDeps, TState>) => TResults[K] | Promise<TResults[K]>;
93
+ }): FlowBuilder<TInput, TDeps, UnionToIntersection<TResults[number]> & TState, TMapperOutput, TBreakOutputs>;
94
+ /**
95
+ * Apply a builder-to-builder transformation, enabling reusable sub-flows.
96
+ *
97
+ * @example
98
+ * function withAuth(builder) {
99
+ * return builder
100
+ * .step('validateToken', ...)
101
+ * .step('loadUser', ...);
102
+ * }
103
+ *
104
+ * createFlow('order')
105
+ * .pipe(withAuth)
106
+ * .step('createOrder', ...)
107
+ * .build();
108
+ */
109
+ pipe<R>(fn: (builder: this) => R): R;
110
+ /**
111
+ * Transform the accumulated state into the final output
112
+ */
113
+ map<TNewOutput>(mapper: (input: TInput, state: TState) => TNewOutput): FlowBuilder<TInput, TDeps, TState, TNewOutput, TBreakOutputs>;
114
+ /**
115
+ * Build the flow definition
116
+ */
117
+ build(): FlowDefinition<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
118
+ }
119
+ export {};
120
+ //# sourceMappingURL=flow-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-builder.d.ts","sourceRoot":"","sources":["../../src/lib/flow-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { FlowConfig, FlowExecutionOptions, FlowState, BaseFlowDependencies, FlowExecutionResult } from './types.js';
2
+ export declare class FlowExecutor<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState = Record<string, unknown>> {
3
+ /**
4
+ * Execute a complete flow from configuration
5
+ * @returns FlowExecutionResult containing the result value and whether flow was short-circuited
6
+ */
7
+ execute(config: FlowConfig<TInput, TDeps, TState>, input: TInput, deps: TDeps, options?: FlowExecutionOptions<TInput, TDeps, TState>): Promise<FlowExecutionResult<TState>>;
8
+ /**
9
+ * Execute a single step with retry logic
10
+ */
11
+ private executeStep;
12
+ /**
13
+ * Execute a step with retry logic
14
+ */
15
+ private executeWithRetry;
16
+ /**
17
+ * Execute a single step without retry
18
+ */
19
+ private executeSingleStep;
20
+ /**
21
+ * Execute a transaction step
22
+ */
23
+ private executeTransaction;
24
+ /**
25
+ * Execute an event publishing step
26
+ */
27
+ private executeEvent;
28
+ /**
29
+ * Publish a single event to a specific channel
30
+ */
31
+ private publishEvent;
32
+ }
33
+ //# sourceMappingURL=flow-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-executor.d.ts","sourceRoot":"","sources":["../../src/lib/flow-executor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAEV,UAAU,EACV,oBAAoB,EAIpB,SAAS,EACT,oBAAoB,EAGpB,mBAAmB,EAGpB,MAAM,YAAY,CAAC;AAuEpB,qBAAa,YAAY,CACvB,MAAM,EACN,KAAK,SAAS,oBAAoB,EAClC,MAAM,SAAS,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAElD;;;OAGG;IACG,OAAO,CACX,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,EACzC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,KAAK,EACX,OAAO,CAAC,EAAE,oBAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,GACpD,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IA4IvC;;OAEG;YACW,WAAW;IAgBzB;;OAEG;YACW,gBAAgB;IA4D9B;;OAEG;YACW,iBAAiB;IA+F/B;;OAEG;YACW,kBAAkB;IA4BhC;;OAEG;YACW,YAAY;IA+C1B;;OAEG;YACW,YAAY;CAc3B"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @celom/prose - Declarative workflow DSL for orchestrating complex business operations
3
+ */
4
+ export * from './types.js';
5
+ export { ValidationError, FlowExecutionError, TimeoutError } from './types.js';
6
+ export { createFlow, FlowBuilder, } from './flow-builder.js';
7
+ export type { FlowObserver } from './observer.js';
8
+ export { DefaultObserver, NoOpObserver } from './observer.js';
9
+ export { PinoFlowObserver, type PinoLike } from './pino-observer.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/E,OAAO,EACL,UAAU,EACV,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { BaseFlowDependencies, FlowContext, FlowState } from './types.js';
2
+ /**
3
+ * Observer interface for monitoring flow execution
4
+ * All methods are optional - implement only what you need
5
+ */
6
+ export interface FlowObserver<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> {
7
+ /**
8
+ * Called when a flow starts execution
9
+ */
10
+ onFlowStart?: (flowName: string, input: TInput) => void;
11
+ /**
12
+ * Called when a flow completes successfully
13
+ */
14
+ onFlowComplete?: (flowName: string, output: TState, totalDuration: number) => void;
15
+ /**
16
+ * Called when a flow fails with an error
17
+ */
18
+ onFlowError?: (flowName: string, error: Error, totalDuration: number) => void;
19
+ /**
20
+ * Called when a step starts execution
21
+ */
22
+ onStepStart?: (stepName: string, context: FlowContext<TInput, TDeps, TState>) => void;
23
+ /**
24
+ * Called when a step completes successfully
25
+ */
26
+ onStepComplete?: (stepName: string, result: unknown, duration: number, context: FlowContext<TInput, TDeps, TState>) => void;
27
+ /**
28
+ * Called when a step fails with an error
29
+ */
30
+ onStepError?: (stepName: string, error: Error, duration: number, context: FlowContext<TInput, TDeps, TState>) => void;
31
+ /**
32
+ * Called when a step is retried
33
+ */
34
+ onStepRetry?: (stepName: string, attempt: number, maxAttempts: number, error: Error) => void;
35
+ /**
36
+ * Called when a step is skipped due to condition
37
+ */
38
+ onStepSkipped?: (stepName: string, context: FlowContext<TInput, TDeps, TState>) => void;
39
+ /**
40
+ * Called when a flow is short-circuited via breakIf
41
+ */
42
+ onFlowBreak?: (flowName: string, breakStepName: string, returnValue: unknown, totalDuration: number) => void;
43
+ }
44
+ /**
45
+ * Default observer implementation that logs to console
46
+ * Useful for development and debugging
47
+ */
48
+ export declare class DefaultObserver<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> implements FlowObserver<TInput, TDeps, TState> {
49
+ private logger?;
50
+ constructor(logger?: {
51
+ debug?: (msg: string) => void;
52
+ error?: (msg: string, error: Error) => void;
53
+ warn?: (msg: string) => void;
54
+ } | undefined);
55
+ onFlowStart(flowName: string, input: TInput): void;
56
+ onFlowComplete(flowName: string, output: TState, totalDuration: number): void;
57
+ onFlowError(flowName: string, error: Error, totalDuration: number): void;
58
+ onStepStart(stepName: string): void;
59
+ onStepComplete(stepName: string, result: unknown, duration: number): void;
60
+ onStepError(stepName: string, error: Error, duration: number): void;
61
+ onStepRetry(stepName: string, attempt: number, maxAttempts: number, error: Error): void;
62
+ onStepSkipped(stepName: string): void;
63
+ onFlowBreak(flowName: string, breakStepName: string, returnValue: unknown, totalDuration: number): void;
64
+ }
65
+ /**
66
+ * No-op observer that does nothing
67
+ * Useful for testing or when observability is not needed
68
+ */
69
+ export declare class NoOpObserver<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> implements FlowObserver<TInput, TDeps, TState> {
70
+ }
71
+ //# sourceMappingURL=observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../src/lib/observer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { BaseFlowDependencies, FlowState } from './types.js';
2
+ import { FlowObserver } from './observer.js';
3
+ /**
4
+ * Minimal pino-compatible logger interface.
5
+ * Avoids a direct pino dependency — satisfied by fastify.log.
6
+ */
7
+ export interface PinoLike {
8
+ info: (obj: Record<string, unknown>, msg: string) => void;
9
+ debug: (obj: Record<string, unknown>, msg: string) => void;
10
+ warn: (obj: Record<string, unknown>, msg: string) => void;
11
+ error: (obj: Record<string, unknown>, msg: string) => void;
12
+ child: (bindings: Record<string, unknown>) => PinoLike;
13
+ }
14
+ export declare class PinoFlowObserver<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> implements FlowObserver<TInput, TDeps, TState> {
15
+ private logger;
16
+ constructor(logger: PinoLike);
17
+ onFlowStart(flowName: string, _input: TInput): void;
18
+ onFlowComplete(flowName: string, _output: TState, totalDuration: number): void;
19
+ onFlowError(flowName: string, error: Error, totalDuration: number): void;
20
+ onStepStart(stepName: string, _context: unknown): void;
21
+ onStepComplete(stepName: string, result: unknown, duration: number, _context: unknown): void;
22
+ onStepError(stepName: string, error: Error, duration: number, _context: unknown): void;
23
+ onStepRetry(stepName: string, attempt: number, maxAttempts: number, error: Error): void;
24
+ onStepSkipped(stepName: string, _context: unknown): void;
25
+ onFlowBreak(flowName: string, breakStepName: string, _returnValue: unknown, totalDuration: number): void;
26
+ }
27
+ //# sourceMappingURL=pino-observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pino-observer.d.ts","sourceRoot":"","sources":["../../src/lib/pino-observer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,QAAQ,CAAC;CACxD;AAED,qBAAa,gBAAgB,CAC3B,MAAM,EACN,KAAK,SAAS,oBAAoB,EAClC,MAAM,SAAS,SAAS,CACxB,YAAW,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC;IAE9C,OAAO,CAAC,MAAM,CAAW;gBAEb,MAAM,EAAE,QAAQ;IAI5B,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAInD,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GACpB,IAAI;IAOP,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAOxE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAItD,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,GAChB,IAAI;IAcP,WAAW,CACT,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,GAChB,IAAI;IAOP,WAAW,CACT,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,GACX,IAAI;IAOP,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAIxD,WAAW,CACT,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,OAAO,EACrB,aAAa,EAAE,MAAM,GACpB,IAAI;CAMR"}
@@ -0,0 +1,269 @@
1
+ import { FlowObserver } from './observer.js';
2
+ /**
3
+ * A database client capable of running transactions.
4
+ *
5
+ * Any ORM / driver that exposes a `transaction()` method satisfies this
6
+ * (e.g. Drizzle, Knex, Prisma).
7
+ */
8
+ export interface DatabaseClient {
9
+ transaction<T>(fn: (tx: TransactionClient) => Promise<T>): Promise<T>;
10
+ }
11
+ /**
12
+ * The transaction client passed into transaction step handlers.
13
+ *
14
+ * Intentionally opaque so consumers can narrow it to their ORM's
15
+ * transaction type via the generic parameter on `.transaction()`.
16
+ */
17
+ export type TransactionClient = unknown;
18
+ /**
19
+ * A flow event that can be published.
20
+ *
21
+ * Only `eventType` is required by the framework; everything else is
22
+ * pass-through data attached by the application.
23
+ */
24
+ export interface FlowEvent {
25
+ eventType: string;
26
+ [key: string]: unknown;
27
+ }
28
+ /**
29
+ * An event publisher capable of publishing events to named channels.
30
+ */
31
+ export interface FlowEventPublisher {
32
+ publish(channel: string, event: FlowEvent): Promise<void> | void;
33
+ }
34
+ export type BaseFlowDependencies = {
35
+ db?: DatabaseClient;
36
+ eventPublisher?: FlowEventPublisher;
37
+ };
38
+ export type FlowState = Record<string, unknown>;
39
+ /**
40
+ * Flow metadata tracked during execution
41
+ */
42
+ export interface FlowMeta {
43
+ flowName: string;
44
+ startedAt: Date;
45
+ currentStep?: string;
46
+ correlationId?: string;
47
+ }
48
+ /**
49
+ * Context passed to each step in the flow
50
+ */
51
+ export interface FlowContext<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> {
52
+ readonly input: Readonly<TInput>;
53
+ state: TState;
54
+ deps: TDeps;
55
+ meta: FlowMeta;
56
+ /** AbortSignal for cooperative cancellation. Aborted on timeout or external signal. */
57
+ signal: AbortSignal;
58
+ }
59
+ /**
60
+ * Result of a step execution
61
+ */
62
+ export type StepResult<T> = T | void | undefined;
63
+ /**
64
+ * Condition checker for conditional steps
65
+ */
66
+ export type StepCondition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> = (ctx: FlowContext<TInput, TDeps, TState>) => boolean;
67
+ /**
68
+ * Error handling configuration for flow execution
69
+ */
70
+ export interface ErrorHandlingConfig {
71
+ /** Throw error if event publisher is missing (default: true) */
72
+ throwOnMissingEventPublisher?: boolean;
73
+ /** Throw error if database is missing for transaction (default: true) */
74
+ throwOnMissingDatabase?: boolean;
75
+ }
76
+ /**
77
+ * Options for flow execution
78
+ */
79
+ export interface FlowExecutionOptions<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> {
80
+ correlationId?: string;
81
+ throwOnError?: boolean;
82
+ /** Timeout in milliseconds for the entire flow */
83
+ timeout?: number;
84
+ /** Timeout in milliseconds for individual steps */
85
+ stepTimeout?: number;
86
+ /** External AbortSignal for caller-driven cancellation */
87
+ signal?: AbortSignal;
88
+ observer?: FlowObserver<TInput, TDeps, TState>;
89
+ errorHandling?: ErrorHandlingConfig;
90
+ }
91
+ /**
92
+ * Base properties shared by all step types
93
+ */
94
+ interface BaseStepDefinition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> {
95
+ name: string;
96
+ condition?: StepCondition<TInput, TDeps, TState>;
97
+ retryOptions?: RetryOptions;
98
+ }
99
+ /**
100
+ * Validation step - validates input or state without returning data
101
+ */
102
+ export interface ValidationStepDefinition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> extends BaseStepDefinition<TInput, TDeps, TState> {
103
+ type: 'validate';
104
+ handler: (ctx: FlowContext<TInput, TDeps, TState>) => void | Promise<void>;
105
+ }
106
+ /**
107
+ * Executor step - performs work and returns state to merge
108
+ */
109
+ export interface ExecutorStepDefinition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> extends BaseStepDefinition<TInput, TDeps, TState> {
110
+ type: 'step';
111
+ handler: (ctx: FlowContext<TInput, TDeps, TState>) => StepResult<unknown> | Promise<StepResult<unknown>>;
112
+ }
113
+ /**
114
+ * Transaction step - performs work within a database transaction
115
+ */
116
+ export interface TransactionStepDefinition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> extends BaseStepDefinition<TInput, TDeps, TState> {
117
+ type: 'transaction';
118
+ handler: (ctx: FlowContext<TInput, TDeps, TState>, tx: TransactionClient) => unknown | Promise<unknown>;
119
+ }
120
+ /**
121
+ * Event step - publishes events to a specific channel
122
+ */
123
+ export interface EventStepDefinition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> extends BaseStepDefinition<TInput, TDeps, TState> {
124
+ type: 'event';
125
+ channel: string;
126
+ handler: (ctx: FlowContext<TInput, TDeps, TState>) => FlowEvent | FlowEvent[] | void | Promise<FlowEvent | FlowEvent[] | void>;
127
+ }
128
+ /**
129
+ * Break condition checker for short-circuit flow termination
130
+ */
131
+ export type BreakCondition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> = (ctx: FlowContext<TInput, TDeps, TState>) => boolean;
132
+ /**
133
+ * Break return value generator
134
+ */
135
+ export type BreakReturnValue<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState, TBreakOutput> = (ctx: FlowContext<TInput, TDeps, TState>) => TBreakOutput;
136
+ /**
137
+ * Break step - short-circuits the flow if condition is met
138
+ *
139
+ * @example
140
+ * .step('validateToken', validateVerificationTokenStep)
141
+ * .breakIf(
142
+ * (ctx) => ctx.state.alreadyVerified,
143
+ * (ctx) => ({ success: true, alreadyVerified: true })
144
+ * )
145
+ */
146
+ export interface BreakStepDefinition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> extends BaseStepDefinition<TInput, TDeps, TState> {
147
+ type: 'break';
148
+ breakCondition: BreakCondition<TInput, TDeps, TState>;
149
+ breakReturnValue?: BreakReturnValue<TInput, TDeps, TState, unknown>;
150
+ }
151
+ /**
152
+ * Discriminated union of all step types
153
+ */
154
+ export type StepDefinition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> = ValidationStepDefinition<TInput, TDeps, TState> | ExecutorStepDefinition<TInput, TDeps, TState> | TransactionStepDefinition<TInput, TDeps, TState> | EventStepDefinition<TInput, TDeps, TState> | BreakStepDefinition<TInput, TDeps, TState>;
155
+ /**
156
+ * Merge strategy for parallel execution
157
+ * - 'shallow': Default - later results override earlier ones (silent overwrites)
158
+ * - 'error-on-conflict': Throw error if keys conflict between results
159
+ * - 'deep': Perform deep merge of nested objects
160
+ */
161
+ export type MergeStrategy = 'shallow' | 'error-on-conflict' | 'deep';
162
+ /**
163
+ * Retry configuration for a step
164
+ */
165
+ export interface RetryOptions {
166
+ maxAttempts: number;
167
+ delayMs: number;
168
+ backoffMultiplier?: number;
169
+ maxDelayMs?: number;
170
+ shouldRetry?: (error: Error) => boolean;
171
+ /** Timeout in milliseconds for this specific step (overrides flow-level stepTimeout) */
172
+ stepTimeout?: number;
173
+ }
174
+ /**
175
+ * Timeout configuration for flow or step execution
176
+ */
177
+ export interface TimeoutOptions {
178
+ /** Timeout in milliseconds for the entire flow */
179
+ timeout?: number;
180
+ /** Timeout in milliseconds for individual steps (overrides flow timeout for steps) */
181
+ stepTimeout?: number;
182
+ }
183
+ /**
184
+ * Error thrown when a step or flow times out
185
+ */
186
+ export declare class TimeoutError extends Error {
187
+ flowName: string;
188
+ stepName?: string | undefined;
189
+ timeoutMs?: number | undefined;
190
+ constructor(message: string, flowName: string, stepName?: string | undefined, timeoutMs?: number | undefined);
191
+ }
192
+ /**
193
+ * Internal result from flow executor indicating whether flow completed normally or short-circuited
194
+ */
195
+ export interface FlowExecutionResult<TState> {
196
+ /** The result value (either accumulated state or break return value) */
197
+ value: TState;
198
+ /** Whether the flow was short-circuited via breakIf */
199
+ didBreak: boolean;
200
+ }
201
+ /**
202
+ * Flow configuration - just the definition without execution
203
+ */
204
+ export interface FlowConfig<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState> {
205
+ name: string;
206
+ steps: StepDefinition<TInput, TDeps, TState>[];
207
+ }
208
+ /**
209
+ * Helper type to infer the correct output type
210
+ * Uses tuple wrapping to properly handle the never type
211
+ */
212
+ export type InferFlowOutput<TState, TMapperOutput> = [TMapperOutput] extends [
213
+ never
214
+ ] ? TState : TMapperOutput;
215
+ /**
216
+ * Flow definition containing all steps and execution method
217
+ */
218
+ export interface FlowDefinition<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState, TMapperOutput = never, TBreakOutputs = never> {
219
+ name: string;
220
+ steps: StepDefinition<TInput, TDeps, TState>[];
221
+ execute: (input: TInput, deps: TDeps, options?: FlowExecutionOptions<TInput, TDeps, TState>) => Promise<InferFlowOutput<TState, TMapperOutput> | TBreakOutputs>;
222
+ }
223
+ /**
224
+ * Validation issue details
225
+ */
226
+ export interface ValidationIssue {
227
+ field: string;
228
+ message: string;
229
+ value?: unknown;
230
+ }
231
+ /**
232
+ * Error thrown during validation
233
+ * Supports both single field errors and multiple validation issues
234
+ */
235
+ export declare class ValidationError extends Error {
236
+ readonly issues: ValidationIssue[];
237
+ constructor(message: string, issues?: ValidationIssue[] | string);
238
+ /**
239
+ * Create a validation error for a single field
240
+ */
241
+ static single(field: string, message: string, value?: unknown): ValidationError;
242
+ /**
243
+ * Create a validation error for multiple fields
244
+ */
245
+ static multiple(issues: ValidationIssue[]): ValidationError;
246
+ /**
247
+ * Convert to JSON for serialization
248
+ */
249
+ toJSON(): {
250
+ name: string;
251
+ message: string;
252
+ issues: ValidationIssue[];
253
+ };
254
+ /**
255
+ * Get a single field error (for backward compatibility)
256
+ */
257
+ get field(): string | undefined;
258
+ }
259
+ /**
260
+ * Error thrown during flow execution
261
+ */
262
+ export declare class FlowExecutionError extends Error {
263
+ flowName: string;
264
+ stepName?: string | undefined;
265
+ originalError?: Error | undefined;
266
+ constructor(message: string, flowName: string, stepName?: string | undefined, originalError?: Error | undefined);
267
+ }
268
+ export {};
269
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Deep merge utility for combining objects recursively.
3
+ * - Plain objects are merged recursively
4
+ * - Arrays are concatenated (not overwritten)
5
+ * - Non-plain objects (Date, Map, Set, etc.) are treated as primitives
6
+ */
7
+ export declare function deepMerge(...objects: Array<Record<string, unknown> | null | undefined>): Record<string, unknown>;
8
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,GAAG,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,GAC5D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkCzB"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Type inference smoke test for FlowBuilder's cons-list internals.
3
+ * This file is NOT meant to be executed — only type-checked.
4
+ *
5
+ * Run: npx tsc --noEmit --project packages/prose/tsconfig.lib.json
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=puppet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"puppet.d.ts","sourceRoot":"","sources":["../src/puppet.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@celom/prose",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
+ "license": "MIT",
4
5
  "author": "Carlos Mimoso",
5
6
  "description": "Declarative workflow DSL for orchestrating complex business operations in Javascript/Typescript.",
6
7
  "keywords": [