@rxova/journey-core 0.6.0 → 0.6.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 (2) hide show
  1. package/README.md +78 -3
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -11,11 +11,13 @@ npm i @rxova/journey-core
11
11
  ## What You Get
12
12
 
13
13
  - Deterministic transition matching (first match wins).
14
- - Timeline + pointer navigation model.
15
- - Built-in `goToNextStep()`, `terminateJourney()`, `completeJourney()`, `goToPreviousStep()`, and `goToLastVisitedStep()`.
14
+ - Timeline + pointer navigation model (`history.timeline` + `history.index`).
15
+ - Built-in navigation and terminal events:
16
+ `goToNextStep()`, `goToPreviousStep()`, `goToLastVisitedStep()`, `completeJourney()`, `terminateJourney()`.
17
+ - Async guard/effect lifecycle state in `snapshot.async`.
16
18
  - Typed observability stream via `subscribeEvent`.
17
19
  - Step metadata updates via `updateStepMetadata`.
18
- - Optional persistence helpers.
20
+ - Optional persistence with schema versioning and migration hooks.
19
21
 
20
22
  ## Quickstart
21
23
 
@@ -48,6 +50,72 @@ const snapshot = machine.getSnapshot();
48
50
  console.log(snapshot.history.timeline, snapshot.history.index, snapshot.currentStepId);
49
51
  ```
50
52
 
53
+ ## Behavioral Guarantees
54
+
55
+ - Transition selection is ordered: the first matching transition wins.
56
+ - `send({ type: "back" })` falls back to previous-step navigation when no explicit `back` transition exists.
57
+ - Once status is `complete` or `terminated`, pointer navigation and transitions no-op until `resetMachine()`.
58
+ - Forward navigation after moving back truncates timeline tail before appending the next step.
59
+ - Snapshot shape is stable: `currentStepId === history.timeline[history.index]`.
60
+
61
+ ## Async Lifecycle
62
+
63
+ When guards/effects are async, step async state is tracked in `snapshot.async.byStep[stepId]`:
64
+
65
+ - `evaluating-when`: async guard in progress
66
+ - `running-effect`: async effect in progress
67
+ - `error`: guard/effect rejected
68
+ - `idle`: no active async work
69
+
70
+ `clearStepError(stepId?)` resets a step from `error` to `idle`.
71
+
72
+ ## Persistence
73
+
74
+ Persistence is optional and disabled automatically if storage is unavailable.
75
+
76
+ ```ts
77
+ const machine = createJourneyMachine(journey, {
78
+ persistence: {
79
+ key: "checkout:journey",
80
+ version: 2,
81
+ clearOnReset: false,
82
+ migrate: (legacySnapshot, persistedVersion) => {
83
+ if (persistedVersion < 2) {
84
+ return {
85
+ currentStepId: "start",
86
+ history: { timeline: ["start"], index: 0 },
87
+ context: { name: "" },
88
+ status: "running",
89
+ visited: { start: true, review: false },
90
+ stepMeta: { start: undefined, review: undefined }
91
+ };
92
+ }
93
+ return legacySnapshot as never;
94
+ },
95
+ onError: (error) => {
96
+ console.error("Persistence error", error);
97
+ }
98
+ }
99
+ });
100
+ ```
101
+
102
+ Hydration coercion is defensive: malformed timeline/index/visited/status values fall back to safe defaults.
103
+
104
+ ## Observability
105
+
106
+ Use `subscribeEvent` to inspect transition and navigation lifecycle events:
107
+
108
+ - `transition.start`
109
+ - `transition.success`
110
+ - `transition.error`
111
+ - `step.exit`
112
+ - `step.enter`
113
+ - `navigation.previous`
114
+ - `navigation.lastVisited`
115
+ - `journey.complete`
116
+ - `journey.close`
117
+ - `metadata.updated`
118
+
51
119
  ## Transition Ergonomics
52
120
 
53
121
  ```ts
@@ -55,6 +123,13 @@ import { createTransitions, tx } from "@rxova/journey-core";
55
123
 
56
124
  const transitions = createTransitions(
57
125
  tx.from("start").on("goToNextStep").to("review"),
126
+ tx
127
+ .from("review")
128
+ .on("goToNextStep")
129
+ .choose(
130
+ tx.when(({ context }) => context.canSubmit).to("done", { id: "review-submit" }),
131
+ tx.otherwise().to("review", { id: "review-stay" })
132
+ ),
58
133
  tx.from("review").toComplete()
59
134
  );
60
135
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rxova/journey-core",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Journey core state machine.",
5
5
  "keywords": [
6
6
  "journey",