@rytejs/core 0.5.0 → 0.6.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.cts CHANGED
@@ -2,8 +2,9 @@ import { ZodType, z } from 'zod';
2
2
 
3
3
  /**
4
4
  * Shape of the configuration object passed to {@link defineWorkflow}.
5
+ * Exported for internal package use only — not re-exported from index.ts.
5
6
  */
6
- interface WorkflowConfig {
7
+ interface WorkflowConfigInput {
7
8
  /** Optional version number for schema migrations. Defaults to 1. */
8
9
  modelVersion?: number;
9
10
  /** Record of state names to Zod schemas defining their data shape. */
@@ -15,18 +16,39 @@ interface WorkflowConfig {
15
16
  /** Record of error codes to Zod schemas defining their data shape. */
16
17
  errors: Record<string, ZodType>;
17
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
+ }
18
36
  type StateNames<T extends WorkflowConfig> = keyof T["states"] & string;
19
37
  type CommandNames<T extends WorkflowConfig> = keyof T["commands"] & string;
20
38
  type EventNames<T extends WorkflowConfig> = keyof T["events"] & string;
21
39
  type ErrorCodes<T extends WorkflowConfig> = keyof T["errors"] & string;
22
- /** Infers the data type for a given state. */
23
- type StateData<T extends WorkflowConfig, S extends StateNames<T>> = T["states"][S] extends ZodType ? z.infer<T["states"][S]> : never;
24
- /** Infers the payload type for a given command. */
25
- type CommandPayload<T extends WorkflowConfig, C extends CommandNames<T>> = T["commands"][C] extends ZodType ? z.infer<T["commands"][C]> : never;
26
- /** Infers the data type for a given event. */
27
- type EventData<T extends WorkflowConfig, E extends EventNames<T>> = T["events"][E] extends ZodType ? z.infer<T["events"][E]> : never;
28
- /** Infers the data type for a given error code. */
29
- type ErrorData<T extends WorkflowConfig, C extends ErrorCodes<T>> = T["errors"][C] extends ZodType ? z.infer<T["errors"][C]> : never;
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]>;
30
52
  /** Workflow narrowed to a specific known state. */
31
53
  interface WorkflowOf<TConfig extends WorkflowConfig, S extends StateNames<TConfig>> {
32
54
  /** Unique workflow instance identifier. */
@@ -64,6 +86,11 @@ type PipelineError<TConfig extends WorkflowConfig = WorkflowConfig> = {
64
86
  category: "unexpected";
65
87
  error: unknown;
66
88
  message: string;
89
+ } | {
90
+ category: "dependency";
91
+ name: string;
92
+ error: unknown;
93
+ message: string;
67
94
  };
68
95
  /** Return type of {@link WorkflowRouter.dispatch}. Discriminated union on `ok`. */
69
96
  type DispatchResult<TConfig extends WorkflowConfig = WorkflowConfig> = {
@@ -137,7 +164,7 @@ interface WorkflowDefinition<TConfig extends WorkflowConfig = WorkflowConfig> {
137
164
  */
138
165
  createWorkflow<S extends StateNames<TConfig>>(id: string, config: {
139
166
  initialState: S;
140
- data: z.infer<TConfig["states"][S]>;
167
+ data: StateData<TConfig, S>;
141
168
  }): WorkflowOf<TConfig, S>;
142
169
  /**
143
170
  * Returns the Zod schema for a given state name.
@@ -201,7 +228,22 @@ interface WorkflowDefinition<TConfig extends WorkflowConfig = WorkflowConfig> {
201
228
  * @param config - Object with `states`, `commands`, `events`, `errors` — each a record of Zod schemas
202
229
  * @returns A {@link WorkflowDefinition} with methods for creating instances and accessing schemas
203
230
  */
204
- declare function defineWorkflow<const TConfig extends WorkflowConfig>(name: string, config: TConfig): WorkflowDefinition<TConfig>;
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
+ }>;
205
247
 
206
248
  /** A phantom-typed key for type-safe middleware state storage via {@link Context.set} and {@link Context.get}. */
207
249
  interface ContextKey<T> {
@@ -391,12 +433,16 @@ type HandlerEntry = {
391
433
  interface RouterOptions {
392
434
  /** Callback invoked when a lifecycle hook throws. Defaults to `console.error`. */
393
435
  onHookError?: (error: unknown) => void;
436
+ /** Wrap deps in a Proxy to catch dependency errors. Defaults to `true`. */
437
+ wrapDeps?: boolean;
394
438
  }
395
439
  declare class StateBuilder<TConfig extends WorkflowConfig, TDeps, TState extends StateNames<TConfig>> {
396
440
  /** @internal */ readonly middleware: AnyMiddleware[];
397
441
  /** @internal */ readonly handlers: Map<string, HandlerEntry>;
398
- on: <C extends CommandNames<TConfig>>(command: C, ...fns: [...AnyMiddleware[], (ctx: Context<TConfig, TDeps, TState, C>) => void | Promise<void>]) => this;
399
- use: (middleware: (ctx: Context<TConfig, TDeps, TState>, next: () => Promise<void>) => Promise<void>) => this;
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;
400
446
  }
401
447
  /**
402
448
  * Routes commands to handlers based on workflow state.
@@ -413,6 +459,7 @@ declare class WorkflowRouter<TConfig extends WorkflowConfig, TDeps = {}> {
413
459
  private wildcardHandlers;
414
460
  private hookRegistry;
415
461
  private readonly onHookError;
462
+ private readonly wrapDeps;
416
463
  /**
417
464
  * @param definition - The workflow definition describing states, commands, events, and errors
418
465
  * @param deps - Dependencies injected into every handler context
@@ -449,7 +496,14 @@ declare class WorkflowRouter<TConfig extends WorkflowConfig, TDeps = {}> {
449
496
  * Registers a wildcard handler that matches any state.
450
497
  * @param state - Must be `"*"` to match all states
451
498
  * @param command - The command name to handle
452
- * @param fns - Optional inline middleware followed by the terminal handler
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
453
507
  */
454
508
  on<C extends CommandNames<TConfig>>(state: "*", command: C, ...fns: [
455
509
  ...AnyMiddleware[],
package/dist/index.d.ts CHANGED
@@ -2,8 +2,9 @@ import { ZodType, z } from 'zod';
2
2
 
3
3
  /**
4
4
  * Shape of the configuration object passed to {@link defineWorkflow}.
5
+ * Exported for internal package use only — not re-exported from index.ts.
5
6
  */
6
- interface WorkflowConfig {
7
+ interface WorkflowConfigInput {
7
8
  /** Optional version number for schema migrations. Defaults to 1. */
8
9
  modelVersion?: number;
9
10
  /** Record of state names to Zod schemas defining their data shape. */
@@ -15,18 +16,39 @@ interface WorkflowConfig {
15
16
  /** Record of error codes to Zod schemas defining their data shape. */
16
17
  errors: Record<string, ZodType>;
17
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
+ }
18
36
  type StateNames<T extends WorkflowConfig> = keyof T["states"] & string;
19
37
  type CommandNames<T extends WorkflowConfig> = keyof T["commands"] & string;
20
38
  type EventNames<T extends WorkflowConfig> = keyof T["events"] & string;
21
39
  type ErrorCodes<T extends WorkflowConfig> = keyof T["errors"] & string;
22
- /** Infers the data type for a given state. */
23
- type StateData<T extends WorkflowConfig, S extends StateNames<T>> = T["states"][S] extends ZodType ? z.infer<T["states"][S]> : never;
24
- /** Infers the payload type for a given command. */
25
- type CommandPayload<T extends WorkflowConfig, C extends CommandNames<T>> = T["commands"][C] extends ZodType ? z.infer<T["commands"][C]> : never;
26
- /** Infers the data type for a given event. */
27
- type EventData<T extends WorkflowConfig, E extends EventNames<T>> = T["events"][E] extends ZodType ? z.infer<T["events"][E]> : never;
28
- /** Infers the data type for a given error code. */
29
- type ErrorData<T extends WorkflowConfig, C extends ErrorCodes<T>> = T["errors"][C] extends ZodType ? z.infer<T["errors"][C]> : never;
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]>;
30
52
  /** Workflow narrowed to a specific known state. */
31
53
  interface WorkflowOf<TConfig extends WorkflowConfig, S extends StateNames<TConfig>> {
32
54
  /** Unique workflow instance identifier. */
@@ -64,6 +86,11 @@ type PipelineError<TConfig extends WorkflowConfig = WorkflowConfig> = {
64
86
  category: "unexpected";
65
87
  error: unknown;
66
88
  message: string;
89
+ } | {
90
+ category: "dependency";
91
+ name: string;
92
+ error: unknown;
93
+ message: string;
67
94
  };
68
95
  /** Return type of {@link WorkflowRouter.dispatch}. Discriminated union on `ok`. */
69
96
  type DispatchResult<TConfig extends WorkflowConfig = WorkflowConfig> = {
@@ -137,7 +164,7 @@ interface WorkflowDefinition<TConfig extends WorkflowConfig = WorkflowConfig> {
137
164
  */
138
165
  createWorkflow<S extends StateNames<TConfig>>(id: string, config: {
139
166
  initialState: S;
140
- data: z.infer<TConfig["states"][S]>;
167
+ data: StateData<TConfig, S>;
141
168
  }): WorkflowOf<TConfig, S>;
142
169
  /**
143
170
  * Returns the Zod schema for a given state name.
@@ -201,7 +228,22 @@ interface WorkflowDefinition<TConfig extends WorkflowConfig = WorkflowConfig> {
201
228
  * @param config - Object with `states`, `commands`, `events`, `errors` — each a record of Zod schemas
202
229
  * @returns A {@link WorkflowDefinition} with methods for creating instances and accessing schemas
203
230
  */
204
- declare function defineWorkflow<const TConfig extends WorkflowConfig>(name: string, config: TConfig): WorkflowDefinition<TConfig>;
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
+ }>;
205
247
 
206
248
  /** A phantom-typed key for type-safe middleware state storage via {@link Context.set} and {@link Context.get}. */
207
249
  interface ContextKey<T> {
@@ -391,12 +433,16 @@ type HandlerEntry = {
391
433
  interface RouterOptions {
392
434
  /** Callback invoked when a lifecycle hook throws. Defaults to `console.error`. */
393
435
  onHookError?: (error: unknown) => void;
436
+ /** Wrap deps in a Proxy to catch dependency errors. Defaults to `true`. */
437
+ wrapDeps?: boolean;
394
438
  }
395
439
  declare class StateBuilder<TConfig extends WorkflowConfig, TDeps, TState extends StateNames<TConfig>> {
396
440
  /** @internal */ readonly middleware: AnyMiddleware[];
397
441
  /** @internal */ readonly handlers: Map<string, HandlerEntry>;
398
- on: <C extends CommandNames<TConfig>>(command: C, ...fns: [...AnyMiddleware[], (ctx: Context<TConfig, TDeps, TState, C>) => void | Promise<void>]) => this;
399
- use: (middleware: (ctx: Context<TConfig, TDeps, TState>, next: () => Promise<void>) => Promise<void>) => this;
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;
400
446
  }
401
447
  /**
402
448
  * Routes commands to handlers based on workflow state.
@@ -413,6 +459,7 @@ declare class WorkflowRouter<TConfig extends WorkflowConfig, TDeps = {}> {
413
459
  private wildcardHandlers;
414
460
  private hookRegistry;
415
461
  private readonly onHookError;
462
+ private readonly wrapDeps;
416
463
  /**
417
464
  * @param definition - The workflow definition describing states, commands, events, and errors
418
465
  * @param deps - Dependencies injected into every handler context
@@ -449,7 +496,14 @@ declare class WorkflowRouter<TConfig extends WorkflowConfig, TDeps = {}> {
449
496
  * Registers a wildcard handler that matches any state.
450
497
  * @param state - Must be `"*"` to match all states
451
498
  * @param command - The command name to handle
452
- * @param fns - Optional inline middleware followed by the terminal handler
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
453
507
  */
454
508
  on<C extends CommandNames<TConfig>>(state: "*", command: C, ...fns: [
455
509
  ...AnyMiddleware[],
package/dist/index.js CHANGED
@@ -15,6 +15,15 @@ var DomainErrorSignal = class extends Error {
15
15
  this.name = "DomainErrorSignal";
16
16
  }
17
17
  };
18
+ var DependencyErrorSignal = class extends Error {
19
+ constructor(depName, error) {
20
+ const original = error instanceof Error ? error.message : String(error);
21
+ super(`Dependency "${depName}" failed: ${original}`);
22
+ this.depName = depName;
23
+ this.error = error;
24
+ this.name = "DependencyErrorSignal";
25
+ }
26
+ };
18
27
 
19
28
  // src/definition.ts
20
29
  function defineWorkflow(name, config) {
@@ -38,6 +47,7 @@ function defineWorkflow(name, config) {
38
47
  data: result.data,
39
48
  createdAt: now,
40
49
  updatedAt: now
50
+ // biome-ignore lint/suspicious/noExplicitAny: narrowed by the public overload's generic S parameter
41
51
  };
42
52
  },
43
53
  getStateSchema(stateName) {
@@ -106,6 +116,7 @@ function defineWorkflow(name, config) {
106
116
  createdAt: new Date(snap.createdAt),
107
117
  updatedAt: new Date(snap.updatedAt)
108
118
  }
119
+ // biome-ignore lint/suspicious/noExplicitAny: Prettify<any> produces { [x: string]: any } instead of any, making unknown data incompatible
109
120
  };
110
121
  }
111
122
  };
@@ -256,8 +267,75 @@ function compose(middleware) {
256
267
  };
257
268
  }
258
269
 
270
+ // src/wrap-deps.ts
271
+ function createDepProxy(obj, depName) {
272
+ return new Proxy(obj, {
273
+ get(target, prop, receiver) {
274
+ if (typeof prop === "symbol") {
275
+ return Reflect.get(target, prop, receiver);
276
+ }
277
+ const value = Reflect.get(target, prop, receiver);
278
+ if (value === null || value === void 0) {
279
+ return value;
280
+ }
281
+ if (typeof value === "function") {
282
+ return (...args) => {
283
+ try {
284
+ const result = value.apply(target, args);
285
+ if (result != null && typeof result === "object" && typeof result.then === "function") {
286
+ return result.catch((err) => {
287
+ throw new DependencyErrorSignal(depName, err);
288
+ });
289
+ }
290
+ return result;
291
+ } catch (err) {
292
+ throw new DependencyErrorSignal(depName, err);
293
+ }
294
+ };
295
+ }
296
+ if (typeof value === "object") {
297
+ return createDepProxy(value, depName);
298
+ }
299
+ return value;
300
+ }
301
+ });
302
+ }
303
+ function wrapDeps(deps) {
304
+ return new Proxy(deps, {
305
+ get(target, prop, receiver) {
306
+ if (typeof prop === "symbol") {
307
+ return Reflect.get(target, prop, receiver);
308
+ }
309
+ const value = Reflect.get(target, prop, receiver);
310
+ if (value === null || value === void 0) {
311
+ return value;
312
+ }
313
+ const depName = String(prop);
314
+ if (typeof value === "function") {
315
+ return (...args) => {
316
+ try {
317
+ const result = value.apply(target, args);
318
+ if (result != null && typeof result === "object" && typeof result.then === "function") {
319
+ return result.catch((err) => {
320
+ throw new DependencyErrorSignal(depName, err);
321
+ });
322
+ }
323
+ return result;
324
+ } catch (err) {
325
+ throw new DependencyErrorSignal(depName, err);
326
+ }
327
+ };
328
+ }
329
+ if (typeof value === "object") {
330
+ return createDepProxy(value, depName);
331
+ }
332
+ return value;
333
+ }
334
+ });
335
+ }
336
+
259
337
  // src/context.ts
260
- function createContext(definition, originalWorkflow, command, deps) {
338
+ function createContext(definition, originalWorkflow, command, deps, options) {
261
339
  let mutableState = originalWorkflow.state;
262
340
  let mutableData = {
263
341
  ...originalWorkflow.data
@@ -267,7 +345,7 @@ function createContext(definition, originalWorkflow, command, deps) {
267
345
  const ctx = {
268
346
  command,
269
347
  workflow: originalWorkflow,
270
- deps,
348
+ deps: options?.wrapDeps !== false && deps != null && typeof deps === "object" ? wrapDeps(deps) : deps,
271
349
  get data() {
272
350
  return { ...mutableData };
273
351
  },
@@ -385,7 +463,12 @@ var StateBuilder = class {
385
463
  middleware = [];
386
464
  /** @internal */
387
465
  handlers = /* @__PURE__ */ new Map();
388
- on = (command, ...fns) => {
466
+ constructor() {
467
+ this.on = this.on.bind(this);
468
+ this.use = this.use.bind(this);
469
+ }
470
+ // Implementation
471
+ on(command, ...fns) {
389
472
  if (fns.length === 0) throw new Error("on() requires at least a handler");
390
473
  const handler = fns.pop();
391
474
  const inlineMiddleware = fns;
@@ -394,11 +477,11 @@ var StateBuilder = class {
394
477
  };
395
478
  this.handlers.set(command, { inlineMiddleware, handler: wrappedHandler });
396
479
  return this;
397
- };
398
- use = (middleware) => {
480
+ }
481
+ use(middleware) {
399
482
  this.middleware.push(middleware);
400
483
  return this;
401
- };
484
+ }
402
485
  };
403
486
  var WorkflowRouter = class _WorkflowRouter {
404
487
  /**
@@ -410,6 +493,7 @@ var WorkflowRouter = class _WorkflowRouter {
410
493
  this.definition = definition;
411
494
  this.deps = deps;
412
495
  this.onHookError = options.onHookError ?? console.error;
496
+ this.wrapDeps = options.wrapDeps !== false;
413
497
  }
414
498
  globalMiddleware = [];
415
499
  // biome-ignore lint/suspicious/noExplicitAny: type erasure — builders store handlers for different state types
@@ -419,6 +503,7 @@ var WorkflowRouter = class _WorkflowRouter {
419
503
  wildcardHandlers = /* @__PURE__ */ new Map();
420
504
  hookRegistry = new HookRegistry();
421
505
  onHookError;
506
+ wrapDeps;
422
507
  /**
423
508
  * Adds global middleware, merges another router, or applies a plugin.
424
509
  * @param arg - A middleware function, another {@link WorkflowRouter} to merge, or a {@link Plugin}
@@ -588,7 +673,8 @@ var WorkflowRouter = class _WorkflowRouter {
588
673
  this.definition,
589
674
  workflow,
590
675
  validatedCommand,
591
- this.deps
676
+ this.deps,
677
+ { wrapDeps: this.wrapDeps }
592
678
  );
593
679
  await this.hookRegistry.emit("dispatch:start", this.onHookError, ctx);
594
680
  try {
@@ -636,6 +722,16 @@ var WorkflowRouter = class _WorkflowRouter {
636
722
  message: err.message
637
723
  }
638
724
  };
725
+ } else if (err instanceof DependencyErrorSignal) {
726
+ result = {
727
+ ok: false,
728
+ error: {
729
+ category: "dependency",
730
+ name: err.depName,
731
+ error: err.error,
732
+ message: err.message
733
+ }
734
+ };
639
735
  } else {
640
736
  result = {
641
737
  ok: false,