@rytejs/core 0.3.0 → 0.5.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/dist/index.cjs +154 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +274 -17
- package/dist/index.d.ts +274 -17
- package/dist/index.js +150 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -116,6 +116,120 @@ function createKey(name) {
|
|
|
116
116
|
return { id: Symbol(name) };
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
// src/migration.ts
|
|
120
|
+
var MigrationError = class extends Error {
|
|
121
|
+
/**
|
|
122
|
+
* @param fromVersion - The schema version the migration started from
|
|
123
|
+
* @param toVersion - The schema version the migration was attempting to reach
|
|
124
|
+
* @param cause - The underlying error that caused the failure
|
|
125
|
+
*/
|
|
126
|
+
constructor(fromVersion, toVersion, cause) {
|
|
127
|
+
super(
|
|
128
|
+
`Migration ${fromVersion} \u2192 ${toVersion} failed: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
129
|
+
);
|
|
130
|
+
this.fromVersion = fromVersion;
|
|
131
|
+
this.toVersion = toVersion;
|
|
132
|
+
this.cause = cause;
|
|
133
|
+
this.name = "MigrationError";
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
function defineMigrations(definition, migrationMap) {
|
|
137
|
+
const targetVersion = definition.config.modelVersion ?? 1;
|
|
138
|
+
const entries = Object.entries(migrationMap).map(([k, v]) => {
|
|
139
|
+
const normalized = typeof v === "function" ? { fn: v } : { fn: v.up, description: v.description };
|
|
140
|
+
return [Number(k), normalized];
|
|
141
|
+
});
|
|
142
|
+
for (const [version] of entries) {
|
|
143
|
+
if (version <= 1) {
|
|
144
|
+
throw new Error(`Migration keys must be > 1 (version 1 is the baseline). Got: ${version}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
entries.sort((a, b) => a[0] - b[0]);
|
|
148
|
+
if (entries.length > 0) {
|
|
149
|
+
const highest = entries[entries.length - 1];
|
|
150
|
+
if (!highest || highest[0] !== targetVersion) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`Highest migration key (${highest?.[0]}) does not match definition modelVersion (${targetVersion})`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
for (let i = 0; i < entries.length; i++) {
|
|
156
|
+
const entry = entries[i];
|
|
157
|
+
const expected = targetVersion - entries.length + 1 + i;
|
|
158
|
+
if (!entry || entry[0] !== expected) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`Migration version gap: expected ${expected} but found ${entry?.[0]}. Migrations must be sequential from 2 to ${targetVersion}.`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
definition,
|
|
167
|
+
targetVersion,
|
|
168
|
+
migrations: new Map(entries)
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function migrate(pipeline, snapshot, options) {
|
|
172
|
+
if (!Number.isInteger(snapshot.modelVersion) || snapshot.modelVersion < 1) {
|
|
173
|
+
const error = new MigrationError(
|
|
174
|
+
snapshot.modelVersion,
|
|
175
|
+
pipeline.targetVersion,
|
|
176
|
+
new Error(
|
|
177
|
+
`Invalid snapshot modelVersion: ${snapshot.modelVersion}. Must be a positive integer.`
|
|
178
|
+
)
|
|
179
|
+
);
|
|
180
|
+
options?.onError?.(error);
|
|
181
|
+
return { ok: false, error };
|
|
182
|
+
}
|
|
183
|
+
if (snapshot.definitionName !== pipeline.definition.name) {
|
|
184
|
+
const error = new MigrationError(
|
|
185
|
+
snapshot.modelVersion,
|
|
186
|
+
pipeline.targetVersion,
|
|
187
|
+
new Error(
|
|
188
|
+
`Snapshot definition '${snapshot.definitionName}' does not match pipeline definition '${pipeline.definition.name}'`
|
|
189
|
+
)
|
|
190
|
+
);
|
|
191
|
+
options?.onError?.(error);
|
|
192
|
+
return { ok: false, error };
|
|
193
|
+
}
|
|
194
|
+
if (snapshot.modelVersion > pipeline.targetVersion) {
|
|
195
|
+
const error = new MigrationError(
|
|
196
|
+
snapshot.modelVersion,
|
|
197
|
+
pipeline.targetVersion,
|
|
198
|
+
new Error(
|
|
199
|
+
`Snapshot modelVersion (${snapshot.modelVersion}) is higher than target (${pipeline.targetVersion}). Cannot downgrade.`
|
|
200
|
+
)
|
|
201
|
+
);
|
|
202
|
+
options?.onError?.(error);
|
|
203
|
+
return { ok: false, error };
|
|
204
|
+
}
|
|
205
|
+
if (snapshot.modelVersion === pipeline.targetVersion) {
|
|
206
|
+
return { ok: true, snapshot };
|
|
207
|
+
}
|
|
208
|
+
let current = { ...snapshot };
|
|
209
|
+
for (let version = current.modelVersion + 1; version <= pipeline.targetVersion; version++) {
|
|
210
|
+
const migration = pipeline.migrations.get(version);
|
|
211
|
+
if (!migration) {
|
|
212
|
+
const error = new MigrationError(
|
|
213
|
+
version - 1,
|
|
214
|
+
version,
|
|
215
|
+
new Error(`No migration function found for version ${version}`)
|
|
216
|
+
);
|
|
217
|
+
options?.onError?.(error);
|
|
218
|
+
return { ok: false, error };
|
|
219
|
+
}
|
|
220
|
+
const fromVersion = version - 1;
|
|
221
|
+
try {
|
|
222
|
+
current = { ...migration.fn(current), modelVersion: version };
|
|
223
|
+
} catch (cause) {
|
|
224
|
+
const error = new MigrationError(fromVersion, version, cause);
|
|
225
|
+
options?.onError?.(error);
|
|
226
|
+
return { ok: false, error };
|
|
227
|
+
}
|
|
228
|
+
options?.onStep?.(fromVersion, version, current, migration.description);
|
|
229
|
+
}
|
|
230
|
+
return { ok: true, snapshot: current };
|
|
231
|
+
}
|
|
232
|
+
|
|
119
233
|
// src/plugin.ts
|
|
120
234
|
var PLUGIN_SYMBOL = /* @__PURE__ */ Symbol.for("ryte:plugin");
|
|
121
235
|
function definePlugin(fn) {
|
|
@@ -271,7 +385,7 @@ var StateBuilder = class {
|
|
|
271
385
|
middleware = [];
|
|
272
386
|
/** @internal */
|
|
273
387
|
handlers = /* @__PURE__ */ new Map();
|
|
274
|
-
on(command, ...fns) {
|
|
388
|
+
on = (command, ...fns) => {
|
|
275
389
|
if (fns.length === 0) throw new Error("on() requires at least a handler");
|
|
276
390
|
const handler = fns.pop();
|
|
277
391
|
const inlineMiddleware = fns;
|
|
@@ -280,13 +394,18 @@ var StateBuilder = class {
|
|
|
280
394
|
};
|
|
281
395
|
this.handlers.set(command, { inlineMiddleware, handler: wrappedHandler });
|
|
282
396
|
return this;
|
|
283
|
-
}
|
|
284
|
-
use(middleware) {
|
|
397
|
+
};
|
|
398
|
+
use = (middleware) => {
|
|
285
399
|
this.middleware.push(middleware);
|
|
286
400
|
return this;
|
|
287
|
-
}
|
|
401
|
+
};
|
|
288
402
|
};
|
|
289
403
|
var WorkflowRouter = class _WorkflowRouter {
|
|
404
|
+
/**
|
|
405
|
+
* @param definition - The workflow definition describing states, commands, events, and errors
|
|
406
|
+
* @param deps - Dependencies injected into every handler context
|
|
407
|
+
* @param options - Router configuration options
|
|
408
|
+
*/
|
|
290
409
|
constructor(definition, deps = {}, options = {}) {
|
|
291
410
|
this.definition = definition;
|
|
292
411
|
this.deps = deps;
|
|
@@ -300,7 +419,10 @@ var WorkflowRouter = class _WorkflowRouter {
|
|
|
300
419
|
wildcardHandlers = /* @__PURE__ */ new Map();
|
|
301
420
|
hookRegistry = new HookRegistry();
|
|
302
421
|
onHookError;
|
|
303
|
-
/**
|
|
422
|
+
/**
|
|
423
|
+
* Adds global middleware, merges another router, or applies a plugin.
|
|
424
|
+
* @param arg - A middleware function, another {@link WorkflowRouter} to merge, or a {@link Plugin}
|
|
425
|
+
*/
|
|
304
426
|
use(arg) {
|
|
305
427
|
if (arg instanceof _WorkflowRouter) {
|
|
306
428
|
this.merge(arg);
|
|
@@ -348,7 +470,11 @@ var WorkflowRouter = class _WorkflowRouter {
|
|
|
348
470
|
parentBuilder.middleware.push(...childBuilder.middleware);
|
|
349
471
|
}
|
|
350
472
|
}
|
|
351
|
-
/**
|
|
473
|
+
/**
|
|
474
|
+
* Registers handlers for one or more states.
|
|
475
|
+
* @param name - A state name or array of state names to register handlers for
|
|
476
|
+
* @param setup - Callback that receives a state builder to register commands and middleware
|
|
477
|
+
*/
|
|
352
478
|
state(name, setup) {
|
|
353
479
|
const names = Array.isArray(name) ? name : [name];
|
|
354
480
|
const isMulti = Array.isArray(name);
|
|
@@ -387,7 +513,12 @@ var WorkflowRouter = class _WorkflowRouter {
|
|
|
387
513
|
}
|
|
388
514
|
throw new Error(`Unknown event or state: ${first}`);
|
|
389
515
|
}
|
|
390
|
-
/**
|
|
516
|
+
/**
|
|
517
|
+
* Dispatches a command to the appropriate handler and returns the result.
|
|
518
|
+
* @param workflow - The current workflow instance to dispatch against
|
|
519
|
+
* @param command - The command with its type and payload
|
|
520
|
+
* @returns A {@link DispatchResult} indicating success or failure with the updated workflow and events
|
|
521
|
+
*/
|
|
391
522
|
async dispatch(workflow, command) {
|
|
392
523
|
if (!this.definition.hasState(workflow.state)) {
|
|
393
524
|
return {
|
|
@@ -506,7 +637,14 @@ var WorkflowRouter = class _WorkflowRouter {
|
|
|
506
637
|
}
|
|
507
638
|
};
|
|
508
639
|
} else {
|
|
509
|
-
|
|
640
|
+
result = {
|
|
641
|
+
ok: false,
|
|
642
|
+
error: {
|
|
643
|
+
category: "unexpected",
|
|
644
|
+
error: err,
|
|
645
|
+
message: err instanceof Error ? err.message : String(err)
|
|
646
|
+
}
|
|
647
|
+
};
|
|
510
648
|
}
|
|
511
649
|
await this.hookRegistry.emit("error", this.onHookError, result.error, ctx);
|
|
512
650
|
await this.hookRegistry.emit("dispatch:end", this.onHookError, ctx, result);
|
|
@@ -516,11 +654,14 @@ var WorkflowRouter = class _WorkflowRouter {
|
|
|
516
654
|
};
|
|
517
655
|
export {
|
|
518
656
|
DomainErrorSignal,
|
|
657
|
+
MigrationError,
|
|
519
658
|
ValidationError,
|
|
520
659
|
WorkflowRouter,
|
|
521
660
|
createKey,
|
|
661
|
+
defineMigrations,
|
|
522
662
|
definePlugin,
|
|
523
663
|
defineWorkflow,
|
|
524
|
-
isPlugin
|
|
664
|
+
isPlugin,
|
|
665
|
+
migrate
|
|
525
666
|
};
|
|
526
667
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../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":["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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/definition.ts","../src/key.ts","../src/migration.ts","../src/plugin.ts","../src/compose.ts","../src/context.ts","../src/hooks.ts","../src/router.ts"],"sourcesContent":["import type { ZodType, z } from \"zod\";\n\n/**\n * Shape of the configuration object passed to {@link defineWorkflow}.\n */\nexport interface WorkflowConfig {\n\t/** Optional version number for schema migrations. Defaults to 1. */\n\tmodelVersion?: number;\n\t/** Record of state names to Zod schemas defining their data shape. */\n\tstates: Record<string, ZodType>;\n\t/** Record of command names to Zod schemas defining their payload shape. */\n\tcommands: Record<string, ZodType>;\n\t/** Record of event names to Zod schemas defining their data shape. */\n\tevents: Record<string, ZodType>;\n\t/** Record of error codes to Zod schemas defining their data shape. */\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\n/** Infers the data type for a given state. */\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\n/** Infers the payload type for a given command. */\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\n/** Infers the data type for a given event. */\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\n/** Infers the data type for a given error code. */\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\t/** Unique workflow instance identifier. */\n\treadonly id: string;\n\t/** Name of the workflow definition this instance belongs to. */\n\treadonly definitionName: string;\n\t/** Current state name. */\n\treadonly state: S;\n\t/** State data, typed according to the state's Zod schema. */\n\treadonly data: StateData<TConfig, S>;\n\t/** Timestamp of workflow creation. */\n\treadonly createdAt: Date;\n\t/** Timestamp of last state change. */\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\n/** Discriminated union of all pipeline error types on `category`. */\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\t| {\n\t\t\tcategory: \"unexpected\";\n\t\t\terror: unknown;\n\t\t\tmessage: string;\n\t };\n\n/** Return type of {@link WorkflowRouter.dispatch}. Discriminated union on `ok`. */\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/**\n * Thrown internally when Zod validation fails during dispatch.\n * Caught by the router and returned as a validation error in {@link DispatchResult}.\n *\n * @param source - Which validation stage failed\n * @param issues - Array of Zod validation issues\n */\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/**\n * Thrown internally when a handler calls `ctx.error()`.\n * Caught by the router and returned as a domain error in {@link DispatchResult}.\n *\n * @param code - The error code string\n * @param data - The error data payload\n */\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/**\n * The result of {@link defineWorkflow} — holds schemas and creates workflow instances.\n */\nexport interface WorkflowDefinition<TConfig extends WorkflowConfig = WorkflowConfig> {\n\t/** The raw Zod schema configuration. */\n\treadonly config: TConfig;\n\t/** The workflow definition name. */\n\treadonly name: string;\n\t/**\n\t * Creates a new workflow instance in a given initial state.\n\t *\n\t * @param id - Unique identifier for this workflow instance\n\t * @param config - Object containing `initialState` and the corresponding `data`\n\t * @returns A {@link WorkflowOf} narrowed to the initial state\n\t */\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\t/**\n\t * Returns the Zod schema for a given state name.\n\t *\n\t * @param stateName - The state name to look up\n\t * @throws If the state name is not found in the config\n\t */\n\tgetStateSchema(stateName: string): ZodType;\n\t/**\n\t * Returns the Zod schema for a given command name.\n\t *\n\t * @param commandName - The command name to look up\n\t * @throws If the command name is not found in the config\n\t */\n\tgetCommandSchema(commandName: string): ZodType;\n\t/**\n\t * Returns the Zod schema for a given event name.\n\t *\n\t * @param eventName - The event name to look up\n\t * @throws If the event name is not found in the config\n\t */\n\tgetEventSchema(eventName: string): ZodType;\n\t/**\n\t * Returns the Zod schema for a given error code.\n\t *\n\t * @param errorCode - The error code to look up\n\t * @throws If the error code is not found in the config\n\t */\n\tgetErrorSchema(errorCode: string): ZodType;\n\t/**\n\t * Returns `true` if the given state name exists in the config.\n\t *\n\t * @param stateName - The state name to check\n\t */\n\thasState(stateName: string): boolean;\n\t/**\n\t * Serializes a workflow instance into a plain, JSON-safe snapshot.\n\t *\n\t * @param workflow - The workflow instance to serialize\n\t * @returns A {@link WorkflowSnapshot} representing the current state\n\t */\n\tsnapshot(workflow: Workflow<TConfig>): WorkflowSnapshot<TConfig>;\n\t/**\n\t * Restores a workflow instance from a plain snapshot, validating the state data.\n\t *\n\t * @param snapshot - The snapshot to restore from\n\t * @returns A result object: `{ ok: true, workflow }` or `{ ok: false, error }`\n\t */\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 *\n * @param name - Unique name for this workflow type\n * @param config - Object with `states`, `commands`, `events`, `errors` — each a record of Zod schemas\n * @returns A {@link WorkflowDefinition} with methods for creating instances and accessing schemas\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 via {@link Context.set} and {@link Context.get}. */\nexport interface ContextKey<T> {\n\t/** @internal Phantom type brand — not used at runtime. */\n\treadonly _phantom: T;\n\t/** Internal symbol providing uniqueness. */\n\treadonly id: symbol;\n}\n\n/**\n * Creates a unique typed key for storing and retrieving values in context.\n *\n * @param name - Debug label (uniqueness comes from an internal `Symbol`)\n * @returns A {@link ContextKey} for use with `ctx.set()`, `ctx.get()`, and `ctx.getOrNull()`\n */\nexport function createKey<T>(name: string): ContextKey<T> {\n\treturn { id: Symbol(name) } as ContextKey<T>;\n}\n","import type { WorkflowDefinition } from \"./definition.js\";\nimport type { WorkflowSnapshot } from \"./snapshot.js\";\nimport type { WorkflowConfig } from \"./types.js\";\n\n/** A function that transforms a snapshot's data from one version to the next. */\nexport type MigrationFn = (snapshot: WorkflowSnapshot) => WorkflowSnapshot;\n\n/** A migration entry — either a bare {@link MigrationFn} or an object with a description. */\nexport type MigrationEntry = MigrationFn | { description: string; up: MigrationFn };\n\n/** Internal normalized migration step with optional description. */\ninterface NormalizedMigration {\n\tfn: MigrationFn;\n\tdescription?: string;\n}\n\n/** A validated migration pipeline ready to transform snapshots. */\nexport interface MigrationPipeline<TConfig extends WorkflowConfig = WorkflowConfig> {\n\t/** The workflow definition this pipeline belongs to. */\n\treadonly definition: WorkflowDefinition<TConfig>;\n\t/** The target schema version to migrate snapshots to. */\n\treadonly targetVersion: number;\n\t/** Map of version number to normalized migration step. */\n\treadonly migrations: ReadonlyMap<number, NormalizedMigration>;\n}\n\n/** Result of {@link migrate}. */\nexport type MigrateResult =\n\t| { ok: true; snapshot: WorkflowSnapshot }\n\t| { ok: false; error: MigrationError };\n\n/** Options for {@link migrate}. */\nexport interface MigrateOptions {\n\t/**\n\t * Called after each successful migration step.\n\t * @param fromVersion - The version before this step\n\t * @param toVersion - The version after this step\n\t * @param snapshot - The snapshot after this step\n\t * @param description - Optional description from the migration entry\n\t */\n\tonStep?: (\n\t\tfromVersion: number,\n\t\ttoVersion: number,\n\t\tsnapshot: WorkflowSnapshot,\n\t\tdescription?: string,\n\t) => void;\n\t/**\n\t * Called when a migration step fails.\n\t * @param error - The {@link MigrationError} describing the failure\n\t */\n\tonError?: (error: MigrationError) => void;\n}\n\n/** Error thrown when a migration step fails. */\nexport class MigrationError extends Error {\n\t/**\n\t * @param fromVersion - The schema version the migration started from\n\t * @param toVersion - The schema version the migration was attempting to reach\n\t * @param cause - The underlying error that caused the failure\n\t */\n\tconstructor(\n\t\tpublic readonly fromVersion: number,\n\t\tpublic readonly toVersion: number,\n\t\tpublic readonly cause: unknown,\n\t) {\n\t\tsuper(\n\t\t\t`Migration ${fromVersion} → ${toVersion} failed: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t);\n\t\tthis.name = \"MigrationError\";\n\t}\n}\n\n/**\n * Creates a validated migration pipeline from a definition and version-keyed transform functions.\n * Each key is the target version — the function transforms from (key - 1) to key.\n *\n * @param definition - The workflow definition the migrations belong to\n * @param migrationMap - A record mapping target version numbers to {@link MigrationEntry} values\n * @returns A validated {@link MigrationPipeline} ready for use with {@link migrate}\n * @throws If migration keys are not sequential from 2 to the definition's `modelVersion`, or if the highest key does not match `modelVersion`\n */\nexport function defineMigrations<TConfig extends WorkflowConfig>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tmigrationMap: Record<number, MigrationEntry>,\n): MigrationPipeline<TConfig> {\n\tconst targetVersion = definition.config.modelVersion ?? 1;\n\tconst entries = Object.entries(migrationMap).map(([k, v]) => {\n\t\tconst normalized: NormalizedMigration =\n\t\t\ttypeof v === \"function\" ? { fn: v } : { fn: v.up, description: v.description };\n\t\treturn [Number(k), normalized] as const;\n\t});\n\n\tfor (const [version] of entries) {\n\t\tif (version <= 1) {\n\t\t\tthrow new Error(`Migration keys must be > 1 (version 1 is the baseline). Got: ${version}`);\n\t\t}\n\t}\n\n\tentries.sort((a, b) => a[0] - b[0]);\n\n\tif (entries.length > 0) {\n\t\tconst highest = entries[entries.length - 1];\n\t\tif (!highest || highest[0] !== targetVersion) {\n\t\t\tthrow new Error(\n\t\t\t\t`Highest migration key (${highest?.[0]}) does not match definition modelVersion (${targetVersion})`,\n\t\t\t);\n\t\t}\n\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\tconst entry = entries[i];\n\t\t\tconst expected = targetVersion - entries.length + 1 + i;\n\t\t\tif (!entry || entry[0] !== expected) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Migration version gap: expected ${expected} but found ${entry?.[0]}. Migrations must be sequential from 2 to ${targetVersion}.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tdefinition,\n\t\ttargetVersion,\n\t\tmigrations: new Map(entries),\n\t};\n}\n\n/**\n * Runs the migration chain from the snapshot's modelVersion to the pipeline's targetVersion.\n * Returns a Result. Auto-stamps modelVersion after each step.\n *\n * @param pipeline - The {@link MigrationPipeline} created by {@link defineMigrations}\n * @param snapshot - The workflow snapshot to migrate\n * @param options - Optional callbacks for step progress and error reporting\n * @returns A {@link MigrateResult} with the migrated snapshot on success, or a {@link MigrationError} on failure\n */\nexport function migrate<TConfig extends WorkflowConfig>(\n\tpipeline: MigrationPipeline<TConfig>,\n\tsnapshot: WorkflowSnapshot,\n\toptions?: MigrateOptions,\n): MigrateResult {\n\tif (!Number.isInteger(snapshot.modelVersion) || snapshot.modelVersion < 1) {\n\t\tconst error = new MigrationError(\n\t\t\tsnapshot.modelVersion,\n\t\t\tpipeline.targetVersion,\n\t\t\tnew Error(\n\t\t\t\t`Invalid snapshot modelVersion: ${snapshot.modelVersion}. Must be a positive integer.`,\n\t\t\t),\n\t\t);\n\t\toptions?.onError?.(error);\n\t\treturn { ok: false, error };\n\t}\n\n\tif (snapshot.definitionName !== pipeline.definition.name) {\n\t\tconst error = new MigrationError(\n\t\t\tsnapshot.modelVersion,\n\t\t\tpipeline.targetVersion,\n\t\t\tnew Error(\n\t\t\t\t`Snapshot definition '${snapshot.definitionName}' does not match pipeline definition '${pipeline.definition.name}'`,\n\t\t\t),\n\t\t);\n\t\toptions?.onError?.(error);\n\t\treturn { ok: false, error };\n\t}\n\n\tif (snapshot.modelVersion > pipeline.targetVersion) {\n\t\tconst error = new MigrationError(\n\t\t\tsnapshot.modelVersion,\n\t\t\tpipeline.targetVersion,\n\t\t\tnew Error(\n\t\t\t\t`Snapshot modelVersion (${snapshot.modelVersion}) is higher than target (${pipeline.targetVersion}). Cannot downgrade.`,\n\t\t\t),\n\t\t);\n\t\toptions?.onError?.(error);\n\t\treturn { ok: false, error };\n\t}\n\n\tif (snapshot.modelVersion === pipeline.targetVersion) {\n\t\treturn { ok: true, snapshot };\n\t}\n\n\tlet current = { ...snapshot };\n\tfor (let version = current.modelVersion + 1; version <= pipeline.targetVersion; version++) {\n\t\tconst migration = pipeline.migrations.get(version);\n\t\tif (!migration) {\n\t\t\tconst error = new MigrationError(\n\t\t\t\tversion - 1,\n\t\t\t\tversion,\n\t\t\t\tnew Error(`No migration function found for version ${version}`),\n\t\t\t);\n\t\t\toptions?.onError?.(error);\n\t\t\treturn { ok: false, error };\n\t\t}\n\n\t\tconst fromVersion = version - 1;\n\t\ttry {\n\t\t\tcurrent = { ...migration.fn(current), modelVersion: version };\n\t\t} catch (cause) {\n\t\t\tconst error = new MigrationError(fromVersion, version, cause);\n\t\t\toptions?.onError?.(error);\n\t\t\treturn { ok: false, error };\n\t\t}\n\n\t\toptions?.onStep?.(fromVersion, version, current, migration.description);\n\t}\n\n\treturn { ok: true, snapshot: current };\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 {@link WorkflowRouter.use}. */\nexport type Plugin<TConfig extends WorkflowConfig, TDeps> = ((\n\trouter: WorkflowRouter<TConfig, TDeps>,\n) => void) & { readonly [PLUGIN_SYMBOL]: true };\n\n/**\n * Brands a function as a Ryte plugin for use with {@link WorkflowRouter.use}.\n *\n * @param fn - A function that configures a router (adds handlers, middleware, hooks)\n * @returns A branded {@link Plugin} function\n */\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/**\n * Checks whether a value is a branded Ryte plugin.\n *\n * @param value - The value to check\n * @returns `true` if the value is a {@link Plugin}\n */\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\t/** The command being dispatched, with type and validated payload. */\n\treadonly command: {\n\t\treadonly type: TCommand;\n\t\treadonly payload: CommandPayload<TConfig, TCommand>;\n\t};\n\t/** The original workflow before any mutations. */\n\treadonly workflow: WorkflowOf<TConfig, TState>;\n\t/** Dependencies injected via the router constructor. */\n\treadonly deps: TDeps;\n\n\t/** Current state data (reflects mutations from {@link update}). */\n\treadonly data: StateData<TConfig, TState>;\n\t/**\n\t * Merges partial data into the current state. Validates against the state's Zod schema.\n\t * @param data - Partial state data to merge\n\t */\n\tupdate(data: Partial<StateData<TConfig, TState>>): void;\n\n\t/**\n\t * Transitions the workflow to a new state with new data. Validates against the target state's Zod schema.\n\t * @param target - Target state name\n\t * @param data - Data for the target state\n\t */\n\ttransition<Target extends StateNames<TConfig>>(\n\t\ttarget: Target,\n\t\tdata: StateData<TConfig, Target>,\n\t): void;\n\n\t/**\n\t * Emits a domain event. Validates event data against the event's Zod schema.\n\t * @param event - Event with type and data\n\t */\n\temit<E extends EventNames<TConfig>>(event: { type: E; data: EventData<TConfig, E> }): void;\n\t/** Accumulated events emitted during this dispatch. */\n\treadonly events: ReadonlyArray<{ type: EventNames<TConfig>; data: unknown }>;\n\n\t/**\n\t * Signals a domain error. Validates error data and throws internally (caught by the router).\n\t * @param err - Error with code and data\n\t */\n\terror<C extends ErrorCodes<TConfig>>(err: { code: C; data: ErrorData<TConfig, C> }): never;\n\n\t/**\n\t * Stores a value in context-scoped middleware state.\n\t * @param key - A {@link ContextKey} created via {@link createKey}\n\t * @param value - The value to store\n\t */\n\tset<T>(key: ContextKey<T>, value: T): void;\n\t/**\n\t * Retrieves a value from context-scoped middleware state. Throws if not set.\n\t * @param key - A {@link ContextKey} created via {@link createKey}\n\t */\n\tget<T>(key: ContextKey<T>): T;\n\t/**\n\t * Retrieves a value from context-scoped middleware state, or `undefined` if not set.\n\t * @param key - A {@link ContextKey} created via {@link createKey}\n\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\n/** Options for the {@link WorkflowRouter} constructor. */\nexport interface RouterOptions {\n\t/** Callback invoked when a lifecycle hook throws. Defaults to `console.error`. */\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\t/**\n\t * @param definition - The workflow definition describing states, commands, events, and errors\n\t * @param deps - Dependencies injected into every handler context\n\t * @param options - Router configuration options\n\t */\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/**\n\t * Adds global middleware, merges another router, or applies a plugin.\n\t * @param arg - A middleware function, another {@link WorkflowRouter} to merge, or a {@link Plugin}\n\t */\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/**\n\t * Registers handlers for one or more states.\n\t * @param name - A state name or array of state names to register handlers for\n\t * @param setup - Callback that receives a state builder to register commands and middleware\n\t */\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/**\n\t * Registers a lifecycle hook callback.\n\t * @param event - The lifecycle event name\n\t * @param callback - The callback to invoke when the event fires\n\t */\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/**\n\t * Registers a wildcard handler that matches any state.\n\t * @param state - Must be `\"*\"` to match all states\n\t * @param command - The command name to handle\n\t * @param fns - Optional inline middleware followed by the terminal handler\n\t */\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/**\n\t * Dispatches a command to the appropriate handler and returns the result.\n\t * @param workflow - The current workflow instance to dispatch against\n\t * @param command - The command with its type and payload\n\t * @returns A {@link DispatchResult} indicating success or failure with the updated workflow and events\n\t */\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\tresult = {\n\t\t\t\t\tok: false as const,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcategory: \"unexpected\" as const,\n\t\t\t\t\t\terror: err,\n\t\t\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t},\n\t\t\t\t};\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":[]}
|