@rxova/journey-core 0.7.0 → 1.0.0-rc.2
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 +236 -105
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +4 -4
- package/dist/journey-builder/index.d.cts +5 -0
- package/dist/journey-builder/index.d.ts +5 -0
- package/dist/journey-builder/types.d.cts +126 -0
- package/dist/journey-builder/types.d.ts +126 -0
- package/dist/journey-machine/async-state.d.cts +12 -0
- package/dist/journey-machine/async-state.d.ts +12 -0
- package/dist/journey-machine/computed.d.cts +2 -0
- package/dist/journey-machine/computed.d.ts +2 -0
- package/dist/journey-machine/controls.d.cts +17 -0
- package/dist/journey-machine/controls.d.ts +17 -0
- package/dist/journey-machine/helpers.d.cts +52 -0
- package/dist/journey-machine/helpers.d.ts +52 -0
- package/dist/journey-machine/index.d.cts +3 -0
- package/dist/journey-machine/index.d.ts +3 -0
- package/dist/journey-machine/navigation.d.cts +32 -0
- package/dist/journey-machine/navigation.d.ts +32 -0
- package/dist/journey-machine/plugin-controller.d.cts +15 -0
- package/dist/journey-machine/plugin-controller.d.ts +15 -0
- package/dist/journey-machine/resolve-journey-definition.d.cts +2 -0
- package/dist/journey-machine/resolve-journey-definition.d.ts +2 -0
- package/dist/journey-machine/runtime.d.cts +33 -0
- package/dist/journey-machine/runtime.d.ts +33 -0
- package/dist/journey-machine/send.d.cts +9 -0
- package/dist/journey-machine/send.d.ts +9 -0
- package/dist/plugins/analytics/index.cjs +2 -0
- package/dist/plugins/analytics/index.cjs.map +7 -0
- package/dist/plugins/analytics/index.d.cts +25 -0
- package/dist/plugins/analytics/index.d.ts +25 -0
- package/dist/plugins/analytics/index.js +2 -0
- package/dist/plugins/analytics/index.js.map +7 -0
- package/dist/plugins/autosave/index.cjs +2 -0
- package/dist/plugins/autosave/index.cjs.map +7 -0
- package/dist/plugins/autosave/index.d.cts +17 -0
- package/dist/plugins/autosave/index.d.ts +17 -0
- package/dist/plugins/autosave/index.js +2 -0
- package/dist/plugins/autosave/index.js.map +7 -0
- package/dist/plugins/diagnostics/diagnostics.d.cts +3 -0
- package/dist/plugins/diagnostics/diagnostics.d.ts +3 -0
- package/dist/plugins/diagnostics/index.cjs +2 -0
- package/dist/plugins/diagnostics/index.cjs.map +7 -0
- package/dist/plugins/diagnostics/index.d.cts +15 -0
- package/dist/plugins/diagnostics/index.d.ts +15 -0
- package/dist/plugins/diagnostics/index.js +2 -0
- package/dist/plugins/diagnostics/index.js.map +7 -0
- package/dist/plugins/execution-paths/execution-paths.d.cts +6 -0
- package/dist/plugins/execution-paths/execution-paths.d.ts +6 -0
- package/dist/plugins/execution-paths/index.cjs +2 -0
- package/dist/plugins/execution-paths/index.cjs.map +7 -0
- package/dist/plugins/execution-paths/index.d.cts +18 -0
- package/dist/plugins/execution-paths/index.d.ts +18 -0
- package/dist/plugins/execution-paths/index.js +2 -0
- package/dist/plugins/execution-paths/index.js.map +7 -0
- package/dist/plugins/persistence/controller.d.cts +17 -0
- package/dist/plugins/persistence/controller.d.ts +17 -0
- package/dist/plugins/persistence/index.cjs +2 -0
- package/dist/plugins/persistence/index.cjs.map +7 -0
- package/dist/plugins/persistence/index.d.cts +12 -0
- package/dist/plugins/persistence/index.d.ts +12 -0
- package/dist/plugins/persistence/index.js +2 -0
- package/dist/plugins/persistence/index.js.map +7 -0
- package/dist/plugins/replay/index.cjs +2 -0
- package/dist/plugins/replay/index.cjs.map +7 -0
- package/dist/plugins/replay/index.d.cts +27 -0
- package/dist/plugins/replay/index.d.ts +27 -0
- package/dist/plugins/replay/index.js +2 -0
- package/dist/plugins/replay/index.js.map +7 -0
- package/dist/types/analytics.types.d.cts +33 -0
- package/dist/types/analytics.types.d.ts +33 -0
- package/dist/types/autosave.types.d.cts +23 -0
- package/dist/types/autosave.types.d.ts +23 -0
- package/dist/types/diagnostics.types.d.cts +38 -0
- package/dist/types/diagnostics.types.d.ts +38 -0
- package/dist/types/index.d.cts +9 -0
- package/dist/types/index.d.ts +9 -4
- package/dist/types/journey.types.d.cts +191 -0
- package/dist/types/journey.types.d.ts +140 -167
- package/dist/types/machine.types.d.cts +104 -0
- package/dist/types/machine.types.d.ts +104 -0
- package/dist/types/observation.types.d.cts +83 -0
- package/dist/types/observation.types.d.ts +83 -0
- package/dist/types/persistence.types.d.cts +34 -0
- package/dist/types/persistence.types.d.ts +13 -20
- package/dist/types/replay.types.d.cts +35 -0
- package/dist/types/replay.types.d.ts +35 -0
- package/dist/types/transitions.types.d.cts +122 -0
- package/dist/types/transitions.types.d.ts +100 -57
- package/package.json +92 -2
- package/dist/machine-helpers.d.ts +0 -23
- package/dist/machine.d.ts +0 -11
- package/dist/persistence.d.ts +0 -17
- package/dist/transitions.d.ts +0 -62
- package/dist/types.d.ts +0 -1
package/README.md
CHANGED
|
@@ -1,152 +1,283 @@
|
|
|
1
1
|
# @rxova/journey-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Typed state machine for multi-step UI flows.
|
|
4
|
+
|
|
5
|
+
<p>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@rxova/journey-core">
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@rxova/journey-core?color=0f8f6a" alt="npm" />
|
|
8
|
+
</a>
|
|
9
|
+
<img src="https://img.shields.io/badge/7.58%20kB-brotli-0f8f6a" alt="size" />
|
|
10
|
+
<img src="https://img.shields.io/badge/zero%20dependencies-black" alt="zero deps" />
|
|
11
|
+
<img src="https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white" alt="TypeScript" />
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
`@rxova/journey-core` is approaching a `1.0.0-rc` contract freeze. The current public model is:
|
|
15
|
+
|
|
16
|
+
- JSON-only runtime `context`
|
|
17
|
+
- static step `meta`
|
|
18
|
+
- transition-side state updates through `updateContext(...)`
|
|
19
|
+
- documented lifecycle callbacks and events as the supported extension surface
|
|
4
20
|
|
|
5
21
|
## Install
|
|
6
22
|
|
|
7
23
|
```bash
|
|
8
|
-
pnpm add @rxova/journey-core
|
|
9
|
-
yarn add @rxova/journey-core
|
|
10
24
|
npm i @rxova/journey-core
|
|
11
|
-
bun add @rxova/journey-core
|
|
12
25
|
```
|
|
13
26
|
|
|
14
|
-
|
|
27
|
+
## Quickstart
|
|
15
28
|
|
|
16
|
-
|
|
29
|
+
```ts
|
|
30
|
+
import { createJourneyMachine } from "@rxova/journey-core";
|
|
17
31
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- Step metadata updates via `updateStepMetadata`.
|
|
25
|
-
- Optional persistence with schema versioning and migration hooks.
|
|
32
|
+
const machine = createJourneyMachine({
|
|
33
|
+
initial: "account",
|
|
34
|
+
context: { name: "" },
|
|
35
|
+
steps: { account: {}, details: {}, review: {} },
|
|
36
|
+
transitions: ["account", "details", "review"]
|
|
37
|
+
});
|
|
26
38
|
|
|
27
|
-
|
|
39
|
+
machine.startJourney();
|
|
40
|
+
|
|
41
|
+
await machine.send({ type: "goToNextStep" }); // account → details
|
|
42
|
+
await machine.send({ type: "goToNextStep" }); // details → review
|
|
43
|
+
await machine.goToPreviousStep(); // review → details
|
|
44
|
+
|
|
45
|
+
const snap = machine.getSnapshot();
|
|
46
|
+
console.log(snap.currentStepId); // "details"
|
|
47
|
+
console.log(snap.history.timeline); // ["account", "details"]
|
|
48
|
+
console.log(snap.status); // "running"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Three Transition Modes
|
|
52
|
+
|
|
53
|
+
Reserved step ids: `*`, `global`, `COMPLETE`, and `TERMINATED`. They are used by the runtime and cannot be used as real step names.
|
|
54
|
+
|
|
55
|
+
### Linear
|
|
56
|
+
|
|
57
|
+
Array shorthand for sequential flows. Steps can carry synchronous `updateContext` transitions and timeouts.
|
|
28
58
|
|
|
29
59
|
```ts
|
|
30
|
-
|
|
60
|
+
transitions: [
|
|
61
|
+
"account",
|
|
62
|
+
{
|
|
63
|
+
step: "details",
|
|
64
|
+
updateContext: ({ context }) => ({ ...context, step: 2 }),
|
|
65
|
+
timeoutMs: 5000
|
|
66
|
+
},
|
|
67
|
+
"payment",
|
|
68
|
+
"review"
|
|
69
|
+
];
|
|
70
|
+
```
|
|
31
71
|
|
|
32
|
-
|
|
33
|
-
type Event = "goToNextStep" | "completeJourney" | "back";
|
|
34
|
-
type Ctx = { name: string };
|
|
72
|
+
### Graph
|
|
35
73
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
74
|
+
Step-keyed transitions with guards, `updateContext`, and branching.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
transitions: {
|
|
78
|
+
login: {
|
|
79
|
+
goToNextStep: [
|
|
80
|
+
{ to: "admin", when: ({ context }) => context.role === "admin" },
|
|
81
|
+
{ to: "dashboard" }
|
|
82
|
+
]
|
|
42
83
|
},
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
};
|
|
84
|
+
admin: { completeJourney: true },
|
|
85
|
+
dashboard: { completeJourney: true }
|
|
86
|
+
}
|
|
87
|
+
```
|
|
48
88
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
89
|
+
#### Graph Builder
|
|
90
|
+
|
|
91
|
+
For larger flows, `createJourneyBuilder` lets each step declare its own transitions co-located with its component. It compiles to the same `JourneyDefinition` — no new runtime concepts.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
// builder.ts — typed singleton
|
|
95
|
+
const { createStep, to, build } = createJourneyBuilder<Context, StepId, EventMap>();
|
|
96
|
+
|
|
97
|
+
// steps/login.step.ts — co-located with Login.tsx
|
|
98
|
+
export const loginStep = createStep("login", {
|
|
99
|
+
on: {
|
|
100
|
+
submit: [to("admin").when(({ context }) => context.role === "admin"), to("dashboard")]
|
|
101
|
+
}
|
|
102
|
+
});
|
|
53
103
|
|
|
54
|
-
|
|
55
|
-
|
|
104
|
+
// journey.ts — one-screen assembly
|
|
105
|
+
const definition = build({
|
|
106
|
+
initial: "login",
|
|
107
|
+
context: { role: "user" },
|
|
108
|
+
steps: [loginStep, adminStep, dashboardStep]
|
|
109
|
+
});
|
|
56
110
|
```
|
|
57
111
|
|
|
58
|
-
|
|
112
|
+
Use the **factory form** when you need `event.payload` narrowed to the specific event type:
|
|
59
113
|
|
|
60
|
-
|
|
114
|
+
```ts
|
|
115
|
+
submit: ({ to }) => [to("admin").when(({ context, event }) => event.payload?.username !== "")];
|
|
116
|
+
```
|
|
61
117
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- `send({ type: "back" })` falls back to previous-step navigation when no explicit `back` transition exists.
|
|
65
|
-
- Once status is `complete` or `terminated`, pointer navigation and transitions no-op until `resetMachine()`.
|
|
66
|
-
- Forward navigation after moving back truncates timeline tail before appending the next step.
|
|
67
|
-
- Snapshot shape is stable: `currentStepId === history.timeline[history.index]`.
|
|
118
|
+
Each transition modifier is single-use at the type level. Calling `.when()`, `.updateContext()`,
|
|
119
|
+
`.onEnter()`, `.onLeave()`, `.label()`, or `.timeoutMs()` twice on the same builder is a TypeScript error. If you bypass the type system, runtime keeps the existing last-call-wins behavior.
|
|
68
120
|
|
|
69
|
-
|
|
121
|
+
### Headless
|
|
70
122
|
|
|
71
|
-
|
|
123
|
+
Omit `transitions` entirely. The machine holds state, history, and context, but the caller decides where to go. Useful for custom renderers, server-driven flows, or when the navigation logic lives outside the definition.
|
|
72
124
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
125
|
+
```ts
|
|
126
|
+
const machine = createJourneyMachine({
|
|
127
|
+
initial: "start",
|
|
128
|
+
context: {},
|
|
129
|
+
steps: { start: {}, configure: {}, confirm: {} }
|
|
130
|
+
// no transitions — the caller drives the flow
|
|
131
|
+
});
|
|
77
132
|
|
|
78
|
-
|
|
133
|
+
machine.startJourney();
|
|
134
|
+
await machine.goToStepById("configure");
|
|
135
|
+
await machine.goToStepById("confirm");
|
|
136
|
+
await machine.goToPreviousStep(); // back to configure
|
|
137
|
+
await machine.completeJourney();
|
|
138
|
+
```
|
|
79
139
|
|
|
80
|
-
`
|
|
140
|
+
In headless mode, `goToStepById(...)` is the navigation primitive. `goToNextStep()` and custom events are explicit no-ops until you define transitions and move into linear or graph mode.
|
|
81
141
|
|
|
82
|
-
`
|
|
142
|
+
After `dispose()`, send-style APIs resolve with `transitioned: false` and `error: JourneyDisposedError`. Control APIs such as `startJourney()` and `updateContext()` stay no-op and emit a development warning.
|
|
83
143
|
|
|
84
|
-
|
|
144
|
+
`updateContext()` is the ordered context-write API. It runs through the same queue as `send()`, so it applies against the latest committed snapshot when it executes.
|
|
145
|
+
|
|
146
|
+
## Step Lifecycle
|
|
85
147
|
|
|
86
|
-
|
|
148
|
+
Run side effects when a step is entered or left by attaching `onEnter` / `onLeave` directly to the step definition. Both callbacks receive the current `context` and are observational. They do not change transition selection or mutate context. Use transition `updateContext` for synchronous state commits that belong to the transition itself.
|
|
87
149
|
|
|
88
150
|
```ts
|
|
89
|
-
const machine = createJourneyMachine(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
migrate: (legacySnapshot, persistedVersion) => {
|
|
95
|
-
if (persistedVersion < 2) {
|
|
96
|
-
return {
|
|
97
|
-
currentStepId: "start",
|
|
98
|
-
history: { timeline: ["start"], index: 0 },
|
|
99
|
-
context: { name: "" },
|
|
100
|
-
status: "running",
|
|
101
|
-
visited: { start: true, review: false },
|
|
102
|
-
stepMeta: { start: undefined, review: undefined }
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
return legacySnapshot as never;
|
|
151
|
+
const machine = createJourneyMachine({
|
|
152
|
+
context: { username: "" },
|
|
153
|
+
steps: {
|
|
154
|
+
login: {
|
|
155
|
+
onLeave: ({ context }) => analytics.track("login_left", { user: context.username })
|
|
106
156
|
},
|
|
107
|
-
|
|
108
|
-
|
|
157
|
+
dashboard: {
|
|
158
|
+
onEnter: ({ context }) => analytics.track("dashboard_entered"),
|
|
159
|
+
onLeave: ({ context }) => console.log("leaving dashboard")
|
|
109
160
|
}
|
|
110
|
-
}
|
|
161
|
+
},
|
|
162
|
+
transitions: ["login", "dashboard"]
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
With the graph builder, callbacks sit alongside transitions on the step:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
const dashboardStep = createStep("dashboard", {
|
|
170
|
+
onEnter: ({ context }) => analytics.track("dashboard_entered"),
|
|
171
|
+
onLeave: ({ context }) => console.log("leaving dashboard"),
|
|
172
|
+
on: { submit: [to("review")] }
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
In React, use `useJourneyStepLifecycle` when the callback needs access to component state or React context:
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
const { useJourneyStepLifecycle } = createJourney(definition);
|
|
180
|
+
|
|
181
|
+
function Dashboard() {
|
|
182
|
+
useJourneyStepLifecycle("dashboard", {
|
|
183
|
+
onEnter: ({ context }) => analytics.track("dashboard_entered"),
|
|
184
|
+
onLeave: ({ context }) => console.log("leaving dashboard")
|
|
185
|
+
});
|
|
186
|
+
// ...
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The hook always calls the latest version of your callbacks without re-subscribing.
|
|
191
|
+
|
|
192
|
+
## Features
|
|
193
|
+
|
|
194
|
+
- **Async guards** — `when` can be async, with per-transition `timeoutMs` and `AbortSignal`-based cancellation. Step async state is tracked in `snapshot.async.byStep[stepId]` (`idle`, `evaluating-when`, `error`)
|
|
195
|
+
- **Timeline history** — `goToPreviousStep()`, `goToLastVisitedStep()`, deterministic back/forward. Snapshot exposes `history.timeline` and `history.index` so you always know where the user has been
|
|
196
|
+
- **Computed state** — `getComputed()` returns derived flags: `isFirstStep`, `isLastStep`, `isLoading`, `isComplete`, `isTerminated`, `activeStepIndex`, `stepCount`, `mode` (`linear` | `graph` | `headless`)
|
|
197
|
+
- **Observability** — `subscribeEvent()` streams typed lifecycle events: `journey.start`, `transition.start`, `transition.success`, `step.enter`, `step.exit`, `journey.completed`, `journey.terminated`, and more
|
|
198
|
+
- **Step metadata** — attach typed metadata per step and read it with `getStepMeta(stepId)`. Metadata is definition data, not mutable runtime state
|
|
199
|
+
- **Terminal events** — `completeJourney()` and `terminateJourney()` with typed payloads. Once terminal, all navigation no-ops until `resetJourney()`
|
|
200
|
+
- **Snapshot** — one object holds everything that changes at runtime: `currentStepId`, `context`, `history`, `visited`, `status` (`idled`, `running`, `completed`, `terminated`), and `async`
|
|
201
|
+
- **Global transitions** — cross-cutting handlers via the `global` key, useful for close-confirmation or abort flows
|
|
202
|
+
|
|
203
|
+
## Persistence
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
import { createPersistencePlugin } from "@rxova/journey-core/persistence";
|
|
207
|
+
|
|
208
|
+
const machine = createJourneyMachine(definition, {
|
|
209
|
+
plugins: [
|
|
210
|
+
createPersistencePlugin({
|
|
211
|
+
key: "checkout",
|
|
212
|
+
version: 2,
|
|
213
|
+
blockList: ["payment.cardNumber"]
|
|
214
|
+
})
|
|
215
|
+
]
|
|
111
216
|
});
|
|
112
217
|
```
|
|
113
218
|
|
|
114
|
-
|
|
219
|
+
Versioned snapshot storage with migrations, context allow/block lists, and configurable reset behavior. Defaults to `localStorage` when available.
|
|
220
|
+
|
|
221
|
+
If `migrate(...)` returns data that no longer matches a valid snapshot, Journey reports the error through `onError` (or a development warning when `onError` is omitted) and falls back to the initial snapshot.
|
|
222
|
+
|
|
223
|
+
## Autosave
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
import { createAutosavePlugin } from "@rxova/journey-core/autosave";
|
|
227
|
+
|
|
228
|
+
const machine = createJourneyMachine(definition, {
|
|
229
|
+
plugins: [
|
|
230
|
+
createAutosavePlugin({
|
|
231
|
+
key: "checkout-draft",
|
|
232
|
+
debounceMs: 300,
|
|
233
|
+
allowList: ["profile", "shipping"]
|
|
234
|
+
})
|
|
235
|
+
]
|
|
236
|
+
});
|
|
115
237
|
|
|
116
|
-
|
|
238
|
+
await machine.flushAutosave();
|
|
239
|
+
```
|
|
117
240
|
|
|
118
|
-
|
|
241
|
+
Autosave adds debounced draft persistence, hydration, `getAutosaveState()`, `flushAutosave()`, and `clearAutosave()` without requiring the persistence plugin as a separate public dependency.
|
|
119
242
|
|
|
120
|
-
|
|
121
|
-
- `transition.start`
|
|
122
|
-
- `transition.success`
|
|
123
|
-
- `transition.error`
|
|
124
|
-
- `step.exit`
|
|
125
|
-
- `step.enter`
|
|
126
|
-
- `navigation.previous`
|
|
127
|
-
- `navigation.lastVisited`
|
|
128
|
-
- `journey.complete`
|
|
129
|
-
- `journey.close`
|
|
130
|
-
- `metadata.updated`
|
|
243
|
+
## Analytics
|
|
131
244
|
|
|
132
|
-
|
|
245
|
+
```ts
|
|
246
|
+
import { createAnalyticsPlugin } from "@rxova/journey-core/analytics";
|
|
247
|
+
|
|
248
|
+
const machine = createJourneyMachine(definition, {
|
|
249
|
+
plugins: [
|
|
250
|
+
createAnalyticsPlugin({
|
|
251
|
+
machineId: "checkout",
|
|
252
|
+
track: (event) => analytics.track(event.name, event.payload)
|
|
253
|
+
})
|
|
254
|
+
]
|
|
255
|
+
});
|
|
256
|
+
```
|
|
133
257
|
|
|
134
|
-
|
|
258
|
+
Analytics normalizes Journey lifecycle events into a stable event envelope and adds `trackAnalyticsEvent(...)` for custom markers.
|
|
135
259
|
|
|
136
|
-
##
|
|
260
|
+
## DevTools
|
|
137
261
|
|
|
138
262
|
```ts
|
|
139
|
-
import {
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
tx.from("start").on("goToNextStep").to("review"),
|
|
143
|
-
tx
|
|
144
|
-
.from("review")
|
|
145
|
-
.on("goToNextStep")
|
|
146
|
-
.choose(
|
|
147
|
-
tx.when(({ context }) => context.canSubmit).to("done", { id: "review-submit" }),
|
|
148
|
-
tx.otherwise().to("review", { id: "review-stay" })
|
|
149
|
-
),
|
|
150
|
-
tx.from("review").toComplete()
|
|
151
|
-
);
|
|
263
|
+
import { attachJourneyDevtools } from "@rxova/journey-devtools-bridge";
|
|
264
|
+
|
|
265
|
+
const detach = attachJourneyDevtools(machine, { label: "Checkout" });
|
|
152
266
|
```
|
|
267
|
+
|
|
268
|
+
## Documentation
|
|
269
|
+
|
|
270
|
+
- [Pre-1.0 Migration](https://rxova.org/docs/core/pre-1-0-migration)
|
|
271
|
+
- [Stability Contract](https://rxova.org/docs/core/stability)
|
|
272
|
+
- [Quickstart](https://rxova.org/docs/core/getting-started)
|
|
273
|
+
- [Usage Modes](https://rxova.org/docs/core/usage)
|
|
274
|
+
- [Async Lifecycle](https://rxova.org/docs/core/async)
|
|
275
|
+
- [Persistence](https://rxova.org/docs/core/persistence)
|
|
276
|
+
- [Autosave](https://rxova.org/docs/core/autosave)
|
|
277
|
+
- [Analytics Plugin](https://rxova.org/docs/core/plugins/analytics-plugin)
|
|
278
|
+
- [Plugins](https://rxova.org/docs/core/plugins/overview)
|
|
279
|
+
- [API Reference](https://rxova.org/docs/core/api/overview)
|
|
280
|
+
|
|
281
|
+
## License
|
|
282
|
+
|
|
283
|
+
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var W=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var he=(e,r)=>{for(var s in r)W(e,s,{get:r[s],enumerable:!0})},be=(e,r,s,d)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of ge(r))!Re.call(e,a)&&a!==s&&W(e,a,{get:()=>r[a],enumerable:!(d=Ce(r,a))||d.enumerable});return e};var Ne=e=>be(W({},"__esModule",{value:!0}),e);var Ue={};he(Ue,{JOURNEY_ASYNC_PHASE:()=>R,JOURNEY_EVENT:()=>O,JOURNEY_STATUS:()=>m,JOURNEY_WILDCARD:()=>w,createJourneyMachine:()=>ie,createPersistenceController:()=>V,createTransitions:()=>ue,tx:()=>de});module.exports=Ne(Ue);var m={RUNNING:"running",COMPLETE:"complete",TERMINATED:"terminated"},w="*",O={GO_TO_STEP_BY_ID:"goToStepById"},R={IDLE:"idle",EVALUATING_WHEN:"evaluating-when",RUNNING_EFFECT:"running-effect",ERROR:"error"};var Y=(e,r,s)=>{if(!(r in e))throw new Error(s)},oe=e=>typeof e!="number"||!Number.isFinite(e)?1:Math.max(1,Math.trunc(e)),J=()=>Date.now(),we=e=>[...new Set(e)],Oe=(e,r)=>Object.fromEntries(r.map(s=>[s,e[s]===!0])),F=(e,r)=>{let s=r??we(e),d=Object.fromEntries(s.map(a=>[a,!1]));for(let a of e)d[a]=!0;return d},Ae=(e,r)=>({...e,[r]:!0}),z=e=>typeof e=="object"&&e!==null&&"then"in e&&typeof e.then=="function",L=()=>({phase:R.IDLE,eventType:null,transitionId:null,error:null}),U=e=>({isLoading:!1,byStep:Object.fromEntries(Object.keys(e).map(s=>[s,L()]))}),Q=e=>e.type===O.GO_TO_STEP_BY_ID&&"stepId"in e,K=e=>e==="COMPLETE"||e==="TERMINATED",re=(e,r)=>{let s=r;for(let[d,a]of e.entries()){if(!a||typeof a!="object")throw new Error(`Journey transition at index ${d} must be an object.`);if(typeof a.from!="string"||typeof a.event!="string")throw new Error(`Journey transition at index ${d} must define string "from" and "event".`);if(a.from!==w&&!(a.from in s))throw new Error(`Journey transition at index ${d} references unknown from step "${a.from}".`);if(a.event==="completeJourney"||a.event==="terminateJourney"){if("to"in a&&a.to!==void 0)throw new Error(`Journey transition at index ${d} with event "${a.event}" cannot define "to".`);continue}if(typeof a.to!="string")throw new Error(`Journey transition at index ${d} with event "${a.event}" must define string "to".`);if(!K(a.to)&&!(a.to in s))throw new Error(`Journey transition at index ${d} points to unknown step "${a.to}".`)}},P=(e,r,s={})=>({transitioned:r,...s.transitionId!==void 0?{transitionId:s.transitionId}:{},..."error"in s?{error:s.error}:{},snapshot:e}),_=(e,r,s,d,a,c,y)=>{if(e.length===0)throw new Error("Journey timeline cannot be empty.");let t=Math.max(0,Math.min(Math.trunc(r),e.length-1)),M=e[t],f=Object.keys(c);return{status:d,currentStepId:M,history:{timeline:[...e],index:t},context:s,visited:y?Oe(y,f):F(e,f),stepMeta:{...c},async:a}},ae=async(e,r,s,d)=>{for(let a of e){let c=a.from===w||a.from===r.currentStepId,y=a.event===s.type;if(!c||!y)continue;if(!a.when)return a;let t=a.when({context:r.context,from:r.currentStepId,timeline:r.history.timeline,index:r.history.index,event:s}),M=z(t);M&&d?.onAsyncGuardStart?.(a);let f;try{f=await t}catch(C){throw M&&d?.onAsyncGuardError?.(a,C),C}if(M&&d?.onAsyncGuardSuccess?.(a),f)return a}return null},X=(e,r,s)=>{let d=e.history.timeline.slice(0,e.history.index+1),a=d;r!==e.currentStepId&&(a=[...d,r]);let c=a.length-1,y=Ae(e.visited,r);return _(a,c,s,e.status,e.async,e.stepMeta,y)};var G=e=>typeof e=="object"&&e!==null,se=e=>e===m.RUNNING||e===m.COMPLETE||e===m.TERMINATED,De=()=>{let e=globalThis.localStorage;return!e||typeof e.getItem!="function"||typeof e.setItem!="function"||typeof e.removeItem!="function"?null:e},_e=e=>{if(!e)return null;let r=e.storage;if(r==null)try{r=De()}catch(s){return e.onError?.(s),null}return r?{key:e.key,storage:r,version:e.version??1,clearOnReset:e.clearOnReset??!0,serialize:e.serialize??JSON.stringify,deserialize:e.deserialize??JSON.parse,...e.migrate?{migrate:e.migrate}:{},...e.onError?{onError:e.onError}:{}}:null},ke=(e,r,s)=>{let d=F(r,s);if(G(e)){let a=!1,c={...d};for(let y of s){let t=e[y];if(t===!0){c[y]=!0;continue}if(t===!1){d[y]&&(a=!0);continue}a=!0}return{visited:c,needsRewrite:a}}if(Array.isArray(e)){let a=F(e.filter(y=>typeof y=="string"&&s.includes(y)),s);return{visited:Object.fromEntries(s.map(y=>[y,d[y]||a[y]])),needsRewrite:!0}}return{visited:d,needsRewrite:!0}},pe=(e,r,s,d)=>{if(!G(e))return null;let a=!1,c=G(e.history)?e.history:null;c||(a=!0);let y=c?.timeline??e.timeline,t=Array.isArray(y)?y.filter(x=>typeof x=="string"&&x in r):[],M=typeof e.currentStepId=="string"&&e.currentStepId in r?e.currentStepId:typeof e.current=="string"&&e.current in r?e.current:null;if(t.length===0){if(!M)return null;t.push(M),a=!0}let f=t.length-1,C=c?.index??e.index;if(typeof C=="number"&&Number.isFinite(C))f=Math.max(0,Math.min(Math.trunc(C),t.length-1)),f!==C&&(a=!0);else if(M){let x=t.lastIndexOf(M);x>=0&&(f=x,a=!0)}let S=se(e.status)?e.status:m.RUNNING;se(e.status)||(a=!0);let g=Object.keys(r),{visited:h,needsRewrite:I}=ke(e.visited,t,g);I&&(a=!0);let E=G(e.stepMeta)?e.stepMeta:null;E||(a=!0);let D=Object.fromEntries(Object.keys(r).map(x=>{let l=x,k=E?E[x]:void 0;return k===void 0?[l,d[l]]:[l,k]}));return{snapshot:{currentStepId:t[f],history:{timeline:t,index:f},context:"context"in e?e.context:s,status:S,visited:h,stepMeta:D},needsRewrite:a}},V=e=>{let{initial:r,context:s,stepMeta:d,steps:a,options:c}=e,y=_e(c?.persistence),t=S=>{y?.onError?.(S)},M=S=>{if(y)try{let g={version:y.version,snapshot:{currentStepId:S.currentStepId,history:{timeline:[...S.history.timeline],index:S.history.index},context:S.context,status:S.status,visited:{...S.visited},stepMeta:{...S.stepMeta}}};y.storage.setItem(y.key,y.serialize(g))}catch(g){t(g)}},f=()=>{if(y)try{y.storage.removeItem(y.key)}catch(S){t(S)}},C=()=>{let S=_([r],0,s,m.RUNNING,U(a),d);if(!y)return S;try{let g=y.storage.getItem(y.key);if(!g)return S;let h=y.deserialize(g);if(!G(h))return S;let I=h.version;if(typeof I!="number")return S;let E=null,D=!1;if(I===y.version){let l=pe(h.snapshot,a,s,d);E=l?.snapshot??null,D=!!l?.needsRewrite}else if(y.migrate){let l=y.migrate(h.snapshot,I);E=pe(l,a,s,d)?.snapshot??null,D=E!==null}if(!E)return S;let x=_(E.history.timeline,E.history.index,E.context,E.status,U(a),E.stepMeta,E.visited);return D&&M(x),x}catch(g){return t(g),S}};return{clearOnReset:y?.clearOnReset??!0,hydrateSnapshot:C,persistSnapshot:M,removePersistedSnapshot:f}};function ie(e,r){if(!e.steps||typeof e.steps!="object")throw new Error("Journey steps must be a record object.");if(!Array.isArray(e.transitions))throw new Error("Journey transitions must be an array.");for(let n of Object.keys(e.steps))if(n==="*")throw new Error('Step id "*" is reserved as a wildcard and cannot be used as a step name.');Y(e.steps,e.initial,`Journey initial step "${e.initial}" does not exist in steps registry.`),re(e.transitions,e.steps);let s=()=>{let n={};for(let o of Object.keys(e.steps))n[o]=e.steps[o].meta;return n},{clearOnReset:d,hydrateSnapshot:a,persistSnapshot:c,removePersistedSnapshot:y}=V({initial:e.initial,context:e.context,stepMeta:s(),steps:e.steps,...r?{options:r}:{}}),t=a();t={...t,async:U(e.steps)};let M=r?.completeOnNoNextStep??!0,f={type:"journey.start",stepId:t.currentStepId,timestamp:J()},C=new Set,S=new Set,g=Promise.resolve(),h=0,I=!1,E=n=>!I&&n===h,D=()=>{h+=1,g=Promise.resolve()},x=()=>{for(let n of C)n()},l=n=>{for(let o of S)o(n)},k=(n,o)=>{let p=h,i=async()=>E(p)?n(p):o(),T=v=>{g=v.then(()=>{},()=>{})},u=g.then(i,i);return T(u),u},le=n=>n===R.EVALUATING_WHEN||n===R.RUNNING_EFFECT,$=(n,o,p)=>{if(p!==void 0&&!E(p))return;let i=t.async.byStep[n]??L(),T=o(i);if(i.phase===T.phase&&i.eventType===T.eventType&&i.transitionId===T.transitionId&&i.error===T.error)return;let u={...t.async.byStep,[n]:T},v=Object.values(u).some(N=>le(N.phase));t={...t,async:{isLoading:v,byStep:u}},x()},Z=(n,o,p,i,T)=>{$(n,()=>({phase:o,eventType:p,transitionId:i??null,error:null}),T)},B=(n,o)=>{$(n,()=>L(),o)},ee=(n,o,p,i,T)=>{$(n,()=>({phase:R.ERROR,eventType:o,transitionId:i??null,error:p}),T)},te=(n,o)=>{if(t.status!==m.RUNNING)return P(t,!1);let p=oe(n);if(t.history.index===0)return P(t,!1);let i=t.currentStepId,T=Math.max(0,t.history.index-p),u=t.history.index-T;return u<=0?P(t,!1):(l({type:"step.exit",stepId:i,timestamp:J()}),t=_(t.history.timeline,T,t.context,t.status,t.async,t.stepMeta,t.visited),c(t),x(),l({type:"navigation.previous",from:i,to:t.currentStepId,requestedSteps:p,appliedSteps:u,timestamp:J()}),l({type:"step.enter",stepId:t.currentStepId,timestamp:J()}),P(t,!0,{...o!==void 0?{transitionId:o}:{}}))},Se=n=>{if(t.status!==m.RUNNING)return P(t,!1);let o=t.history.timeline.length-1;if(t.history.index>=o)return P(t,!1);let p=t.currentStepId;return l({type:"step.exit",stepId:p,timestamp:J()}),t=_(t.history.timeline,o,t.context,t.status,t.async,t.stepMeta,t.visited),c(t),x(),l({type:"navigation.lastVisited",from:p,to:t.currentStepId,timestamp:J()}),l({type:"step.enter",stepId:t.currentStepId,timestamp:J()}),P(t,!0,{...n!==void 0?{transitionId:n}:{}})},A=()=>P(t,!1),ce=(n,o)=>P(t,!1,{...o!==void 0?{transitionId:o}:{},error:n}),q=(n,o,p,i,T)=>(ee(n,o,p,i??void 0,T),l({type:"transition.error",from:n,eventType:o,transitionId:i,error:p,timestamp:J()}),ce(p,i??void 0)),Ee=(n,o,p)=>{B(o,p);let i=t.currentStepId,T=X(t,n,t.context);return T.currentStepId!==i&&l({type:"step.exit",stepId:i,timestamp:J()}),t=T,c(t),x(),l({type:"transition.success",from:o,to:t.currentStepId,eventType:O.GO_TO_STEP_BY_ID,transitionId:O.GO_TO_STEP_BY_ID,timestamp:J()}),T.currentStepId!==i&&l({type:"step.enter",stepId:t.currentStepId,timestamp:J()}),P(t,!0,{transitionId:O.GO_TO_STEP_BY_ID})},xe=(n,o,p)=>{if(!Q(n))return{transitionsToEvaluate:e.transitions,earlyResult:null};Y(e.steps,n.stepId,`Cannot goToStepById unknown step "${n.stepId}".`);let i=e.transitions.filter(T=>(T.from==="*"||T.from===o)&&T.event===O.GO_TO_STEP_BY_ID&&"to"in T&&T.to===n.stepId);return i.length===0?{transitionsToEvaluate:e.transitions,earlyResult:Ee(n.stepId,o,p)}:{transitionsToEvaluate:i,earlyResult:null}},Je=async(n,o,p,i)=>{let T;try{T=await ae(n,t,o,{onAsyncGuardStart:u=>{Z(p,R.EVALUATING_WHEN,o.type,u.id,i)},onAsyncGuardSuccess:()=>{B(p,i)},onAsyncGuardError:(u,v)=>{ee(p,o.type,v,u.id,i)}})}catch(u){return E(i)?{transition:null,earlyResult:q(p,o.type,u,null,i)}:{transition:null,earlyResult:A()}}return{transition:T,earlyResult:null}},ve=(n,o)=>{if(Q(n))return A();if(n.type==="goToPreviousStep"||n.type==="back"){let p=te(1,n.type);return p.transitioned&&l({type:"transition.success",from:o,to:p.snapshot.currentStepId,eventType:n.type,transitionId:null,timestamp:J()}),p}return n.type==="goToNextStep"&&M&&!Me(o,"goToNextStep")?ne(o,"COMPLETE",n,null,t.context):A()},Ie=async(n,o,p,i)=>{let T=t.context;if(!n.effect)return{nextContext:T,earlyResult:null};let u;try{u=n.effect({context:t.context,from:t.currentStepId,timeline:t.history.timeline,index:t.history.index,event:o})}catch(N){return E(i)?{nextContext:null,earlyResult:q(p,o.type,N,n.id??null,i)}:{nextContext:null,earlyResult:A()}}z(u)&&Z(p,R.RUNNING_EFFECT,o.type,n.id,i);let v;try{v=await u}catch(N){return E(i)?{nextContext:null,earlyResult:q(p,o.type,N,n.id??null,i)}:{nextContext:null,earlyResult:A()}}return E(i)?(v!==void 0&&(T=v),{nextContext:T,earlyResult:null}):{nextContext:null,earlyResult:A()}},me=n=>n.event==="completeJourney"?"COMPLETE":n.event==="terminateJourney"?"TERMINATED":n.to,Me=(n,o)=>e.transitions.some(p=>(p.from==="*"||p.from===n)&&p.event===o),ne=(n,o,p,i,T)=>{let u=t.history.timeline.slice(0,t.history.index+1);return t={...t,history:{timeline:u,index:u.length-1},context:T,status:o==="COMPLETE"?m.COMPLETE:m.TERMINATED},c(t),x(),l({type:"transition.success",from:n,to:o,eventType:p.type,transitionId:i,timestamp:J()}),l({type:o==="COMPLETE"?"journey.complete":"journey.close",stepId:t.currentStepId,timestamp:J()}),P(t,!0,{...i!==null?{transitionId:i}:{}})},fe=(n,o,p,i,T)=>{Y(e.steps,o,`Transition points to unknown step "${o}".`);let u=t.currentStepId;return u!==o&&l({type:"step.exit",stepId:u,timestamp:J()}),t=X(t,o,T),c(t),x(),l({type:"transition.success",from:n,to:t.currentStepId,eventType:p.type,transitionId:i.id??null,timestamp:J()}),u!==t.currentStepId&&l({type:"step.enter",stepId:t.currentStepId,timestamp:J()}),P(t,!0,{...i.id!==void 0?{transitionId:i.id}:{}})},Pe=async(n,o)=>{if(t.status!==m.RUNNING)return A();let p=t.currentStepId,i=n;l({type:"transition.start",from:p,event:n,timestamp:J()});let T=xe(n,p,o);if(T.earlyResult)return T.earlyResult;let u=await Je(T.transitionsToEvaluate,i,p,o);if(u.earlyResult)return u.earlyResult;if(!E(o))return A();let{transition:v}=u;if(!v)return ve(n,p);let N=await Ie(v,i,p,o);if(N.earlyResult)return N.earlyResult;B(p,o);let H=me(v);return K(H)?ne(p,H,i,v.id??null,N.nextContext):fe(p,H,i,v,N.nextContext)},b={getSnapshot:()=>t,subscribe:n=>I?()=>{}:(C.add(n),()=>{C.delete(n)}),subscribeSelector:(n,o,p)=>{if(I)return()=>{};let i=p??Object.is,T=n(t);return b.subscribe(()=>{let u=n(t);if(i(T,u))return;let v=T;T=u,o(u,v)})},subscribeEvent:n=>{if(I)return()=>{};S.add(n);try{n(f)}catch(o){throw S.delete(n),o}return()=>{S.delete(n)}},subscribeStart:n=>b.subscribeEvent(o=>{o.type==="journey.start"&&n(o)}),subscribeComplete:n=>b.subscribeEvent(o=>{o.type==="journey.complete"&&n(o)}),subscribeTerminate:n=>b.subscribeEvent(o=>{o.type==="journey.close"&&n(o)}),resetMachine:()=>(I||(D(),t=_([e.initial],0,e.context,m.RUNNING,U(e.steps),s()),d?y():c(t),x()),t),updateContext:n=>(I||(t={...t,context:n(t.context)},c(t),x()),t),updateStepMetadata:(n,o)=>{if(I||!(n in e.steps))return t;let p=t.stepMeta[n],i=o(p);return Object.is(p,i)||(t={...t,stepMeta:{...t.stepMeta,[n]:i}},c(t),x(),l({type:"metadata.updated",stepId:n,previous:p,next:i,timestamp:J()})),t},clearStepError:n=>{if(I)return t;let o=n??t.currentStepId;return o in e.steps&&B(o),t},dispose:()=>{I||(I=!0,D(),C.clear(),S.clear())},goToPreviousStep:n=>k(async()=>te(n,"goToPreviousStep"),()=>P(t,!1)),goToLastVisitedStep:()=>k(async()=>Se("goToLastVisitedStep"),()=>P(t,!1)),goToNextStep:()=>b.send({type:"goToNextStep"}),terminateJourney:n=>n===void 0?b.send({type:"terminateJourney"}):b.send({type:"terminateJourney",payload:n}),completeJourney:n=>n===void 0?b.send({type:"completeJourney"}):b.send({type:"completeJourney",payload:n}),send:n=>k(async o=>Pe(n,o),A)};return b}var Te=e=>({to:(r,s={})=>({...s,to:r,...e?{when:e}:{}})}),ye=(e,r)=>r==="completeJourney"?{complete:(s={})=>({...s,from:e,event:r})}:r==="terminateJourney"?{terminate:(s={})=>({...s,from:e,event:r})}:{to:(s,d={})=>({...d,from:e,event:r,to:s}),choose:(...s)=>s.map(d=>({...d,from:e,event:r})),when:s=>Te(s),otherwise:()=>Te()},j=(e,r,s={})=>({...s,from:e,event:r}),de={from:e=>({on:r=>ye(e,r),toComplete:(r={})=>j(e,"completeJourney",r),toTerminate:(r={})=>j(e,"terminateJourney",r)}),any:()=>({on:e=>ye(w,e),toComplete:(e={})=>j(w,"completeJourney",e),toTerminate:(e={})=>j(w,"terminateJourney",e)}),when:e=>({to:(r,s={})=>({...s,to:r,when:e})}),otherwise:()=>({to:(e,r={})=>({...r,to:e})})},ue=(...e)=>e.flatMap(r=>Array.isArray(r)?[...r]:[r]);0&&(module.exports={JOURNEY_ASYNC_PHASE,JOURNEY_EVENT,JOURNEY_STATUS,JOURNEY_WILDCARD,createJourneyMachine,createPersistenceController,createTransitions,tx});
|
|
1
|
+
"use strict";var te=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var He=Object.getOwnPropertyNames;var Pe=Object.prototype.hasOwnProperty;var $e=(e,n)=>{for(var o in n)te(e,o,{get:n[o],enumerable:!0})},je=(e,n,o,p)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of He(n))!Pe.call(e,s)&&s!==o&&te(e,s,{get:()=>n[s],enumerable:!(p=Le(n,s))||p.enumerable});return e};var Be=e=>je(te({},"__esModule",{value:!0}),e);var Ke={};$e(Ke,{JourneyDisposedError:()=>G,createJourneyBuilder:()=>Ae,createJourneyMachine:()=>Re});module.exports=Be(Ke);var V=(e,n,o)=>{if(!(n in e))throw new Error(o)},Q=e=>typeof e=="object"&&e!==null&&!Array.isArray(e)&&(Object.getPrototypeOf(e)===Object.prototype||Object.getPrototypeOf(e)===null),q=e=>Array.isArray(e)?e.map(n=>q(n)):Q(e)?Object.fromEntries(Object.entries(e).map(([n,o])=>[n,q(o)])):e,pe=e=>{if(e===null)return"null";if(Array.isArray(e))return"array";if(typeof e=="object"){let n=e.constructor?.name;return n&&n!=="Object"?n:"object"}return typeof e};function oe(e,n,o,p=[]){if(e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean")return;let s=p.length===0?n:`${n}.${p.join(".")}`;if(e===void 0)throw new Error(`${s} must be JSON-serializable. Received undefined.`);if(typeof e=="bigint"||typeof e=="symbol"||typeof e=="function")throw new Error(`${s} must be JSON-serializable. Received ${typeof e}.`);if(typeof e!="object")throw new Error(`${s} must be JSON-serializable. Received ${pe(e)}.`);if(o.seen.has(e))throw new Error(`${s} must be JSON-serializable. Circular references are not supported.`);if(o.seen.add(e),Array.isArray(e)){for(let[t,i]of e.entries())oe(i,n,o,[...p,String(t)]);return}if(!Q(e))throw new Error(`${s} must be JSON-serializable. Received non-plain ${pe(e)}.`);for(let[t,i]of Object.entries(e))oe(i,n,o,[...p,t])}function j(e,n="Journey context"){return oe(e,n,{seen:new WeakSet}),e}var B=e=>q(j(e)),_=e=>Array.isArray(e)?e.map(n=>_(n)):e instanceof Date?new Date(e.getTime()):e instanceof Map?new Map([...e.entries()].map(([n,o])=>[_(n),_(o)])):e instanceof Set?new Set([...e].map(n=>_(n))):Q(e)?Object.fromEntries(Object.entries(e).map(([n,o])=>[n,_(o)])):e,ie=e=>{if(typeof e!="object"&&typeof e!="function"||e===null)return e;if(typeof structuredClone=="function")try{return structuredClone(e)}catch{return _(e)}else return _(e)},re=e=>{if(!(typeof e!="object"||e===null||Object.isFrozen(e))){if(Array.isArray(e)){for(let n of e)re(n);Object.freeze(e);return}if(Q(e)){for(let n of Object.values(e))re(n);Object.freeze(e)}}},le=e=>typeof e!="number"||!Number.isFinite(e)?1:Math.max(1,Math.trunc(e)),b=()=>Date.now(),ye=e=>[...new Set(e)],De=(e,n)=>Object.fromEntries(n.map(o=>[o,e[o]===!0])),_e=(e,n)=>{let o=n??ye(e),p=Object.fromEntries(o.map(s=>[s,!1]));for(let s of e)p[s]=!0;return p},Ne=(e,n)=>({...e,[n]:!0}),ae=e=>typeof e=="object"&&e!==null&&"then"in e&&typeof e.then=="function",Te=e=>typeof e=="number"&&Number.isFinite(e),z=(e,n)=>{if(e!==void 0&&!Te(e))throw new Error(`${n} must define a finite numeric "timeoutMs" when provided.`)},se=class extends Error{constructor(o){super(o);this.name="JourneyTimeoutError"}},G=class extends Error{constructor(o){super(`Journey machine has been disposed; "${o}" can no longer be used.`);this.name="JourneyDisposedError";this.operation=o}},ce=()=>{let e=globalThis;if(typeof e.__DEV__=="boolean")return e.__DEV__;let n=e.process?.env?.NODE_ENV;return n===void 0||n==="development"},X=(e,n)=>{if(!(!ce()||typeof console>"u")){if(n===void 0){console.warn(e);return}console.warn(e,n)}},Se=(e,n)=>{if(!(!ce()||typeof console>"u")){if(n===void 0){console.error(e);return}console.error(e,n)}},Fe=async(e,n,o)=>!Te(n)||n<=0?await e:await new Promise((p,s)=>{let t=setTimeout(()=>{s(o())},n);e.then(i=>{clearTimeout(t),p(i)},i=>{clearTimeout(t),s(i)})}),Ge=async(e,n)=>{if(n.aborted)throw n.reason;return await new Promise((o,p)=>{let s=()=>{n.removeEventListener("abort",s),p(n.reason)};n.addEventListener("abort",s,{once:!0}),e.then(t=>{n.removeEventListener("abort",s),o(t)},t=>{n.removeEventListener("abort",s),p(t)})})},Y=()=>({phase:"idle",eventType:null,transitionId:null,error:null}),Z=e=>({isLoading:!1,byStep:Object.fromEntries(Object.keys(e).map(o=>[o,Y()]))}),ee=e=>e.type==="goToStepById"&&"stepId"in e,K=e=>e==="COMPLETE"||e==="TERMINATED",fe=e=>e.event==="completeJourney"?"COMPLETE":e.event==="terminateJourney"?"TERMINATED":e.to,Je=(e,n)=>{let o=n,p=new Set(["from","event","to","when","updateContext","onEnter","onLeave","id","label","timeoutMs"]);for(let[s,t]of e.entries()){if(!t||typeof t!="object")throw new Error(`Journey transition at index ${s} must be an object.`);for(let i of Object.keys(t))if(!p.has(i))throw new Error(`Journey transition at index ${s} contains unsupported field "${i}".`);if(typeof t.from!="string"||typeof t.event!="string")throw new Error(`Journey transition at index ${s} must define string "from" and "event".`);if(t.from!=="*"&&!(t.from in o))throw new Error(`Journey transition at index ${s} references unknown from step "${t.from}".`);if(z(t.timeoutMs,`Journey transition at index ${s}`),t.when!==void 0&&typeof t.when!="function")throw new Error(`Journey transition at index ${s} must define "when" as a function when provided.`);if(t.updateContext!==void 0&&typeof t.updateContext!="function")throw new Error(`Journey transition at index ${s} must define "updateContext" as a function when provided.`);if(t.onEnter!==void 0&&typeof t.onEnter!="function")throw new Error(`Journey transition at index ${s} must define "onEnter" as a function when provided.`);if(t.onLeave!==void 0&&typeof t.onLeave!="function")throw new Error(`Journey transition at index ${s} must define "onLeave" as a function when provided.`);if(t.id!==void 0&&typeof t.id!="string")throw new Error(`Journey transition at index ${s} must define "id" as a string when provided.`);if(t.label!==void 0&&typeof t.label!="string")throw new Error(`Journey transition at index ${s} must define "label" as a string when provided.`);if(t.event==="completeJourney"||t.event==="terminateJourney"){if("to"in t&&t.to!==void 0)throw new Error(`Journey transition at index ${s} with event "${t.event}" cannot define "to".`);continue}if(typeof t.to!="string")throw new Error(`Journey transition at index ${s} with event "${t.event}" must define string "to".`);if(!K(t.to)&&!(t.to in o))throw new Error(`Journey transition at index ${s} points to unknown step "${t.to}".`)}},k=(e,n,o={})=>({transitioned:n,...o.transitionId!==void 0?{transitionId:o.transitionId}:{},...o.label!==void 0?{label:o.label}:{},..."error"in o?{error:o.error}:{},snapshot:e}),D=(e,n,o,p,s,t)=>{if(e.length===0)throw new Error("Journey timeline cannot be empty.");let i=Math.max(0,Math.min(Math.trunc(n),e.length-1)),r=e[i],d=ye(t?[...Object.keys(t),...e]:e);return{status:p,currentStepId:r,history:{timeline:[...e],index:i},context:B(o),visited:t?De(t,d):_e(e,d),async:q(s)}},H=e=>{let n={...e,history:{timeline:[...e.history.timeline],index:e.history.index},context:B(e.context),visited:{...e.visited},async:q(e.async)};return re(n),n},xe=async(e,n,o,p,s,t,i)=>{for(let r of e){let d=r.from==="*"||r.from===n.currentStepId,l=r.event===o.type;if(!d||!l)continue;if(!r.when)return r;let y;if(p.aborted)throw p.reason;y=r.when({snapshot:n,context:n.context,from:n.currentStepId,timeline:n.history.timeline,index:n.history.index,event:o,signal:p,handlers:s});let a=ae(y),u=a?y:null,E;try{a?(t?.onAsyncGuardStart?.(r),E=await Fe(Ge(u,p),r.timeoutMs??i,()=>new se(`Transition guard timed out after ${r.timeoutMs??i}ms (event: ${o.type}, transition: ${r.id??"<anonymous>"}).`))):E=y}catch(g){throw a&&t?.onAsyncGuardError?.(r,g),g}if(a&&t?.onAsyncGuardSuccess?.(r),E)return r}return null},me=(e,n,o)=>{let p=e.history.timeline.slice(0,e.history.index+1),s=p;n!==e.currentStepId&&(s=[...p,n]);let t=s.length-1,i=Ne(e.visited,n);return D(s,t,o,e.status,e.async,i)};var he=({runtime:e})=>{let n=i=>i==="evaluating-when",o=i=>Object.values(i.byStep).reduce((r,d)=>r+(n(d.phase)?1:0),0),p=o(e.peekSnapshot().async),s=i=>{p=o(i)},t=(i,r,d)=>{if(d!==void 0&&!e.isRunActive(d))return;let l=e.peekSnapshot(),y=l.async.byStep[i]??Y(),a=r(y);if(y.phase===a.phase&&y.eventType===a.eventType&&y.transitionId===a.transitionId&&y.error===a.error)return;let u={...l.async.byStep,[i]:a},E=n(y.phase),g=n(a.phase),P=E===g?p:p+(g?1:-1);e.setSnapshot({...l,async:{isLoading:P>0,byStep:u}},{notify:!0,reason:"async"}),p=P};return{syncState:s,updateStepAsync:t,setStepLoading:(i,r,d,l,y)=>{t(i,()=>({phase:r,eventType:d,transitionId:l??null,error:null}),y)},setStepIdle:(i,r)=>{t(i,()=>Y(),r)},setStepError:(i,r,d,l,y)=>{t(i,()=>({phase:"error",eventType:r,transitionId:l??null,error:d}),y)}}};var Ve=e=>e.map(n=>typeof n=="string"?n:n.step),ze=e=>{let n=0;for(let o in e)e[o]&&(n+=1);return n},ve=(e,n,o)=>{let p=e.transitions===void 0?"headless":Array.isArray(e.transitions)?"linear":"graph",s=p==="linear"?Ve(e.transitions):null;return()=>{let t=o(),i=t.history.index,r={activeStepId:t.currentStepId,activeStepIndex:i,visitedStepCount:ze(t.visited),isLoading:t.async.isLoading,isIdle:t.status==="idled",isRunning:t.status==="running",isComplete:t.status==="completed",isTerminated:t.status==="terminated",isInitialStep:t.currentStepId===n.initial};if(p==="linear"&&s!==null){let d=s.length,l=s.indexOf(t.currentStepId);return{...r,activeStepIndex:l===-1?i:l,mode:"linear",stepCount:d,journeyLength:d,isFirstStep:l===0,isLastStep:l===d-1,stepOrder:s}}return p==="graph"?{...r,mode:"graph"}:{...r,mode:"headless"}}};var Ee=({runtime:e,asyncState:n,initial:o,initialContext:p,steps:s})=>{let t=r=>{X(`Journey machine has been disposed; "${r}" is a no-op.`)},i=()=>D([o],0,B(p),"idled",Z(s));return{startJourney:()=>e.isDisposed()?(t("startJourney"),Promise.resolve(e.getSnapshot())):e.queue(async()=>{let r=e.peekSnapshot();if(r.status!=="idled")return e.getSnapshot();let d=e.setSnapshot({...r,status:"running"},{notify:!0,reason:"start"});return e.emit({type:"journey.start",stepId:d.currentStepId,timestamp:b()}),e.getSnapshot()},()=>e.getSnapshot()),resetJourney:()=>e.isDisposed()?(t("resetJourney"),Promise.resolve(e.getSnapshot())):(e.cancelInFlight(),e.queue(async()=>{let r=e.setSnapshot(i(),{notify:!0,reason:"reset"});return e.emit({type:"journey.reset",stepId:r.currentStepId,timestamp:b()}),n.syncState(r.async),e.getSnapshot()},()=>e.getSnapshot())),updateContext:r=>e.isDisposed()?(t("updateContext"),Promise.resolve(e.getSnapshot())):e.queue(async()=>{let d=e.peekSnapshot(),l=j(r(B(d.context)));return e.setSnapshot({...d,context:l},{notify:!0,reason:"context"})},()=>e.getSnapshot()),clearStepError:r=>e.isDisposed()?(t("clearStepError"),Promise.resolve(e.getSnapshot())):e.queue(async()=>{let d=e.peekSnapshot(),l=r??d.currentStepId;return l in s&&n.setStepIdle(l),e.getSnapshot()},()=>e.getSnapshot()),dispose:()=>{e.dispose()}}};var be=({runtime:e,steps:n,transitions:o,scheduleLifecycle:p})=>({applyPreviousNavigation:(s,t,i=0)=>{let r=e.peekSnapshot();if(r.status!=="running")return k(e.getSnapshot(),!1);let d=le(s);if(r.history.index===0)return k(e.getSnapshot(),!1);let l=r.currentStepId,y=Math.max(0,r.history.index-d),a=r.history.index-y;if(a<=0)return k(e.getSnapshot(),!1);e.emit({type:"step.exit",stepId:l,timestamp:b()});let u=e.setSnapshot(D(r.history.timeline,y,r.context,r.status,r.async,r.visited),{notify:!0,reason:"navigation"});return e.emit({type:"navigation.previous",from:l,to:u.currentStepId,requestedSteps:d,appliedSteps:a,timestamp:b()}),e.emit({type:"step.enter",stepId:u.currentStepId,timestamp:b()}),p({previousSnapshot:r,snapshot:u,from:l,to:u.currentStepId,event:{type:"goToPreviousStep"},transitionId:t??null,runVersion:i}),k(u,!0,{...t!==void 0?{transitionId:t}:{}})},applyLastVisitedNavigation:(s,t=0)=>{let i=e.peekSnapshot();if(i.status!=="running")return k(e.getSnapshot(),!1);let r=i.history.timeline.length-1;if(i.history.index>=r)return k(e.getSnapshot(),!1);let d=i.currentStepId;e.emit({type:"step.exit",stepId:d,timestamp:b()});let l=e.setSnapshot(D(i.history.timeline,r,i.context,i.status,i.async,i.visited),{notify:!0,reason:"navigation"});return e.emit({type:"navigation.lastVisited",from:d,to:l.currentStepId,timestamp:b()}),e.emit({type:"step.enter",stepId:l.currentStepId,timestamp:b()}),p({previousSnapshot:i,snapshot:l,from:d,to:l.currentStepId,event:{type:"goToLastVisitedStep"},transitionId:s??null,runVersion:t}),k(l,!0,{...s!==void 0?{transitionId:s}:{}})},hasDeclaredTransitionForEvent:(s,t)=>o.some(i=>(i.from==="*"||i.from===s)&&i.event===t),commitTerminalTransition:(s,t,i,r,d,l,y=0)=>{let a=e.peekSnapshot(),u=a.history.timeline.slice(0,a.history.index+1),E=e.setSnapshot({...a,history:{timeline:u,index:u.length-1},context:l,status:t==="COMPLETE"?"completed":"terminated"},{notify:!0,reason:"transition"});return e.emit({type:"transition.success",from:s,to:t,eventType:i.type,transitionId:r,...d?.label!==void 0?{label:d.label}:{},timestamp:b()}),e.emit({type:t==="COMPLETE"?"journey.completed":"journey.terminated",stepId:E.currentStepId,timestamp:b()}),p({previousSnapshot:a,snapshot:E,from:s,to:t,event:i,transitionId:r,...d?.label!==void 0?{label:d.label}:{},runVersion:y,...d!==void 0?{transition:d}:{}}),k(E,!0,{...r!==null?{transitionId:r}:{},...d?.label!==void 0?{label:d.label}:{}})},commitStepTransition:(s,t,i,r,d,l=0)=>{V(n,t,`Transition points to unknown step "${t}".`);let y=e.peekSnapshot(),a=y.currentStepId;a!==t&&e.emit({type:"step.exit",stepId:a,timestamp:b()});let u=e.setSnapshot(me(y,t,d),{notify:!0,reason:"transition"});return e.emit({type:"transition.success",from:s,to:u.currentStepId,eventType:i.type,transitionId:r.id,...r.label!==void 0?{label:r.label}:{},timestamp:b()}),a!==u.currentStepId&&e.emit({type:"step.enter",stepId:u.currentStepId,timestamp:b()}),p({previousSnapshot:y,snapshot:u,from:s,to:u.currentStepId,event:i,transitionId:r.id,...r.label!==void 0?{label:r.label}:{},runVersion:l,transition:r}),k(u,!0,{transitionId:r.id,...r.label!==void 0?{label:r.label}:{}})}});var ge=({plugins:e,setupContext:n})=>{let o=[];for(let p of e)try{o.push({name:p.name,hooks:p.setup(n)})}catch(s){for(let r of[...o].reverse())try{r.hooks.dispose?.()}catch{}let t=s instanceof Error?s.message:String(s),i=new Error(`Journey plugin "${p.name}" setup failed: ${t}`);throw Object.assign(i,{cause:s}),i}return{hydrateSnapshot:p=>o.reduce((s,t)=>t.hooks.hydrateSnapshot?.(s)??s,p),onSnapshotChange:({previousSnapshot:p,snapshot:s,reason:t})=>{let i;for(let r of o)try{let d=r.hooks.onSnapshotChange?.({previousSnapshot:p,snapshot:s,reason:t});ae(d)&&X(`Journey plugin "${r.name}" returned a Promise from onSnapshotChange. This hook must be synchronous; returning a Promise blocks the machine and the await is dropped.`)}catch(d){i??(i=d)}if(i!==void 0)throw i},extendMachine:p=>{let s=p,t=p,i=new Map;for(let r of o){let d=r.hooks.augmentMachine?.({machine:p,journey:n.journey,resolvedJourney:n.resolvedJourney});if(d)for(let[l,y]of Object.entries(d)){let a=i.get(l);if(a)throw new Error(`Journey plugin "${r.name}" cannot add "${l}" \u2014 already provided by plugin "${a}".`);if(l in s)throw new Error(`Journey plugin "${r.name}" cannot override machine property "${l}".`);i.set(l,r.name),t[l]=y}}return s},dispose:()=>{let p;for(let s of o)try{s.hooks.dispose?.()}catch(t){p??(p=t)}if(p!==void 0)throw p}}};var Ie=({snapshot:e,onSnapshotChange:n,onDispose:o,onListenerError:p})=>{let s=H(e),t=H(s),i=new Set,r=new Set,d=Promise.resolve(),l=0,y=!1,a=null,u=new Set,E=p??((f,v)=>{Se(`Journey ${v} listener threw an error.`,f)}),g=()=>{for(let f of i)try{f()}catch(v){E(v,"snapshot")}},P=f=>{for(let v of r)try{v(f)}catch(C){E(C,"event")}},c=(f,v={})=>{let C=t,R=H(f),A=H(R);return n?.({previousSnapshot:H(C),snapshot:H(A),reason:v.reason??"transition"}),s=R,t=A,v.notify&&g(),A},S=f=>!y&&f===l,J=()=>{l+=1,a&&!a.signal.aborted&&a.abort(),a=null;for(let f of u)f.signal.aborted||f.abort();u.clear(),d=Promise.resolve()},x=f=>{if(!S(f))return null;let v=new AbortController;return S(f)?(u.add(v),v):(v.abort(),null)},h=f=>{u.delete(f)},T=(f,v)=>{let C=l,R=async()=>{if(!S(C))return v();let L=new AbortController;a=L;try{return S(C)?await f(C,L.signal):(L.abort(),v())}finally{a===L&&(a=null)}},A=d.then(R,R);return d=A.then(()=>{},()=>{}),A},m=f=>y?()=>{}:(i.add(f),()=>{i.delete(f)});return{getSnapshot:()=>t,peekSnapshot:()=>s,setSnapshot:c,isDisposed:()=>y,isRunActive:S,cancelInFlight:J,openLifecycle:x,closeLifecycle:h,queue:T,notify:g,emit:P,subscribe:m,subscribeSelector:(f,v,C)=>{if(y)return()=>{};let R=C??Object.is,A=f(t);return m(()=>{let L=f(t);if(R(A,L))return;let F=A;A=L,v(L,F)})},subscribeEvent:f=>y?()=>{}:(r.add(f),()=>{r.delete(f)}),dispose:()=>{y||(y=!0,J(),i.clear(),r.clear(),o?.())}}};var Ce=(e,n,o,p,s,t,i,r,d)=>{let l=(c="send")=>k(e.getSnapshot(),!1,{...e.isDisposed()?{error:new G(c)}:{}}),y=(c,S,J)=>k(e.getSnapshot(),!1,{...S!==void 0?{transitionId:S}:{},...J!==void 0?{label:J}:{},error:c}),a=(c,S,J,x,h,T,m=!1)=>(m||n.setStepError(c,S,J,x??void 0,T),e.emit({type:"transition.error",from:c,eventType:S,transitionId:x,...h!==void 0?{label:h}:{},error:J,timestamp:b()}),y(J,x??void 0,h)),u=(c,S)=>ee(c)?(V(s,c.stepId,`Cannot goToStepById unknown step "${c.stepId}".`),{transitionsToEvaluate:t.filter(J=>(J.from==="*"||J.from===S)&&J.event==="goToStepById"&&"to"in J&&J.to===c.stepId),earlyResult:null}):{transitionsToEvaluate:t,earlyResult:null},E=async(c,S,J,x,h)=>{let T,m=null,I,M=!1;try{T=await xe(c,H(e.peekSnapshot()),S,h,i,{onAsyncGuardStart:w=>{n.setStepLoading(J,"evaluating-when",S.type,w.id,x)},onAsyncGuardSuccess:()=>{n.setStepIdle(J,x)},onAsyncGuardError:(w,f)=>{m=w.id??null,I=w.label,M=!0,n.setStepError(J,S.type,f,w.id,x)}},d)}catch(w){return e.isRunActive(x)?{transition:null,earlyResult:a(J,S.type,w,m,I,x,M)}:{transition:null,earlyResult:l(S.type)}}return{transition:T,earlyResult:null}},g=(c,S,J)=>{if(ee(c))return l(c.type);if(c.type==="goToPreviousStep"){let x=o.applyPreviousNavigation(1,c.type,J);return x.transitioned&&e.emit({type:"transition.success",from:S,to:x.snapshot.currentStepId,eventType:c.type,transitionId:null,timestamp:b()}),x}return c.type==="goToNextStep"&&!r&&!o.hasDeclaredTransitionForEvent(S,"goToNextStep")||c.type==="completeJourney"&&!o.hasDeclaredTransitionForEvent(S,"completeJourney")?o.commitTerminalTransition(S,"COMPLETE",c,null,void 0,e.peekSnapshot().context,J):c.type==="terminateJourney"&&!o.hasDeclaredTransitionForEvent(S,"terminateJourney")?o.commitTerminalTransition(S,"TERMINATED",c,null,void 0,e.peekSnapshot().context,J):l(c.type)},P=(c,S,J,x)=>{let h=e.peekSnapshot();if(!c.updateContext)return{nextContext:h.context,earlyResult:null};try{let T=c.updateContext({snapshot:H(h),context:h.context,from:h.currentStepId,timeline:h.history.timeline,index:h.history.index,event:S});return{nextContext:j(T),earlyResult:null}}catch(T){return e.isRunActive(x)?{nextContext:null,earlyResult:a(J,S.type,T,c.id,c.label,x)}:{nextContext:null,earlyResult:l(S.type)}}};return{buildCanceledSendResult:l,executeSend:async(c,S,J)=>{if(e.peekSnapshot().status!=="running")return l(c.type);let x=e.peekSnapshot().currentStepId,h=c;if(e.emit({type:"transition.start",from:x,event:c,timestamp:b()}),p){if(ee(c))return o.commitStepTransition(x,c.stepId,h,{from:x,event:"goToStepById",to:c.stepId},e.peekSnapshot().context,S);if(c.type!=="completeJourney"&&c.type!=="terminateJourney"&&c.type!=="goToPreviousStep")return l(c.type)}let T=u(c,x);if(T.earlyResult)return T.earlyResult;let m=await E(T.transitionsToEvaluate,h,x,S,J);if(m.earlyResult)return m.earlyResult;if(!e.isRunActive(S))return l(c.type);let{transition:I}=m;if(!I)return g(c,x,S);n.setStepIdle(x,S);let M=P(I,h,x,S);if(M.earlyResult)return M.earlyResult;let w=fe(I);return K(w)?o.commitTerminalTransition(x,w,h,I.id??null,I,M.nextContext,S):o.commitStepTransition(x,w,h,I,M.nextContext,S)}}};var we=e=>{let n=2166136261;for(let o=0;o<e.length;o+=1)n^=e.charCodeAt(o),n=Math.imul(n,16777619);return(n>>>0).toString(16).padStart(8,"0")},de=e=>{let n=new Map,o=new Set;return e.map(p=>{let s=p.event==="completeJourney"?"COMPLETE":p.event==="terminateJourney"?"TERMINATED":String(p.to),t=JSON.stringify({from:p.from,event:p.event,target:s}),i=(n.get(t)??0)+1;n.set(t,i);let r=JSON.stringify({from:p.from,event:p.event,target:s,ordinal:i}),d=0,l=(()=>{let y=we(r);for(;o.has(y);)d+=1,y=we(`${r}:${d}`);return y})();return o.add(l),{...p,id:l,...p.label!==void 0?{label:p.label}:{}}})},Me=e=>{let n=[],{transitions:o}=e;if(o===void 0)return{...e,transitions:de(n)};if(Array.isArray(o)){if(o.length===0)throw new Error("Journey linear transitions must include the initial step as the first item.");let[t,...i]=o;if(typeof t!="string")throw new Error("Journey linear transitions at index 0 must be a step id string.");if(!(t in e.steps))throw new Error(`Journey linear transitions reference unknown step "${t}".`);let r=e.initial??t;if(e.initial!==void 0&&!o.map(a=>typeof a=="string"?a:a.step).includes(e.initial))throw new Error(`Journey initial step "${e.initial}" does not exist in linear transitions.`);let d=t,l=new Set([t]);for(let[y,a]of i.entries()){let u=y+1;if(typeof a=="string"){if(!(a in e.steps))throw new Error(`Journey linear transitions reference unknown step "${a}".`);if(l.has(a))throw new Error(`Journey linear transitions contain duplicate step "${a}" at index ${u}.`);l.add(a),n.push({from:d,event:"goToNextStep",to:a}),d=a;continue}if(!a||typeof a!="object"||Array.isArray(a))throw new Error(`Journey linear transitions at index ${u} must be a step id string or step config object.`);let E=new Set(["step","label","updateContext","onEnter","onLeave","timeoutMs"]);for(let g of Object.keys(a))if(!E.has(g))throw new Error(`Journey linear transition object at index ${u} contains unsupported field "${g}". Allowed fields are "step", "label", "updateContext", "onEnter", "onLeave", and "timeoutMs".`);if(typeof a.step!="string")throw new Error(`Journey linear transition object at index ${u} must define string "step".`);if(!(a.step in e.steps))throw new Error(`Journey linear transitions reference unknown step "${a.step}".`);if(l.has(a.step))throw new Error(`Journey linear transitions contain duplicate step "${a.step}" at index ${u}.`);if(l.add(a.step),a.updateContext!==void 0&&typeof a.updateContext!="function")throw new Error(`Journey linear transition object at index ${u} must define "updateContext" as a function when provided.`);if(a.onEnter!==void 0&&typeof a.onEnter!="function")throw new Error(`Journey linear transition object at index ${u} must define "onEnter" as a function when provided.`);if(a.onLeave!==void 0&&typeof a.onLeave!="function")throw new Error(`Journey linear transition object at index ${u} must define "onLeave" as a function when provided.`);z(a.timeoutMs,`Journey linear transition object at index ${u}`),n.push({...a.label!==void 0?{label:a.label}:{},...a.timeoutMs!==void 0?{timeoutMs:a.timeoutMs}:{},...a.updateContext!==void 0?{updateContext:a.updateContext}:{},...a.onEnter!==void 0?{onEnter:a.onEnter}:{},...a.onLeave!==void 0?{onLeave:a.onLeave}:{},from:d,event:"goToNextStep",to:a.step}),d=a.step}return{...e,initial:r,transitions:de(n)}}if(!o||typeof o!="object")throw new Error("Journey transitions must be an array or an object map when provided.");let p=o,s=[...Object.entries(p).filter(([t])=>t!=="global"),...p.global?[["global",p.global]]:[]];for(let[t,i]of s){if(t!=="global"&&!(t in e.steps))throw new Error(`Journey transitions reference unknown step "${t}".`);if(!i||typeof i!="object"||Array.isArray(i))throw new Error(`Journey transitions for "${t}" must be an event map object.`);for(let[r,d]of Object.entries(i)){let l=r==="completeJourney"||r==="terminateJourney",y=l&&(d===!0||Array.isArray(d)&&d.length===0)?[{}]:d;if(!Array.isArray(y))throw new Error(`Journey transitions for "${t}.${r}" must be an array.`);for(let[a,u]of y.entries()){if(!u||typeof u!="object")throw new Error(`Journey transition at "${t}.${r}[${a}]" must be an object.`);let E=new Set(l?["when","updateContext","onEnter","onLeave","label","timeoutMs"]:["to","when","updateContext","onEnter","onLeave","label","timeoutMs"]);for(let g of Object.keys(u))if(!E.has(g))throw new Error(`Journey transition at "${t}.${r}[${a}]" contains unsupported field "${g}".`);if(!l&&typeof u.to!="string")throw new Error(`Journey transition at "${t}.${r}[${a}]" must define string "to".`);if(u.when!==void 0&&typeof u.when!="function")throw new Error(`Journey transition at "${t}.${r}[${a}]" must define "when" as a function when provided.`);if(u.updateContext!==void 0&&typeof u.updateContext!="function")throw new Error(`Journey transition at "${t}.${r}[${a}]" must define "updateContext" as a function when provided.`);if(u.onEnter!==void 0&&typeof u.onEnter!="function")throw new Error(`Journey transition at "${t}.${r}[${a}]" must define "onEnter" as a function when provided.`);if(u.onLeave!==void 0&&typeof u.onLeave!="function")throw new Error(`Journey transition at "${t}.${r}[${a}]" must define "onLeave" as a function when provided.`);if(u.label!==void 0&&typeof u.label!="string")throw new Error(`Journey transition at "${t}.${r}[${a}]" must define "label" as a string when provided.`);z(u.timeoutMs,`Journey transition at "${t}.${r}[${a}]"`),n.push({...u,from:t==="global"?"*":t,event:r})}}}return{...e,transitions:de(n)}};function Re(e,n){if(!e.steps||typeof e.steps!="object")throw new Error("Journey steps must be a record object.");if(e.transitions!==void 0&&(e.transitions===null||typeof e.transitions!="object"&&!Array.isArray(e.transitions)))throw new Error("Journey transitions must be an array or an object map when provided.");for(let T of Object.keys(e.steps))if(T==="*"||T==="global"||T==="COMPLETE"||T==="TERMINATED")throw new Error(`Step id "${T}" is reserved and cannot be used as a step name.`);if(e.initial===void 0&&!Array.isArray(e.transitions))throw new Error('Journey "initial" is required for graph and headless definitions. For linear transitions, initial defaults to the first array element.');j(e.context);let o=Me(e);V(o.steps,o.initial,`Journey initial step "${o.initial}" does not exist in steps registry.`),Je(o.transitions,o.steps);let p=n?.requireExplicitCompletion??!1;z(n?.defaultTimeoutMs,"Journey machine options");let s=n?.defaultTimeoutMs,t=B(o.context),i=Object.fromEntries(Object.keys(o.steps).map(T=>[T,ie(o.steps[T].meta)])),r=()=>D([o.initial],0,B(t),"idled",Z(o.steps)),d=ge({plugins:n?.plugins??[],setupContext:{journey:e,resolvedJourney:o,options:{requireExplicitCompletion:p,defaultTimeoutMs:s},buildInitialSnapshot:r}}),l=d.hydrateSnapshot(r());j(l.context,"Journey hydrated context");let y=n?.onListenerError,a=n?.onLifecycleError,u=Ie({snapshot:l,onSnapshotChange:d.onSnapshotChange,onDispose:d.dispose,...y!==void 0?{onListenerError:y}:{}}),E=he({runtime:u}),g=()=>Promise.resolve(k(u.getSnapshot(),!1)),P=({previousSnapshot:T,snapshot:m,from:I,to:M,event:w,transitionId:f,label:v,runVersion:C,transition:R})=>{let A=o.steps[I],L=K(M)?null:o.steps[M],F=o.handlers??{},U=O=>!u.isRunActive(C)||u.isDisposed()?Promise.resolve(k(u.getSnapshot(),!1)):g(O),ne=u.openLifecycle(C);if(!ne)return;let{signal:$}=ne,W=(O,Oe)=>{let ue={phase:Oe,from:I,to:M,eventType:w.type,transitionId:f,...v!==void 0?{label:v}:{}};u.emit({type:"lifecycle.error",...ue,error:O,timestamp:b()}),a?.(O,ue)};(async()=>{try{if(A?.onLeave)try{await A.onLeave({snapshot:T,context:T.context,from:I,to:M,event:w,transitionId:f,...v!==void 0?{label:v}:{},handlers:F,signal:$,dispatch:U})}catch(O){if($.aborted||!u.isRunActive(C))return;W(O,"step.onLeave");return}if(!u.isRunActive(C))return;if(R?.onLeave)try{await R.onLeave({snapshot:T,context:T.context,from:I,to:M,event:w,transitionId:f,...R.label!==void 0?{label:R.label}:{},handlers:F,signal:$,dispatch:U})}catch(O){if($.aborted||!u.isRunActive(C))return;W(O,"transition.onLeave");return}if(!u.isRunActive(C))return;if(L?.onEnter)try{await L.onEnter({snapshot:m,context:m.context,from:I,to:M,event:w,transitionId:f,...v!==void 0?{label:v}:{},handlers:F,signal:$,dispatch:U})}catch(O){if($.aborted||!u.isRunActive(C))return;W(O,"step.onEnter");return}if(!u.isRunActive(C))return;if(R?.onEnter)try{await R.onEnter({snapshot:m,context:m.context,from:I,to:M,event:w,transitionId:f,...R.label!==void 0?{label:R.label}:{},handlers:F,signal:$,dispatch:U})}catch(O){if($.aborted||!u.isRunActive(C))return;W(O,"transition.onEnter");return}}finally{u.closeLifecycle(ne)}})()},c=be({runtime:u,steps:o.steps,transitions:o.transitions,scheduleLifecycle:P}),S=Ce(u,E,c,e.transitions===void 0,o.steps,o.transitions,o.handlers??{},p,s),J=Ee({runtime:u,asyncState:E,initial:o.initial,initialContext:t,steps:o.steps}),x=ve(e,o,u.getSnapshot),h={getSnapshot:u.getSnapshot,getStepMeta:T=>ie(i[T]),getComputed:x,startJourney:J.startJourney,subscribe:u.subscribe,subscribeSelector:u.subscribeSelector,subscribeEvent:u.subscribeEvent,subscribeStart:T=>u.subscribeEvent(m=>{m.type==="journey.start"&&T(m)}),subscribeReset:T=>u.subscribeEvent(m=>{m.type==="journey.reset"&&T(m)}),subscribeComplete:T=>u.subscribeEvent(m=>{m.type==="journey.completed"&&T(m)}),subscribeTerminate:T=>u.subscribeEvent(m=>{m.type==="journey.terminated"&&T(m)}),resetJourney:J.resetJourney,updateContext:J.updateContext,clearStepError:J.clearStepError,dispose:J.dispose,goToPreviousStep:T=>u.queue(async m=>c.applyPreviousNavigation(T,"goToPreviousStep",m),()=>S.buildCanceledSendResult("goToPreviousStep")),goToLastVisitedStep:()=>u.queue(async T=>c.applyLastVisitedNavigation("goToLastVisitedStep",T),()=>S.buildCanceledSendResult("goToLastVisitedStep")),goToNextStep:()=>h.send({type:"goToNextStep"}),goToStepById:T=>h.send({type:"goToStepById",stepId:T}),terminateJourney:T=>T===void 0?h.send({type:"terminateJourney"}):h.send({type:"terminateJourney",payload:T}),completeJourney:T=>T===void 0?h.send({type:"completeJourney"}):h.send({type:"completeJourney",payload:T}),send:T=>u.queue((m,I)=>S.executeSend(T,m,I),()=>S.buildCanceledSendResult(T.type))};return g=h.send,d.extendMachine(h)}function N(e){return{_candidate:e,when(n){return N({...e,_when:n})},updateContext(n){return N({...e,_updateContext:n})},onEnter(n){return N({...e,_onEnter:n})},onLeave(n){return N({...e,_onLeave:n})},label(n){return N({...e,_label:n})},timeoutMs(n){return N({...e,_timeoutMs:n})}}}function ke(e){let n={to:e._to};return e._when!==void 0&&(n.when=e._when),e._updateContext!==void 0&&(n.updateContext=e._updateContext),e._onEnter!==void 0&&(n.onEnter=e._onEnter),e._onLeave!==void 0&&(n.onLeave=e._onLeave),e._label!==void 0&&(n.label=e._label),e._timeoutMs!==void 0&&(n.timeoutMs=e._timeoutMs),n}function qe(e){let n={};return e.when!==void 0&&(n.when=e.when),e.updateContext!==void 0&&(n.updateContext=e.updateContext),e.onEnter!==void 0&&(n.onEnter=e.onEnter),e.onLeave!==void 0&&(n.onLeave=e.onLeave),e.label!==void 0&&(n.label=e.label),e.timeoutMs!==void 0&&(n.timeoutMs=e.timeoutMs),n}function Ae(){function e(t){return N({_to:t,_when:void 0,_updateContext:void 0,_onEnter:void 0,_onLeave:void 0,_label:void 0,_timeoutMs:void 0})}function n(t){return typeof t=="function"?t({to:e}):t}function o(t){return t===!0||t.length===0?t:t.map(i=>qe(i))}function p(t,i){return{id:t,_meta:i?.meta,_onEnter:i?.onEnter,_onLeave:i?.onLeave,_on:i?.on}}function s(t){let i={},r={};for(let d of t.steps)if(i[d.id]={...d._meta!==void 0?{meta:d._meta}:{},...d._onEnter!==void 0?{onEnter:d._onEnter}:{},...d._onLeave!==void 0?{onLeave:d._onLeave}:{}},d._on){let l={};for(let[y,a]of Object.entries(d._on)){if(!a)continue;if(y==="completeJourney"||y==="terminateJourney"){l[y]=o(a);continue}let u=n(a);l[y]=u.map(E=>ke(E._candidate))}r[d.id]=l}if(t.global){let d={};for(let[l,y]of Object.entries(t.global))y!==void 0&&(l==="completeJourney"||l==="terminateJourney"?d[l]=o(y):Array.isArray(y)&&(d[l]=y.map(a=>ke(a._candidate))));r.global=d}return{initial:t.initial,context:t.context,...t.handlers!==void 0?{handlers:t.handlers}:{},steps:i,transitions:r}}return{createStep:p,to:e,build:s}}0&&(module.exports={JourneyDisposedError,createJourneyBuilder,createJourneyMachine});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|