@rxova/journey-core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -112
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,137 +1,79 @@
|
|
|
1
1
|
# @rxova/journey-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p>
|
|
4
|
+
<a href="https://www.npmjs.com/package/@rxova/journey-core">
|
|
5
|
+
<img src="https://img.shields.io/badge/npm-%40rxova%2Fjourney--core-CB3837?logo=npm&logoColor=white" alt="npm package @rxova/journey-core" />
|
|
6
|
+
</a>
|
|
7
|
+
<a href="https://rxova.org/docs/core/getting-started">
|
|
8
|
+
<img src="https://img.shields.io/badge/docs-core-0f8f6a" alt="Core docs" />
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://github.com/rxova/journey/actions/workflows/ci.yml">
|
|
11
|
+
<img src="https://github.com/rxova/journey/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI" />
|
|
12
|
+
</a>
|
|
13
|
+
<img src="https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white" alt="TypeScript" />
|
|
14
|
+
<img src="https://img.shields.io/badge/coverage%20(core)-100%25-brightgreen" alt="Core coverage" />
|
|
15
|
+
<a href="https://www.npmjs.com/package/@rxova/journey-core">
|
|
16
|
+
<img src="https://img.shields.io/npm/v/@rxova/journey-core" alt="npm version" />
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://www.npmjs.com/package/@rxova/journey-core">
|
|
19
|
+
<img src="https://img.shields.io/npm/dm/@rxova/journey-core" alt="npm downloads" />
|
|
20
|
+
</a>
|
|
21
|
+
<a href="https://bundlephobia.com/package/@rxova/journey-core">
|
|
22
|
+
<img src="https://img.shields.io/bundlephobia/minzip/%40rxova%2Fjourney-core" alt="Bundlephobia" />
|
|
23
|
+
</a>
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
Headless runtime for step journeys and non-linear flows.
|
|
27
|
+
|
|
28
|
+
Use `@rxova/journey-core` when you want flow logic that is independent from UI frameworks.
|
|
29
|
+
|
|
30
|
+
`[GETTING STARTED](https://rxova.org/docs/core/getting-started) | [ARCHITECTURE](https://rxova.org/docs/core/architecture) | [API](https://rxova.org/docs/core/api) | [HISTORY](https://rxova.org/docs/core/history) | [PERSISTENCE](https://rxova.org/docs/core/persistence) | [ASYNC](https://rxova.org/docs/core/async) | [EXAMPLES](https://rxova.org/docs/core/examples)`
|
|
4
31
|
|
|
5
32
|
## Install
|
|
6
33
|
|
|
7
34
|
```bash
|
|
8
|
-
|
|
9
|
-
npm install @rxova/journey-core
|
|
10
|
-
yarn add @rxova/journey-core
|
|
35
|
+
npm i @rxova/journey-core
|
|
11
36
|
```
|
|
12
37
|
|
|
13
|
-
##
|
|
38
|
+
## What You Get
|
|
14
39
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
type JourneyDefinition
|
|
20
|
-
} from "@rxova/journey-core";
|
|
21
|
-
|
|
22
|
-
type StepId = "one" | "two" | "three";
|
|
23
|
-
type Event = "next" | "submit";
|
|
24
|
-
type Ctx = { name: string };
|
|
25
|
-
|
|
26
|
-
const journey: JourneyDefinition<Ctx, StepId, Event> = {
|
|
27
|
-
initial: "one",
|
|
28
|
-
context: { name: "" },
|
|
29
|
-
steps: {
|
|
30
|
-
one: {},
|
|
31
|
-
two: {},
|
|
32
|
-
three: {}
|
|
33
|
-
},
|
|
34
|
-
transitions: [
|
|
35
|
-
{ from: "one", event: "next", to: "two" },
|
|
36
|
-
{ from: "two", event: "next", to: "three" },
|
|
37
|
-
{ from: "three", event: "submit", to: JOURNEY_TERMINAL.COMPLETE }
|
|
38
|
-
]
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const machine = createJourneyMachine<Ctx, StepId, Event>(journey);
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## History behavior
|
|
45
|
-
|
|
46
|
-
The machine tracks two related collections:
|
|
47
|
-
|
|
48
|
-
- `history`: ordered list of prior steps. It grows when you move to a different step.
|
|
49
|
-
- `visited`: list of steps you have reached (including current), with duplicates removed. It is not affected by history trimming.
|
|
50
|
-
|
|
51
|
-
Why `visited` is a list (not a `Set`) for the following reasons:
|
|
52
|
-
|
|
53
|
-
- JSON-friendly for snapshots, logs, and persistence.
|
|
54
|
-
- Deterministic order for tests and UI rendering.
|
|
55
|
-
- Easier to consume in TypeScript (`readonly TStepId[]`).
|
|
56
|
-
- It is derived from `history + current` initially, then maintained independently so trimming history does not remove earlier entries.
|
|
57
|
-
|
|
58
|
-
History is used when you target `HISTORY_TARGET` in a transition. It resolves to the most recent valid step in `history`. If history is empty (or contains invalid steps), the machine stays on the current step.
|
|
40
|
+
- Strongly typed journey definition and events.
|
|
41
|
+
- Deterministic transition matching.
|
|
42
|
+
- Built-in history, persistence helpers, and async lifecycle hooks.
|
|
43
|
+
- A reusable machine API you can run in frontend or backend code.
|
|
59
44
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
You can cap history growth with `maxHistory`. When the history exceeds that limit, the oldest entries are trimmed.
|
|
63
|
-
|
|
64
|
-
Defaults:
|
|
65
|
-
|
|
66
|
-
- `maxHistory`: `50`
|
|
67
|
-
- `maxHistory: null` disables trimming entirely.
|
|
68
|
-
|
|
69
|
-
Automatic trimming happens:
|
|
70
|
-
|
|
71
|
-
- After transitions (including `goTo`)
|
|
72
|
-
- After persistence hydrate
|
|
73
|
-
|
|
74
|
-
### Overflow callback
|
|
75
|
-
|
|
76
|
-
`onOverflow` fires only when trimming actually happens. It receives:
|
|
77
|
-
|
|
78
|
-
- `previous`: history before trimming
|
|
79
|
-
- `next`: history after trimming
|
|
80
|
-
- `trimmed`: entries removed
|
|
81
|
-
- `maxHistory`: resolved limit (number or `null`)
|
|
82
|
-
- `reason`: `"auto" | "hydrate" | "manual"`
|
|
83
|
-
- `auto`: trimming happened automatically during a transition (including `goTo`)
|
|
84
|
-
- `hydrate`: trimming happened right after loading persisted state
|
|
85
|
-
- `manual`: trimming happened because you called `trimHistory()`
|
|
86
|
-
|
|
87
|
-
### Config example
|
|
45
|
+
## Quickstart
|
|
88
46
|
|
|
89
47
|
```ts
|
|
90
|
-
|
|
91
|
-
history: {
|
|
92
|
-
maxHistory: 20,
|
|
93
|
-
onOverflow: ({ trimmed, reason }) => {
|
|
94
|
-
console.warn("trimmed history", trimmed, "reason:", reason);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
```
|
|
48
|
+
import { createJourneyMachine, JOURNEY_TERMINAL } from "@rxova/journey-core";
|
|
99
49
|
|
|
100
|
-
|
|
50
|
+
type StepId = "start" | "review";
|
|
51
|
+
type Event = "next" | "submit";
|
|
101
52
|
|
|
102
|
-
|
|
103
|
-
import { HISTORY_TARGET } from "@rxova/journey-core";
|
|
53
|
+
type Ctx = { name: string };
|
|
104
54
|
|
|
105
|
-
|
|
106
|
-
|
|
55
|
+
// 1) Describe the flow as data.
|
|
56
|
+
const journey = {
|
|
57
|
+
initial: "start",
|
|
107
58
|
context: { name: "" },
|
|
108
|
-
steps: {
|
|
109
|
-
one: {},
|
|
110
|
-
two: {},
|
|
111
|
-
three: {}
|
|
112
|
-
},
|
|
59
|
+
steps: { start: {}, review: {} },
|
|
113
60
|
transitions: [
|
|
114
|
-
{ from: "
|
|
115
|
-
{ from: "
|
|
116
|
-
{ from: "*", event: "back", to: HISTORY_TARGET }
|
|
61
|
+
{ from: "start", event: "next", to: "review" },
|
|
62
|
+
{ from: "review", event: "submit", to: JOURNEY_TERMINAL.COMPLETE }
|
|
117
63
|
]
|
|
118
64
|
};
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### Manual history management
|
|
122
65
|
|
|
123
|
-
|
|
124
|
-
const machine = createJourneyMachine
|
|
66
|
+
// 2) Create a machine instance.
|
|
67
|
+
const machine = createJourneyMachine<Ctx, StepId, Event>(journey);
|
|
125
68
|
|
|
126
|
-
|
|
127
|
-
await machine.send({ type: "
|
|
69
|
+
// 3) Drive the flow with typed events.
|
|
70
|
+
await machine.send({ type: "next" });
|
|
128
71
|
|
|
129
|
-
|
|
130
|
-
machine.
|
|
72
|
+
// 4) Read immutable runtime state at any time.
|
|
73
|
+
const snapshot = machine.getSnapshot();
|
|
74
|
+
console.log(snapshot.current);
|
|
131
75
|
```
|
|
132
76
|
|
|
133
|
-
##
|
|
77
|
+
## Coverage Notes
|
|
134
78
|
|
|
135
|
-
-
|
|
136
|
-
- API: ../../docs/API.md
|
|
137
|
-
- React bindings: ../react
|
|
79
|
+
Coverage badge is package-specific (`packages/core/test` against `packages/core/src`), not monorepo-wide.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rxova/journey-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Journey core state machine.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"journey",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
},
|
|
20
20
|
"repository": {
|
|
21
21
|
"type": "git",
|
|
22
|
-
"url": "git+https://github.com/rxova/journey.git"
|
|
22
|
+
"url": "git+https://github.com/rxova/journey.git",
|
|
23
|
+
"directory": "packages/core"
|
|
23
24
|
},
|
|
24
25
|
"publishConfig": {
|
|
25
26
|
"access": "public"
|