@xmachines/play-xstate 3.0.0 → 5.0.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 +190 -68
- package/dist/capabilities.d.ts +93 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +4 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/define-player.d.ts +7 -1
- package/dist/define-player.d.ts.map +1 -1
- package/dist/define-player.js +9 -60
- package/dist/define-player.js.map +1 -1
- package/dist/errors.d.ts +64 -23
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +93 -31
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -6
- package/dist/index.js.map +1 -1
- package/dist/player-actor.d.ts +73 -137
- package/dist/player-actor.d.ts.map +1 -1
- package/dist/player-actor.js +108 -254
- package/dist/player-actor.js.map +1 -1
- package/dist/routing/build-url.d.ts +8 -1
- package/dist/routing/build-url.d.ts.map +1 -1
- package/dist/routing/build-url.js +34 -54
- package/dist/routing/build-url.js.map +1 -1
- package/dist/routing/derive-current-route.d.ts +12 -38
- package/dist/routing/derive-current-route.d.ts.map +1 -1
- package/dist/routing/derive-current-route.js +24 -82
- package/dist/routing/derive-current-route.js.map +1 -1
- package/dist/routing/derive-initial-route.d.ts +2 -1
- package/dist/routing/derive-initial-route.d.ts.map +1 -1
- package/dist/routing/derive-initial-route.js +13 -2
- package/dist/routing/derive-initial-route.js.map +1 -1
- package/dist/routing/derive-route.d.ts +81 -2
- package/dist/routing/derive-route.d.ts.map +1 -1
- package/dist/routing/derive-route.js +97 -3
- package/dist/routing/derive-route.js.map +1 -1
- package/dist/routing/format-play-route-transitions.d.ts +8 -2
- package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
- package/dist/routing/format-play-route-transitions.js +175 -43
- package/dist/routing/format-play-route-transitions.js.map +1 -1
- package/dist/routing/index.d.ts +1 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/types.d.ts +9 -5
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/state-meta.d.ts +52 -0
- package/dist/state-meta.d.ts.map +1 -0
- package/dist/state-meta.js +77 -0
- package/dist/state-meta.js.map +1 -0
- package/dist/types.d.ts +20 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/view/derive-current-view.d.ts +7 -6
- package/dist/view/derive-current-view.d.ts.map +1 -1
- package/dist/view/derive-current-view.js +7 -6
- package/dist/view/derive-current-view.js.map +1 -1
- package/dist/with-routing.d.ts +45 -0
- package/dist/with-routing.d.ts.map +1 -0
- package/dist/with-routing.js +140 -0
- package/dist/with-routing.js.map +1 -0
- package/dist/with-view.d.ts +57 -0
- package/dist/with-view.d.ts.map +1 -0
- package/dist/with-view.js +158 -0
- package/dist/with-view.js.map +1 -0
- package/package.json +40 -18
- package/dist/guards/compose.d.ts +0 -158
- package/dist/guards/compose.d.ts.map +0 -1
- package/dist/guards/compose.js +0 -188
- package/dist/guards/compose.js.map +0 -1
- package/dist/guards/helpers.d.ts +0 -62
- package/dist/guards/helpers.d.ts.map +0 -1
- package/dist/guards/helpers.js +0 -85
- package/dist/guards/helpers.js.map +0 -1
- package/dist/guards/index.d.ts +0 -20
- package/dist/guards/index.d.ts.map +0 -1
- package/dist/guards/index.js +0 -18
- package/dist/guards/index.js.map +0 -1
- package/dist/guards/types.d.ts +0 -22
- package/dist/guards/types.d.ts.map +0 -1
- package/dist/guards/types.js +0 -2
- package/dist/guards/types.js.map +0 -1
package/dist/player-actor.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { Actor, } from "xstate";
|
|
2
|
-
import { AbstractActor, reuseComposedState, shallowEqualExcept, } from "@xmachines/play-actor";
|
|
3
2
|
import { DISPOSE } from "@xmachines/play";
|
|
4
|
-
import {
|
|
3
|
+
import { createWritableAtom } from "@xmachines/play-atom";
|
|
5
4
|
import { ActorThrewNonErrorError, InvalidEventError, InvalidMachineError } from "./errors.js";
|
|
6
|
-
import { deriveCurrentRoute, deriveInitialRoute } from "./routing/index.js";
|
|
7
|
-
import { deriveCurrentView } from "./view/derive-current-view.js";
|
|
8
5
|
/**
|
|
9
6
|
* Tells you if a value is an `Error`, by its identity or by its brand: `instanceof`
|
|
10
7
|
* misses an error from another realm, such as an iframe or `node:vm`. The function
|
|
@@ -25,13 +22,15 @@ const isRealError = (value) => {
|
|
|
25
22
|
/**
|
|
26
23
|
* Normalizes a failure of the actor for `onError`.
|
|
27
24
|
*
|
|
25
|
+
* @internal
|
|
26
|
+
*
|
|
28
27
|
* The function gives an `Error` to the handler without a change. The error of the
|
|
29
28
|
* machine therefore keeps its identity: an `instanceof` test of a consumer still
|
|
30
29
|
* works, and the path without an `onError` throws that same object again. Every
|
|
31
30
|
* other value is ours to build, and it becomes a `PlayError` with a code. That
|
|
32
31
|
* error carries the value from the throw as its `cause`.
|
|
33
32
|
*/
|
|
34
|
-
const toError = (value) => {
|
|
33
|
+
export const toError = (value) => {
|
|
35
34
|
try {
|
|
36
35
|
if (isRealError(value)) {
|
|
37
36
|
return value;
|
|
@@ -45,74 +44,32 @@ const toError = (value) => {
|
|
|
45
44
|
return new ActorThrewNonErrorError(value);
|
|
46
45
|
};
|
|
47
46
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* The function walks exactly the shape that `deriveCurrentView` builds: the spec
|
|
51
|
-
* fields, then `elements`, then the `props` object of each element. It compares
|
|
52
|
-
* each leaf with `Object.is`. It never enters the VALUE of a prop: a new reference
|
|
53
|
-
* therefore emits the view again, also when the contents are equal. This design
|
|
54
|
-
* keeps two things correct: a prop of a container (a Map, a Set, or an instance of a
|
|
55
|
-
* class, which a structural comparison cannot see), and a cyclic value, which gives
|
|
56
|
-
* a structural comparison a recursion without an end.
|
|
57
|
-
*/
|
|
58
|
-
const viewSpecsEquivalent = (a, b) => {
|
|
59
|
-
if (a === b)
|
|
60
|
-
return true;
|
|
61
|
-
if (!a || !b)
|
|
62
|
-
return false;
|
|
63
|
-
if (!shallowEqualExcept(a, b, "elements"))
|
|
64
|
-
return false;
|
|
65
|
-
const aElements = a.elements ?? {};
|
|
66
|
-
const bElements = b.elements ?? {};
|
|
67
|
-
// A derived spec spreads the same static meta.view. Therefore the elements
|
|
68
|
-
// usually have the same reference, and the walk over each element is then not
|
|
69
|
-
// necessary.
|
|
70
|
-
if (aElements === bElements)
|
|
71
|
-
return true;
|
|
72
|
-
const elementKeys = Object.keys(aElements);
|
|
73
|
-
if (elementKeys.length !== Object.keys(bElements).length)
|
|
74
|
-
return false;
|
|
75
|
-
for (const key of elementKeys) {
|
|
76
|
-
const aElement = aElements[key]; // nosemgrep: gitlab.eslint.detect-object-injection
|
|
77
|
-
const bElement = bElements[key]; // nosemgrep: gitlab.eslint.detect-object-injection
|
|
78
|
-
if (aElement === bElement)
|
|
79
|
-
continue;
|
|
80
|
-
if (!aElement || !bElement)
|
|
81
|
-
return false;
|
|
82
|
-
if (!shallowEqualExcept(aElement, bElement, "props"))
|
|
83
|
-
return false;
|
|
84
|
-
if (!shallowEqualExcept(aElement.props ?? {}, bElement.props ?? {}))
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
return true;
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Tells you if a snapshot is worth a propagation to the signals: an active
|
|
47
|
+
* Tells you if a snapshot is worth a propagation to the atoms: an active
|
|
91
48
|
* snapshot, or a "done" snapshot, which means that the machine reached a final state
|
|
92
49
|
* at the top level. The code skips an error snapshot and a stopped snapshot.
|
|
93
|
-
* Therefore the
|
|
50
|
+
* Therefore the atoms keep the last observable state, and they show no artifact of
|
|
94
51
|
* a teardown or of an error.
|
|
95
52
|
*/
|
|
96
53
|
const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snapshot.status === "done";
|
|
97
54
|
/**
|
|
98
|
-
* The concrete XState actor. It implements the
|
|
55
|
+
* The concrete XState actor. It implements the atom protocol of the Play Architecture
|
|
99
56
|
*
|
|
100
|
-
* The class extends
|
|
101
|
-
*
|
|
57
|
+
* The class extends the `Actor` class of XState directly, and it implements
|
|
58
|
+
* {@link @xmachines/play-actor!PlayActor}. It gives you the XState v5 integration, and it keeps the
|
|
102
59
|
* compatibility with the ecosystem, such as the XState inspection and the devtools.
|
|
103
60
|
* The constructor of the base class receives the machine. Therefore a `PlayerActor`
|
|
104
61
|
* **is** the XState actor, and it is no wrapper around one: every member of the
|
|
105
62
|
* XState `Actor` class works on the state of this instance, and this class adds the
|
|
106
|
-
* reactive state on the
|
|
63
|
+
* reactive state on the atoms for the observation by the infrastructure.
|
|
107
64
|
*
|
|
108
65
|
* **Capabilities:** the class implements both the
|
|
109
|
-
* {@link @xmachines/play-
|
|
110
|
-
* {@link @xmachines/play-
|
|
66
|
+
* {@link @xmachines/play-router!index.Routable} interface and the
|
|
67
|
+
* {@link @xmachines/play-view!index.Viewable} interface. It therefore supports the
|
|
111
68
|
* routing and the view rendering.
|
|
112
69
|
*
|
|
113
70
|
* **Architectural context:** the class implements **Actor Authority (INV-01)**,
|
|
114
71
|
* because the guards of the XState machine control every decision of the
|
|
115
|
-
* navigation. The infrastructure observes the
|
|
72
|
+
* navigation. The infrastructure observes the atoms of the actor (`state`,
|
|
116
73
|
* `currentRoute`, and `currentView`), but it changes no state directly: every
|
|
117
74
|
* change goes through the event handlers of the state machine.
|
|
118
75
|
*
|
|
@@ -122,7 +79,7 @@ const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snaps
|
|
|
122
79
|
* The creation of an actor, and its lifecycle
|
|
123
80
|
* ```typescript
|
|
124
81
|
* import { setup } from "xstate";
|
|
125
|
-
* import { definePlayer } from "@xmachines/play-xstate";
|
|
82
|
+
* import { definePlayer, compose, PlayerActor } from "@xmachines/play-xstate";
|
|
126
83
|
*
|
|
127
84
|
* const machine = setup({}).createMachine({
|
|
128
85
|
* initial: 'idle',
|
|
@@ -144,33 +101,31 @@ const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snaps
|
|
|
144
101
|
* const actor = createPlayer();
|
|
145
102
|
* actor.start();
|
|
146
103
|
*
|
|
147
|
-
* // Observe the
|
|
104
|
+
* // Observe the atoms
|
|
148
105
|
* console.log(actor.currentRoute.get()); // '/'
|
|
149
106
|
* console.log(actor.currentView.get()?.root); // 'home'
|
|
150
107
|
* ```
|
|
151
108
|
*
|
|
152
109
|
* @example
|
|
153
|
-
* The
|
|
110
|
+
* The atom lifecycle with a watch
|
|
154
111
|
* ```typescript
|
|
155
|
-
* import {
|
|
112
|
+
* import { watchAtom } from "@xmachines/play-atom";
|
|
156
113
|
*
|
|
157
|
-
* const
|
|
158
|
-
*
|
|
159
|
-
* const pending = watcher.getPending();
|
|
160
|
-
* console.log('State changed:', actor.state.get());
|
|
161
|
-
* });
|
|
114
|
+
* const stop = watchAtom(actor.state, (snapshot) => {
|
|
115
|
+
* console.log('State changed:', snapshot.value);
|
|
162
116
|
* });
|
|
163
117
|
*
|
|
164
|
-
* watcher.watch(actor.state);
|
|
165
118
|
* actor.send({ type: 'play.route', to: '#about' });
|
|
166
|
-
* //
|
|
119
|
+
* // watchAtom delivers the new value from a microtask
|
|
120
|
+
*
|
|
121
|
+
* stop();
|
|
167
122
|
* ```
|
|
168
123
|
*
|
|
169
124
|
* @see [Play RFC](../../docs/rfc/play.md)
|
|
170
125
|
* @see {@link definePlayer} for the creation through a factory
|
|
171
|
-
* @see {@link @xmachines/play-actor!
|
|
172
|
-
* @see {@link @xmachines/play-
|
|
173
|
-
* @see {@link @xmachines/play-
|
|
126
|
+
* @see {@link @xmachines/play-actor!PlayActor} for the atom protocol
|
|
127
|
+
* @see {@link @xmachines/play-router!index.Routable} for the routing capability
|
|
128
|
+
* @see {@link @xmachines/play-view!index.Viewable} for the view rendering capability
|
|
174
129
|
*
|
|
175
130
|
* @remarks
|
|
176
131
|
* **The routing:** this actor supports the `route: {}` config pattern of XState and
|
|
@@ -178,13 +133,27 @@ const isObservableSnapshot = (snapshot) => snapshot.status === "active" || snaps
|
|
|
178
133
|
* `meta.route`, which is the Stately pattern, for a URL template, and it substitutes
|
|
179
134
|
* each parameter.
|
|
180
135
|
*
|
|
181
|
-
* **The pattern of the view
|
|
182
|
-
* `
|
|
183
|
-
*
|
|
184
|
-
*
|
|
136
|
+
* **The pattern of the view atom:** `withView` of `@xmachines/play-xstate/view` adds
|
|
137
|
+
* `currentView`, and that atom is a COMPUTED atom over `state`. One write for each
|
|
138
|
+
* transition — `state.set(snapshot)` — therefore reaches the view and the route in one
|
|
139
|
+
* flush, and no subscriber reads the new state beside an old derivation. The atom
|
|
140
|
+
* memoizes the result, so a repeated read computes no view again.
|
|
185
141
|
*/
|
|
186
|
-
export class PlayerActor extends
|
|
142
|
+
export class PlayerActor extends Actor {
|
|
187
143
|
playerOptions;
|
|
144
|
+
/**
|
|
145
|
+
* The three inputs of the constructor that a CAPABILITY needs.
|
|
146
|
+
*
|
|
147
|
+
* A mixin over a generic base cannot declare a constructor: TypeScript then demands the
|
|
148
|
+
* signature `...args: any[]` (TS2545), which this workspace does not write. A field
|
|
149
|
+
* initializer of a subclass runs after `super()` instead, and it reads these. The
|
|
150
|
+
* routing capability derives `initialRoute` from all three.
|
|
151
|
+
*/
|
|
152
|
+
playerMachine;
|
|
153
|
+
/** @see {@link playerMachine} */
|
|
154
|
+
playerInput;
|
|
155
|
+
/** @see {@link playerMachine} */
|
|
156
|
+
playerRestoredSnapshot;
|
|
188
157
|
/**
|
|
189
158
|
* The live options object of the caller, or an empty object during the construction.
|
|
190
159
|
*
|
|
@@ -204,22 +173,13 @@ export class PlayerActor extends AbstractActor {
|
|
|
204
173
|
get hooks() {
|
|
205
174
|
return this.playerOptions ?? {};
|
|
206
175
|
}
|
|
207
|
-
|
|
208
|
-
* The last snapshot of the view pipeline. XState notifies each observer on EVERY
|
|
209
|
-
* event that it processes, and an event that it ignores delivers the identical
|
|
210
|
-
* snapshot again. deriveCurrentView is pure in the snapshot. Therefore an identical
|
|
211
|
-
* reference can change no result. The first value is undefined, and never a
|
|
212
|
-
* snapshot: the snapshot of the construction has the same reference as the snapshot
|
|
213
|
-
* that start() replays, and that value therefore stops the first view.
|
|
214
|
-
*/
|
|
215
|
-
lastViewSnapshot = undefined;
|
|
216
|
-
// The requirements of the AbstractActor protocol
|
|
176
|
+
// The requirements of the PlayActor contract
|
|
217
177
|
state;
|
|
218
178
|
/**
|
|
219
179
|
* Tells you if the current state of the actor accepts the given event.
|
|
220
180
|
*
|
|
221
181
|
* The type is the event union of the machine. An unknown event type is therefore a
|
|
222
|
-
* compile error. The method evaluates the event against the snapshot
|
|
182
|
+
* compile error. The method evaluates the event against the snapshot atom.
|
|
223
183
|
*
|
|
224
184
|
* @example
|
|
225
185
|
* ```typescript
|
|
@@ -227,85 +187,26 @@ export class PlayerActor extends AbstractActor {
|
|
|
227
187
|
* ```
|
|
228
188
|
*/
|
|
229
189
|
can(event) {
|
|
230
|
-
// A read of the
|
|
231
|
-
// computes its value again on each transition.
|
|
232
|
-
// construction window, where the code can read no snapshot, and an actor with a
|
|
233
|
-
// failed initialization, where XState parks an error snapshot. That snapshot is
|
|
234
|
-
// a truthy object, and it has no `can` method.
|
|
190
|
+
// A read of the atom keeps can() reactive: a computed atom over the atom
|
|
191
|
+
// computes its value again on each transition.
|
|
235
192
|
const snapshot = this.state?.get();
|
|
236
|
-
|
|
193
|
+
// The STATUS decides first, and the presence of the method decides second.
|
|
194
|
+
//
|
|
195
|
+
// An actor answers an event only while it is active. XState 5.32 made that test
|
|
196
|
+
// unnecessary by accident — the error snapshot of a failed initialization carried no
|
|
197
|
+
// `can` method, so a test of the method alone answered `false` for it — and 5.33
|
|
198
|
+
// gives that snapshot a working `can`, which then answered `true` for an actor that
|
|
199
|
+
// processes an event never. The status is what the question is really about, and a
|
|
200
|
+
// `done` actor answers `false` for the same reason.
|
|
201
|
+
//
|
|
202
|
+
// A STOPPED actor is the exception, and it is deliberate: the subscription below
|
|
203
|
+
// updates this atom on a stable state alone, so the atom keeps the last ACTIVE
|
|
204
|
+
// snapshot after a teardown rather than freezing on an artifact of it. `can()`
|
|
205
|
+
// therefore answers for the last live state of a stopped actor.
|
|
206
|
+
if (snapshot?.status !== "active")
|
|
207
|
+
return false;
|
|
208
|
+
return typeof snapshot.can === "function" ? snapshot.can(event) : false;
|
|
237
209
|
}
|
|
238
|
-
/**
|
|
239
|
-
* A TC39 `Signal.Computed`. It derives the current URL path from the `meta.route`
|
|
240
|
-
* template of the active machine state and from the context of the actor.
|
|
241
|
-
*
|
|
242
|
-
* It returns `null` when the current state has no `meta.route` field, and also when
|
|
243
|
-
* it cannot resolve the complete route template. A necessary `:param` that the
|
|
244
|
-
* context does not hold is caught inside the signal, and a
|
|
245
|
-
* `MissingRouteParamError` therefore never leaves `get()`: that condition is
|
|
246
|
-
* temporary during a transition, and the signal computes the value again on the next
|
|
247
|
-
* snapshot.
|
|
248
|
-
*
|
|
249
|
-
* @example
|
|
250
|
-
* ```typescript
|
|
251
|
-
* // It returns "/profile/alice" when context.params.userId === "alice",
|
|
252
|
-
* // and null while the param is still absent.
|
|
253
|
-
* const route = actor.currentRoute.get();
|
|
254
|
-
* ```
|
|
255
|
-
*/
|
|
256
|
-
currentRoute;
|
|
257
|
-
/**
|
|
258
|
-
* The route of the initial state of the machine. The constructor fixes it, and it
|
|
259
|
-
* never changes, also when the code restores the actor from a snapshot.
|
|
260
|
-
*
|
|
261
|
-
* A router bridge compares it with the browser URL, and it therefore separates a
|
|
262
|
-
* deep link (a URL that is not the initial one → the router wins) from a restore
|
|
263
|
-
* (the initial URL, and the actor at a different route from the restore → the actor
|
|
264
|
-
* wins).
|
|
265
|
-
*
|
|
266
|
-
* `deriveInitialRoute` derives the value statically from the machine definition,
|
|
267
|
-
* with the pure `initialTransition` helper of XState: the chain of the initial states
|
|
268
|
-
* and their `meta.route` templates are fixed at the moment of the machine
|
|
269
|
-
* definition, and the substitution of a `:param` uses the real initial context of
|
|
270
|
-
* the machine for the `input` of this actor. The code makes no second actor, and a
|
|
271
|
-
* snapshot of a restore changes the value never: it is always the **default**
|
|
272
|
-
* initial route of the machine.
|
|
273
|
-
*/
|
|
274
|
-
initialRoute;
|
|
275
|
-
/**
|
|
276
|
-
* The reactive signal of the current view spec. The signal derives the spec from
|
|
277
|
-
* the `meta.view` metadata of the active state.
|
|
278
|
-
*
|
|
279
|
-
* It emits a **new object reference** on each real change of the view on the
|
|
280
|
-
* screen: the view of a different state, or a change of a param or of the context
|
|
281
|
-
* that changes the resolved spec. A re-entry with `reenter: true` and new params
|
|
282
|
-
* also changes the spec. A snapshot that changes no view on the screen, such as an
|
|
283
|
-
* assign of the context alone, keeps the previous reference. A provider below the
|
|
284
|
-
* signal therefore mounts the UI again not on every event.
|
|
285
|
-
*
|
|
286
|
-
* The `PlaySpec` of the emission carries the context of the machine in its composed
|
|
287
|
-
* `state` field, under the read-only `/context` subtree. A spec therefore reads the
|
|
288
|
-
* context, and also each URL param, through the ordinary state grammar
|
|
289
|
-
* (`{ $state: "/context/params/section" }`). The context-projection module of
|
|
290
|
-
* `@xmachines/play-actor` holds the complete contract.
|
|
291
|
-
*
|
|
292
|
-
* The signal returns `null` when the current state has no `meta.view` metadata.
|
|
293
|
-
*
|
|
294
|
-
* Two states can declare two separate `meta.view` literals with an identical
|
|
295
|
-
* structure. A transition between those two states then emits two different
|
|
296
|
-
* references, and a provider mounts the UI again. Move the shared literal into one
|
|
297
|
-
* `typedSpec` constant, and the identity then removes the duplicate.
|
|
298
|
-
*
|
|
299
|
-
* @example
|
|
300
|
-
* ```typescript
|
|
301
|
-
* const view = actor.currentView.get();
|
|
302
|
-
* if (view) {
|
|
303
|
-
* console.log(view.root); // for example "root"
|
|
304
|
-
* console.log(view.elements); // the Spec elements of @xmachines/json-render-core
|
|
305
|
-
* }
|
|
306
|
-
* ```
|
|
307
|
-
*/
|
|
308
|
-
currentView = new Signal.State(null);
|
|
309
210
|
constructor(machine, options, input, restoredSnapshot) {
|
|
310
211
|
// A defensive check before super(): a machine that is not an object fails deep
|
|
311
212
|
// inside the constructor of XState, with an opaque TypeError, and not with a coded
|
|
@@ -329,30 +230,19 @@ export class PlayerActor extends AbstractActor {
|
|
|
329
230
|
snapshot: restoredSnapshot,
|
|
330
231
|
inspect: options?.inspect,
|
|
331
232
|
});
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
// pre-start snapshot of this actor IS that default initial state, and the code
|
|
336
|
-
// derives the route from it directly. A restore alone needs the pure
|
|
337
|
-
// `initialTransition` helper of XState. The inert actor scope of that helper runs
|
|
338
|
-
// the initial transition of the machine two more times, and one of them has an
|
|
339
|
-
// undefined `input`. This is a quirk of XState, and it costs too much for each
|
|
340
|
-
// other case.
|
|
341
|
-
this.initialRoute =
|
|
342
|
-
restoredSnapshot === undefined
|
|
343
|
-
? deriveCurrentRoute(this.getSnapshot())
|
|
344
|
-
: deriveInitialRoute(machine, input);
|
|
233
|
+
this.playerMachine = machine;
|
|
234
|
+
this.playerInput = input;
|
|
235
|
+
this.playerRestoredSnapshot = restoredSnapshot;
|
|
345
236
|
this.playerOptions = options || {};
|
|
346
|
-
// Initialize the state
|
|
237
|
+
// Initialize the state atom. Each update is synchronous, with no batching in a
|
|
347
238
|
// microtask: XState groups the transitions of one send() call into one
|
|
348
239
|
// subscription callback already, and a synchronous update shows each guard
|
|
349
240
|
// redirect to a router bridge at once.
|
|
350
|
-
|
|
351
|
-
//
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
});
|
|
241
|
+
// `createWritableAtom`, and not `createAtom`. The overload pair of `createAtom` reads
|
|
242
|
+
// a function argument as a computed atom, and `ReturnType<TMachine["transition"]>` is
|
|
243
|
+
// an unresolved conditional type here, so TypeScript cannot rule a function out. It
|
|
244
|
+
// picks the computed signature, which returns a `ReadonlyAtom` that carries no `set`.
|
|
245
|
+
this.state = createWritableAtom(this.getSnapshot());
|
|
356
246
|
// Observe the transitions of this actor. The code uses `super`, and not `this`, so
|
|
357
247
|
// that the bookkeeping of the next-only subscriptions in the subscribe override
|
|
358
248
|
// stays about the subscriptions of the user code.
|
|
@@ -360,18 +250,25 @@ export class PlayerActor extends AbstractActor {
|
|
|
360
250
|
next: (snapshot) => {
|
|
361
251
|
// Update on a stable state only: an active snapshot, and the "done" snapshot of a
|
|
362
252
|
// final state at the top level. The code skips an error snapshot and a stopped
|
|
363
|
-
// snapshot. Therefore
|
|
253
|
+
// snapshot. Therefore an atom never freezes on an artifact of a teardown.
|
|
364
254
|
if (isObservableSnapshot(snapshot)) {
|
|
365
255
|
// Each state update is synchronous. Therefore a router bridge sees a guard redirect at once.
|
|
366
256
|
this.state.set(snapshot);
|
|
367
|
-
//
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
//
|
|
257
|
+
// ONE write for each transition, and the line above is it. `currentRoute` and
|
|
258
|
+
// `currentView` are computed atoms over `state`, so that write propagates to
|
|
259
|
+
// both in ONE flush, in topological order. No observer therefore reads the new
|
|
260
|
+
// state beside an old derivation, and the composition order of the capabilities
|
|
261
|
+
// decides nothing.
|
|
262
|
+
//
|
|
263
|
+
// `onSnapshot` remains for a capability that must run an EFFECT on a
|
|
264
|
+
// transition. A capability that publishes a value derives it instead.
|
|
265
|
+
//
|
|
266
|
+
// The whole order of one transition:
|
|
267
|
+
// 1. state receives its new value, and every computed atom over it follows
|
|
268
|
+
// 2. onSnapshot runs each capability, in the composition order
|
|
372
269
|
// 3. the onStateChange hook runs
|
|
373
270
|
// 4. send() then calls onTransition
|
|
374
|
-
this.
|
|
271
|
+
this.onSnapshot(snapshot);
|
|
375
272
|
// Call the onStateChange hook
|
|
376
273
|
const onStateChange = this.hooks.onStateChange;
|
|
377
274
|
if (onStateChange) {
|
|
@@ -443,7 +340,7 @@ export class PlayerActor extends AbstractActor {
|
|
|
443
340
|
// A call that reaches in through the construction window, for example a context
|
|
444
341
|
// factory that stops its own `self`, marks the actor as stopped before the code
|
|
445
342
|
// registers its internal subscription. XState drops each observer of a stopped
|
|
446
|
-
// actor. The
|
|
343
|
+
// actor. The atoms therefore move never again. There is nothing to tear down
|
|
447
344
|
// during the construction, and the code ignores such a call.
|
|
448
345
|
if (!this.constructed) {
|
|
449
346
|
return this;
|
|
@@ -496,7 +393,7 @@ export class PlayerActor extends AbstractActor {
|
|
|
496
393
|
// must still run for it, with the correct snapshot from before the send.
|
|
497
394
|
const prevSnapshot = this.getSnapshot();
|
|
498
395
|
// Send the event to the XState actor.
|
|
499
|
-
//
|
|
396
|
+
// The class declares send() to narrow the
|
|
500
397
|
// event type, and TypeScript forbids a super call to an abstract member.
|
|
501
398
|
// Therefore the code reaches the implementation of XState directly. `this` IS the
|
|
502
399
|
// actor. This call is therefore exactly the call of `super.send(event)`: the relay
|
|
@@ -510,12 +407,6 @@ export class PlayerActor extends AbstractActor {
|
|
|
510
407
|
onTransition(this, prevSnapshot, nextSnapshot);
|
|
511
408
|
}
|
|
512
409
|
}
|
|
513
|
-
/**
|
|
514
|
-
* Returns the current snapshot
|
|
515
|
-
*/
|
|
516
|
-
getSnapshot() {
|
|
517
|
-
return super.getSnapshot();
|
|
518
|
-
}
|
|
519
410
|
subscribe(nextListenerOrObserver, errorListener, completeListener) {
|
|
520
411
|
// The subscribe() method of XState accepts a function and also an observer, and it
|
|
521
412
|
// normalizes them internally. The cast joins the two overload signatures only.
|
|
@@ -542,16 +433,6 @@ export class PlayerActor extends AbstractActor {
|
|
|
542
433
|
},
|
|
543
434
|
};
|
|
544
435
|
}
|
|
545
|
-
/**
|
|
546
|
-
* Listens for the events that this actor emits with the `emit` action.
|
|
547
|
-
*
|
|
548
|
-
* @param type - The type of the emitted event to listen for, or `"*"` for every event.
|
|
549
|
-
* @param handler - The actor calls it with each emitted event that matches.
|
|
550
|
-
* @returns The subscription, with an `unsubscribe()` method.
|
|
551
|
-
*/
|
|
552
|
-
on(type, handler) {
|
|
553
|
-
return super.on(type, handler);
|
|
554
|
-
}
|
|
555
436
|
/**
|
|
556
437
|
* Returns the persisted snapshot of this actor.
|
|
557
438
|
*
|
|
@@ -563,55 +444,28 @@ export class PlayerActor extends AbstractActor {
|
|
|
563
444
|
return forward.call(this, options);
|
|
564
445
|
}
|
|
565
446
|
/**
|
|
566
|
-
*
|
|
567
|
-
* each transition. The signal holds the view, and the code computes it not on each
|
|
568
|
-
* read.
|
|
447
|
+
* The point where a capability derives its own atoms from a new snapshot.
|
|
569
448
|
*
|
|
570
|
-
*
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
try {
|
|
578
|
-
const view = deriveCurrentView(snapshot);
|
|
579
|
-
// Emit only after a real change of the view on the screen: deriveCurrentView
|
|
580
|
-
// returns a fresh object on each call, and the identity of the reference therefore
|
|
581
|
-
// tells nothing. A new reference for a snapshot that changes the view not, for
|
|
582
|
-
// example a context-only assign, makes a provider below mount the UI again, and
|
|
583
|
-
// that removes the state of the view. A deep equality test is deliberately NOT
|
|
584
|
-
// here: it sees nothing inside a Map or a Set, and it therefore stops a real
|
|
585
|
-
// change, and it recurses without an end on a cyclic prop. The last spec of an
|
|
586
|
-
// emission IS the current value of the signal. Read it without a track, so that
|
|
587
|
-
// the gate registers currentView never as a dependency of a computation around
|
|
588
|
-
// it.
|
|
589
|
-
const lastEmittedView = Signal.subtle.untrack(() => this.currentView.get());
|
|
590
|
-
// Use the reference of the previous composed state again when the value of the
|
|
591
|
-
// /context projection did not change. A context-only assign that changes no
|
|
592
|
-
// projected value therefore changes the identity of the state not.
|
|
593
|
-
const nextView = reuseComposedState(lastEmittedView, view);
|
|
594
|
-
if (viewSpecsEquivalent(lastEmittedView, nextView)) {
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
this.currentView.set(nextView);
|
|
598
|
-
}
|
|
599
|
-
catch (error) {
|
|
600
|
-
const onError = this.hooks.onError;
|
|
601
|
-
if (onError) {
|
|
602
|
-
onError(this, toError(error));
|
|
603
|
-
}
|
|
604
|
-
// On an error: keep the last valid view, and clear it not
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
/**
|
|
608
|
-
* The dispose method, for the cleanup. It is the alias of {@link stop}.
|
|
449
|
+
* The base derives nothing: `PlayActor` asks for `state` and `send`, and this class
|
|
450
|
+
* gives exactly those.
|
|
451
|
+
*
|
|
452
|
+
* A capability that PUBLISHES a value overrides this method NOT. It derives the value
|
|
453
|
+
* with a computed atom over `state`, as `withRouting` and `withView` both do, and the
|
|
454
|
+
* engine then evaluates every derivation from the one write of a transition, in
|
|
455
|
+
* topological order. The composition order therefore decides no value.
|
|
609
456
|
*
|
|
610
|
-
*
|
|
611
|
-
*
|
|
457
|
+
* This method remains for a capability that must run an EFFECT on a transition. Such a
|
|
458
|
+
* mixin overrides it and calls `super.onSnapshot(snapshot)` FIRST, so that every
|
|
459
|
+
* capability composed before it runs its own effect first.
|
|
460
|
+
*
|
|
461
|
+
* The method runs after `state` holds the new snapshot and before the `onStateChange`
|
|
462
|
+
* hook of the options.
|
|
463
|
+
*
|
|
464
|
+
* @param snapshot - The stable snapshot of this transition.
|
|
612
465
|
*/
|
|
613
|
-
|
|
614
|
-
this.
|
|
466
|
+
onSnapshot(snapshot) {
|
|
467
|
+
// The base class holds no capability. A mixin overrides this method.
|
|
468
|
+
void snapshot;
|
|
615
469
|
}
|
|
616
470
|
/**
|
|
617
471
|
* Stops the actor when the scope of a `using` declaration ends.
|
package/dist/player-actor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"player-actor.js","sourceRoot":"","sources":["../src/player-actor.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,
|
|
1
|
+
{"version":3,"file":"player-actor.js","sourceRoot":"","sources":["../src/player-actor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ParseOptions } from "@xmachines/play-pattern";
|
|
1
2
|
import type { RouteContext } from "./types.js";
|
|
2
3
|
/**
|
|
3
4
|
* Builds a complete URL from a route template and the context of the actor.
|
|
@@ -16,12 +17,18 @@ import type { RouteContext } from "./types.js";
|
|
|
16
17
|
* @param context - The context object of the actor. Each route parameter must be in
|
|
17
18
|
* `context.params`, because the function reads no flat context field. An absent
|
|
18
19
|
* `query` field builds a URL without a query, exactly like `query: {}`.
|
|
20
|
+
* @param options - The caches to read, as {@link ParseOptions}. The default is the cache
|
|
21
|
+
* that `@xmachines/play-pattern` shares with every caller of the process. A parse is
|
|
22
|
+
* deterministic, so this changes how often the parser runs and it changes no answer.
|
|
19
23
|
* @returns The complete URL string.
|
|
20
24
|
*
|
|
21
25
|
* @throws {MissingRouteParamError} When a **necessary** `:param` placeholder has no
|
|
22
26
|
* value in the context. The function omits an optional parameter (`:param?`) in
|
|
23
27
|
* silence when its value is absent. Import the class from
|
|
24
28
|
* `@xmachines/play-xstate/errors`.
|
|
29
|
+
* @throws {InvalidRouteParamError} When a `:param` placeholder carries a dot segment,
|
|
30
|
+
* which a URL resolves away. The template matches the built URL back never, so the
|
|
31
|
+
* actor and the address bar would stay out of step.
|
|
25
32
|
*
|
|
26
33
|
* @example
|
|
27
34
|
* ```typescript
|
|
@@ -32,5 +39,5 @@ import type { RouteContext } from "./types.js";
|
|
|
32
39
|
* // → "/settings" (the optional param is absent, and there is no query string)
|
|
33
40
|
* ```
|
|
34
41
|
*/
|
|
35
|
-
export declare const buildRouteUrl: (routeTemplate: string, context?: RouteContext) => string;
|
|
42
|
+
export declare const buildRouteUrl: (routeTemplate: string, context?: RouteContext, options?: ParseOptions) => string;
|
|
36
43
|
//# sourceMappingURL=build-url.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-url.d.ts","sourceRoot":"","sources":["../../src/routing/build-url.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build-url.d.ts","sourceRoot":"","sources":["../../src/routing/build-url.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,aAAa,GACzB,eAAe,MAAM,EACrB,UAAS,YAA4B,EACrC,UAAU,YAAY,KACpB,MAgEF,CAAC"}
|