@rytejs/core 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -0
- package/dist/index.cjs +223 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -8
- package/dist/index.d.ts +63 -8
- package/dist/index.js +220 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# @rytejs/core
|
|
2
|
+
|
|
3
|
+
Type-safe workflow engine with Zod validation and middleware pipelines.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/helico-tech/rytejs/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.npmjs.com/package/@rytejs/core)
|
|
7
|
+
|
|
8
|
+
## Why Ryte?
|
|
9
|
+
|
|
10
|
+
- **Fully typed from definition to dispatch** -- define your states, commands, events, and errors with Zod schemas. TypeScript infers everything automatically. State names, command payloads, event data, error codes -- all with full autocompletion, no manual type annotations.
|
|
11
|
+
- **Checking `workflow.state` narrows `workflow.data`** -- TypeScript knows exactly which data shape each state has. Discriminated unions, not type casts.
|
|
12
|
+
- **`ctx.error()` is type-checked** -- you can only raise error codes that exist in your definition, with the correct data shape. Domain failures are part of the contract.
|
|
13
|
+
- **Koa-style middleware** -- global, state-scoped, and inline middleware with the onion model. Add auth, logging, or validation without touching handlers.
|
|
14
|
+
- **Fluent builder API** -- chain `.state()`, `.on()`, `.use()` calls. Every method returns `this`.
|
|
15
|
+
- **Composable routers** -- split handlers across files and compose them with `.use()`. Routers are routers.
|
|
16
|
+
- **Zero platform lock-in** -- pure logic with no runtime dependencies beyond Zod. Works on Node.js, Bun, and Deno.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @rytejs/core zod
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Example
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { z } from "zod";
|
|
28
|
+
import { defineWorkflow, WorkflowRouter } from "@rytejs/core";
|
|
29
|
+
|
|
30
|
+
const taskWorkflow = defineWorkflow("task", {
|
|
31
|
+
states: {
|
|
32
|
+
Todo: z.object({ title: z.string(), assignee: z.string().optional() }),
|
|
33
|
+
Done: z.object({ title: z.string(), completedAt: z.coerce.date() }),
|
|
34
|
+
},
|
|
35
|
+
commands: {
|
|
36
|
+
Complete: z.object({}),
|
|
37
|
+
},
|
|
38
|
+
events: {
|
|
39
|
+
TaskCompleted: z.object({ taskId: z.string() }),
|
|
40
|
+
},
|
|
41
|
+
errors: {
|
|
42
|
+
NotAssigned: z.object({ title: z.string() }),
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const router = new WorkflowRouter(taskWorkflow)
|
|
47
|
+
.state("Todo", (state) => {
|
|
48
|
+
state.on("Complete", (ctx) => {
|
|
49
|
+
if (!ctx.data.assignee) {
|
|
50
|
+
ctx.error({ code: "NotAssigned", data: { title: ctx.data.title } });
|
|
51
|
+
}
|
|
52
|
+
ctx.transition("Done", {
|
|
53
|
+
title: ctx.data.title,
|
|
54
|
+
completedAt: new Date(),
|
|
55
|
+
});
|
|
56
|
+
ctx.emit({ type: "TaskCompleted", data: { taskId: ctx.workflow.id } });
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const task = taskWorkflow.createWorkflow("task-1", {
|
|
61
|
+
initialState: "Todo",
|
|
62
|
+
data: { title: "Read the docs", assignee: "alice" },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const result = await router.dispatch(task, {
|
|
66
|
+
type: "Complete",
|
|
67
|
+
payload: {},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (result.ok) {
|
|
71
|
+
console.log(result.workflow.state); // "Done"
|
|
72
|
+
console.log(result.events[0]?.type); // "TaskCompleted"
|
|
73
|
+
} else if (result.error.category === "domain") {
|
|
74
|
+
console.log(result.error.code); // "NotAssigned"
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Type Safety Highlights
|
|
79
|
+
|
|
80
|
+
Every part of the API is fully typed with zero manual annotations:
|
|
81
|
+
|
|
82
|
+
- **State names** -- `router.state("Todo", ...)` only accepts states from your definition
|
|
83
|
+
- **Command names** -- `state.on("Complete", ...)` only accepts commands from your definition
|
|
84
|
+
- **Payload types** -- `ctx.command.payload` is typed based on the command's Zod schema
|
|
85
|
+
- **State data** -- `ctx.data` is typed based on the current state's Zod schema
|
|
86
|
+
- **Transitions** -- `ctx.transition("Done", data)` validates that `data` matches the target state's schema
|
|
87
|
+
- **Events** -- `ctx.emit({ type, data })` validates both type and data against event schemas
|
|
88
|
+
- **Errors** -- `ctx.error({ code, data })` only accepts error codes from your definition with matching data
|
|
89
|
+
- **Discriminated unions** -- `if (workflow.state === "Todo") { workflow.data.title }` narrows automatically
|
|
90
|
+
|
|
91
|
+
## Documentation
|
|
92
|
+
|
|
93
|
+
- [Getting Started](https://helico-tech.github.io/rytejs/guide/getting-started)
|
|
94
|
+
- [Defining Workflows](https://helico-tech.github.io/rytejs/guide/defining-workflows)
|
|
95
|
+
- [Routing Commands](https://helico-tech.github.io/rytejs/guide/routing-commands)
|
|
96
|
+
- [API Reference](https://helico-tech.github.io/rytejs/api/)
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -24,10 +24,30 @@ __export(index_exports, {
|
|
|
24
24
|
ValidationError: () => ValidationError,
|
|
25
25
|
WorkflowRouter: () => WorkflowRouter,
|
|
26
26
|
createKey: () => createKey,
|
|
27
|
-
|
|
27
|
+
definePlugin: () => definePlugin,
|
|
28
|
+
defineWorkflow: () => defineWorkflow,
|
|
29
|
+
isPlugin: () => isPlugin
|
|
28
30
|
});
|
|
29
31
|
module.exports = __toCommonJS(index_exports);
|
|
30
32
|
|
|
33
|
+
// src/types.ts
|
|
34
|
+
var ValidationError = class extends Error {
|
|
35
|
+
constructor(source, issues) {
|
|
36
|
+
super(`Validation failed (${source}): ${issues.map((i) => i.message).join(", ")}`);
|
|
37
|
+
this.source = source;
|
|
38
|
+
this.issues = issues;
|
|
39
|
+
this.name = "ValidationError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var DomainErrorSignal = class extends Error {
|
|
43
|
+
constructor(code, data) {
|
|
44
|
+
super(`Domain error: ${code}`);
|
|
45
|
+
this.code = code;
|
|
46
|
+
this.data = data;
|
|
47
|
+
this.name = "DomainErrorSignal";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
31
51
|
// src/definition.ts
|
|
32
52
|
function defineWorkflow(name, config) {
|
|
33
53
|
return {
|
|
@@ -74,6 +94,51 @@ function defineWorkflow(name, config) {
|
|
|
74
94
|
},
|
|
75
95
|
hasState(stateName) {
|
|
76
96
|
return stateName in config.states;
|
|
97
|
+
},
|
|
98
|
+
snapshot(workflow) {
|
|
99
|
+
return {
|
|
100
|
+
id: workflow.id,
|
|
101
|
+
definitionName: name,
|
|
102
|
+
state: workflow.state,
|
|
103
|
+
data: workflow.data,
|
|
104
|
+
createdAt: workflow.createdAt.toISOString(),
|
|
105
|
+
updatedAt: workflow.updatedAt.toISOString(),
|
|
106
|
+
modelVersion: config.modelVersion ?? 1
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
restore(snap) {
|
|
110
|
+
const stateSchema = config.states[snap.state];
|
|
111
|
+
if (!stateSchema) {
|
|
112
|
+
return {
|
|
113
|
+
ok: false,
|
|
114
|
+
error: new ValidationError("restore", [
|
|
115
|
+
{
|
|
116
|
+
code: "custom",
|
|
117
|
+
message: `Unknown state: ${snap.state}`,
|
|
118
|
+
input: snap.state,
|
|
119
|
+
path: ["state"]
|
|
120
|
+
}
|
|
121
|
+
])
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const result = stateSchema.safeParse(snap.data);
|
|
125
|
+
if (!result.success) {
|
|
126
|
+
return {
|
|
127
|
+
ok: false,
|
|
128
|
+
error: new ValidationError("restore", result.error.issues)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
ok: true,
|
|
133
|
+
workflow: {
|
|
134
|
+
id: snap.id,
|
|
135
|
+
definitionName: snap.definitionName,
|
|
136
|
+
state: snap.state,
|
|
137
|
+
data: result.data,
|
|
138
|
+
createdAt: new Date(snap.createdAt),
|
|
139
|
+
updatedAt: new Date(snap.updatedAt)
|
|
140
|
+
}
|
|
141
|
+
};
|
|
77
142
|
}
|
|
78
143
|
};
|
|
79
144
|
}
|
|
@@ -83,6 +148,17 @@ function createKey(name) {
|
|
|
83
148
|
return { id: Symbol(name) };
|
|
84
149
|
}
|
|
85
150
|
|
|
151
|
+
// src/plugin.ts
|
|
152
|
+
var PLUGIN_SYMBOL = /* @__PURE__ */ Symbol.for("ryte:plugin");
|
|
153
|
+
function definePlugin(fn) {
|
|
154
|
+
const plugin = fn;
|
|
155
|
+
Object.defineProperty(plugin, PLUGIN_SYMBOL, { value: true, writable: false });
|
|
156
|
+
return plugin;
|
|
157
|
+
}
|
|
158
|
+
function isPlugin(value) {
|
|
159
|
+
return typeof value === "function" && PLUGIN_SYMBOL in value;
|
|
160
|
+
}
|
|
161
|
+
|
|
86
162
|
// src/compose.ts
|
|
87
163
|
function compose(middleware) {
|
|
88
164
|
return async (ctx) => {
|
|
@@ -98,24 +174,6 @@ function compose(middleware) {
|
|
|
98
174
|
};
|
|
99
175
|
}
|
|
100
176
|
|
|
101
|
-
// src/types.ts
|
|
102
|
-
var ValidationError = class extends Error {
|
|
103
|
-
constructor(source, issues) {
|
|
104
|
-
super(`Validation failed (${source}): ${issues.map((i) => i.message).join(", ")}`);
|
|
105
|
-
this.source = source;
|
|
106
|
-
this.issues = issues;
|
|
107
|
-
this.name = "ValidationError";
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
var DomainErrorSignal = class extends Error {
|
|
111
|
-
constructor(code, data) {
|
|
112
|
-
super(`Domain error: ${code}`);
|
|
113
|
-
this.code = code;
|
|
114
|
-
this.data = data;
|
|
115
|
-
this.name = "DomainErrorSignal";
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
177
|
// src/context.ts
|
|
120
178
|
function createContext(definition, originalWorkflow, command, deps) {
|
|
121
179
|
let mutableState = originalWorkflow.state;
|
|
@@ -199,6 +257,46 @@ function createContext(definition, originalWorkflow, command, deps) {
|
|
|
199
257
|
return ctx;
|
|
200
258
|
}
|
|
201
259
|
|
|
260
|
+
// src/hooks.ts
|
|
261
|
+
var HOOK_EVENTS = /* @__PURE__ */ new Set([
|
|
262
|
+
"dispatch:start",
|
|
263
|
+
"dispatch:end",
|
|
264
|
+
"transition",
|
|
265
|
+
"error",
|
|
266
|
+
"event"
|
|
267
|
+
]);
|
|
268
|
+
var HookRegistry = class {
|
|
269
|
+
// biome-ignore lint/complexity/noBannedTypes: callbacks have varying signatures per hook event
|
|
270
|
+
hooks = /* @__PURE__ */ new Map();
|
|
271
|
+
/** Register a callback for a hook event. */
|
|
272
|
+
// biome-ignore lint/complexity/noBannedTypes: callbacks have varying signatures per hook event
|
|
273
|
+
add(event, callback) {
|
|
274
|
+
const existing = this.hooks.get(event) ?? [];
|
|
275
|
+
existing.push(callback);
|
|
276
|
+
this.hooks.set(event, existing);
|
|
277
|
+
}
|
|
278
|
+
/** Emit a hook event, calling all registered callbacks. Errors are caught and forwarded. */
|
|
279
|
+
async emit(event, onError, ...args) {
|
|
280
|
+
const callbacks = this.hooks.get(event);
|
|
281
|
+
if (!callbacks) return;
|
|
282
|
+
for (const cb of callbacks) {
|
|
283
|
+
try {
|
|
284
|
+
await cb(...args);
|
|
285
|
+
} catch (err) {
|
|
286
|
+
onError(err);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/** Merge another registry's hooks into this one (used by composable routers). */
|
|
291
|
+
merge(other) {
|
|
292
|
+
for (const [event, callbacks] of other.hooks) {
|
|
293
|
+
const existing = this.hooks.get(event) ?? [];
|
|
294
|
+
existing.push(...callbacks);
|
|
295
|
+
this.hooks.set(event, existing);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
202
300
|
// src/router.ts
|
|
203
301
|
var StateBuilder = class {
|
|
204
302
|
/** @internal */
|
|
@@ -220,20 +318,68 @@ var StateBuilder = class {
|
|
|
220
318
|
return this;
|
|
221
319
|
}
|
|
222
320
|
};
|
|
223
|
-
var WorkflowRouter = class {
|
|
224
|
-
constructor(definition, deps = {}) {
|
|
321
|
+
var WorkflowRouter = class _WorkflowRouter {
|
|
322
|
+
constructor(definition, deps = {}, options = {}) {
|
|
225
323
|
this.definition = definition;
|
|
226
324
|
this.deps = deps;
|
|
325
|
+
this.onHookError = options.onHookError ?? console.error;
|
|
227
326
|
}
|
|
228
327
|
globalMiddleware = [];
|
|
328
|
+
// biome-ignore lint/suspicious/noExplicitAny: type erasure — builders store handlers for different state types
|
|
229
329
|
singleStateBuilders = /* @__PURE__ */ new Map();
|
|
330
|
+
// biome-ignore lint/suspicious/noExplicitAny: type erasure — builders store handlers for different state types
|
|
230
331
|
multiStateBuilders = /* @__PURE__ */ new Map();
|
|
231
332
|
wildcardHandlers = /* @__PURE__ */ new Map();
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
333
|
+
hookRegistry = new HookRegistry();
|
|
334
|
+
onHookError;
|
|
335
|
+
/** Adds global middleware, merges another router, or applies a plugin. */
|
|
336
|
+
use(arg) {
|
|
337
|
+
if (arg instanceof _WorkflowRouter) {
|
|
338
|
+
this.merge(arg);
|
|
339
|
+
} else if (isPlugin(arg)) {
|
|
340
|
+
arg(this);
|
|
341
|
+
} else {
|
|
342
|
+
this.globalMiddleware.push(arg);
|
|
343
|
+
}
|
|
235
344
|
return this;
|
|
236
345
|
}
|
|
346
|
+
merge(child) {
|
|
347
|
+
if (child.definition !== this.definition) {
|
|
348
|
+
throw new Error(
|
|
349
|
+
`Cannot merge router for '${child.definition.name}' into router for '${this.definition.name}': definition mismatch`
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
this.globalMiddleware.push(...child.globalMiddleware);
|
|
353
|
+
this.mergeStateBuilders(this.singleStateBuilders, child.singleStateBuilders);
|
|
354
|
+
this.mergeStateBuilders(this.multiStateBuilders, child.multiStateBuilders);
|
|
355
|
+
for (const [command, entry] of child.wildcardHandlers) {
|
|
356
|
+
if (!this.wildcardHandlers.has(command)) {
|
|
357
|
+
this.wildcardHandlers.set(command, {
|
|
358
|
+
inlineMiddleware: [...entry.inlineMiddleware],
|
|
359
|
+
handler: entry.handler
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
this.hookRegistry.merge(child.hookRegistry);
|
|
364
|
+
}
|
|
365
|
+
mergeStateBuilders(target, source) {
|
|
366
|
+
for (const [stateName, childBuilder] of source) {
|
|
367
|
+
let parentBuilder = target.get(stateName);
|
|
368
|
+
if (!parentBuilder) {
|
|
369
|
+
parentBuilder = new StateBuilder();
|
|
370
|
+
target.set(stateName, parentBuilder);
|
|
371
|
+
}
|
|
372
|
+
for (const [command, entry] of childBuilder.handlers) {
|
|
373
|
+
if (!parentBuilder.handlers.has(command)) {
|
|
374
|
+
parentBuilder.handlers.set(command, {
|
|
375
|
+
inlineMiddleware: [...entry.inlineMiddleware],
|
|
376
|
+
handler: entry.handler
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
parentBuilder.middleware.push(...childBuilder.middleware);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
237
383
|
/** Registers handlers for one or more states. */
|
|
238
384
|
state(name, setup) {
|
|
239
385
|
const names = Array.isArray(name) ? name : [name];
|
|
@@ -249,19 +395,29 @@ var WorkflowRouter = class {
|
|
|
249
395
|
}
|
|
250
396
|
return this;
|
|
251
397
|
}
|
|
252
|
-
|
|
253
|
-
on(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
handler
|
|
263
|
-
|
|
264
|
-
|
|
398
|
+
// biome-ignore lint/suspicious/noExplicitAny: implementation signature must be loose to handle all overloads
|
|
399
|
+
on(...args) {
|
|
400
|
+
const first = args[0];
|
|
401
|
+
if (HOOK_EVENTS.has(first)) {
|
|
402
|
+
this.hookRegistry.add(first, args[1]);
|
|
403
|
+
return this;
|
|
404
|
+
}
|
|
405
|
+
if (first === "*") {
|
|
406
|
+
const command = args[1];
|
|
407
|
+
const fns = args.slice(2);
|
|
408
|
+
if (fns.length === 0) throw new Error("on() requires at least a handler");
|
|
409
|
+
const handler = fns.pop();
|
|
410
|
+
const inlineMiddleware = fns;
|
|
411
|
+
const wrappedHandler = async (ctx, _next) => {
|
|
412
|
+
await handler(ctx);
|
|
413
|
+
};
|
|
414
|
+
this.wildcardHandlers.set(command, {
|
|
415
|
+
inlineMiddleware,
|
|
416
|
+
handler: wrappedHandler
|
|
417
|
+
});
|
|
418
|
+
return this;
|
|
419
|
+
}
|
|
420
|
+
throw new Error(`Unknown event or state: ${first}`);
|
|
265
421
|
}
|
|
266
422
|
/** Dispatches a command to the appropriate handler and returns the result. */
|
|
267
423
|
async dispatch(workflow, command) {
|
|
@@ -335,17 +491,35 @@ var WorkflowRouter = class {
|
|
|
335
491
|
validatedCommand,
|
|
336
492
|
this.deps
|
|
337
493
|
);
|
|
494
|
+
await this.hookRegistry.emit("dispatch:start", this.onHookError, ctx);
|
|
338
495
|
try {
|
|
339
496
|
const composed = compose(chain);
|
|
340
497
|
await composed(ctx);
|
|
341
|
-
|
|
498
|
+
const result = {
|
|
342
499
|
ok: true,
|
|
343
500
|
workflow: ctx.getWorkflowSnapshot(),
|
|
344
501
|
events: [...ctx.events]
|
|
345
502
|
};
|
|
503
|
+
if (result.ok && result.workflow.state !== workflow.state) {
|
|
504
|
+
await this.hookRegistry.emit(
|
|
505
|
+
"transition",
|
|
506
|
+
this.onHookError,
|
|
507
|
+
workflow.state,
|
|
508
|
+
result.workflow.state,
|
|
509
|
+
result.workflow
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
if (result.ok) {
|
|
513
|
+
for (const event of result.events) {
|
|
514
|
+
await this.hookRegistry.emit("event", this.onHookError, event, result.workflow);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
await this.hookRegistry.emit("dispatch:end", this.onHookError, ctx, result);
|
|
518
|
+
return result;
|
|
346
519
|
} catch (err) {
|
|
520
|
+
let result;
|
|
347
521
|
if (err instanceof DomainErrorSignal) {
|
|
348
|
-
|
|
522
|
+
result = {
|
|
349
523
|
ok: false,
|
|
350
524
|
error: {
|
|
351
525
|
category: "domain",
|
|
@@ -353,9 +527,8 @@ var WorkflowRouter = class {
|
|
|
353
527
|
data: err.data
|
|
354
528
|
}
|
|
355
529
|
};
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
return {
|
|
530
|
+
} else if (err instanceof ValidationError) {
|
|
531
|
+
result = {
|
|
359
532
|
ok: false,
|
|
360
533
|
error: {
|
|
361
534
|
category: "validation",
|
|
@@ -364,8 +537,12 @@ var WorkflowRouter = class {
|
|
|
364
537
|
message: err.message
|
|
365
538
|
}
|
|
366
539
|
};
|
|
540
|
+
} else {
|
|
541
|
+
throw err;
|
|
367
542
|
}
|
|
368
|
-
|
|
543
|
+
await this.hookRegistry.emit("error", this.onHookError, result.error, ctx);
|
|
544
|
+
await this.hookRegistry.emit("dispatch:end", this.onHookError, ctx, result);
|
|
545
|
+
return result;
|
|
369
546
|
}
|
|
370
547
|
}
|
|
371
548
|
};
|
|
@@ -375,6 +552,8 @@ var WorkflowRouter = class {
|
|
|
375
552
|
ValidationError,
|
|
376
553
|
WorkflowRouter,
|
|
377
554
|
createKey,
|
|
378
|
-
|
|
555
|
+
definePlugin,
|
|
556
|
+
defineWorkflow,
|
|
557
|
+
isPlugin
|
|
379
558
|
});
|
|
380
559
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/definition.ts","../src/key.ts","../src/compose.ts","../src/types.ts","../src/context.ts","../src/router.ts"],"sourcesContent":["export type { Context } from \"./context.js\";\nexport type { WorkflowDefinition } from \"./definition.js\";\nexport { defineWorkflow } from \"./definition.js\";\nexport type { Handler } from \"./handler.js\";\nexport type { ContextKey } from \"./key.js\";\nexport { createKey } from \"./key.js\";\nexport type { Middleware } from \"./middleware.js\";\nexport { WorkflowRouter } from \"./router.js\";\nexport type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tErrorCodes,\n\tErrorData,\n\tEventData,\n\tEventNames,\n\tPipelineError,\n\tStateData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowOf,\n} from \"./types.js\";\nexport { DomainErrorSignal, ValidationError } from \"./types.js\";\n","import type { ZodType, z } from \"zod\";\nimport type { StateNames, WorkflowConfig, WorkflowOf } from \"./types.js\";\n\n/** The result of defineWorkflow() — holds schemas and creates workflow instances. */\nexport interface WorkflowDefinition<TConfig extends WorkflowConfig = WorkflowConfig> {\n\treadonly config: TConfig;\n\treadonly name: string;\n\tcreateWorkflow<S extends StateNames<TConfig>>(\n\t\tid: string,\n\t\tconfig: { initialState: S; data: z.infer<TConfig[\"states\"][S]> },\n\t): WorkflowOf<TConfig, S>;\n\tgetStateSchema(stateName: string): ZodType;\n\tgetCommandSchema(commandName: string): ZodType;\n\tgetEventSchema(eventName: string): ZodType;\n\tgetErrorSchema(errorCode: string): ZodType;\n\thasState(stateName: string): boolean;\n}\n\n/**\n * Creates a workflow definition from a name and Zod schema configuration.\n */\nexport function defineWorkflow<const TConfig extends WorkflowConfig>(\n\tname: string,\n\tconfig: TConfig,\n): WorkflowDefinition<TConfig> {\n\treturn {\n\t\tconfig,\n\t\tname,\n\n\t\tcreateWorkflow(id, wfConfig) {\n\t\t\tconst schema = config.states[wfConfig.initialState as string];\n\t\t\tif (!schema) throw new Error(`Unknown state: ${wfConfig.initialState as string}`);\n\t\t\tconst result = schema.safeParse(wfConfig.data);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid initial data for state '${wfConfig.initialState as string}': ${result.error.issues.map((i) => i.message).join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst now = new Date();\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tdefinitionName: name,\n\t\t\t\tstate: wfConfig.initialState,\n\t\t\t\tdata: result.data,\n\t\t\t\tcreatedAt: now,\n\t\t\t\tupdatedAt: now,\n\t\t\t} as WorkflowOf<TConfig, typeof wfConfig.initialState>;\n\t\t},\n\n\t\tgetStateSchema(stateName: string): ZodType {\n\t\t\tconst schema = config.states[stateName];\n\t\t\tif (!schema) throw new Error(`Unknown state: ${stateName}`);\n\t\t\treturn schema;\n\t\t},\n\n\t\tgetCommandSchema(commandName: string): ZodType {\n\t\t\tconst schema = config.commands[commandName];\n\t\t\tif (!schema) throw new Error(`Unknown command: ${commandName}`);\n\t\t\treturn schema;\n\t\t},\n\n\t\tgetEventSchema(eventName: string): ZodType {\n\t\t\tconst schema = config.events[eventName];\n\t\t\tif (!schema) throw new Error(`Unknown event: ${eventName}`);\n\t\t\treturn schema;\n\t\t},\n\n\t\tgetErrorSchema(errorCode: string): ZodType {\n\t\t\tconst schema = config.errors[errorCode];\n\t\t\tif (!schema) throw new Error(`Unknown error: ${errorCode}`);\n\t\t\treturn schema;\n\t\t},\n\n\t\thasState(stateName: string): boolean {\n\t\t\treturn stateName in config.states;\n\t\t},\n\t};\n}\n","/** A phantom-typed key for type-safe middleware state storage. */\nexport interface ContextKey<T> {\n\treadonly _phantom: T;\n\treadonly id: symbol;\n}\n\n/** Creates a unique typed key for storing/retrieving values in context. */\nexport function createKey<T>(name: string): ContextKey<T> {\n\treturn { id: Symbol(name) } as ContextKey<T>;\n}\n","type Middleware<TCtx> = (ctx: TCtx, next: () => Promise<void>) => Promise<void>;\n\n/** Composes an array of middleware into a single function (Koa-style onion model). */\nexport function compose<TCtx>(middleware: Middleware<TCtx>[]): (ctx: TCtx) => Promise<void> {\n\treturn async (ctx: TCtx) => {\n\t\tlet index = -1;\n\t\tasync function dispatch(i: number): Promise<void> {\n\t\t\tif (i <= index) throw new Error(\"next() called multiple times\");\n\t\t\tindex = i;\n\t\t\tconst fn = middleware[i];\n\t\t\tif (!fn) return;\n\t\t\tawait fn(ctx, () => dispatch(i + 1));\n\t\t}\n\t\tawait dispatch(0);\n\t};\n}\n","import type { ZodType, z } from \"zod\";\n\nexport interface WorkflowConfig {\n\tstates: Record<string, ZodType>;\n\tcommands: Record<string, ZodType>;\n\tevents: Record<string, ZodType>;\n\terrors: Record<string, ZodType>;\n}\n\nexport type StateNames<T extends WorkflowConfig> = keyof T[\"states\"] & string;\nexport type CommandNames<T extends WorkflowConfig> = keyof T[\"commands\"] & string;\nexport type EventNames<T extends WorkflowConfig> = keyof T[\"events\"] & string;\nexport type ErrorCodes<T extends WorkflowConfig> = keyof T[\"errors\"] & string;\n\nexport type StateData<\n\tT extends WorkflowConfig,\n\tS extends StateNames<T>,\n> = T[\"states\"][S] extends ZodType ? z.infer<T[\"states\"][S]> : never;\n\nexport type CommandPayload<\n\tT extends WorkflowConfig,\n\tC extends CommandNames<T>,\n> = T[\"commands\"][C] extends ZodType ? z.infer<T[\"commands\"][C]> : never;\n\nexport type EventData<\n\tT extends WorkflowConfig,\n\tE extends EventNames<T>,\n> = T[\"events\"][E] extends ZodType ? z.infer<T[\"events\"][E]> : never;\n\nexport type ErrorData<\n\tT extends WorkflowConfig,\n\tC extends ErrorCodes<T>,\n> = T[\"errors\"][C] extends ZodType ? z.infer<T[\"errors\"][C]> : never;\n\n/** Workflow narrowed to a specific known state. */\nexport interface WorkflowOf<TConfig extends WorkflowConfig, S extends StateNames<TConfig>> {\n\treadonly id: string;\n\treadonly definitionName: string;\n\treadonly state: S;\n\treadonly data: StateData<TConfig, S>;\n\treadonly createdAt: Date;\n\treadonly updatedAt: Date;\n}\n\n/** Discriminated union of all possible workflow states — checking .state narrows .data. */\nexport type Workflow<TConfig extends WorkflowConfig = WorkflowConfig> = {\n\t[S in StateNames<TConfig>]: WorkflowOf<TConfig, S>;\n}[StateNames<TConfig>];\n\nexport type PipelineError<TConfig extends WorkflowConfig = WorkflowConfig> =\n\t| {\n\t\t\tcategory: \"validation\";\n\t\t\tsource: \"command\" | \"state\" | \"event\" | \"transition\";\n\t\t\tissues: z.core.$ZodIssue[];\n\t\t\tmessage: string;\n\t }\n\t| {\n\t\t\tcategory: \"domain\";\n\t\t\tcode: ErrorCodes<TConfig>;\n\t\t\tdata: ErrorData<TConfig, ErrorCodes<TConfig>>;\n\t }\n\t| {\n\t\t\tcategory: \"router\";\n\t\t\tcode: \"NO_HANDLER\" | \"UNKNOWN_STATE\";\n\t\t\tmessage: string;\n\t };\n\nexport type DispatchResult<TConfig extends WorkflowConfig = WorkflowConfig> =\n\t| {\n\t\t\tok: true;\n\t\t\tworkflow: Workflow<TConfig>;\n\t\t\tevents: Array<{ type: EventNames<TConfig>; data: unknown }>;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\terror: PipelineError<TConfig>;\n\t };\n\n/** Thrown internally when Zod validation fails during dispatch. */\nexport class ValidationError extends Error {\n\tconstructor(\n\t\tpublic readonly source: \"command\" | \"state\" | \"event\" | \"transition\",\n\t\tpublic readonly issues: z.core.$ZodIssue[],\n\t) {\n\t\tsuper(`Validation failed (${source}): ${issues.map((i) => i.message).join(\", \")}`);\n\t\tthis.name = \"ValidationError\";\n\t}\n}\n\n/** Thrown internally when a handler calls ctx.error(). Caught by the router. */\nexport class DomainErrorSignal extends Error {\n\tconstructor(\n\t\tpublic readonly code: string,\n\t\tpublic readonly data: unknown,\n\t) {\n\t\tsuper(`Domain error: ${code}`);\n\t\tthis.name = \"DomainErrorSignal\";\n\t}\n}\n","import type { WorkflowDefinition } from \"./definition.js\";\nimport type { ContextKey } from \"./key.js\";\nimport type {\n\tCommandNames,\n\tCommandPayload,\n\tErrorCodes,\n\tErrorData,\n\tEventData,\n\tEventNames,\n\tStateData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowOf,\n} from \"./types.js\";\nimport { DomainErrorSignal, ValidationError } from \"./types.js\";\n\n/** Mutable context flowing through the middleware pipeline during dispatch. */\nexport interface Context<\n\tTConfig extends WorkflowConfig,\n\tTDeps,\n\tTState extends StateNames<TConfig> = StateNames<TConfig>,\n\tTCommand extends CommandNames<TConfig> = CommandNames<TConfig>,\n> {\n\treadonly command: {\n\t\treadonly type: TCommand;\n\t\treadonly payload: CommandPayload<TConfig, TCommand>;\n\t};\n\treadonly workflow: WorkflowOf<TConfig, TState>;\n\treadonly deps: TDeps;\n\n\treadonly data: StateData<TConfig, TState>;\n\tupdate(data: Partial<StateData<TConfig, TState>>): void;\n\n\ttransition<Target extends StateNames<TConfig>>(\n\t\ttarget: Target,\n\t\tdata: StateData<TConfig, Target>,\n\t): void;\n\n\temit<E extends EventNames<TConfig>>(event: { type: E; data: EventData<TConfig, E> }): void;\n\treadonly events: ReadonlyArray<{ type: EventNames<TConfig>; data: unknown }>;\n\n\terror<C extends ErrorCodes<TConfig>>(err: { code: C; data: ErrorData<TConfig, C> }): never;\n\n\tset<T>(key: ContextKey<T>, value: T): void;\n\tget<T>(key: ContextKey<T>): T;\n\tgetOrNull<T>(key: ContextKey<T>): T | undefined;\n\n\t/** @internal — not part of the handler API */\n\tgetWorkflowSnapshot(): Workflow<TConfig>;\n}\n\ninterface DomainEvent {\n\ttype: string;\n\tdata: unknown;\n}\n\n/** @internal Creates a context for dispatch. Not part of public API. */\nexport function createContext<TConfig extends WorkflowConfig, TDeps>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\toriginalWorkflow: Workflow<TConfig>,\n\tcommand: { type: string; payload: unknown },\n\tdeps: TDeps,\n): Context<TConfig, TDeps> {\n\tlet mutableState = originalWorkflow.state;\n\tlet mutableData: Record<string, unknown> = {\n\t\t...(originalWorkflow.data as Record<string, unknown>),\n\t};\n\n\tconst accumulatedEvents: DomainEvent[] = [];\n\tconst middlewareState = new Map<symbol, unknown>();\n\n\tconst ctx = {\n\t\tcommand,\n\t\tworkflow: originalWorkflow,\n\t\tdeps,\n\n\t\tget data() {\n\t\t\treturn { ...mutableData } as StateData<TConfig, StateNames<TConfig>>;\n\t\t},\n\n\t\tupdate(data: Record<string, unknown>) {\n\t\t\tconst merged = { ...mutableData, ...data };\n\t\t\tconst schema = definition.getStateSchema(mutableState);\n\t\t\tconst result = schema.safeParse(merged);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new ValidationError(\"state\", result.error.issues);\n\t\t\t}\n\t\t\tmutableData = result.data as Record<string, unknown>;\n\t\t},\n\n\t\ttransition(target: string, data: unknown) {\n\t\t\tif (!definition.hasState(target)) {\n\t\t\t\tthrow new Error(`Unknown state: ${target}`);\n\t\t\t}\n\t\t\tconst schema = definition.getStateSchema(target);\n\t\t\tconst result = schema.safeParse(data);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new ValidationError(\"transition\", result.error.issues);\n\t\t\t}\n\t\t\tmutableState = target;\n\t\t\tmutableData = result.data as Record<string, unknown>;\n\t\t},\n\n\t\temit(event: { type: string; data: unknown }) {\n\t\t\tconst schema = definition.getEventSchema(event.type);\n\t\t\tconst result = schema.safeParse(event.data);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new ValidationError(\"event\", result.error.issues);\n\t\t\t}\n\t\t\taccumulatedEvents.push({ type: event.type, data: result.data });\n\t\t},\n\n\t\tget events() {\n\t\t\treturn [...accumulatedEvents];\n\t\t},\n\n\t\terror(err: { code: string; data: unknown }) {\n\t\t\tconst schema = definition.getErrorSchema(err.code);\n\t\t\tconst result = schema.safeParse(err.data);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid error data for '${err.code}': ${result.error.issues.map((i) => i.message).join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new DomainErrorSignal(err.code, result.data);\n\t\t},\n\n\t\tset<T>(key: ContextKey<T>, value: T) {\n\t\t\tmiddlewareState.set(key.id, value);\n\t\t},\n\n\t\tget<T>(key: ContextKey<T>): T {\n\t\t\tif (!middlewareState.has(key.id)) {\n\t\t\t\tthrow new Error(`Context key not set: ${key.id.toString()}`);\n\t\t\t}\n\t\t\treturn middlewareState.get(key.id) as T;\n\t\t},\n\n\t\tgetOrNull<T>(key: ContextKey<T>): T | undefined {\n\t\t\treturn middlewareState.get(key.id) as T | undefined;\n\t\t},\n\n\t\tgetWorkflowSnapshot(): Workflow<TConfig> {\n\t\t\treturn {\n\t\t\t\tid: originalWorkflow.id,\n\t\t\t\tdefinitionName: originalWorkflow.definitionName,\n\t\t\t\tstate: mutableState,\n\t\t\t\tdata: { ...mutableData },\n\t\t\t\tcreatedAt: originalWorkflow.createdAt,\n\t\t\t\tupdatedAt: new Date(),\n\t\t\t} as Workflow<TConfig>;\n\t\t},\n\t};\n\n\treturn ctx as unknown as Context<TConfig, TDeps>;\n}\n","import { compose } from \"./compose.js\";\nimport { type Context, createContext } from \"./context.js\";\nimport type { WorkflowDefinition } from \"./definition.js\";\nimport type {\n\tCommandNames,\n\tDispatchResult,\n\tErrorCodes,\n\tErrorData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n} from \"./types.js\";\nimport { DomainErrorSignal, ValidationError } from \"./types.js\";\n\ntype AnyMiddleware = (ctx: any, next: () => Promise<void>) => Promise<void>;\ntype AnyHandler = (ctx: any) => void | Promise<void>;\n\ntype HandlerEntry = { inlineMiddleware: AnyMiddleware[]; handler: AnyMiddleware };\n\nclass StateBuilder<TConfig extends WorkflowConfig, TDeps, TState extends StateNames<TConfig>> {\n\t/** @internal */ readonly middleware: AnyMiddleware[] = [];\n\t/** @internal */ readonly handlers = new Map<string, HandlerEntry>();\n\n\ton<C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\t...fns: [...AnyMiddleware[], (ctx: Context<TConfig, TDeps, TState, C>) => void | Promise<void>]\n\t): this {\n\t\tif (fns.length === 0) throw new Error(\"on() requires at least a handler\");\n\t\tconst handler = fns.pop() as AnyHandler;\n\t\tconst inlineMiddleware = fns as AnyMiddleware[];\n\t\tconst wrappedHandler: AnyMiddleware = async (ctx, _next) => {\n\t\t\tawait handler(ctx);\n\t\t};\n\t\tthis.handlers.set(command as string, { inlineMiddleware, handler: wrappedHandler });\n\t\treturn this;\n\t}\n\n\tuse(\n\t\tmiddleware: (ctx: Context<TConfig, TDeps, TState>, next: () => Promise<void>) => Promise<void>,\n\t): this {\n\t\tthis.middleware.push(middleware as AnyMiddleware);\n\t\treturn this;\n\t}\n}\n\n/**\n * Routes commands to handlers based on workflow state.\n *\n * Supports global middleware, state-scoped middleware, inline middleware,\n * wildcard handlers, and multi-state handlers.\n */\nexport class WorkflowRouter<TConfig extends WorkflowConfig, TDeps = {}> {\n\tprivate globalMiddleware: AnyMiddleware[] = [];\n\tprivate singleStateBuilders = new Map<string, StateBuilder<TConfig, TDeps, any>>();\n\tprivate multiStateBuilders = new Map<string, StateBuilder<TConfig, TDeps, any>>();\n\tprivate wildcardHandlers = new Map<string, HandlerEntry>();\n\n\tconstructor(\n\t\tprivate readonly definition: WorkflowDefinition<TConfig>,\n\t\tprivate readonly deps: TDeps = {} as TDeps,\n\t) {}\n\n\t/** Adds global middleware that wraps all dispatches. */\n\tuse(\n\t\tmiddleware: (ctx: Context<TConfig, TDeps>, next: () => Promise<void>) => Promise<void>,\n\t): this {\n\t\tthis.globalMiddleware.push(middleware as AnyMiddleware);\n\t\treturn this;\n\t}\n\n\t/** Registers handlers for one or more states. */\n\tstate<P extends StateNames<TConfig> | readonly StateNames<TConfig>[]>(\n\t\tname: P,\n\t\tsetup: (\n\t\t\tstate: StateBuilder<\n\t\t\t\tTConfig,\n\t\t\t\tTDeps,\n\t\t\t\tP extends readonly (infer S)[] ? S & StateNames<TConfig> : P & StateNames<TConfig>\n\t\t\t>,\n\t\t) => void,\n\t): this {\n\t\tconst names = Array.isArray(name) ? name : [name];\n\t\tconst isMulti = Array.isArray(name);\n\t\tconst routerMap = isMulti ? this.multiStateBuilders : this.singleStateBuilders;\n\n\t\tfor (const n of names as string[]) {\n\t\t\tlet router = routerMap.get(n);\n\t\t\tif (!router) {\n\t\t\t\trouter = new StateBuilder<TConfig, TDeps, any>();\n\t\t\t\trouterMap.set(n, router);\n\t\t\t}\n\t\t\tsetup(router as any);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** Registers a wildcard handler that matches any state. */\n\ton<C extends CommandNames<TConfig>>(\n\t\t_state: \"*\",\n\t\tcommand: C,\n\t\t...fns: [\n\t\t\t...AnyMiddleware[],\n\t\t\t(ctx: Context<TConfig, TDeps, StateNames<TConfig>, C>) => void | Promise<void>,\n\t\t]\n\t): this {\n\t\tif (fns.length === 0) throw new Error(\"on() requires at least a handler\");\n\t\tconst handler = fns.pop() as AnyHandler;\n\t\tconst inlineMiddleware = fns as AnyMiddleware[];\n\t\tconst wrappedHandler: AnyMiddleware = async (ctx, _next) => {\n\t\t\tawait handler(ctx);\n\t\t};\n\t\tthis.wildcardHandlers.set(command as string, {\n\t\t\tinlineMiddleware,\n\t\t\thandler: wrappedHandler,\n\t\t});\n\t\treturn this;\n\t}\n\n\t/** Dispatches a command to the appropriate handler and returns the result. */\n\tasync dispatch(\n\t\tworkflow: Workflow<TConfig>,\n\t\tcommand: { type: CommandNames<TConfig>; payload: unknown },\n\t): Promise<DispatchResult<TConfig>> {\n\t\tif (!this.definition.hasState(workflow.state)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"router\",\n\t\t\t\t\tcode: \"UNKNOWN_STATE\",\n\t\t\t\t\tmessage: `Unknown state: ${workflow.state}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst commandSchema = this.definition.getCommandSchema(command.type);\n\t\tconst payloadResult = commandSchema.safeParse(command.payload);\n\t\tif (!payloadResult.success) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"validation\",\n\t\t\t\t\tsource: \"command\",\n\t\t\t\t\tissues: payloadResult.error.issues,\n\t\t\t\t\tmessage: `Invalid command payload: ${payloadResult.error.issues.map((i) => i.message).join(\", \")}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconst validatedCommand = { type: command.type, payload: payloadResult.data };\n\n\t\tconst stateName = workflow.state;\n\t\tconst singleRouter = this.singleStateBuilders.get(stateName);\n\t\tconst multiRouter = this.multiStateBuilders.get(stateName);\n\t\tconst singleHandler = singleRouter?.handlers.get(command.type);\n\t\tconst multiHandler = multiRouter?.handlers.get(command.type);\n\t\tconst wildcardHandler = this.wildcardHandlers.get(command.type);\n\n\t\tlet routeEntry: HandlerEntry | undefined;\n\t\tlet matchedRouter: StateBuilder<TConfig, TDeps, any> | undefined;\n\n\t\tif (singleHandler) {\n\t\t\trouteEntry = singleHandler;\n\t\t\tmatchedRouter = singleRouter;\n\t\t} else if (multiHandler) {\n\t\t\trouteEntry = multiHandler;\n\t\t\tmatchedRouter = multiRouter;\n\t\t} else if (wildcardHandler) {\n\t\t\trouteEntry = wildcardHandler;\n\t\t\tmatchedRouter = undefined;\n\t\t}\n\n\t\tif (!routeEntry) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"router\",\n\t\t\t\t\tcode: \"NO_HANDLER\",\n\t\t\t\t\tmessage: `No handler for command '${command.type}' in state '${stateName}'`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst stateMiddleware: AnyMiddleware[] = [];\n\t\tif (matchedRouter) {\n\t\t\tif (singleRouter) stateMiddleware.push(...singleRouter.middleware);\n\t\t\tif (multiRouter && multiRouter !== singleRouter)\n\t\t\t\tstateMiddleware.push(...multiRouter.middleware);\n\t\t}\n\n\t\tconst chain: AnyMiddleware[] = [\n\t\t\t...this.globalMiddleware,\n\t\t\t...stateMiddleware,\n\t\t\t...routeEntry.inlineMiddleware,\n\t\t\trouteEntry.handler,\n\t\t];\n\n\t\tconst ctx = createContext<TConfig, TDeps>(\n\t\t\tthis.definition,\n\t\t\tworkflow,\n\t\t\tvalidatedCommand,\n\t\t\tthis.deps,\n\t\t);\n\n\t\ttry {\n\t\t\tconst composed = compose(chain);\n\t\t\tawait composed(ctx);\n\t\t\treturn {\n\t\t\t\tok: true as const,\n\t\t\t\tworkflow: ctx.getWorkflowSnapshot(),\n\t\t\t\tevents: [...ctx.events],\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tif (err instanceof DomainErrorSignal) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false as const,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcategory: \"domain\" as const,\n\t\t\t\t\t\tcode: err.code as ErrorCodes<TConfig>,\n\t\t\t\t\t\tdata: err.data as ErrorData<TConfig, ErrorCodes<TConfig>>,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (err instanceof ValidationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false as const,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcategory: \"validation\" as const,\n\t\t\t\t\t\tsource: err.source,\n\t\t\t\t\t\tissues: err.issues,\n\t\t\t\t\t\tmessage: err.message,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/definition.ts","../src/key.ts","../src/plugin.ts","../src/compose.ts","../src/context.ts","../src/hooks.ts","../src/router.ts"],"sourcesContent":["export type { Context } from \"./context.js\";\nexport type { WorkflowDefinition } from \"./definition.js\";\nexport { defineWorkflow } from \"./definition.js\";\nexport type { Handler } from \"./handler.js\";\nexport type { HookEvent } from \"./hooks.js\";\nexport type { ContextKey } from \"./key.js\";\nexport { createKey } from \"./key.js\";\nexport type { Middleware } from \"./middleware.js\";\nexport type { Plugin } from \"./plugin.js\";\nexport { definePlugin, isPlugin } from \"./plugin.js\";\nexport type { ReadonlyContext } from \"./readonly-context.js\";\nexport type { RouterOptions } from \"./router.js\";\nexport { WorkflowRouter } from \"./router.js\";\nexport type { WorkflowSnapshot } from \"./snapshot.js\";\nexport type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tErrorCodes,\n\tErrorData,\n\tEventData,\n\tEventNames,\n\tPipelineError,\n\tStateData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowOf,\n} from \"./types.js\";\nexport { DomainErrorSignal, ValidationError } from \"./types.js\";\n","import type { ZodType, z } from \"zod\";\n\nexport interface WorkflowConfig {\n\tmodelVersion?: number;\n\tstates: Record<string, ZodType>;\n\tcommands: Record<string, ZodType>;\n\tevents: Record<string, ZodType>;\n\terrors: Record<string, ZodType>;\n}\n\nexport type StateNames<T extends WorkflowConfig> = keyof T[\"states\"] & string;\nexport type CommandNames<T extends WorkflowConfig> = keyof T[\"commands\"] & string;\nexport type EventNames<T extends WorkflowConfig> = keyof T[\"events\"] & string;\nexport type ErrorCodes<T extends WorkflowConfig> = keyof T[\"errors\"] & string;\n\nexport type StateData<\n\tT extends WorkflowConfig,\n\tS extends StateNames<T>,\n> = T[\"states\"][S] extends ZodType ? z.infer<T[\"states\"][S]> : never;\n\nexport type CommandPayload<\n\tT extends WorkflowConfig,\n\tC extends CommandNames<T>,\n> = T[\"commands\"][C] extends ZodType ? z.infer<T[\"commands\"][C]> : never;\n\nexport type EventData<\n\tT extends WorkflowConfig,\n\tE extends EventNames<T>,\n> = T[\"events\"][E] extends ZodType ? z.infer<T[\"events\"][E]> : never;\n\nexport type ErrorData<\n\tT extends WorkflowConfig,\n\tC extends ErrorCodes<T>,\n> = T[\"errors\"][C] extends ZodType ? z.infer<T[\"errors\"][C]> : never;\n\n/** Workflow narrowed to a specific known state. */\nexport interface WorkflowOf<TConfig extends WorkflowConfig, S extends StateNames<TConfig>> {\n\treadonly id: string;\n\treadonly definitionName: string;\n\treadonly state: S;\n\treadonly data: StateData<TConfig, S>;\n\treadonly createdAt: Date;\n\treadonly updatedAt: Date;\n}\n\n/** Discriminated union of all possible workflow states — checking .state narrows .data. */\nexport type Workflow<TConfig extends WorkflowConfig = WorkflowConfig> = {\n\t[S in StateNames<TConfig>]: WorkflowOf<TConfig, S>;\n}[StateNames<TConfig>];\n\nexport type PipelineError<TConfig extends WorkflowConfig = WorkflowConfig> =\n\t| {\n\t\t\tcategory: \"validation\";\n\t\t\tsource: \"command\" | \"state\" | \"event\" | \"transition\" | \"restore\";\n\t\t\tissues: z.core.$ZodIssue[];\n\t\t\tmessage: string;\n\t }\n\t| {\n\t\t\tcategory: \"domain\";\n\t\t\tcode: ErrorCodes<TConfig>;\n\t\t\tdata: ErrorData<TConfig, ErrorCodes<TConfig>>;\n\t }\n\t| {\n\t\t\tcategory: \"router\";\n\t\t\tcode: \"NO_HANDLER\" | \"UNKNOWN_STATE\";\n\t\t\tmessage: string;\n\t };\n\nexport type DispatchResult<TConfig extends WorkflowConfig = WorkflowConfig> =\n\t| {\n\t\t\tok: true;\n\t\t\tworkflow: Workflow<TConfig>;\n\t\t\tevents: Array<{ type: EventNames<TConfig>; data: unknown }>;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\terror: PipelineError<TConfig>;\n\t };\n\n/** Thrown internally when Zod validation fails during dispatch. */\nexport class ValidationError extends Error {\n\tconstructor(\n\t\tpublic readonly source: \"command\" | \"state\" | \"event\" | \"transition\" | \"restore\",\n\t\tpublic readonly issues: z.core.$ZodIssue[],\n\t) {\n\t\tsuper(`Validation failed (${source}): ${issues.map((i) => i.message).join(\", \")}`);\n\t\tthis.name = \"ValidationError\";\n\t}\n}\n\n/** Thrown internally when a handler calls ctx.error(). Caught by the router. */\nexport class DomainErrorSignal extends Error {\n\tconstructor(\n\t\tpublic readonly code: string,\n\t\tpublic readonly data: unknown,\n\t) {\n\t\tsuper(`Domain error: ${code}`);\n\t\tthis.name = \"DomainErrorSignal\";\n\t}\n}\n","import type { ZodType, z } from \"zod\";\nimport type { WorkflowSnapshot } from \"./snapshot.js\";\nimport type { StateNames, Workflow, WorkflowConfig, WorkflowOf } from \"./types.js\";\nimport { ValidationError } from \"./types.js\";\n\n/** The result of defineWorkflow() — holds schemas and creates workflow instances. */\nexport interface WorkflowDefinition<TConfig extends WorkflowConfig = WorkflowConfig> {\n\treadonly config: TConfig;\n\treadonly name: string;\n\tcreateWorkflow<S extends StateNames<TConfig>>(\n\t\tid: string,\n\t\tconfig: { initialState: S; data: z.infer<TConfig[\"states\"][S]> },\n\t): WorkflowOf<TConfig, S>;\n\tgetStateSchema(stateName: string): ZodType;\n\tgetCommandSchema(commandName: string): ZodType;\n\tgetEventSchema(eventName: string): ZodType;\n\tgetErrorSchema(errorCode: string): ZodType;\n\thasState(stateName: string): boolean;\n\tsnapshot(workflow: Workflow<TConfig>): WorkflowSnapshot<TConfig>;\n\trestore(\n\t\tsnapshot: WorkflowSnapshot<TConfig>,\n\t): { ok: true; workflow: Workflow<TConfig> } | { ok: false; error: ValidationError };\n}\n\n/**\n * Creates a workflow definition from a name and Zod schema configuration.\n */\nexport function defineWorkflow<const TConfig extends WorkflowConfig>(\n\tname: string,\n\tconfig: TConfig,\n): WorkflowDefinition<TConfig> {\n\treturn {\n\t\tconfig,\n\t\tname,\n\n\t\tcreateWorkflow(id, wfConfig) {\n\t\t\tconst schema = config.states[wfConfig.initialState as string];\n\t\t\tif (!schema) throw new Error(`Unknown state: ${wfConfig.initialState as string}`);\n\t\t\tconst result = schema.safeParse(wfConfig.data);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid initial data for state '${wfConfig.initialState as string}': ${result.error.issues.map((i) => i.message).join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst now = new Date();\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tdefinitionName: name,\n\t\t\t\tstate: wfConfig.initialState,\n\t\t\t\tdata: result.data,\n\t\t\t\tcreatedAt: now,\n\t\t\t\tupdatedAt: now,\n\t\t\t} as WorkflowOf<TConfig, typeof wfConfig.initialState>;\n\t\t},\n\n\t\tgetStateSchema(stateName: string): ZodType {\n\t\t\tconst schema = config.states[stateName];\n\t\t\tif (!schema) throw new Error(`Unknown state: ${stateName}`);\n\t\t\treturn schema;\n\t\t},\n\n\t\tgetCommandSchema(commandName: string): ZodType {\n\t\t\tconst schema = config.commands[commandName];\n\t\t\tif (!schema) throw new Error(`Unknown command: ${commandName}`);\n\t\t\treturn schema;\n\t\t},\n\n\t\tgetEventSchema(eventName: string): ZodType {\n\t\t\tconst schema = config.events[eventName];\n\t\t\tif (!schema) throw new Error(`Unknown event: ${eventName}`);\n\t\t\treturn schema;\n\t\t},\n\n\t\tgetErrorSchema(errorCode: string): ZodType {\n\t\t\tconst schema = config.errors[errorCode];\n\t\t\tif (!schema) throw new Error(`Unknown error: ${errorCode}`);\n\t\t\treturn schema;\n\t\t},\n\n\t\thasState(stateName: string): boolean {\n\t\t\treturn stateName in config.states;\n\t\t},\n\n\t\tsnapshot(workflow: Workflow<TConfig>): WorkflowSnapshot<TConfig> {\n\t\t\treturn {\n\t\t\t\tid: workflow.id,\n\t\t\t\tdefinitionName: name,\n\t\t\t\tstate: workflow.state,\n\t\t\t\tdata: workflow.data,\n\t\t\t\tcreatedAt: workflow.createdAt.toISOString(),\n\t\t\t\tupdatedAt: workflow.updatedAt.toISOString(),\n\t\t\t\tmodelVersion: config.modelVersion ?? 1,\n\t\t\t} as WorkflowSnapshot<TConfig>;\n\t\t},\n\n\t\trestore(\n\t\t\tsnap: WorkflowSnapshot<TConfig>,\n\t\t): { ok: true; workflow: Workflow<TConfig> } | { ok: false; error: ValidationError } {\n\t\t\tconst stateSchema = config.states[snap.state as string];\n\t\t\tif (!stateSchema) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: new ValidationError(\"restore\", [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\t\t\tmessage: `Unknown state: ${snap.state}`,\n\t\t\t\t\t\t\tinput: snap.state,\n\t\t\t\t\t\t\tpath: [\"state\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t]),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst result = stateSchema.safeParse(snap.data);\n\t\t\tif (!result.success) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: new ValidationError(\"restore\", result.error.issues),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tworkflow: {\n\t\t\t\t\tid: snap.id,\n\t\t\t\t\tdefinitionName: snap.definitionName,\n\t\t\t\t\tstate: snap.state,\n\t\t\t\t\tdata: result.data,\n\t\t\t\t\tcreatedAt: new Date(snap.createdAt),\n\t\t\t\t\tupdatedAt: new Date(snap.updatedAt),\n\t\t\t\t} as Workflow<TConfig>,\n\t\t\t};\n\t\t},\n\t};\n}\n","/** A phantom-typed key for type-safe middleware state storage. */\nexport interface ContextKey<T> {\n\treadonly _phantom: T;\n\treadonly id: symbol;\n}\n\n/** Creates a unique typed key for storing/retrieving values in context. */\nexport function createKey<T>(name: string): ContextKey<T> {\n\treturn { id: Symbol(name) } as ContextKey<T>;\n}\n","import type { WorkflowRouter } from \"./router.js\";\nimport type { WorkflowConfig } from \"./types.js\";\n\nconst PLUGIN_SYMBOL: unique symbol = Symbol.for(\"ryte:plugin\");\n\n/** A branded plugin function that can be passed to router.use(). */\nexport type Plugin<TConfig extends WorkflowConfig, TDeps> = ((\n\trouter: WorkflowRouter<TConfig, TDeps>,\n) => void) & { readonly [PLUGIN_SYMBOL]: true };\n\n/** Brands a function as a Ryte plugin for use with router.use(). */\nexport function definePlugin<TConfig extends WorkflowConfig, TDeps>(\n\tfn: (router: WorkflowRouter<TConfig, TDeps>) => void,\n): Plugin<TConfig, TDeps> {\n\tconst plugin = fn as Plugin<TConfig, TDeps>;\n\tObject.defineProperty(plugin, PLUGIN_SYMBOL, { value: true, writable: false });\n\treturn plugin;\n}\n\n/** Checks whether a value is a branded Ryte plugin. */\nexport function isPlugin(value: unknown): value is Plugin<WorkflowConfig, unknown> {\n\treturn typeof value === \"function\" && PLUGIN_SYMBOL in value;\n}\n","type Middleware<TCtx> = (ctx: TCtx, next: () => Promise<void>) => Promise<void>;\n\n/** Composes an array of middleware into a single function (Koa-style onion model). */\nexport function compose<TCtx>(middleware: Middleware<TCtx>[]): (ctx: TCtx) => Promise<void> {\n\treturn async (ctx: TCtx) => {\n\t\tlet index = -1;\n\t\tasync function dispatch(i: number): Promise<void> {\n\t\t\tif (i <= index) throw new Error(\"next() called multiple times\");\n\t\t\tindex = i;\n\t\t\tconst fn = middleware[i];\n\t\t\tif (!fn) return;\n\t\t\tawait fn(ctx, () => dispatch(i + 1));\n\t\t}\n\t\tawait dispatch(0);\n\t};\n}\n","import type { WorkflowDefinition } from \"./definition.js\";\nimport type { ContextKey } from \"./key.js\";\nimport type {\n\tCommandNames,\n\tCommandPayload,\n\tErrorCodes,\n\tErrorData,\n\tEventData,\n\tEventNames,\n\tStateData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowOf,\n} from \"./types.js\";\nimport { DomainErrorSignal, ValidationError } from \"./types.js\";\n\n/** Mutable context flowing through the middleware pipeline during dispatch. */\nexport interface Context<\n\tTConfig extends WorkflowConfig,\n\tTDeps,\n\tTState extends StateNames<TConfig> = StateNames<TConfig>,\n\tTCommand extends CommandNames<TConfig> = CommandNames<TConfig>,\n> {\n\treadonly command: {\n\t\treadonly type: TCommand;\n\t\treadonly payload: CommandPayload<TConfig, TCommand>;\n\t};\n\treadonly workflow: WorkflowOf<TConfig, TState>;\n\treadonly deps: TDeps;\n\n\treadonly data: StateData<TConfig, TState>;\n\tupdate(data: Partial<StateData<TConfig, TState>>): void;\n\n\ttransition<Target extends StateNames<TConfig>>(\n\t\ttarget: Target,\n\t\tdata: StateData<TConfig, Target>,\n\t): void;\n\n\temit<E extends EventNames<TConfig>>(event: { type: E; data: EventData<TConfig, E> }): void;\n\treadonly events: ReadonlyArray<{ type: EventNames<TConfig>; data: unknown }>;\n\n\terror<C extends ErrorCodes<TConfig>>(err: { code: C; data: ErrorData<TConfig, C> }): never;\n\n\tset<T>(key: ContextKey<T>, value: T): void;\n\tget<T>(key: ContextKey<T>): T;\n\tgetOrNull<T>(key: ContextKey<T>): T | undefined;\n\n\t/** @internal — not part of the handler API */\n\tgetWorkflowSnapshot(): Workflow<TConfig>;\n}\n\ninterface DomainEvent {\n\ttype: string;\n\tdata: unknown;\n}\n\n/** @internal Creates a context for dispatch. Not part of public API. */\nexport function createContext<TConfig extends WorkflowConfig, TDeps>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\toriginalWorkflow: Workflow<TConfig>,\n\tcommand: { type: string; payload: unknown },\n\tdeps: TDeps,\n): Context<TConfig, TDeps> {\n\tlet mutableState = originalWorkflow.state;\n\tlet mutableData: Record<string, unknown> = {\n\t\t...(originalWorkflow.data as Record<string, unknown>),\n\t};\n\n\tconst accumulatedEvents: DomainEvent[] = [];\n\tconst middlewareState = new Map<symbol, unknown>();\n\n\tconst ctx = {\n\t\tcommand,\n\t\tworkflow: originalWorkflow,\n\t\tdeps,\n\n\t\tget data() {\n\t\t\treturn { ...mutableData } as StateData<TConfig, StateNames<TConfig>>;\n\t\t},\n\n\t\tupdate(data: Record<string, unknown>) {\n\t\t\tconst merged = { ...mutableData, ...data };\n\t\t\tconst schema = definition.getStateSchema(mutableState);\n\t\t\tconst result = schema.safeParse(merged);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new ValidationError(\"state\", result.error.issues);\n\t\t\t}\n\t\t\tmutableData = result.data as Record<string, unknown>;\n\t\t},\n\n\t\ttransition(target: string, data: unknown) {\n\t\t\tif (!definition.hasState(target)) {\n\t\t\t\tthrow new Error(`Unknown state: ${target}`);\n\t\t\t}\n\t\t\tconst schema = definition.getStateSchema(target);\n\t\t\tconst result = schema.safeParse(data);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new ValidationError(\"transition\", result.error.issues);\n\t\t\t}\n\t\t\tmutableState = target;\n\t\t\tmutableData = result.data as Record<string, unknown>;\n\t\t},\n\n\t\temit(event: { type: string; data: unknown }) {\n\t\t\tconst schema = definition.getEventSchema(event.type);\n\t\t\tconst result = schema.safeParse(event.data);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new ValidationError(\"event\", result.error.issues);\n\t\t\t}\n\t\t\taccumulatedEvents.push({ type: event.type, data: result.data });\n\t\t},\n\n\t\tget events() {\n\t\t\treturn [...accumulatedEvents];\n\t\t},\n\n\t\terror(err: { code: string; data: unknown }) {\n\t\t\tconst schema = definition.getErrorSchema(err.code);\n\t\t\tconst result = schema.safeParse(err.data);\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid error data for '${err.code}': ${result.error.issues.map((i) => i.message).join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new DomainErrorSignal(err.code, result.data);\n\t\t},\n\n\t\tset<T>(key: ContextKey<T>, value: T) {\n\t\t\tmiddlewareState.set(key.id, value);\n\t\t},\n\n\t\tget<T>(key: ContextKey<T>): T {\n\t\t\tif (!middlewareState.has(key.id)) {\n\t\t\t\tthrow new Error(`Context key not set: ${key.id.toString()}`);\n\t\t\t}\n\t\t\treturn middlewareState.get(key.id) as T;\n\t\t},\n\n\t\tgetOrNull<T>(key: ContextKey<T>): T | undefined {\n\t\t\treturn middlewareState.get(key.id) as T | undefined;\n\t\t},\n\n\t\tgetWorkflowSnapshot(): Workflow<TConfig> {\n\t\t\treturn {\n\t\t\t\tid: originalWorkflow.id,\n\t\t\t\tdefinitionName: originalWorkflow.definitionName,\n\t\t\t\tstate: mutableState,\n\t\t\t\tdata: { ...mutableData },\n\t\t\t\tcreatedAt: originalWorkflow.createdAt,\n\t\t\t\tupdatedAt: new Date(),\n\t\t\t} as Workflow<TConfig>;\n\t\t},\n\t};\n\n\treturn ctx as unknown as Context<TConfig, TDeps>;\n}\n","/** The lifecycle hook event names. */\nexport type HookEvent = \"dispatch:start\" | \"dispatch:end\" | \"transition\" | \"error\" | \"event\";\n\nexport const HOOK_EVENTS: ReadonlySet<string> = new Set<HookEvent>([\n\t\"dispatch:start\",\n\t\"dispatch:end\",\n\t\"transition\",\n\t\"error\",\n\t\"event\",\n]);\n\n/**\n * Internal registry for lifecycle hook callbacks.\n * Hooks are observers — errors are caught and forwarded, never affecting dispatch.\n */\nexport class HookRegistry {\n\t// biome-ignore lint/complexity/noBannedTypes: callbacks have varying signatures per hook event\n\tprivate hooks = new Map<string, Function[]>();\n\n\t/** Register a callback for a hook event. */\n\t// biome-ignore lint/complexity/noBannedTypes: callbacks have varying signatures per hook event\n\tadd(event: string, callback: Function): void {\n\t\tconst existing = this.hooks.get(event) ?? [];\n\t\texisting.push(callback);\n\t\tthis.hooks.set(event, existing);\n\t}\n\n\t/** Emit a hook event, calling all registered callbacks. Errors are caught and forwarded. */\n\tasync emit(event: string, onError: (err: unknown) => void, ...args: unknown[]): Promise<void> {\n\t\tconst callbacks = this.hooks.get(event);\n\t\tif (!callbacks) return;\n\t\tfor (const cb of callbacks) {\n\t\t\ttry {\n\t\t\t\tawait cb(...args);\n\t\t\t} catch (err) {\n\t\t\t\tonError(err);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Merge another registry's hooks into this one (used by composable routers). */\n\tmerge(other: HookRegistry): void {\n\t\tfor (const [event, callbacks] of other.hooks) {\n\t\t\tconst existing = this.hooks.get(event) ?? [];\n\t\t\texisting.push(...callbacks);\n\t\t\tthis.hooks.set(event, existing);\n\t\t}\n\t}\n}\n","import { compose } from \"./compose.js\";\nimport { type Context, createContext } from \"./context.js\";\nimport type { WorkflowDefinition } from \"./definition.js\";\nimport { HOOK_EVENTS, HookRegistry } from \"./hooks.js\";\nimport type { Plugin } from \"./plugin.js\";\nimport { isPlugin } from \"./plugin.js\";\nimport type { ReadonlyContext } from \"./readonly-context.js\";\nimport type {\n\tCommandNames,\n\tDispatchResult,\n\tErrorCodes,\n\tErrorData,\n\tEventNames,\n\tPipelineError,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n} from \"./types.js\";\nimport { DomainErrorSignal, ValidationError } from \"./types.js\";\n\n// biome-ignore lint/suspicious/noExplicitAny: internal type erasure for heterogeneous middleware storage\ntype AnyMiddleware = (ctx: any, next: () => Promise<void>) => Promise<void>;\n// biome-ignore lint/suspicious/noExplicitAny: internal type erasure for heterogeneous handler storage\ntype AnyHandler = (ctx: any) => void | Promise<void>;\n\ntype HandlerEntry = {\n\tinlineMiddleware: AnyMiddleware[];\n\thandler: AnyMiddleware;\n};\n\nexport interface RouterOptions {\n\tonHookError?: (error: unknown) => void;\n}\n\nclass StateBuilder<TConfig extends WorkflowConfig, TDeps, TState extends StateNames<TConfig>> {\n\t/** @internal */ readonly middleware: AnyMiddleware[] = [];\n\t/** @internal */ readonly handlers = new Map<string, HandlerEntry>();\n\n\ton<C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\t...fns: [...AnyMiddleware[], (ctx: Context<TConfig, TDeps, TState, C>) => void | Promise<void>]\n\t): this {\n\t\tif (fns.length === 0) throw new Error(\"on() requires at least a handler\");\n\t\tconst handler = fns.pop() as AnyHandler;\n\t\tconst inlineMiddleware = fns as AnyMiddleware[];\n\t\tconst wrappedHandler: AnyMiddleware = async (ctx, _next) => {\n\t\t\tawait handler(ctx);\n\t\t};\n\t\tthis.handlers.set(command as string, { inlineMiddleware, handler: wrappedHandler });\n\t\treturn this;\n\t}\n\n\tuse(\n\t\tmiddleware: (ctx: Context<TConfig, TDeps, TState>, next: () => Promise<void>) => Promise<void>,\n\t): this {\n\t\tthis.middleware.push(middleware as AnyMiddleware);\n\t\treturn this;\n\t}\n}\n\n/**\n * Routes commands to handlers based on workflow state.\n *\n * Supports global middleware, state-scoped middleware, inline middleware,\n * wildcard handlers, and multi-state handlers.\n */\n// biome-ignore lint/complexity/noBannedTypes: {} is correct here — TDeps defaults to \"no deps\", inferred away when deps are provided\nexport class WorkflowRouter<TConfig extends WorkflowConfig, TDeps = {}> {\n\tprivate globalMiddleware: AnyMiddleware[] = [];\n\t// biome-ignore lint/suspicious/noExplicitAny: type erasure — builders store handlers for different state types\n\tprivate singleStateBuilders = new Map<string, StateBuilder<TConfig, TDeps, any>>();\n\t// biome-ignore lint/suspicious/noExplicitAny: type erasure — builders store handlers for different state types\n\tprivate multiStateBuilders = new Map<string, StateBuilder<TConfig, TDeps, any>>();\n\tprivate wildcardHandlers = new Map<string, HandlerEntry>();\n\tprivate hookRegistry = new HookRegistry();\n\tprivate readonly onHookError: (error: unknown) => void;\n\n\tconstructor(\n\t\tprivate readonly definition: WorkflowDefinition<TConfig>,\n\t\tprivate readonly deps: TDeps = {} as TDeps,\n\t\toptions: RouterOptions = {},\n\t) {\n\t\tthis.onHookError = options.onHookError ?? console.error;\n\t}\n\n\t/** Adds global middleware, merges another router, or applies a plugin. */\n\tuse(\n\t\targ:\n\t\t\t| ((ctx: Context<TConfig, TDeps>, next: () => Promise<void>) => Promise<void>)\n\t\t\t| WorkflowRouter<TConfig, TDeps>\n\t\t\t| Plugin<TConfig, TDeps>,\n\t): this {\n\t\tif (arg instanceof WorkflowRouter) {\n\t\t\tthis.merge(arg);\n\t\t} else if (isPlugin(arg)) {\n\t\t\t(arg as (router: WorkflowRouter<TConfig, TDeps>) => void)(this);\n\t\t} else {\n\t\t\tthis.globalMiddleware.push(arg as AnyMiddleware);\n\t\t}\n\t\treturn this;\n\t}\n\n\tprivate merge(child: WorkflowRouter<TConfig, TDeps>): void {\n\t\tif (child.definition !== this.definition) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot merge router for '${child.definition.name}' into router for '${this.definition.name}': definition mismatch`,\n\t\t\t);\n\t\t}\n\n\t\tthis.globalMiddleware.push(...child.globalMiddleware);\n\t\tthis.mergeStateBuilders(this.singleStateBuilders, child.singleStateBuilders);\n\t\tthis.mergeStateBuilders(this.multiStateBuilders, child.multiStateBuilders);\n\n\t\tfor (const [command, entry] of child.wildcardHandlers) {\n\t\t\tif (!this.wildcardHandlers.has(command)) {\n\t\t\t\tthis.wildcardHandlers.set(command, {\n\t\t\t\t\tinlineMiddleware: [...entry.inlineMiddleware],\n\t\t\t\t\thandler: entry.handler,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthis.hookRegistry.merge(child.hookRegistry);\n\t}\n\n\tprivate mergeStateBuilders(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: type erasure — builders store handlers for different state types\n\t\ttarget: Map<string, StateBuilder<TConfig, TDeps, any>>,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: type erasure — builders store handlers for different state types\n\t\tsource: Map<string, StateBuilder<TConfig, TDeps, any>>,\n\t): void {\n\t\tfor (const [stateName, childBuilder] of source) {\n\t\t\tlet parentBuilder = target.get(stateName);\n\t\t\tif (!parentBuilder) {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: type erasure — state name is dynamic at runtime\n\t\t\t\tparentBuilder = new StateBuilder<TConfig, TDeps, any>();\n\t\t\t\ttarget.set(stateName, parentBuilder);\n\t\t\t}\n\t\t\tfor (const [command, entry] of childBuilder.handlers) {\n\t\t\t\tif (!parentBuilder.handlers.has(command)) {\n\t\t\t\t\tparentBuilder.handlers.set(command, {\n\t\t\t\t\t\tinlineMiddleware: [...entry.inlineMiddleware],\n\t\t\t\t\t\thandler: entry.handler,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tparentBuilder.middleware.push(...childBuilder.middleware);\n\t\t}\n\t}\n\n\t/** Registers handlers for one or more states. */\n\tstate<P extends StateNames<TConfig> | readonly StateNames<TConfig>[]>(\n\t\tname: P,\n\t\tsetup: (\n\t\t\tstate: StateBuilder<\n\t\t\t\tTConfig,\n\t\t\t\tTDeps,\n\t\t\t\tP extends readonly (infer S)[] ? S & StateNames<TConfig> : P & StateNames<TConfig>\n\t\t\t>,\n\t\t) => void,\n\t): this {\n\t\tconst names = Array.isArray(name) ? name : [name];\n\t\tconst isMulti = Array.isArray(name);\n\t\tconst routerMap = isMulti ? this.multiStateBuilders : this.singleStateBuilders;\n\n\t\tfor (const n of names as string[]) {\n\t\t\tlet router = routerMap.get(n);\n\t\t\tif (!router) {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: type erasure — state name is dynamic at runtime\n\t\t\t\trouter = new StateBuilder<TConfig, TDeps, any>();\n\t\t\t\trouterMap.set(n, router);\n\t\t\t}\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: type erasure — setup callback expects a specific state type\n\t\t\tsetup(router as any);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** Registers a lifecycle hook callback. */\n\ton(\n\t\tevent: \"dispatch:start\",\n\t\tcallback: (ctx: ReadonlyContext<TConfig, TDeps>) => void | Promise<void>,\n\t): this;\n\ton(\n\t\tevent: \"dispatch:end\",\n\t\tcallback: (\n\t\t\tctx: ReadonlyContext<TConfig, TDeps>,\n\t\t\tresult: DispatchResult<TConfig>,\n\t\t) => void | Promise<void>,\n\t): this;\n\ton(\n\t\tevent: \"transition\",\n\t\tcallback: (\n\t\t\tfrom: StateNames<TConfig>,\n\t\t\tto: StateNames<TConfig>,\n\t\t\tworkflow: Workflow<TConfig>,\n\t\t) => void | Promise<void>,\n\t): this;\n\ton(\n\t\tevent: \"error\",\n\t\tcallback: (\n\t\t\terror: PipelineError<TConfig>,\n\t\t\tctx: ReadonlyContext<TConfig, TDeps>,\n\t\t) => void | Promise<void>,\n\t): this;\n\ton(\n\t\tevent: \"event\",\n\t\tcallback: (\n\t\t\tevent: { type: EventNames<TConfig>; data: unknown },\n\t\t\tworkflow: Workflow<TConfig>,\n\t\t) => void | Promise<void>,\n\t): this;\n\t/** Registers a wildcard handler that matches any state. */\n\ton<C extends CommandNames<TConfig>>(\n\t\tstate: \"*\",\n\t\tcommand: C,\n\t\t...fns: [\n\t\t\t...AnyMiddleware[],\n\t\t\t(ctx: Context<TConfig, TDeps, StateNames<TConfig>, C>) => void | Promise<void>,\n\t\t]\n\t): this;\n\t// biome-ignore lint/suspicious/noExplicitAny: implementation signature must be loose to handle all overloads\n\ton(...args: any[]): this {\n\t\tconst first = args[0] as string;\n\n\t\tif (HOOK_EVENTS.has(first)) {\n\t\t\t// biome-ignore lint/complexity/noBannedTypes: callbacks have varying signatures per hook event\n\t\t\tthis.hookRegistry.add(first, args[1] as Function);\n\t\t\treturn this;\n\t\t}\n\n\t\tif (first === \"*\") {\n\t\t\tconst command = args[1] as string;\n\t\t\tconst fns = args.slice(2) as unknown[];\n\t\t\tif (fns.length === 0) throw new Error(\"on() requires at least a handler\");\n\t\t\tconst handler = fns.pop() as AnyHandler;\n\t\t\tconst inlineMiddleware = fns as AnyMiddleware[];\n\t\t\tconst wrappedHandler: AnyMiddleware = async (ctx, _next) => {\n\t\t\t\tawait handler(ctx);\n\t\t\t};\n\t\t\tthis.wildcardHandlers.set(command, {\n\t\t\t\tinlineMiddleware,\n\t\t\t\thandler: wrappedHandler,\n\t\t\t});\n\t\t\treturn this;\n\t\t}\n\n\t\tthrow new Error(`Unknown event or state: ${first}`);\n\t}\n\n\t/** Dispatches a command to the appropriate handler and returns the result. */\n\tasync dispatch(\n\t\tworkflow: Workflow<TConfig>,\n\t\tcommand: { type: CommandNames<TConfig>; payload: unknown },\n\t): Promise<DispatchResult<TConfig>> {\n\t\tif (!this.definition.hasState(workflow.state)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"router\",\n\t\t\t\t\tcode: \"UNKNOWN_STATE\",\n\t\t\t\t\tmessage: `Unknown state: ${workflow.state}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst commandSchema = this.definition.getCommandSchema(command.type);\n\t\tconst payloadResult = commandSchema.safeParse(command.payload);\n\t\tif (!payloadResult.success) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"validation\",\n\t\t\t\t\tsource: \"command\",\n\t\t\t\t\tissues: payloadResult.error.issues,\n\t\t\t\t\tmessage: `Invalid command payload: ${payloadResult.error.issues.map((i) => i.message).join(\", \")}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconst validatedCommand = { type: command.type, payload: payloadResult.data };\n\n\t\tconst stateName = workflow.state;\n\t\tconst singleRouter = this.singleStateBuilders.get(stateName);\n\t\tconst multiRouter = this.multiStateBuilders.get(stateName);\n\t\tconst singleHandler = singleRouter?.handlers.get(command.type);\n\t\tconst multiHandler = multiRouter?.handlers.get(command.type);\n\t\tconst wildcardHandler = this.wildcardHandlers.get(command.type);\n\n\t\tlet routeEntry: HandlerEntry | undefined;\n\t\t// biome-ignore lint/suspicious/noExplicitAny: type erasure — matched router's state type is dynamic\n\t\tlet matchedRouter: StateBuilder<TConfig, TDeps, any> | undefined;\n\n\t\tif (singleHandler) {\n\t\t\trouteEntry = singleHandler;\n\t\t\tmatchedRouter = singleRouter;\n\t\t} else if (multiHandler) {\n\t\t\trouteEntry = multiHandler;\n\t\t\tmatchedRouter = multiRouter;\n\t\t} else if (wildcardHandler) {\n\t\t\trouteEntry = wildcardHandler;\n\t\t\tmatchedRouter = undefined;\n\t\t}\n\n\t\tif (!routeEntry) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"router\",\n\t\t\t\t\tcode: \"NO_HANDLER\",\n\t\t\t\t\tmessage: `No handler for command '${command.type}' in state '${stateName}'`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst stateMiddleware: AnyMiddleware[] = [];\n\t\tif (matchedRouter) {\n\t\t\tif (singleRouter) stateMiddleware.push(...singleRouter.middleware);\n\t\t\tif (multiRouter && multiRouter !== singleRouter)\n\t\t\t\tstateMiddleware.push(...multiRouter.middleware);\n\t\t}\n\n\t\tconst chain: AnyMiddleware[] = [\n\t\t\t...this.globalMiddleware,\n\t\t\t...stateMiddleware,\n\t\t\t...routeEntry.inlineMiddleware,\n\t\t\trouteEntry.handler,\n\t\t];\n\n\t\tconst ctx = createContext<TConfig, TDeps>(\n\t\t\tthis.definition,\n\t\t\tworkflow,\n\t\t\tvalidatedCommand,\n\t\t\tthis.deps,\n\t\t);\n\n\t\t// Hook: dispatch:start\n\t\tawait this.hookRegistry.emit(\"dispatch:start\", this.onHookError, ctx);\n\n\t\ttry {\n\t\t\tconst composed = compose(chain);\n\t\t\tawait composed(ctx);\n\t\t\tconst result: DispatchResult<TConfig> = {\n\t\t\t\tok: true as const,\n\t\t\t\tworkflow: ctx.getWorkflowSnapshot(),\n\t\t\t\tevents: [...ctx.events],\n\t\t\t};\n\n\t\t\t// Hook: transition (if state changed)\n\t\t\tif (result.ok && result.workflow.state !== workflow.state) {\n\t\t\t\tawait this.hookRegistry.emit(\n\t\t\t\t\t\"transition\",\n\t\t\t\t\tthis.onHookError,\n\t\t\t\t\tworkflow.state,\n\t\t\t\t\tresult.workflow.state,\n\t\t\t\t\tresult.workflow,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Hook: event (for each emitted event)\n\t\t\tif (result.ok) {\n\t\t\t\tfor (const event of result.events) {\n\t\t\t\t\tawait this.hookRegistry.emit(\"event\", this.onHookError, event, result.workflow);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Hook: dispatch:end\n\t\t\tawait this.hookRegistry.emit(\"dispatch:end\", this.onHookError, ctx, result);\n\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tlet result: DispatchResult<TConfig>;\n\t\t\tif (err instanceof DomainErrorSignal) {\n\t\t\t\tresult = {\n\t\t\t\t\tok: false as const,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcategory: \"domain\" as const,\n\t\t\t\t\t\tcode: err.code as ErrorCodes<TConfig>,\n\t\t\t\t\t\tdata: err.data as ErrorData<TConfig, ErrorCodes<TConfig>>,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} else if (err instanceof ValidationError) {\n\t\t\t\tresult = {\n\t\t\t\t\tok: false as const,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcategory: \"validation\" as const,\n\t\t\t\t\t\tsource: err.source,\n\t\t\t\t\t\tissues: err.issues,\n\t\t\t\t\t\tmessage: err.message,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\t// Hook: error\n\t\t\tawait this.hookRegistry.emit(\"error\", this.onHookError, result.error, ctx);\n\n\t\t\t// Hook: dispatch:end\n\t\t\tawait this.hookRegistry.emit(\"dispatch:end\", this.onHookError, ctx, result);\n\n\t\t\treturn result;\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
|