@rxova/journey-core 1.0.0-rc.3 → 1.0.1

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.
Files changed (158) hide show
  1. package/README.md +185 -189
  2. package/dist/connectors/immer/immer.cjs +2 -0
  3. package/dist/connectors/immer/immer.cjs.map +7 -0
  4. package/dist/connectors/immer/immer.d.cts +11 -0
  5. package/dist/connectors/immer/immer.d.ts +11 -0
  6. package/dist/connectors/immer/immer.js +2 -0
  7. package/dist/connectors/immer/immer.js.map +7 -0
  8. package/dist/connectors/immer/immer.types.d.cts +9 -0
  9. package/dist/connectors/immer/immer.types.d.ts +9 -0
  10. package/dist/core/errors.d.cts +57 -0
  11. package/dist/core/errors.d.ts +57 -0
  12. package/dist/core/helpers.d.cts +40 -0
  13. package/dist/core/helpers.d.ts +40 -0
  14. package/dist/core/machine.d.cts +9 -0
  15. package/dist/core/machine.d.ts +9 -0
  16. package/dist/core/runtime.d.cts +115 -0
  17. package/dist/core/runtime.d.ts +115 -0
  18. package/dist/core/runtime.types.d.cts +112 -0
  19. package/dist/core/runtime.types.d.ts +112 -0
  20. package/dist/core/store.d.cts +31 -0
  21. package/dist/core/store.d.ts +31 -0
  22. package/dist/core/types.d.cts +481 -0
  23. package/dist/core/types.d.ts +481 -0
  24. package/dist/diagnostics/diagnostics.helpers.d.cts +17 -0
  25. package/dist/diagnostics/diagnostics.helpers.d.ts +17 -0
  26. package/dist/diagnostics/diagnostics.types.d.cts +22 -0
  27. package/dist/diagnostics/diagnostics.types.d.ts +22 -0
  28. package/dist/graph/bag.types.d.cts +91 -0
  29. package/dist/graph/bag.types.d.ts +91 -0
  30. package/dist/graph/graph.d.cts +63 -0
  31. package/dist/graph/graph.d.ts +63 -0
  32. package/dist/graph/graph.types.d.cts +212 -0
  33. package/dist/graph/graph.types.d.ts +212 -0
  34. package/dist/graph/work.d.cts +81 -0
  35. package/dist/graph/work.d.ts +81 -0
  36. package/dist/index.cjs +1 -1
  37. package/dist/index.cjs.map +4 -4
  38. package/dist/index.d.cts +13 -5
  39. package/dist/index.d.ts +13 -5
  40. package/dist/index.js +1 -1
  41. package/dist/index.js.map +4 -4
  42. package/dist/linear/linear.d.cts +33 -0
  43. package/dist/linear/linear.d.ts +33 -0
  44. package/dist/linear/linear.types.d.cts +28 -0
  45. package/dist/linear/linear.types.d.ts +28 -0
  46. package/dist/plugins/analytics/analytics.d.cts +8 -0
  47. package/dist/plugins/analytics/analytics.d.ts +8 -0
  48. package/dist/plugins/analytics/analytics.helpers.d.cts +2 -0
  49. package/dist/plugins/analytics/analytics.helpers.d.ts +2 -0
  50. package/dist/plugins/analytics/analytics.types.d.cts +27 -0
  51. package/dist/plugins/analytics/analytics.types.d.ts +27 -0
  52. package/dist/plugins/execution-paths/execution-paths.d.cts +7 -4
  53. package/dist/plugins/execution-paths/execution-paths.d.ts +7 -4
  54. package/dist/plugins/execution-paths/execution-paths.types.d.cts +21 -0
  55. package/dist/plugins/execution-paths/execution-paths.types.d.ts +21 -0
  56. package/dist/plugins/index.cjs +2 -0
  57. package/dist/plugins/index.cjs.map +7 -0
  58. package/dist/plugins/index.d.cts +19 -0
  59. package/dist/plugins/index.d.ts +19 -0
  60. package/dist/plugins/index.js +2 -0
  61. package/dist/plugins/index.js.map +7 -0
  62. package/dist/plugins/persistence/persistence.d.cts +16 -0
  63. package/dist/plugins/persistence/persistence.d.ts +16 -0
  64. package/dist/plugins/persistence/persistence.helpers.d.cts +34 -0
  65. package/dist/plugins/persistence/persistence.helpers.d.ts +34 -0
  66. package/dist/plugins/persistence/persistence.types.d.cts +63 -0
  67. package/dist/plugins/persistence/persistence.types.d.ts +63 -0
  68. package/dist/plugins/replay/replay.d.cts +7 -0
  69. package/dist/plugins/replay/replay.d.ts +7 -0
  70. package/dist/plugins/replay/replay.helpers.d.cts +22 -0
  71. package/dist/plugins/replay/replay.helpers.d.ts +22 -0
  72. package/dist/plugins/replay/replay.types.d.cts +28 -0
  73. package/dist/plugins/replay/replay.types.d.ts +28 -0
  74. package/package.json +61 -80
  75. package/dist/journey-builder/index.d.cts +0 -5
  76. package/dist/journey-builder/index.d.ts +0 -5
  77. package/dist/journey-builder/types.d.cts +0 -126
  78. package/dist/journey-builder/types.d.ts +0 -126
  79. package/dist/journey-machine/async-state.d.cts +0 -12
  80. package/dist/journey-machine/async-state.d.ts +0 -12
  81. package/dist/journey-machine/computed.d.cts +0 -2
  82. package/dist/journey-machine/computed.d.ts +0 -2
  83. package/dist/journey-machine/controls.d.cts +0 -17
  84. package/dist/journey-machine/controls.d.ts +0 -17
  85. package/dist/journey-machine/helpers.d.cts +0 -52
  86. package/dist/journey-machine/helpers.d.ts +0 -52
  87. package/dist/journey-machine/index.d.cts +0 -3
  88. package/dist/journey-machine/index.d.ts +0 -3
  89. package/dist/journey-machine/navigation.d.cts +0 -32
  90. package/dist/journey-machine/navigation.d.ts +0 -32
  91. package/dist/journey-machine/plugin-controller.d.cts +0 -15
  92. package/dist/journey-machine/plugin-controller.d.ts +0 -15
  93. package/dist/journey-machine/resolve-journey-definition.d.cts +0 -2
  94. package/dist/journey-machine/resolve-journey-definition.d.ts +0 -2
  95. package/dist/journey-machine/runtime.d.cts +0 -33
  96. package/dist/journey-machine/runtime.d.ts +0 -33
  97. package/dist/journey-machine/send.d.cts +0 -9
  98. package/dist/journey-machine/send.d.ts +0 -9
  99. package/dist/plugins/analytics/index.cjs +0 -2
  100. package/dist/plugins/analytics/index.cjs.map +0 -7
  101. package/dist/plugins/analytics/index.d.cts +0 -25
  102. package/dist/plugins/analytics/index.d.ts +0 -25
  103. package/dist/plugins/analytics/index.js +0 -2
  104. package/dist/plugins/analytics/index.js.map +0 -7
  105. package/dist/plugins/autosave/index.cjs +0 -2
  106. package/dist/plugins/autosave/index.cjs.map +0 -7
  107. package/dist/plugins/autosave/index.d.cts +0 -17
  108. package/dist/plugins/autosave/index.d.ts +0 -17
  109. package/dist/plugins/autosave/index.js +0 -2
  110. package/dist/plugins/autosave/index.js.map +0 -7
  111. package/dist/plugins/diagnostics/diagnostics.d.cts +0 -3
  112. package/dist/plugins/diagnostics/diagnostics.d.ts +0 -3
  113. package/dist/plugins/diagnostics/index.cjs +0 -2
  114. package/dist/plugins/diagnostics/index.cjs.map +0 -7
  115. package/dist/plugins/diagnostics/index.d.cts +0 -15
  116. package/dist/plugins/diagnostics/index.d.ts +0 -15
  117. package/dist/plugins/diagnostics/index.js +0 -2
  118. package/dist/plugins/diagnostics/index.js.map +0 -7
  119. package/dist/plugins/execution-paths/index.cjs +0 -2
  120. package/dist/plugins/execution-paths/index.cjs.map +0 -7
  121. package/dist/plugins/execution-paths/index.d.cts +0 -18
  122. package/dist/plugins/execution-paths/index.d.ts +0 -18
  123. package/dist/plugins/execution-paths/index.js +0 -2
  124. package/dist/plugins/execution-paths/index.js.map +0 -7
  125. package/dist/plugins/persistence/controller.d.cts +0 -17
  126. package/dist/plugins/persistence/controller.d.ts +0 -17
  127. package/dist/plugins/persistence/index.cjs +0 -2
  128. package/dist/plugins/persistence/index.cjs.map +0 -7
  129. package/dist/plugins/persistence/index.d.cts +0 -12
  130. package/dist/plugins/persistence/index.d.ts +0 -12
  131. package/dist/plugins/persistence/index.js +0 -2
  132. package/dist/plugins/persistence/index.js.map +0 -7
  133. package/dist/plugins/replay/index.cjs +0 -2
  134. package/dist/plugins/replay/index.cjs.map +0 -7
  135. package/dist/plugins/replay/index.d.cts +0 -27
  136. package/dist/plugins/replay/index.d.ts +0 -27
  137. package/dist/plugins/replay/index.js +0 -2
  138. package/dist/plugins/replay/index.js.map +0 -7
  139. package/dist/types/analytics.types.d.cts +0 -33
  140. package/dist/types/analytics.types.d.ts +0 -33
  141. package/dist/types/autosave.types.d.cts +0 -23
  142. package/dist/types/autosave.types.d.ts +0 -23
  143. package/dist/types/diagnostics.types.d.cts +0 -38
  144. package/dist/types/diagnostics.types.d.ts +0 -38
  145. package/dist/types/index.d.cts +0 -9
  146. package/dist/types/index.d.ts +0 -9
  147. package/dist/types/journey.types.d.cts +0 -191
  148. package/dist/types/journey.types.d.ts +0 -191
  149. package/dist/types/machine.types.d.cts +0 -104
  150. package/dist/types/machine.types.d.ts +0 -104
  151. package/dist/types/observation.types.d.cts +0 -83
  152. package/dist/types/observation.types.d.ts +0 -83
  153. package/dist/types/persistence.types.d.cts +0 -34
  154. package/dist/types/persistence.types.d.ts +0 -34
  155. package/dist/types/replay.types.d.cts +0 -35
  156. package/dist/types/replay.types.d.ts +0 -35
  157. package/dist/types/transitions.types.d.cts +0 -122
  158. package/dist/types/transitions.types.d.ts +0 -122
@@ -0,0 +1,91 @@
1
+ import type { GraphOnEntry, GraphStepConfig } from "./graph.types.js";
2
+ import type { JourneyEventObject } from "../core/types.js";
3
+ /**
4
+ * One declaration point for a journey's types.
5
+ *
6
+ * Two things need it. Steps authored in separate files have to name the shape
7
+ * they satisfy, and `withTypes` needs somewhere to pin types that the
8
+ * definition cannot infer on its own. Everything except `context`, `stepId`
9
+ * and `events` is optional and falls back.
10
+ */
11
+ export type Bag = {
12
+ context: unknown;
13
+ stepId: string;
14
+ events: JourneyEventObject;
15
+ meta?: unknown;
16
+ handlers?: unknown;
17
+ /**
18
+ * Result type per event name, for events declaring `run`.
19
+ *
20
+ * Load-bearing rather than a convenience: a declared `run` sits at a property
21
+ * position, which is not an inference site, so `commit`'s `result` is
22
+ * `unknown` unless it is pinned here. One result type per event name — not
23
+ * per (step, event) pair.
24
+ */
25
+ results?: Record<string, unknown>;
26
+ };
27
+ /**
28
+ * `meta`, `handlers` and `results` are optional on the bag, so these must infer
29
+ * from an optional property. Matching `{ meta: infer T }` — a *required*
30
+ * property — silently skipped anyone who mirrored the constraint and wrote
31
+ * `meta?: MyMeta`: they got the fallback instead of their own type, and the
32
+ * eventual error pointed nowhere near the bag declaration. `NonNullable` strips
33
+ * the `undefined` that optionality adds.
34
+ */
35
+ export type MetaOf<TBag extends Bag> = TBag extends {
36
+ meta?: infer TMeta;
37
+ } ? [TMeta] extends [undefined] ? Record<string, unknown> : NonNullable<TMeta> : Record<string, unknown>;
38
+ export type HandlersOf<TBag extends Bag> = TBag extends {
39
+ handlers?: infer THandlers;
40
+ } ? [THandlers] extends [undefined] ? Record<string, never> : NonNullable<THandlers> : Record<string, never>;
41
+ export type ResultsOf<TBag extends Bag> = TBag extends {
42
+ results?: infer TResults;
43
+ } ? [TResults] extends [undefined] ? Record<string, never> : NonNullable<TResults> : Record<string, never>;
44
+ /**
45
+ * The declared result for one event, or `unknown` when the bag pins none.
46
+ *
47
+ * The empty-default check comes first and is load-bearing: `ResultsOf` falls
48
+ * back to `Record<string, never>`, whose `keyof` is `string`, so without it
49
+ * every event name "matches" and resolves to `never` — which rejects every
50
+ * `run` rather than accepting any.
51
+ */
52
+ export type ResultOf<TBag extends Bag, TType extends string> = [ResultsOf<TBag>] extends [
53
+ Record<string, never>
54
+ ] ? unknown : TType extends keyof ResultsOf<TBag> ? ResultsOf<TBag>[TType] : unknown;
55
+ /**
56
+ * One step's config for a pinned bag — what a step authored in its own file
57
+ * annotates itself with.
58
+ *
59
+ * ```ts
60
+ * export const loginStep: GraphStep<AuthBag> = {
61
+ * metadata: { label: "Login" },
62
+ * on: { submit: "twofa" }
63
+ * };
64
+ * ```
65
+ */
66
+ export type GraphStep<TBag extends Bag> = Omit<GraphStepConfig<TBag["context"], TBag["stepId"], TBag["events"], MetaOf<TBag>, HandlersOf<TBag>>, "on"> & {
67
+ readonly on?: {
68
+ readonly [TType in TBag["events"]["type"]]?: GraphOnEntry<TBag["context"], TBag["stepId"], TBag["events"], HandlersOf<TBag>, MetaOf<TBag>, ResultOf<TBag, TType>, Extract<TBag["events"], {
69
+ type: TType;
70
+ }>>;
71
+ };
72
+ };
73
+ /**
74
+ * A whole graph definition for a pinned bag, for the case `withTypes` cannot
75
+ * express: a standalone definition passed to the factory more than once, with
76
+ * different options each time.
77
+ *
78
+ * ```ts
79
+ * export const definition = {
80
+ * initial: "login",
81
+ * context: initialContext,
82
+ * steps: { login: { on: { submit: "twofa" } }, twofa: {} }
83
+ * } satisfies GraphDefinition<AuthBag>;
84
+ * ```
85
+ */
86
+ export type GraphDefinition<TBag extends Bag> = {
87
+ readonly initial: TBag["stepId"];
88
+ readonly context: TBag["context"];
89
+ readonly handlers?: HandlersOf<TBag>;
90
+ readonly steps: Readonly<Record<TBag["stepId"], GraphStep<TBag>>>;
91
+ };
@@ -0,0 +1,63 @@
1
+ import type { RuntimeStep, RuntimeTransition } from "../core/runtime.types.js";
2
+ import type { GraphJourneyMachine, GraphJourneyOptions, GraphStepConfig, LooseGraphDefinition } from "./graph.types.js";
3
+ import type { AnySendWork } from "../core/runtime.types.js";
4
+ import type { Bag, GraphDefinition, HandlersOf, MetaOf } from "./bag.types.js";
5
+ import type { AnyJourneyPlugin, CompletePayloadOf, JourneyEventObject, JourneyTerminationPayloads, TerminatePayloadOf } from "../core/types.js";
6
+ /**
7
+ * Flattens each step's colocated `on` into the runtime's flat transition list,
8
+ * in declaration order, and validates every target.
9
+ *
10
+ * Order is per step, then per event, then per candidate. That differs from the
11
+ * old central map's global per-event order, but only for the same event
12
+ * declared from two steps — and candidates are filtered by `from` before order
13
+ * is consulted, so the selected edge is unchanged. `first-enabled-in-declared-
14
+ * order` is asserted directly in graph.test.ts.
15
+ *
16
+ * `from` cannot dangle here: it is the key of the step that declares the entry.
17
+ */
18
+ export declare function normalizeGraphDefinition(definition: LooseGraphDefinition): {
19
+ stepIds: string[];
20
+ steps: Record<string, RuntimeStep>;
21
+ transitions: RuntimeTransition[];
22
+ eventWork: Record<string, AnySendWork>;
23
+ };
24
+ /**
25
+ * Creates a graph journey runtime from a pure-data definition.
26
+ *
27
+ * `send(event, payload?)` is the primary verb; `goToStepById` is
28
+ * transition-gated sugar (fires only if an enabled transition targets that
29
+ * id). Timeline moves bypass transition gating — retracing a walked path is
30
+ * always legal. Step `onLeave` effects still run after those moves commit.
31
+ */
32
+ export declare function createGraphJourney<TContext, TStepId extends string, TEvents extends JourneyEventObject = JourneyEventObject, THandlers = unknown, TMeta = Record<string, unknown>, const TPlugins extends readonly AnyJourneyPlugin[] = readonly [], TTerminationPayloads extends JourneyTerminationPayloads = JourneyTerminationPayloads>(definition: {
33
+ readonly steps: Readonly<Record<TStepId, GraphStepConfig<NoInfer<TContext>, NoInfer<TStepId>, NoInfer<TEvents>, TMeta, NoInfer<THandlers>>>>;
34
+ readonly initial: NoInfer<TStepId>;
35
+ readonly context: TContext;
36
+ readonly handlers?: THandlers;
37
+ /** @internal Builder-produced; opaque by design (see GraphJourneyDefinition). */
38
+ readonly eventWork?: Readonly<Record<string, unknown>>;
39
+ readonly $events?: TEvents;
40
+ readonly $payloads?: TTerminationPayloads;
41
+ }, options?: GraphJourneyOptions<NoInfer<THandlers>, TPlugins, NoInfer<TStepId>>): GraphJourneyMachine<TContext, TStepId, TEvents, TMeta, TPlugins, CompletePayloadOf<TTerminationPayloads>, TerminatePayloadOf<TTerminationPayloads>>;
42
+ /**
43
+ * Creates a graph journey factory with its types pinned up front instead of
44
+ * inferred.
45
+ *
46
+ * Reach for it when the definition cannot supply a type on its own —
47
+ * `handlers`, a `meta` shape, or a `run` result, none of which sit at an
48
+ * inference site — or when the same bag is shared by steps authored in
49
+ * separate files. The definition is then *checked* against the bag rather than
50
+ * read for types.
51
+ *
52
+ * ```ts
53
+ * const login = withGraphTypes<AuthBag>()({
54
+ * initial: "login",
55
+ * context: initialContext,
56
+ * steps: { login: { on: { submit: "twofa" } }, twofa: {} }
57
+ * });
58
+ * ```
59
+ *
60
+ * Plain `createGraphJourney(definition)` stays the default: step ids infer from
61
+ * the `steps` keys and event names from the `on` keys.
62
+ */
63
+ export declare const withGraphTypes: <TBag extends Bag>() => <const TPlugins extends readonly AnyJourneyPlugin[] = readonly []>(definition: GraphDefinition<TBag>, options?: GraphJourneyOptions<HandlersOf<TBag>, TPlugins, TBag["stepId"]>) => GraphJourneyMachine<TBag["context"], TBag["stepId"], TBag["events"], MetaOf<TBag>, TPlugins>;
@@ -0,0 +1,63 @@
1
+ import type { RuntimeStep, RuntimeTransition } from "../core/runtime.types.js";
2
+ import type { GraphJourneyMachine, GraphJourneyOptions, GraphStepConfig, LooseGraphDefinition } from "./graph.types.js";
3
+ import type { AnySendWork } from "../core/runtime.types.js";
4
+ import type { Bag, GraphDefinition, HandlersOf, MetaOf } from "./bag.types.js";
5
+ import type { AnyJourneyPlugin, CompletePayloadOf, JourneyEventObject, JourneyTerminationPayloads, TerminatePayloadOf } from "../core/types.js";
6
+ /**
7
+ * Flattens each step's colocated `on` into the runtime's flat transition list,
8
+ * in declaration order, and validates every target.
9
+ *
10
+ * Order is per step, then per event, then per candidate. That differs from the
11
+ * old central map's global per-event order, but only for the same event
12
+ * declared from two steps — and candidates are filtered by `from` before order
13
+ * is consulted, so the selected edge is unchanged. `first-enabled-in-declared-
14
+ * order` is asserted directly in graph.test.ts.
15
+ *
16
+ * `from` cannot dangle here: it is the key of the step that declares the entry.
17
+ */
18
+ export declare function normalizeGraphDefinition(definition: LooseGraphDefinition): {
19
+ stepIds: string[];
20
+ steps: Record<string, RuntimeStep>;
21
+ transitions: RuntimeTransition[];
22
+ eventWork: Record<string, AnySendWork>;
23
+ };
24
+ /**
25
+ * Creates a graph journey runtime from a pure-data definition.
26
+ *
27
+ * `send(event, payload?)` is the primary verb; `goToStepById` is
28
+ * transition-gated sugar (fires only if an enabled transition targets that
29
+ * id). Timeline moves bypass transition gating — retracing a walked path is
30
+ * always legal. Step `onLeave` effects still run after those moves commit.
31
+ */
32
+ export declare function createGraphJourney<TContext, TStepId extends string, TEvents extends JourneyEventObject = JourneyEventObject, THandlers = unknown, TMeta = Record<string, unknown>, const TPlugins extends readonly AnyJourneyPlugin[] = readonly [], TTerminationPayloads extends JourneyTerminationPayloads = JourneyTerminationPayloads>(definition: {
33
+ readonly steps: Readonly<Record<TStepId, GraphStepConfig<NoInfer<TContext>, NoInfer<TStepId>, NoInfer<TEvents>, TMeta, NoInfer<THandlers>>>>;
34
+ readonly initial: NoInfer<TStepId>;
35
+ readonly context: TContext;
36
+ readonly handlers?: THandlers;
37
+ /** @internal Builder-produced; opaque by design (see GraphJourneyDefinition). */
38
+ readonly eventWork?: Readonly<Record<string, unknown>>;
39
+ readonly $events?: TEvents;
40
+ readonly $payloads?: TTerminationPayloads;
41
+ }, options?: GraphJourneyOptions<NoInfer<THandlers>, TPlugins, NoInfer<TStepId>>): GraphJourneyMachine<TContext, TStepId, TEvents, TMeta, TPlugins, CompletePayloadOf<TTerminationPayloads>, TerminatePayloadOf<TTerminationPayloads>>;
42
+ /**
43
+ * Creates a graph journey factory with its types pinned up front instead of
44
+ * inferred.
45
+ *
46
+ * Reach for it when the definition cannot supply a type on its own —
47
+ * `handlers`, a `meta` shape, or a `run` result, none of which sit at an
48
+ * inference site — or when the same bag is shared by steps authored in
49
+ * separate files. The definition is then *checked* against the bag rather than
50
+ * read for types.
51
+ *
52
+ * ```ts
53
+ * const login = withGraphTypes<AuthBag>()({
54
+ * initial: "login",
55
+ * context: initialContext,
56
+ * steps: { login: { on: { submit: "twofa" } }, twofa: {} }
57
+ * });
58
+ * ```
59
+ *
60
+ * Plain `createGraphJourney(definition)` stays the default: step ids infer from
61
+ * the `steps` keys and event names from the `on` keys.
62
+ */
63
+ export declare const withGraphTypes: <TBag extends Bag>() => <const TPlugins extends readonly AnyJourneyPlugin[] = readonly []>(definition: GraphDefinition<TBag>, options?: GraphJourneyOptions<HandlersOf<TBag>, TPlugins, TBag["stepId"]>) => GraphJourneyMachine<TBag["context"], TBag["stepId"], TBag["events"], MetaOf<TBag>, TPlugins>;
@@ -0,0 +1,212 @@
1
+ import type { AnySendWork, RuntimeStep, RuntimeTransition } from "../core/runtime.types.js";
2
+ import type { AnyJourneyPlugin, ContextUpdater, GraphSnapshot, JourneyEventObject, JourneyEventPayload, JourneyMachineBase, JourneyRuntimeOptions, JourneyTerminationPayloads, NavigationResult, OnEnterHook, OnLeaveHook, PluginApis, StepHookArgs } from "../core/types.js";
3
+ /**
4
+ * Guards are sync and pure: they are evaluated during snapshot derivation to
5
+ * compute `availableEvents`/`availableSteps`, so they receive no event payload
6
+ * and cannot be async. Caller-driven async validation belongs in navigation work.
7
+ */
8
+ export type TransitionGuard<TContext, THandlers> = (args: {
9
+ readonly context: TContext;
10
+ readonly handlers: THandlers;
11
+ }) => boolean;
12
+ export type GraphHookArgs<TContext, TStepId extends string, TEvents extends JourneyEventObject, TMeta = Record<string, unknown>> = StepHookArgs<TContext, TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>>;
13
+ /** One colocated candidate; `from` is the step that declares it. */
14
+ export type GraphTransition<TContext = unknown, TStepId extends string = string, TEvents extends JourneyEventObject = JourneyEventObject, THandlers = unknown, TMeta = Record<string, unknown>, TTrigger extends JourneyEventObject = TEvents> = {
15
+ readonly to: TStepId;
16
+ readonly when?: TransitionGuard<TContext, THandlers>;
17
+ /**
18
+ * Names this edge. Several candidates on one event differ only by guard, so
19
+ * the name is what tells them apart in timeout messages, step-hook
20
+ * `transition` args, and the plugin structure view — a priority index says
21
+ * where the edge sits, not what it is.
22
+ */
23
+ readonly label?: string;
24
+ /**
25
+ * Budget for this edge's `onTransition`, overriding `defaultTimeoutMs`. One
26
+ * edge waiting on a slow third party is not a reason to widen the budget for
27
+ * every other edge in the graph.
28
+ */
29
+ readonly timeoutMs?: number;
30
+ /** Async effect, post-commit, cannot cancel; a throw is handled like an `onEnter` throw. */
31
+ readonly onTransition?: (args: Omit<GraphHookArgs<TContext, TStepId, TEvents, TMeta>, "event"> & {
32
+ readonly event: TTrigger | null;
33
+ }) => void | Promise<void>;
34
+ };
35
+ /**
36
+ * What one event maps to on a step. Three forms, discriminated at the top
37
+ * level so nothing has to sniff inside a candidate:
38
+ *
39
+ * - a step id — one unguarded candidate;
40
+ * - an array — ordered candidates, first enabled wins;
41
+ * - an object — async the machine owns, whose staged context the candidates
42
+ * are then evaluated against.
43
+ *
44
+ * A guarded lone candidate is `[{ to, when }]`: the extra brackets read
45
+ * honestly, since a guarded lone candidate means the event can fail.
46
+ */
47
+ export type GraphOnEntry<TContext = unknown, TStepId extends string = string, TEvents extends JourneyEventObject = JourneyEventObject, THandlers = unknown, TMeta = Record<string, unknown>, TResult = unknown, TTrigger extends JourneyEventObject = TEvents> = TStepId | readonly GraphTransition<TContext, TStepId, TEvents, THandlers, TMeta, TTrigger>[] | {
48
+ readonly run: (args: SendWorkArgs<TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>, THandlers>) => TResult | Promise<TResult>;
49
+ /**
50
+ * Declared as a method rather than a function-typed property on purpose.
51
+ * Method parameters are checked bivariantly, which is what lets a
52
+ * `commit` whose `result` is a concrete type sit in this slot when the
53
+ * slot's own `TResult` is the `unknown` fallback — the escape hatch the
54
+ * `work()` helper relies on to hand back an inferred config.
55
+ */
56
+ commit?(args: SendWorkArgs<TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>, THandlers> & {
57
+ readonly result: TResult;
58
+ readonly updateContext: (updater: ContextUpdater<TContext>) => void;
59
+ }): void;
60
+ /** Names this work in timeout and error messages. */
61
+ readonly label?: string;
62
+ /**
63
+ * Budget for `run`, overriding `defaultTimeoutMs`. This is the edge that
64
+ * usually needs its own: `run` is where a definition's third-party call
65
+ * lives.
66
+ */
67
+ readonly timeoutMs?: number;
68
+ readonly candidates: readonly GraphTransition<TContext, TStepId, TEvents, THandlers, TMeta, TTrigger>[];
69
+ };
70
+ export type GraphStepConfig<TContext = unknown, TStepId extends string = string, TEvents extends JourneyEventObject = JourneyEventObject, TMeta = Record<string, unknown>, THandlers = unknown> = {
71
+ readonly metadata?: TMeta;
72
+ /** Outgoing transitions, keyed by event. */
73
+ readonly on?: {
74
+ readonly [TType in TEvents["type"]]?: GraphOnEntry<TContext, TStepId, TEvents, THandlers, TMeta, unknown, Extract<TEvents, {
75
+ type: TType;
76
+ }>>;
77
+ };
78
+ readonly onEnter?: OnEnterHook<TContext, TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>>;
79
+ readonly onLeave?: OnLeaveHook<TContext, TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>>;
80
+ };
81
+ /**
82
+ * Pure-data graph definition (also what the builder's `build()` produces).
83
+ * `$events` is a phantom carrier for the declared event union — never set at
84
+ * runtime.
85
+ */
86
+ export type GraphJourneyDefinition<TContext = unknown, TStepId extends string = string, TEvents extends JourneyEventObject = JourneyEventObject, THandlers = unknown, TMeta = Record<string, unknown>, TTerminationPayloads extends JourneyTerminationPayloads = JourneyTerminationPayloads> = {
87
+ readonly steps: Readonly<Record<TStepId, GraphStepConfig<TContext, TStepId, TEvents, TMeta, THandlers>>>;
88
+ readonly initial: TStepId;
89
+ readonly context: TContext;
90
+ readonly handlers?: THandlers;
91
+ /**
92
+ * Work declared on an event, collected by `normalizeGraphDefinition`.
93
+ *
94
+ * @internal Its keys are a private encoding of the (origin step, event) pair
95
+ * and its values are internal work shapes. Typed as `unknown` on purpose so
96
+ * neither is nameable from the public surface: hand this field straight back
97
+ * to a factory, never construct or read it.
98
+ */
99
+ readonly eventWork?: Readonly<Record<string, unknown>>;
100
+ /**
101
+ * Phantom type carrier — never read at runtime. Names the event union, which
102
+ * the definition's other fields cannot infer on their own.
103
+ */
104
+ readonly $events?: TEvents;
105
+ /**
106
+ * Phantom type carrier — never read at runtime. Names the completion and
107
+ * termination payload types, so `controls.complete`/`terminate` and
108
+ * `snapshot.machine.outcome` are typed instead of `unknown`.
109
+ */
110
+ readonly $payloads?: TTerminationPayloads;
111
+ };
112
+ export type GraphJourneyOptions<THandlers = unknown, TPlugins extends readonly AnyJourneyPlugin[] = readonly [], TStepId extends string = string> = JourneyRuntimeOptions<TPlugins, TStepId> & {
113
+ /** Overrides the definition's handlers — one definition serves app and tests. */
114
+ handlers?: THandlers;
115
+ };
116
+ export type SendArgs<TEvents extends JourneyEventObject, TType extends TEvents["type"]> = JourneyEventPayload<TEvents, TType> extends undefined ? [] : [payload: JourneyEventPayload<TEvents, TType>];
117
+ /**
118
+ * Arguments for work attached to a `send`.
119
+ *
120
+ * There is no `to`: the work runs *before* routing, so no target has been
121
+ * chosen yet. `handlers` is threaded through because this is the async that a
122
+ * definition owns, and injected clients reach it no other way — step hooks
123
+ * deliberately do not receive handlers.
124
+ */
125
+ export type SendWorkArgs<TStepId extends string, TEvents extends JourneyEventObject, TSnap, THandlers> = {
126
+ readonly snapshot: TSnap;
127
+ readonly from: TStepId;
128
+ readonly event: TEvents;
129
+ readonly handlers: THandlers;
130
+ };
131
+ /**
132
+ * Async attached to an event, run before the guards choose an edge.
133
+ *
134
+ * `run` is awaited while the machine holds its position. `commit` then stages
135
+ * context synchronously, and the guards are evaluated against that staged
136
+ * context — so the work supplies the facts routing is decided from without
137
+ * guards ever becoming async. If `run` throws, or no candidate is enabled once
138
+ * the context is staged, nothing commits and the machine stays put.
139
+ */
140
+ export type SendWork<TContext, TStepId extends string, TEvents extends JourneyEventObject, TSnap, THandlers = unknown, TResult = void> = {
141
+ readonly run: (args: SendWorkArgs<TStepId, TEvents, TSnap, THandlers>) => TResult | Promise<TResult>;
142
+ readonly commit?: (args: SendWorkArgs<TStepId, TEvents, TSnap, THandlers> & {
143
+ readonly result: TResult;
144
+ readonly updateContext: (updater: ContextUpdater<TContext>) => void;
145
+ }) => void;
146
+ };
147
+ /**
148
+ * Declared events get exact payload tuples; undeclared events fall back to
149
+ * `(type, payload?)`.
150
+ *
151
+ * `send` takes no work: async that decides an event's outcome is declared on
152
+ * the step, which is the graph's one channel for it.
153
+ */
154
+ export type SendVerb<TStepId extends string, TEvents extends JourneyEventObject> = JourneyEventObject extends TEvents ? (type: string, payload?: unknown) => Promise<NavigationResult<TStepId>> : <TType extends TEvents["type"]>(type: TType, ...payload: SendArgs<TEvents, TType>) => Promise<NavigationResult<TStepId>>;
155
+ export type GraphJourneyMachine<TContext, TStepId extends string, TEvents extends JourneyEventObject = JourneyEventObject, TMeta = Record<string, unknown>, TPlugins extends readonly AnyJourneyPlugin[] = readonly [], TCompletePayload = unknown, TTerminatePayload = unknown> = JourneyMachineBase<TContext, TStepId, GraphSnapshot<TContext, TStepId, TMeta, TEvents, TCompletePayload, TTerminatePayload>, TCompletePayload, TTerminatePayload> & {
156
+ /**
157
+ * The graph's primary verb — its presence is itself the machine-type
158
+ * discriminant (linear has no events).
159
+ */
160
+ send: SendVerb<TStepId, TEvents>;
161
+ readonly plugins: PluginApis<TPlugins>;
162
+ };
163
+ /**
164
+ * Internal, generics-erased view of one colocated `on` entry. The three forms
165
+ * are discriminated structurally at the top level — string, array, object —
166
+ * so normalization never has to sniff inside a candidate.
167
+ */
168
+ export type LooseOnEntry = string | readonly LooseTransition[] | {
169
+ readonly run: AnySendWork["run"];
170
+ readonly commit?: AnySendWork["commit"];
171
+ readonly label?: string;
172
+ readonly timeoutMs?: number;
173
+ readonly candidates: readonly LooseTransition[];
174
+ };
175
+ /** A colocated candidate: `from` is the step that declares it. */
176
+ export type LooseTransition = {
177
+ readonly to: string;
178
+ readonly when?: NonNullable<RuntimeTransition["when"]>;
179
+ readonly onTransition?: NonNullable<RuntimeTransition["onTransition"]>;
180
+ readonly label?: string;
181
+ readonly timeoutMs?: number;
182
+ };
183
+ /** Internal, generics-erased view of a definition used by normalization. */
184
+ export type LooseGraphDefinition = {
185
+ readonly steps: Readonly<Record<string, GraphStepConfig & {
186
+ readonly on?: Readonly<Record<string, LooseOnEntry>>;
187
+ }>>;
188
+ readonly initial: string;
189
+ readonly context: unknown;
190
+ readonly handlers?: unknown;
191
+ };
192
+ export type MutableRuntimeStep = {
193
+ metadata: unknown;
194
+ onEnter?: NonNullable<RuntimeStep["onEnter"]>;
195
+ onLeave?: NonNullable<RuntimeStep["onLeave"]>;
196
+ };
197
+ export type MutableSendWork = {
198
+ run: AnySendWork["run"];
199
+ commit?: NonNullable<AnySendWork["commit"]>;
200
+ label?: string;
201
+ timeoutMs?: number;
202
+ };
203
+ export type MutableRuntimeTransition = {
204
+ event: string;
205
+ from: string;
206
+ to: string;
207
+ index: number;
208
+ label?: string;
209
+ timeoutMs?: number;
210
+ when?: NonNullable<RuntimeTransition["when"]>;
211
+ onTransition?: NonNullable<RuntimeTransition["onTransition"]>;
212
+ };
@@ -0,0 +1,212 @@
1
+ import type { AnySendWork, RuntimeStep, RuntimeTransition } from "../core/runtime.types.js";
2
+ import type { AnyJourneyPlugin, ContextUpdater, GraphSnapshot, JourneyEventObject, JourneyEventPayload, JourneyMachineBase, JourneyRuntimeOptions, JourneyTerminationPayloads, NavigationResult, OnEnterHook, OnLeaveHook, PluginApis, StepHookArgs } from "../core/types.js";
3
+ /**
4
+ * Guards are sync and pure: they are evaluated during snapshot derivation to
5
+ * compute `availableEvents`/`availableSteps`, so they receive no event payload
6
+ * and cannot be async. Caller-driven async validation belongs in navigation work.
7
+ */
8
+ export type TransitionGuard<TContext, THandlers> = (args: {
9
+ readonly context: TContext;
10
+ readonly handlers: THandlers;
11
+ }) => boolean;
12
+ export type GraphHookArgs<TContext, TStepId extends string, TEvents extends JourneyEventObject, TMeta = Record<string, unknown>> = StepHookArgs<TContext, TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>>;
13
+ /** One colocated candidate; `from` is the step that declares it. */
14
+ export type GraphTransition<TContext = unknown, TStepId extends string = string, TEvents extends JourneyEventObject = JourneyEventObject, THandlers = unknown, TMeta = Record<string, unknown>, TTrigger extends JourneyEventObject = TEvents> = {
15
+ readonly to: TStepId;
16
+ readonly when?: TransitionGuard<TContext, THandlers>;
17
+ /**
18
+ * Names this edge. Several candidates on one event differ only by guard, so
19
+ * the name is what tells them apart in timeout messages, step-hook
20
+ * `transition` args, and the plugin structure view — a priority index says
21
+ * where the edge sits, not what it is.
22
+ */
23
+ readonly label?: string;
24
+ /**
25
+ * Budget for this edge's `onTransition`, overriding `defaultTimeoutMs`. One
26
+ * edge waiting on a slow third party is not a reason to widen the budget for
27
+ * every other edge in the graph.
28
+ */
29
+ readonly timeoutMs?: number;
30
+ /** Async effect, post-commit, cannot cancel; a throw is handled like an `onEnter` throw. */
31
+ readonly onTransition?: (args: Omit<GraphHookArgs<TContext, TStepId, TEvents, TMeta>, "event"> & {
32
+ readonly event: TTrigger | null;
33
+ }) => void | Promise<void>;
34
+ };
35
+ /**
36
+ * What one event maps to on a step. Three forms, discriminated at the top
37
+ * level so nothing has to sniff inside a candidate:
38
+ *
39
+ * - a step id — one unguarded candidate;
40
+ * - an array — ordered candidates, first enabled wins;
41
+ * - an object — async the machine owns, whose staged context the candidates
42
+ * are then evaluated against.
43
+ *
44
+ * A guarded lone candidate is `[{ to, when }]`: the extra brackets read
45
+ * honestly, since a guarded lone candidate means the event can fail.
46
+ */
47
+ export type GraphOnEntry<TContext = unknown, TStepId extends string = string, TEvents extends JourneyEventObject = JourneyEventObject, THandlers = unknown, TMeta = Record<string, unknown>, TResult = unknown, TTrigger extends JourneyEventObject = TEvents> = TStepId | readonly GraphTransition<TContext, TStepId, TEvents, THandlers, TMeta, TTrigger>[] | {
48
+ readonly run: (args: SendWorkArgs<TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>, THandlers>) => TResult | Promise<TResult>;
49
+ /**
50
+ * Declared as a method rather than a function-typed property on purpose.
51
+ * Method parameters are checked bivariantly, which is what lets a
52
+ * `commit` whose `result` is a concrete type sit in this slot when the
53
+ * slot's own `TResult` is the `unknown` fallback — the escape hatch the
54
+ * `work()` helper relies on to hand back an inferred config.
55
+ */
56
+ commit?(args: SendWorkArgs<TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>, THandlers> & {
57
+ readonly result: TResult;
58
+ readonly updateContext: (updater: ContextUpdater<TContext>) => void;
59
+ }): void;
60
+ /** Names this work in timeout and error messages. */
61
+ readonly label?: string;
62
+ /**
63
+ * Budget for `run`, overriding `defaultTimeoutMs`. This is the edge that
64
+ * usually needs its own: `run` is where a definition's third-party call
65
+ * lives.
66
+ */
67
+ readonly timeoutMs?: number;
68
+ readonly candidates: readonly GraphTransition<TContext, TStepId, TEvents, THandlers, TMeta, TTrigger>[];
69
+ };
70
+ export type GraphStepConfig<TContext = unknown, TStepId extends string = string, TEvents extends JourneyEventObject = JourneyEventObject, TMeta = Record<string, unknown>, THandlers = unknown> = {
71
+ readonly metadata?: TMeta;
72
+ /** Outgoing transitions, keyed by event. */
73
+ readonly on?: {
74
+ readonly [TType in TEvents["type"]]?: GraphOnEntry<TContext, TStepId, TEvents, THandlers, TMeta, unknown, Extract<TEvents, {
75
+ type: TType;
76
+ }>>;
77
+ };
78
+ readonly onEnter?: OnEnterHook<TContext, TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>>;
79
+ readonly onLeave?: OnLeaveHook<TContext, TStepId, TEvents, GraphSnapshot<TContext, TStepId, TMeta, TEvents>>;
80
+ };
81
+ /**
82
+ * Pure-data graph definition (also what the builder's `build()` produces).
83
+ * `$events` is a phantom carrier for the declared event union — never set at
84
+ * runtime.
85
+ */
86
+ export type GraphJourneyDefinition<TContext = unknown, TStepId extends string = string, TEvents extends JourneyEventObject = JourneyEventObject, THandlers = unknown, TMeta = Record<string, unknown>, TTerminationPayloads extends JourneyTerminationPayloads = JourneyTerminationPayloads> = {
87
+ readonly steps: Readonly<Record<TStepId, GraphStepConfig<TContext, TStepId, TEvents, TMeta, THandlers>>>;
88
+ readonly initial: TStepId;
89
+ readonly context: TContext;
90
+ readonly handlers?: THandlers;
91
+ /**
92
+ * Work declared on an event, collected by `normalizeGraphDefinition`.
93
+ *
94
+ * @internal Its keys are a private encoding of the (origin step, event) pair
95
+ * and its values are internal work shapes. Typed as `unknown` on purpose so
96
+ * neither is nameable from the public surface: hand this field straight back
97
+ * to a factory, never construct or read it.
98
+ */
99
+ readonly eventWork?: Readonly<Record<string, unknown>>;
100
+ /**
101
+ * Phantom type carrier — never read at runtime. Names the event union, which
102
+ * the definition's other fields cannot infer on their own.
103
+ */
104
+ readonly $events?: TEvents;
105
+ /**
106
+ * Phantom type carrier — never read at runtime. Names the completion and
107
+ * termination payload types, so `controls.complete`/`terminate` and
108
+ * `snapshot.machine.outcome` are typed instead of `unknown`.
109
+ */
110
+ readonly $payloads?: TTerminationPayloads;
111
+ };
112
+ export type GraphJourneyOptions<THandlers = unknown, TPlugins extends readonly AnyJourneyPlugin[] = readonly [], TStepId extends string = string> = JourneyRuntimeOptions<TPlugins, TStepId> & {
113
+ /** Overrides the definition's handlers — one definition serves app and tests. */
114
+ handlers?: THandlers;
115
+ };
116
+ export type SendArgs<TEvents extends JourneyEventObject, TType extends TEvents["type"]> = JourneyEventPayload<TEvents, TType> extends undefined ? [] : [payload: JourneyEventPayload<TEvents, TType>];
117
+ /**
118
+ * Arguments for work attached to a `send`.
119
+ *
120
+ * There is no `to`: the work runs *before* routing, so no target has been
121
+ * chosen yet. `handlers` is threaded through because this is the async that a
122
+ * definition owns, and injected clients reach it no other way — step hooks
123
+ * deliberately do not receive handlers.
124
+ */
125
+ export type SendWorkArgs<TStepId extends string, TEvents extends JourneyEventObject, TSnap, THandlers> = {
126
+ readonly snapshot: TSnap;
127
+ readonly from: TStepId;
128
+ readonly event: TEvents;
129
+ readonly handlers: THandlers;
130
+ };
131
+ /**
132
+ * Async attached to an event, run before the guards choose an edge.
133
+ *
134
+ * `run` is awaited while the machine holds its position. `commit` then stages
135
+ * context synchronously, and the guards are evaluated against that staged
136
+ * context — so the work supplies the facts routing is decided from without
137
+ * guards ever becoming async. If `run` throws, or no candidate is enabled once
138
+ * the context is staged, nothing commits and the machine stays put.
139
+ */
140
+ export type SendWork<TContext, TStepId extends string, TEvents extends JourneyEventObject, TSnap, THandlers = unknown, TResult = void> = {
141
+ readonly run: (args: SendWorkArgs<TStepId, TEvents, TSnap, THandlers>) => TResult | Promise<TResult>;
142
+ readonly commit?: (args: SendWorkArgs<TStepId, TEvents, TSnap, THandlers> & {
143
+ readonly result: TResult;
144
+ readonly updateContext: (updater: ContextUpdater<TContext>) => void;
145
+ }) => void;
146
+ };
147
+ /**
148
+ * Declared events get exact payload tuples; undeclared events fall back to
149
+ * `(type, payload?)`.
150
+ *
151
+ * `send` takes no work: async that decides an event's outcome is declared on
152
+ * the step, which is the graph's one channel for it.
153
+ */
154
+ export type SendVerb<TStepId extends string, TEvents extends JourneyEventObject> = JourneyEventObject extends TEvents ? (type: string, payload?: unknown) => Promise<NavigationResult<TStepId>> : <TType extends TEvents["type"]>(type: TType, ...payload: SendArgs<TEvents, TType>) => Promise<NavigationResult<TStepId>>;
155
+ export type GraphJourneyMachine<TContext, TStepId extends string, TEvents extends JourneyEventObject = JourneyEventObject, TMeta = Record<string, unknown>, TPlugins extends readonly AnyJourneyPlugin[] = readonly [], TCompletePayload = unknown, TTerminatePayload = unknown> = JourneyMachineBase<TContext, TStepId, GraphSnapshot<TContext, TStepId, TMeta, TEvents, TCompletePayload, TTerminatePayload>, TCompletePayload, TTerminatePayload> & {
156
+ /**
157
+ * The graph's primary verb — its presence is itself the machine-type
158
+ * discriminant (linear has no events).
159
+ */
160
+ send: SendVerb<TStepId, TEvents>;
161
+ readonly plugins: PluginApis<TPlugins>;
162
+ };
163
+ /**
164
+ * Internal, generics-erased view of one colocated `on` entry. The three forms
165
+ * are discriminated structurally at the top level — string, array, object —
166
+ * so normalization never has to sniff inside a candidate.
167
+ */
168
+ export type LooseOnEntry = string | readonly LooseTransition[] | {
169
+ readonly run: AnySendWork["run"];
170
+ readonly commit?: AnySendWork["commit"];
171
+ readonly label?: string;
172
+ readonly timeoutMs?: number;
173
+ readonly candidates: readonly LooseTransition[];
174
+ };
175
+ /** A colocated candidate: `from` is the step that declares it. */
176
+ export type LooseTransition = {
177
+ readonly to: string;
178
+ readonly when?: NonNullable<RuntimeTransition["when"]>;
179
+ readonly onTransition?: NonNullable<RuntimeTransition["onTransition"]>;
180
+ readonly label?: string;
181
+ readonly timeoutMs?: number;
182
+ };
183
+ /** Internal, generics-erased view of a definition used by normalization. */
184
+ export type LooseGraphDefinition = {
185
+ readonly steps: Readonly<Record<string, GraphStepConfig & {
186
+ readonly on?: Readonly<Record<string, LooseOnEntry>>;
187
+ }>>;
188
+ readonly initial: string;
189
+ readonly context: unknown;
190
+ readonly handlers?: unknown;
191
+ };
192
+ export type MutableRuntimeStep = {
193
+ metadata: unknown;
194
+ onEnter?: NonNullable<RuntimeStep["onEnter"]>;
195
+ onLeave?: NonNullable<RuntimeStep["onLeave"]>;
196
+ };
197
+ export type MutableSendWork = {
198
+ run: AnySendWork["run"];
199
+ commit?: NonNullable<AnySendWork["commit"]>;
200
+ label?: string;
201
+ timeoutMs?: number;
202
+ };
203
+ export type MutableRuntimeTransition = {
204
+ event: string;
205
+ from: string;
206
+ to: string;
207
+ index: number;
208
+ label?: string;
209
+ timeoutMs?: number;
210
+ when?: NonNullable<RuntimeTransition["when"]>;
211
+ onTransition?: NonNullable<RuntimeTransition["onTransition"]>;
212
+ };