@celom/prose 0.1.1 → 0.1.4
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +631 -0
- package/dist/lib/flow-builder.d.ts +111 -0
- package/dist/lib/flow-builder.d.ts.map +1 -0
- package/dist/lib/flow-executor.d.ts +33 -0
- package/dist/lib/flow-executor.d.ts.map +1 -0
- package/dist/lib/index.d.ts +10 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/observer.d.ts +71 -0
- package/dist/lib/observer.d.ts.map +1 -0
- package/dist/lib/pino-observer.d.ts +27 -0
- package/dist/lib/pino-observer.d.ts.map +1 -0
- package/dist/lib/types.d.ts +269 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +8 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/puppet.d.ts +8 -0
- package/dist/puppet.d.ts.map +1 -0
- package/package.json +3 -1
package/dist/index.d.ts
ADDED
|
@@ -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,631 @@
|
|
|
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
|
+
head: { name: e, type: "transaction", handler: t },
|
|
366
|
+
tail: this.steps
|
|
367
|
+
},
|
|
368
|
+
this.length + 1,
|
|
369
|
+
this.outputMapper
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Add an event publishing step with explicit channel
|
|
374
|
+
*/
|
|
375
|
+
event(e, t, r = "publishEvent") {
|
|
376
|
+
return new f(
|
|
377
|
+
this.name,
|
|
378
|
+
{ head: { name: r, type: "event", channel: e, handler: t }, tail: this.steps },
|
|
379
|
+
this.length + 1,
|
|
380
|
+
this.outputMapper
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Add multiple events to publish to the same channel
|
|
385
|
+
*/
|
|
386
|
+
events(e, t, r = "publishEvents") {
|
|
387
|
+
const o = async (n) => {
|
|
388
|
+
const i = [];
|
|
389
|
+
for (const s of t) {
|
|
390
|
+
const a = await s(n);
|
|
391
|
+
a && (Array.isArray(a) ? i.push(...a) : i.push(a));
|
|
392
|
+
}
|
|
393
|
+
return i.length > 0 ? i : void 0;
|
|
394
|
+
};
|
|
395
|
+
return new f(
|
|
396
|
+
this.name,
|
|
397
|
+
{ head: { name: r, type: "event", channel: e, handler: o }, tail: this.steps },
|
|
398
|
+
this.length + 1,
|
|
399
|
+
this.outputMapper
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
breakIf(e, t) {
|
|
403
|
+
const r = `break_${this.length}`;
|
|
404
|
+
return new f(
|
|
405
|
+
this.name,
|
|
406
|
+
{ head: { name: r, type: "break", breakCondition: e, breakReturnValue: t }, tail: this.steps },
|
|
407
|
+
this.length + 1,
|
|
408
|
+
this.outputMapper
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Add a retry configuration to the last step
|
|
413
|
+
*/
|
|
414
|
+
withRetry(e) {
|
|
415
|
+
return this.steps === null ? this : new f(
|
|
416
|
+
this.name,
|
|
417
|
+
{ head: { ...this.steps.head, retryOptions: e }, tail: this.steps.tail },
|
|
418
|
+
this.length,
|
|
419
|
+
this.outputMapper
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Add a parallel execution step that runs multiple handlers concurrently
|
|
424
|
+
* and merges their results into the flow state.
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* .parallel('fetchAll', 'shallow',
|
|
428
|
+
* (ctx) => ({ users: fetchUsers(ctx.input.orgId) }),
|
|
429
|
+
* (ctx) => ({ posts: fetchPosts(ctx.input.orgId) }),
|
|
430
|
+
* )
|
|
431
|
+
*/
|
|
432
|
+
parallel(e, t, ...r) {
|
|
433
|
+
const o = async (n) => {
|
|
434
|
+
const i = await Promise.all(
|
|
435
|
+
r.map((s) => s(n))
|
|
436
|
+
);
|
|
437
|
+
if (t === "error-on-conflict") {
|
|
438
|
+
const s = /* @__PURE__ */ new Set();
|
|
439
|
+
for (const a of i)
|
|
440
|
+
if (a && typeof a == "object")
|
|
441
|
+
for (const h in a) {
|
|
442
|
+
if (s.has(h))
|
|
443
|
+
throw new Error(
|
|
444
|
+
`[Workflow:${e}] Key conflict detected in parallel merge: '${h}'`
|
|
445
|
+
);
|
|
446
|
+
s.add(h);
|
|
447
|
+
}
|
|
448
|
+
return Object.assign({}, ...i);
|
|
449
|
+
}
|
|
450
|
+
return t === "deep" ? v(
|
|
451
|
+
{},
|
|
452
|
+
...i
|
|
453
|
+
) : Object.assign({}, ...i);
|
|
454
|
+
};
|
|
455
|
+
return new f(
|
|
456
|
+
this.name,
|
|
457
|
+
{
|
|
458
|
+
head: { name: e, type: "step", handler: o },
|
|
459
|
+
tail: this.steps
|
|
460
|
+
},
|
|
461
|
+
this.length + 1,
|
|
462
|
+
this.outputMapper
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Apply a builder-to-builder transformation, enabling reusable sub-flows.
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* function withAuth(builder) {
|
|
470
|
+
* return builder
|
|
471
|
+
* .step('validateToken', ...)
|
|
472
|
+
* .step('loadUser', ...);
|
|
473
|
+
* }
|
|
474
|
+
*
|
|
475
|
+
* createFlow('order')
|
|
476
|
+
* .pipe(withAuth)
|
|
477
|
+
* .step('createOrder', ...)
|
|
478
|
+
* .build();
|
|
479
|
+
*/
|
|
480
|
+
pipe(e) {
|
|
481
|
+
return e(this);
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Transform the accumulated state into the final output
|
|
485
|
+
*/
|
|
486
|
+
map(e) {
|
|
487
|
+
return new f(
|
|
488
|
+
this.name,
|
|
489
|
+
this.steps,
|
|
490
|
+
this.length,
|
|
491
|
+
e
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Build the flow definition
|
|
496
|
+
*/
|
|
497
|
+
build() {
|
|
498
|
+
const e = this.toArray(), t = /* @__PURE__ */ new Set(), r = [];
|
|
499
|
+
for (const s of e)
|
|
500
|
+
t.has(s.name) && r.push(s.name), t.add(s.name);
|
|
501
|
+
if (r.length > 0)
|
|
502
|
+
throw new Error(
|
|
503
|
+
`Flow '${this.name}' has duplicate step names: ${r.join(", ")}. Each step must have a unique name for proper debugging and observability.`
|
|
504
|
+
);
|
|
505
|
+
const o = new T(), n = {
|
|
506
|
+
name: this.name,
|
|
507
|
+
steps: e
|
|
508
|
+
}, i = this.outputMapper;
|
|
509
|
+
return {
|
|
510
|
+
name: n.name,
|
|
511
|
+
steps: n.steps,
|
|
512
|
+
execute: async (s, a, h) => {
|
|
513
|
+
const p = await o.execute(n, s, a, h);
|
|
514
|
+
return p.didBreak ? p.value : i ? i(s, p.value) : p.value;
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
class C {
|
|
520
|
+
constructor(e) {
|
|
521
|
+
this.logger = e;
|
|
522
|
+
}
|
|
523
|
+
onFlowStart(e, t) {
|
|
524
|
+
this.logger?.debug?.(
|
|
525
|
+
`[Workflow] Flow ${e} started. Input: ${t}`
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
onFlowComplete(e, t, r) {
|
|
529
|
+
this.logger?.debug?.(
|
|
530
|
+
`[Workflow] Flow ${e} completed. Output: ${t} - (${r}ms)`
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
onFlowError(e, t, r) {
|
|
534
|
+
this.logger?.error?.(
|
|
535
|
+
`[Workflow] Flow failed: ${e} (${r}ms)`,
|
|
536
|
+
t
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
onStepStart(e) {
|
|
540
|
+
this.logger?.debug?.(`[Workflow] Step started: ${e}`);
|
|
541
|
+
}
|
|
542
|
+
onStepComplete(e, t, r) {
|
|
543
|
+
this.logger?.debug?.(
|
|
544
|
+
`[Workflow] Step completed: ${e} (${r}ms)`
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
onStepError(e, t, r) {
|
|
548
|
+
this.logger?.error?.(
|
|
549
|
+
`[Workflow] Step failed: ${e} (${r}ms)`,
|
|
550
|
+
t
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
onStepRetry(e, t, r, o) {
|
|
554
|
+
this.logger?.warn?.(
|
|
555
|
+
`[Workflow] Step retry: ${e} (attempt ${t}/${r}) - ${o.message}`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
onStepSkipped(e) {
|
|
559
|
+
this.logger?.debug?.(`[Workflow] Step skipped: ${e}`);
|
|
560
|
+
}
|
|
561
|
+
onFlowBreak(e, t, r, o) {
|
|
562
|
+
this.logger?.debug?.(
|
|
563
|
+
`[Workflow] Flow ${e} short-circuited at '${t}' (${o}ms)`
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
class O {
|
|
568
|
+
// All methods intentionally left empty
|
|
569
|
+
}
|
|
570
|
+
class W {
|
|
571
|
+
logger;
|
|
572
|
+
constructor(e) {
|
|
573
|
+
this.logger = e.child({ component: "workflow" });
|
|
574
|
+
}
|
|
575
|
+
onFlowStart(e, t) {
|
|
576
|
+
this.logger.info({ flow: e }, "Flow started");
|
|
577
|
+
}
|
|
578
|
+
onFlowComplete(e, t, r) {
|
|
579
|
+
this.logger.info(
|
|
580
|
+
{ flow: e, durationMs: r },
|
|
581
|
+
"Flow completed"
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
onFlowError(e, t, r) {
|
|
585
|
+
this.logger.error(
|
|
586
|
+
{ flow: e, durationMs: r, err: t },
|
|
587
|
+
"Flow failed"
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
onStepStart(e, t) {
|
|
591
|
+
this.logger.debug({ step: e }, "Step started");
|
|
592
|
+
}
|
|
593
|
+
onStepComplete(e, t, r, o) {
|
|
594
|
+
const n = {
|
|
595
|
+
step: e,
|
|
596
|
+
durationMs: r
|
|
597
|
+
};
|
|
598
|
+
t && typeof t == "object" && (n.resultKeys = Object.keys(t)), this.logger.info(n, "Step completed");
|
|
599
|
+
}
|
|
600
|
+
onStepError(e, t, r, o) {
|
|
601
|
+
this.logger.error(
|
|
602
|
+
{ step: e, durationMs: r, err: t },
|
|
603
|
+
"Step failed"
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
onStepRetry(e, t, r, o) {
|
|
607
|
+
this.logger.warn(
|
|
608
|
+
{ step: e, attempt: t, maxAttempts: r, err: o },
|
|
609
|
+
"Step retrying"
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
onStepSkipped(e, t) {
|
|
613
|
+
this.logger.debug({ step: e }, "Step skipped");
|
|
614
|
+
}
|
|
615
|
+
onFlowBreak(e, t, r, o) {
|
|
616
|
+
this.logger.info(
|
|
617
|
+
{ flow: e, breakStep: t, durationMs: o },
|
|
618
|
+
"Flow short-circuited"
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
export {
|
|
623
|
+
C as DefaultObserver,
|
|
624
|
+
f as FlowBuilder,
|
|
625
|
+
d as FlowExecutionError,
|
|
626
|
+
O as NoOpObserver,
|
|
627
|
+
W as PinoFlowObserver,
|
|
628
|
+
k as TimeoutError,
|
|
629
|
+
b as ValidationError,
|
|
630
|
+
D as createFlow
|
|
631
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
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
|
+
* Converts a union type to an intersection type.
|
|
8
|
+
* Used to merge return types from parallel/sequence handlers.
|
|
9
|
+
*/
|
|
10
|
+
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new flow with the given name
|
|
13
|
+
*/
|
|
14
|
+
export declare function createFlow<TInput, TDeps extends BaseFlowDependencies = never>(name: string): FlowBuilder<TInput, TDeps, Record<string, never>, never, never>;
|
|
15
|
+
/**
|
|
16
|
+
* FlowBuilder provides a fluent API for creating declarative workflows
|
|
17
|
+
*/
|
|
18
|
+
export declare class FlowBuilder<TInput, TDeps extends BaseFlowDependencies, TState extends FlowState, TMapperOutput = never, TBreakOutputs = never> {
|
|
19
|
+
private name;
|
|
20
|
+
private steps;
|
|
21
|
+
private length;
|
|
22
|
+
private outputMapper?;
|
|
23
|
+
constructor(name: string, steps?: StepNode<StepDefinition<TInput, TDeps, TState>> | null, length?: number, mapper?: (input: TInput, state: TState) => TMapperOutput);
|
|
24
|
+
private toArray;
|
|
25
|
+
/**
|
|
26
|
+
* Add a validation step
|
|
27
|
+
*/
|
|
28
|
+
validate(name: string, handler: (ctx: FlowContext<TInput, TDeps, TState>) => void | Promise<void>): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
|
|
29
|
+
/**
|
|
30
|
+
* Add a regular step that can return state to merge
|
|
31
|
+
*/
|
|
32
|
+
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>;
|
|
33
|
+
/**
|
|
34
|
+
* Add a conditional step that only executes if condition is met
|
|
35
|
+
*/
|
|
36
|
+
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>;
|
|
37
|
+
/**
|
|
38
|
+
* Add a transaction step for database operations
|
|
39
|
+
*/
|
|
40
|
+
transaction<TResult extends object>(name: string, handler: (ctx: FlowContext<TInput, TDeps, TState>, tx: unknown) => TResult | Promise<TResult>): FlowBuilder<TInput, TDeps, TResult & TState, TMapperOutput, TBreakOutputs>;
|
|
41
|
+
/**
|
|
42
|
+
* Add an event publishing step with explicit channel
|
|
43
|
+
*/
|
|
44
|
+
event(channel: string, builder: (ctx: FlowContext<TInput, TDeps, TState>) => FlowEvent | FlowEvent[] | void | Promise<FlowEvent | FlowEvent[] | void>, name?: string): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
|
|
45
|
+
/**
|
|
46
|
+
* Add multiple events to publish to the same channel
|
|
47
|
+
*/
|
|
48
|
+
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>;
|
|
49
|
+
/**
|
|
50
|
+
* Add a break condition that short-circuits the flow if met.
|
|
51
|
+
* When the condition returns true, the flow stops and returns the value
|
|
52
|
+
* from the returnValue function (or the accumulated state if not provided).
|
|
53
|
+
*
|
|
54
|
+
* @param condition - Function that returns true to break the flow
|
|
55
|
+
* @param returnValue - Optional function to compute the return value when breaking
|
|
56
|
+
* @returns New FlowBuilder with break step added
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* .step('validateToken', validateVerificationTokenStep)
|
|
60
|
+
* .breakIf(
|
|
61
|
+
* (ctx) => ctx.state.alreadyVerified,
|
|
62
|
+
* (ctx) => ({ success: true, alreadyVerified: true })
|
|
63
|
+
* )
|
|
64
|
+
* .step('getAccount', getAccountStep) // Only runs if not already verified
|
|
65
|
+
*/
|
|
66
|
+
breakIf(condition: (ctx: FlowContext<TInput, TDeps, TState>) => boolean): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs | TState>;
|
|
67
|
+
breakIf<TBreakOutput>(condition: (ctx: FlowContext<TInput, TDeps, TState>) => boolean, returnValue: (ctx: FlowContext<TInput, TDeps, TState>) => TBreakOutput): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs | TBreakOutput>;
|
|
68
|
+
/**
|
|
69
|
+
* Add a retry configuration to the last step
|
|
70
|
+
*/
|
|
71
|
+
withRetry(options: RetryOptions): FlowBuilder<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
|
|
72
|
+
/**
|
|
73
|
+
* Add a parallel execution step that runs multiple handlers concurrently
|
|
74
|
+
* and merges their results into the flow state.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* .parallel('fetchAll', 'shallow',
|
|
78
|
+
* (ctx) => ({ users: fetchUsers(ctx.input.orgId) }),
|
|
79
|
+
* (ctx) => ({ posts: fetchPosts(ctx.input.orgId) }),
|
|
80
|
+
* )
|
|
81
|
+
*/
|
|
82
|
+
parallel<TResults extends object[]>(name: string, strategy: MergeStrategy, ...handlers: {
|
|
83
|
+
[K in keyof TResults]: (ctx: FlowContext<TInput, TDeps, TState>) => TResults[K] | Promise<TResults[K]>;
|
|
84
|
+
}): FlowBuilder<TInput, TDeps, UnionToIntersection<TResults[number]> & TState, TMapperOutput, TBreakOutputs>;
|
|
85
|
+
/**
|
|
86
|
+
* Apply a builder-to-builder transformation, enabling reusable sub-flows.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* function withAuth(builder) {
|
|
90
|
+
* return builder
|
|
91
|
+
* .step('validateToken', ...)
|
|
92
|
+
* .step('loadUser', ...);
|
|
93
|
+
* }
|
|
94
|
+
*
|
|
95
|
+
* createFlow('order')
|
|
96
|
+
* .pipe(withAuth)
|
|
97
|
+
* .step('createOrder', ...)
|
|
98
|
+
* .build();
|
|
99
|
+
*/
|
|
100
|
+
pipe<R>(fn: (builder: this) => R): R;
|
|
101
|
+
/**
|
|
102
|
+
* Transform the accumulated state into the final output
|
|
103
|
+
*/
|
|
104
|
+
map<TNewOutput>(mapper: (input: TInput, state: TState) => TNewOutput): FlowBuilder<TInput, TDeps, TState, TNewOutput, TBreakOutputs>;
|
|
105
|
+
/**
|
|
106
|
+
* Build the flow definition
|
|
107
|
+
*/
|
|
108
|
+
build(): FlowDefinition<TInput, TDeps, TState, TMapperOutput, TBreakOutputs>;
|
|
109
|
+
}
|
|
110
|
+
export {};
|
|
111
|
+
//# 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"}
|
package/dist/puppet.d.ts
ADDED
|
@@ -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
|
+
"version": "0.1.4",
|
|
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": [
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
"type": "git",
|
|
21
22
|
"url": "git+https://github.com/celom/prose.git"
|
|
22
23
|
},
|
|
24
|
+
"homepage": "https://celom.github.io/prose/",
|
|
23
25
|
"private": false,
|
|
24
26
|
"publishConfig": {
|
|
25
27
|
"access": "public"
|