@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/README.md +10 -4
- package/dist/index.cjs +103 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -14
- package/dist/index.d.ts +68 -14
- package/dist/index.js +103 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
-
/**
|
|
23
|
-
type
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
type
|
|
28
|
-
/**
|
|
29
|
-
type
|
|
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:
|
|
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
|
|
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
|
-
|
|
399
|
-
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
23
|
-
type
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
type
|
|
28
|
-
/**
|
|
29
|
-
type
|
|
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:
|
|
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
|
|
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
|
-
|
|
399
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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,
|