@rytejs/core 0.6.0 → 0.7.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.d.ts CHANGED
@@ -1,335 +1,14 @@
1
- import { ZodType, z } from 'zod';
2
-
3
- /**
4
- * Shape of the configuration object passed to {@link defineWorkflow}.
5
- * Exported for internal package use only — not re-exported from index.ts.
6
- */
7
- interface WorkflowConfigInput {
8
- /** Optional version number for schema migrations. Defaults to 1. */
9
- modelVersion?: number;
10
- /** Record of state names to Zod schemas defining their data shape. */
11
- states: Record<string, ZodType>;
12
- /** Record of command names to Zod schemas defining their payload shape. */
13
- commands: Record<string, ZodType>;
14
- /** Record of event names to Zod schemas defining their data shape. */
15
- events: Record<string, ZodType>;
16
- /** Record of error codes to Zod schemas defining their data shape. */
17
- errors: Record<string, ZodType>;
18
- }
19
- /**
20
- * Workflow configuration with pre-resolved types for IDE completion.
21
- *
22
- * Extends {@link WorkflowConfigInput} with a `_resolved` phantom type that
23
- * caches `z.infer` results. This exists because Zod v4's `z.infer` uses
24
- * conditional types that TypeScript defers in deep generic chains, breaking
25
- * IDE autocomplete. The `_resolved` property is never set at runtime — it is
26
- * populated at the type level by {@link defineWorkflow}'s return type.
27
- */
28
- interface WorkflowConfig extends WorkflowConfigInput {
29
- _resolved: {
30
- states: Record<string, unknown>;
31
- commands: Record<string, unknown>;
32
- events: Record<string, unknown>;
33
- errors: Record<string, unknown>;
34
- };
35
- }
36
- type StateNames<T extends WorkflowConfig> = keyof T["states"] & string;
37
- type CommandNames<T extends WorkflowConfig> = keyof T["commands"] & string;
38
- type EventNames<T extends WorkflowConfig> = keyof T["events"] & string;
39
- type ErrorCodes<T extends WorkflowConfig> = keyof T["errors"] & string;
40
- /** Forces TypeScript to flatten a type for better IDE autocomplete. */
41
- type Prettify<T> = {
42
- [K in keyof T]: T[K];
43
- } & {};
44
- /** Resolves the data type for a given state from pre-computed types. */
45
- type StateData<T extends WorkflowConfig, S extends StateNames<T>> = Prettify<T["_resolved"]["states"][S]>;
46
- /** Resolves the payload type for a given command from pre-computed types. */
47
- type CommandPayload<T extends WorkflowConfig, C extends CommandNames<T>> = Prettify<T["_resolved"]["commands"][C]>;
48
- /** Resolves the data type for a given event from pre-computed types. */
49
- type EventData<T extends WorkflowConfig, E extends EventNames<T>> = Prettify<T["_resolved"]["events"][E]>;
50
- /** Resolves the data type for a given error code from pre-computed types. */
51
- type ErrorData<T extends WorkflowConfig, C extends ErrorCodes<T>> = Prettify<T["_resolved"]["errors"][C]>;
52
- /** Workflow narrowed to a specific known state. */
53
- interface WorkflowOf<TConfig extends WorkflowConfig, S extends StateNames<TConfig>> {
54
- /** Unique workflow instance identifier. */
55
- readonly id: string;
56
- /** Name of the workflow definition this instance belongs to. */
57
- readonly definitionName: string;
58
- /** Current state name. */
59
- readonly state: S;
60
- /** State data, typed according to the state's Zod schema. */
61
- readonly data: StateData<TConfig, S>;
62
- /** Timestamp of workflow creation. */
63
- readonly createdAt: Date;
64
- /** Timestamp of last state change. */
65
- readonly updatedAt: Date;
66
- }
67
- /** Discriminated union of all possible workflow states — checking .state narrows .data. */
68
- type Workflow<TConfig extends WorkflowConfig = WorkflowConfig> = {
69
- [S in StateNames<TConfig>]: WorkflowOf<TConfig, S>;
70
- }[StateNames<TConfig>];
71
- /** Discriminated union of all pipeline error types on `category`. */
72
- type PipelineError<TConfig extends WorkflowConfig = WorkflowConfig> = {
73
- category: "validation";
74
- source: "command" | "state" | "event" | "transition" | "restore";
75
- issues: z.core.$ZodIssue[];
76
- message: string;
77
- } | {
78
- category: "domain";
79
- code: ErrorCodes<TConfig>;
80
- data: ErrorData<TConfig, ErrorCodes<TConfig>>;
81
- } | {
82
- category: "router";
83
- code: "NO_HANDLER" | "UNKNOWN_STATE";
84
- message: string;
85
- } | {
86
- category: "unexpected";
87
- error: unknown;
88
- message: string;
89
- } | {
90
- category: "dependency";
91
- name: string;
92
- error: unknown;
93
- message: string;
94
- };
95
- /** Return type of {@link WorkflowRouter.dispatch}. Discriminated union on `ok`. */
96
- type DispatchResult<TConfig extends WorkflowConfig = WorkflowConfig> = {
97
- ok: true;
98
- workflow: Workflow<TConfig>;
99
- events: Array<{
100
- type: EventNames<TConfig>;
101
- data: unknown;
102
- }>;
103
- } | {
104
- ok: false;
105
- error: PipelineError<TConfig>;
106
- };
107
- /**
108
- * Thrown internally when Zod validation fails during dispatch.
109
- * Caught by the router and returned as a validation error in {@link DispatchResult}.
110
- *
111
- * @param source - Which validation stage failed
112
- * @param issues - Array of Zod validation issues
113
- */
114
- declare class ValidationError extends Error {
115
- readonly source: "command" | "state" | "event" | "transition" | "restore";
116
- readonly issues: z.core.$ZodIssue[];
117
- constructor(source: "command" | "state" | "event" | "transition" | "restore", issues: z.core.$ZodIssue[]);
118
- }
119
- /**
120
- * Thrown internally when a handler calls `ctx.error()`.
121
- * Caught by the router and returned as a domain error in {@link DispatchResult}.
122
- *
123
- * @param code - The error code string
124
- * @param data - The error data payload
125
- */
126
- declare class DomainErrorSignal extends Error {
127
- readonly code: string;
128
- readonly data: unknown;
129
- constructor(code: string, data: unknown);
130
- }
131
-
132
- /** A plain, JSON-safe representation of a workflow's state for serialization and storage. */
133
- interface WorkflowSnapshot<TConfig extends WorkflowConfig = WorkflowConfig> {
134
- /** Unique workflow instance identifier. */
135
- readonly id: string;
136
- /** Name of the workflow definition. */
137
- readonly definitionName: string;
138
- /** Current state name. */
139
- readonly state: StateNames<TConfig>;
140
- /** State data (untyped — validated on {@link WorkflowDefinition.restore}). */
141
- readonly data: unknown;
142
- /** ISO 8601 timestamp of workflow creation. */
143
- readonly createdAt: string;
144
- /** ISO 8601 timestamp of last state change. */
145
- readonly updatedAt: string;
146
- /** Schema version number for migration support. */
147
- readonly modelVersion: number;
148
- }
149
-
150
- /**
151
- * The result of {@link defineWorkflow} — holds schemas and creates workflow instances.
152
- */
153
- interface WorkflowDefinition<TConfig extends WorkflowConfig = WorkflowConfig> {
154
- /** The raw Zod schema configuration. */
155
- readonly config: TConfig;
156
- /** The workflow definition name. */
157
- readonly name: string;
158
- /**
159
- * Creates a new workflow instance in a given initial state.
160
- *
161
- * @param id - Unique identifier for this workflow instance
162
- * @param config - Object containing `initialState` and the corresponding `data`
163
- * @returns A {@link WorkflowOf} narrowed to the initial state
164
- */
165
- createWorkflow<S extends StateNames<TConfig>>(id: string, config: {
166
- initialState: S;
167
- data: StateData<TConfig, S>;
168
- }): WorkflowOf<TConfig, S>;
169
- /**
170
- * Returns the Zod schema for a given state name.
171
- *
172
- * @param stateName - The state name to look up
173
- * @throws If the state name is not found in the config
174
- */
175
- getStateSchema(stateName: string): ZodType;
176
- /**
177
- * Returns the Zod schema for a given command name.
178
- *
179
- * @param commandName - The command name to look up
180
- * @throws If the command name is not found in the config
181
- */
182
- getCommandSchema(commandName: string): ZodType;
183
- /**
184
- * Returns the Zod schema for a given event name.
185
- *
186
- * @param eventName - The event name to look up
187
- * @throws If the event name is not found in the config
188
- */
189
- getEventSchema(eventName: string): ZodType;
190
- /**
191
- * Returns the Zod schema for a given error code.
192
- *
193
- * @param errorCode - The error code to look up
194
- * @throws If the error code is not found in the config
195
- */
196
- getErrorSchema(errorCode: string): ZodType;
197
- /**
198
- * Returns `true` if the given state name exists in the config.
199
- *
200
- * @param stateName - The state name to check
201
- */
202
- hasState(stateName: string): boolean;
203
- /**
204
- * Serializes a workflow instance into a plain, JSON-safe snapshot.
205
- *
206
- * @param workflow - The workflow instance to serialize
207
- * @returns A {@link WorkflowSnapshot} representing the current state
208
- */
209
- snapshot(workflow: Workflow<TConfig>): WorkflowSnapshot<TConfig>;
210
- /**
211
- * Restores a workflow instance from a plain snapshot, validating the state data.
212
- *
213
- * @param snapshot - The snapshot to restore from
214
- * @returns A result object: `{ ok: true, workflow }` or `{ ok: false, error }`
215
- */
216
- restore(snapshot: WorkflowSnapshot<TConfig>): {
217
- ok: true;
218
- workflow: Workflow<TConfig>;
219
- } | {
220
- ok: false;
221
- error: ValidationError;
222
- };
223
- }
224
- /**
225
- * Creates a workflow definition from a name and Zod schema configuration.
226
- *
227
- * @param name - Unique name for this workflow type
228
- * @param config - Object with `states`, `commands`, `events`, `errors` — each a record of Zod schemas
229
- * @returns A {@link WorkflowDefinition} with methods for creating instances and accessing schemas
230
- */
231
- declare function defineWorkflow<const TConfig extends WorkflowConfigInput>(name: string, config: TConfig): WorkflowDefinition<TConfig & {
232
- _resolved: {
233
- states: {
234
- [K in keyof TConfig["states"]]: z.infer<TConfig["states"][K]>;
235
- };
236
- commands: {
237
- [K in keyof TConfig["commands"]]: z.infer<TConfig["commands"][K]>;
238
- };
239
- events: {
240
- [K in keyof TConfig["events"]]: z.infer<TConfig["events"][K]>;
241
- };
242
- errors: {
243
- [K in keyof TConfig["errors"]]: z.infer<TConfig["errors"][K]>;
244
- };
245
- };
246
- }>;
247
-
248
- /** A phantom-typed key for type-safe middleware state storage via {@link Context.set} and {@link Context.get}. */
249
- interface ContextKey<T> {
250
- /** @internal Phantom type brand — not used at runtime. */
251
- readonly _phantom: T;
252
- /** Internal symbol providing uniqueness. */
253
- readonly id: symbol;
254
- }
255
- /**
256
- * Creates a unique typed key for storing and retrieving values in context.
257
- *
258
- * @param name - Debug label (uniqueness comes from an internal `Symbol`)
259
- * @returns A {@link ContextKey} for use with `ctx.set()`, `ctx.get()`, and `ctx.getOrNull()`
260
- */
261
- declare function createKey<T>(name: string): ContextKey<T>;
262
-
263
- /** Mutable context flowing through the middleware pipeline during dispatch. */
264
- interface Context<TConfig extends WorkflowConfig, TDeps, TState extends StateNames<TConfig> = StateNames<TConfig>, TCommand extends CommandNames<TConfig> = CommandNames<TConfig>> {
265
- /** The command being dispatched, with type and validated payload. */
266
- readonly command: {
267
- readonly type: TCommand;
268
- readonly payload: CommandPayload<TConfig, TCommand>;
269
- };
270
- /** The original workflow before any mutations. */
271
- readonly workflow: WorkflowOf<TConfig, TState>;
272
- /** Dependencies injected via the router constructor. */
273
- readonly deps: TDeps;
274
- /** Current state data (reflects mutations from {@link update}). */
275
- readonly data: StateData<TConfig, TState>;
276
- /**
277
- * Merges partial data into the current state. Validates against the state's Zod schema.
278
- * @param data - Partial state data to merge
279
- */
280
- update(data: Partial<StateData<TConfig, TState>>): void;
281
- /**
282
- * Transitions the workflow to a new state with new data. Validates against the target state's Zod schema.
283
- * @param target - Target state name
284
- * @param data - Data for the target state
285
- */
286
- transition<Target extends StateNames<TConfig>>(target: Target, data: StateData<TConfig, Target>): void;
287
- /**
288
- * Emits a domain event. Validates event data against the event's Zod schema.
289
- * @param event - Event with type and data
290
- */
291
- emit<E extends EventNames<TConfig>>(event: {
292
- type: E;
293
- data: EventData<TConfig, E>;
294
- }): void;
295
- /** Accumulated events emitted during this dispatch. */
296
- readonly events: ReadonlyArray<{
297
- type: EventNames<TConfig>;
298
- data: unknown;
299
- }>;
300
- /**
301
- * Signals a domain error. Validates error data and throws internally (caught by the router).
302
- * @param err - Error with code and data
303
- */
304
- error<C extends ErrorCodes<TConfig>>(err: {
305
- code: C;
306
- data: ErrorData<TConfig, C>;
307
- }): never;
308
- /**
309
- * Stores a value in context-scoped middleware state.
310
- * @param key - A {@link ContextKey} created via {@link createKey}
311
- * @param value - The value to store
312
- */
313
- set<T>(key: ContextKey<T>, value: T): void;
314
- /**
315
- * Retrieves a value from context-scoped middleware state. Throws if not set.
316
- * @param key - A {@link ContextKey} created via {@link createKey}
317
- */
318
- get<T>(key: ContextKey<T>): T;
319
- /**
320
- * Retrieves a value from context-scoped middleware state, or `undefined` if not set.
321
- * @param key - A {@link ContextKey} created via {@link createKey}
322
- */
323
- getOrNull<T>(key: ContextKey<T>): T | undefined;
324
- /** @internal — not part of the handler API */
325
- getWorkflowSnapshot(): Workflow<TConfig>;
326
- }
1
+ import { C as Context, W as WorkflowDefinition } from './plugin-DHN3Pk52.js';
2
+ export { a as ContextKey, G as GenericPlugin, P as Plugin, R as ReadonlyContext, b as RouterOptions, c as WorkflowRouter, d as createKey, e as defineGenericPlugin, f as definePlugin, g as defineWorkflow, i as isPlugin } from './plugin-DHN3Pk52.js';
3
+ import { W as WorkflowConfig, S as StateNames, C as CommandNames, a as WorkflowSnapshot } from './snapshot-D5iZubCz.js';
4
+ export { b as CommandPayload, c as ConfigOf, D as DispatchResult, d as DomainErrorSignal, E as ErrorCodes, e as ErrorData, f as EventData, g as EventNames, P as PipelineError, h as StateData, V as ValidationError, i as Workflow, j as WorkflowOf } from './snapshot-D5iZubCz.js';
5
+ import 'zod';
327
6
 
328
7
  /** Terminal handler function — receives fully typed context with state and command narrowing. */
329
8
  type Handler<TConfig extends WorkflowConfig, TDeps, TState extends StateNames<TConfig>, TCommand extends CommandNames<TConfig>> = (ctx: Context<TConfig, TDeps, TState, TCommand>) => void | Promise<void>;
330
9
 
331
10
  /** The lifecycle hook event names. */
332
- type HookEvent = "dispatch:start" | "dispatch:end" | "transition" | "error" | "event";
11
+ type HookEvent = "dispatch:start" | "dispatch:end" | "pipeline:start" | "pipeline:end" | "transition" | "error" | "event";
333
12
 
334
13
  /**
335
14
  * Koa-style middleware function with full context narrowing via defaults.
@@ -418,127 +97,4 @@ declare function defineMigrations<TConfig extends WorkflowConfig>(definition: Wo
418
97
  */
419
98
  declare function migrate<TConfig extends WorkflowConfig>(pipeline: MigrationPipeline<TConfig>, snapshot: WorkflowSnapshot, options?: MigrateOptions): MigrateResult;
420
99
 
421
- /**
422
- * Read-only subset of Context for hook callbacks.
423
- * Includes context-key access (set/get) but excludes dispatch mutation methods.
424
- */
425
- type ReadonlyContext<TConfig extends WorkflowConfig, TDeps, TState extends StateNames<TConfig> = StateNames<TConfig>, TCommand extends CommandNames<TConfig> = CommandNames<TConfig>> = Omit<Context<TConfig, TDeps, TState, TCommand>, "update" | "transition" | "emit" | "error" | "getWorkflowSnapshot">;
426
-
427
- type AnyMiddleware = (ctx: any, next: () => Promise<void>) => Promise<void>;
428
- type HandlerEntry = {
429
- inlineMiddleware: AnyMiddleware[];
430
- handler: AnyMiddleware;
431
- };
432
- /** Options for the {@link WorkflowRouter} constructor. */
433
- interface RouterOptions {
434
- /** Callback invoked when a lifecycle hook throws. Defaults to `console.error`. */
435
- onHookError?: (error: unknown) => void;
436
- /** Wrap deps in a Proxy to catch dependency errors. Defaults to `true`. */
437
- wrapDeps?: boolean;
438
- }
439
- declare class StateBuilder<TConfig extends WorkflowConfig, TDeps, TState extends StateNames<TConfig>> {
440
- /** @internal */ readonly middleware: AnyMiddleware[];
441
- /** @internal */ readonly handlers: Map<string, HandlerEntry>;
442
- constructor();
443
- on<C extends CommandNames<TConfig>>(command: C, handler: (ctx: Context<TConfig, TDeps, TState, C>) => void | Promise<void>): this;
444
- on<C extends CommandNames<TConfig>>(command: C, ...fns: [...AnyMiddleware[], (ctx: Context<TConfig, TDeps, TState, C>) => void | Promise<void>]): this;
445
- use(middleware: (ctx: Context<TConfig, TDeps, TState>, next: () => Promise<void>) => Promise<void>): this;
446
- }
447
- /**
448
- * Routes commands to handlers based on workflow state.
449
- *
450
- * Supports global middleware, state-scoped middleware, inline middleware,
451
- * wildcard handlers, and multi-state handlers.
452
- */
453
- declare class WorkflowRouter<TConfig extends WorkflowConfig, TDeps = {}> {
454
- private readonly definition;
455
- private readonly deps;
456
- private globalMiddleware;
457
- private singleStateBuilders;
458
- private multiStateBuilders;
459
- private wildcardHandlers;
460
- private hookRegistry;
461
- private readonly onHookError;
462
- private readonly wrapDeps;
463
- /**
464
- * @param definition - The workflow definition describing states, commands, events, and errors
465
- * @param deps - Dependencies injected into every handler context
466
- * @param options - Router configuration options
467
- */
468
- constructor(definition: WorkflowDefinition<TConfig>, deps?: TDeps, options?: RouterOptions);
469
- /**
470
- * Adds global middleware, merges another router, or applies a plugin.
471
- * @param arg - A middleware function, another {@link WorkflowRouter} to merge, or a {@link Plugin}
472
- */
473
- use(arg: ((ctx: Context<TConfig, TDeps>, next: () => Promise<void>) => Promise<void>) | WorkflowRouter<TConfig, TDeps> | Plugin<TConfig, TDeps>): this;
474
- private merge;
475
- private mergeStateBuilders;
476
- /**
477
- * Registers handlers for one or more states.
478
- * @param name - A state name or array of state names to register handlers for
479
- * @param setup - Callback that receives a state builder to register commands and middleware
480
- */
481
- state<P extends StateNames<TConfig> | readonly StateNames<TConfig>[]>(name: P, setup: (state: StateBuilder<TConfig, TDeps, P extends readonly (infer S)[] ? S & StateNames<TConfig> : P & StateNames<TConfig>>) => void): this;
482
- /**
483
- * Registers a lifecycle hook callback.
484
- * @param event - The lifecycle event name
485
- * @param callback - The callback to invoke when the event fires
486
- */
487
- on(event: "dispatch:start", callback: (ctx: ReadonlyContext<TConfig, TDeps>) => void | Promise<void>): this;
488
- on(event: "dispatch:end", callback: (ctx: ReadonlyContext<TConfig, TDeps>, result: DispatchResult<TConfig>) => void | Promise<void>): this;
489
- on(event: "transition", callback: (from: StateNames<TConfig>, to: StateNames<TConfig>, workflow: Workflow<TConfig>) => void | Promise<void>): this;
490
- on(event: "error", callback: (error: PipelineError<TConfig>, ctx: ReadonlyContext<TConfig, TDeps>) => void | Promise<void>): this;
491
- on(event: "event", callback: (event: {
492
- type: EventNames<TConfig>;
493
- data: unknown;
494
- }, workflow: Workflow<TConfig>) => void | Promise<void>): this;
495
- /**
496
- * Registers a wildcard handler that matches any state.
497
- * @param state - Must be `"*"` to match all states
498
- * @param command - The command name to handle
499
- * @param handler - The terminal handler
500
- */
501
- on<C extends CommandNames<TConfig>>(state: "*", command: C, handler: (ctx: Context<TConfig, TDeps, StateNames<TConfig>, C>) => void | Promise<void>): this;
502
- /**
503
- * Registers a wildcard handler that matches any state, with inline middleware.
504
- * @param state - Must be `"*"` to match all states
505
- * @param command - The command name to handle
506
- * @param fns - Inline middleware followed by the terminal handler
507
- */
508
- on<C extends CommandNames<TConfig>>(state: "*", command: C, ...fns: [
509
- ...AnyMiddleware[],
510
- (ctx: Context<TConfig, TDeps, StateNames<TConfig>, C>) => void | Promise<void>
511
- ]): this;
512
- /**
513
- * Dispatches a command to the appropriate handler and returns the result.
514
- * @param workflow - The current workflow instance to dispatch against
515
- * @param command - The command with its type and payload
516
- * @returns A {@link DispatchResult} indicating success or failure with the updated workflow and events
517
- */
518
- dispatch(workflow: Workflow<TConfig>, command: {
519
- type: CommandNames<TConfig>;
520
- payload: unknown;
521
- }): Promise<DispatchResult<TConfig>>;
522
- }
523
-
524
- declare const PLUGIN_SYMBOL: unique symbol;
525
- /** A branded plugin function that can be passed to {@link WorkflowRouter.use}. */
526
- type Plugin<TConfig extends WorkflowConfig, TDeps> = ((router: WorkflowRouter<TConfig, TDeps>) => void) & {
527
- readonly [PLUGIN_SYMBOL]: true;
528
- };
529
- /**
530
- * Brands a function as a Ryte plugin for use with {@link WorkflowRouter.use}.
531
- *
532
- * @param fn - A function that configures a router (adds handlers, middleware, hooks)
533
- * @returns A branded {@link Plugin} function
534
- */
535
- declare function definePlugin<TConfig extends WorkflowConfig, TDeps>(fn: (router: WorkflowRouter<TConfig, TDeps>) => void): Plugin<TConfig, TDeps>;
536
- /**
537
- * Checks whether a value is a branded Ryte plugin.
538
- *
539
- * @param value - The value to check
540
- * @returns `true` if the value is a {@link Plugin}
541
- */
542
- declare function isPlugin(value: unknown): value is Plugin<WorkflowConfig, unknown>;
543
-
544
- export { type CommandNames, type CommandPayload, type Context, type ContextKey, type DispatchResult, DomainErrorSignal, type ErrorCodes, type ErrorData, type EventData, type EventNames, type Handler, type HookEvent, type Middleware, type MigrateOptions, type MigrateResult, type MigrationEntry, MigrationError, type MigrationFn, type MigrationPipeline, type PipelineError, type Plugin, type ReadonlyContext, type RouterOptions, type StateData, type StateNames, ValidationError, type Workflow, type WorkflowConfig, type WorkflowDefinition, type WorkflowOf, WorkflowRouter, type WorkflowSnapshot, createKey, defineMigrations, definePlugin, defineWorkflow, isPlugin, migrate };
100
+ export { CommandNames, Context, type Handler, type HookEvent, type Middleware, type MigrateOptions, type MigrateResult, type MigrationEntry, MigrationError, type MigrationFn, type MigrationPipeline, StateNames, WorkflowConfig, WorkflowDefinition, WorkflowSnapshot, defineMigrations, migrate };
package/dist/index.js CHANGED
@@ -1,3 +1,7 @@
1
+ import {
2
+ compose
3
+ } from "./chunk-YTJGSTKG.js";
4
+
1
5
  // src/types.ts
2
6
  var ValidationError = class extends Error {
3
7
  constructor(source, issues) {
@@ -73,7 +77,13 @@ function defineWorkflow(name, config) {
73
77
  hasState(stateName) {
74
78
  return stateName in config.states;
75
79
  },
76
- snapshot(workflow) {
80
+ hasCommand(commandName) {
81
+ return commandName in config.commands;
82
+ },
83
+ hasEvent(eventName) {
84
+ return eventName in config.events;
85
+ },
86
+ serialize(workflow) {
77
87
  return {
78
88
  id: workflow.id,
79
89
  definitionName: name,
@@ -81,10 +91,11 @@ function defineWorkflow(name, config) {
81
91
  data: workflow.data,
82
92
  createdAt: workflow.createdAt.toISOString(),
83
93
  updatedAt: workflow.updatedAt.toISOString(),
84
- modelVersion: config.modelVersion ?? 1
94
+ modelVersion: config.modelVersion ?? 1,
95
+ version: workflow.version ?? 1
85
96
  };
86
97
  },
87
- restore(snap) {
98
+ deserialize(snap) {
88
99
  const stateSchema = config.states[snap.state];
89
100
  if (!stateSchema) {
90
101
  return {
@@ -248,25 +259,13 @@ function definePlugin(fn) {
248
259
  Object.defineProperty(plugin, PLUGIN_SYMBOL, { value: true, writable: false });
249
260
  return plugin;
250
261
  }
262
+ function defineGenericPlugin(fn) {
263
+ return definePlugin(fn);
264
+ }
251
265
  function isPlugin(value) {
252
266
  return typeof value === "function" && PLUGIN_SYMBOL in value;
253
267
  }
254
268
 
255
- // src/compose.ts
256
- function compose(middleware) {
257
- return async (ctx) => {
258
- let index = -1;
259
- async function dispatch(i) {
260
- if (i <= index) throw new Error("next() called multiple times");
261
- index = i;
262
- const fn = middleware[i];
263
- if (!fn) return;
264
- await fn(ctx, () => dispatch(i + 1));
265
- }
266
- await dispatch(0);
267
- };
268
- }
269
-
270
269
  // src/wrap-deps.ts
271
270
  function createDepProxy(obj, depName) {
272
271
  return new Proxy(obj, {
@@ -421,6 +420,8 @@ function createContext(definition, originalWorkflow, command, deps, options) {
421
420
  var HOOK_EVENTS = /* @__PURE__ */ new Set([
422
421
  "dispatch:start",
423
422
  "dispatch:end",
423
+ "pipeline:start",
424
+ "pipeline:end",
424
425
  "transition",
425
426
  "error",
426
427
  "event"
@@ -605,6 +606,25 @@ var WorkflowRouter = class _WorkflowRouter {
605
606
  * @returns A {@link DispatchResult} indicating success or failure with the updated workflow and events
606
607
  */
607
608
  async dispatch(workflow, command) {
609
+ await this.hookRegistry.emit("dispatch:start", this.onHookError, workflow, command);
610
+ let result;
611
+ try {
612
+ result = await this.executePipeline(workflow, command);
613
+ } catch (err) {
614
+ result = {
615
+ ok: false,
616
+ error: {
617
+ category: "unexpected",
618
+ error: err,
619
+ message: err instanceof Error ? err.message : String(err)
620
+ }
621
+ };
622
+ } finally {
623
+ await this.hookRegistry.emit("dispatch:end", this.onHookError, workflow, command, result);
624
+ }
625
+ return result;
626
+ }
627
+ async executePipeline(workflow, command) {
608
628
  if (!this.definition.hasState(workflow.state)) {
609
629
  return {
610
630
  ok: false,
@@ -676,7 +696,7 @@ var WorkflowRouter = class _WorkflowRouter {
676
696
  this.deps,
677
697
  { wrapDeps: this.wrapDeps }
678
698
  );
679
- await this.hookRegistry.emit("dispatch:start", this.onHookError, ctx);
699
+ await this.hookRegistry.emit("pipeline:start", this.onHookError, ctx);
680
700
  try {
681
701
  const composed = compose(chain);
682
702
  await composed(ctx);
@@ -699,7 +719,7 @@ var WorkflowRouter = class _WorkflowRouter {
699
719
  await this.hookRegistry.emit("event", this.onHookError, event, result.workflow);
700
720
  }
701
721
  }
702
- await this.hookRegistry.emit("dispatch:end", this.onHookError, ctx, result);
722
+ await this.hookRegistry.emit("pipeline:end", this.onHookError, ctx, result);
703
723
  return result;
704
724
  } catch (err) {
705
725
  let result;
@@ -743,7 +763,7 @@ var WorkflowRouter = class _WorkflowRouter {
743
763
  };
744
764
  }
745
765
  await this.hookRegistry.emit("error", this.onHookError, result.error, ctx);
746
- await this.hookRegistry.emit("dispatch:end", this.onHookError, ctx, result);
766
+ await this.hookRegistry.emit("pipeline:end", this.onHookError, ctx, result);
747
767
  return result;
748
768
  }
749
769
  }
@@ -754,6 +774,7 @@ export {
754
774
  ValidationError,
755
775
  WorkflowRouter,
756
776
  createKey,
777
+ defineGenericPlugin,
757
778
  defineMigrations,
758
779
  definePlugin,
759
780
  defineWorkflow,