@xmachines/play-xstate 4.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.
Files changed (42) hide show
  1. package/README.md +61 -30
  2. package/dist/capabilities.d.ts +4 -3
  3. package/dist/capabilities.d.ts.map +1 -1
  4. package/dist/capabilities.js.map +1 -1
  5. package/dist/errors.d.ts +38 -0
  6. package/dist/errors.d.ts.map +1 -1
  7. package/dist/errors.js +44 -0
  8. package/dist/errors.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js +2 -2
  11. package/dist/player-actor.d.ts +30 -29
  12. package/dist/player-actor.d.ts.map +1 -1
  13. package/dist/player-actor.js +51 -41
  14. package/dist/player-actor.js.map +1 -1
  15. package/dist/routing/build-url.d.ts +8 -1
  16. package/dist/routing/build-url.d.ts.map +1 -1
  17. package/dist/routing/build-url.js +34 -54
  18. package/dist/routing/build-url.js.map +1 -1
  19. package/dist/routing/derive-current-route.d.ts +11 -2
  20. package/dist/routing/derive-current-route.d.ts.map +1 -1
  21. package/dist/routing/derive-current-route.js +22 -6
  22. package/dist/routing/derive-current-route.js.map +1 -1
  23. package/dist/routing/derive-initial-route.d.ts +2 -1
  24. package/dist/routing/derive-initial-route.d.ts.map +1 -1
  25. package/dist/routing/derive-initial-route.js +2 -2
  26. package/dist/routing/derive-initial-route.js.map +1 -1
  27. package/dist/routing/format-play-route-transitions.js +10 -5
  28. package/dist/routing/format-play-route-transitions.js.map +1 -1
  29. package/dist/types.d.ts +2 -2
  30. package/dist/types.d.ts.map +1 -1
  31. package/dist/view/derive-current-view.d.ts +6 -5
  32. package/dist/view/derive-current-view.d.ts.map +1 -1
  33. package/dist/view/derive-current-view.js +5 -4
  34. package/dist/view/derive-current-view.js.map +1 -1
  35. package/dist/with-routing.d.ts.map +1 -1
  36. package/dist/with-routing.js +66 -4
  37. package/dist/with-routing.js.map +1 -1
  38. package/dist/with-view.d.ts +19 -4
  39. package/dist/with-view.d.ts.map +1 -1
  40. package/dist/with-view.js +64 -56
  41. package/dist/with-view.js.map +1 -1
  42. package/package.json +14 -13
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @xmachines/play-xstate
2
2
 
3
- > XState v5 adapter for the XMachines Play Architecture. It binds a state machine to the actor base, with signal-driven reactivity and a router integration.
3
+ > XState v5 adapter for the XMachines Play Architecture. It binds a state machine to the actor base, with atom-driven reactivity and a router integration.
4
4
 
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-4.0.0-blue)](https://www.npmjs.com/package/@xmachines/play-xstate)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-5.0.0-blue)](https://www.npmjs.com/package/@xmachines/play-xstate)
6
6
 
7
7
  ---
8
8
 
@@ -13,10 +13,24 @@
13
13
  ## Installation
14
14
 
15
15
  ```bash
16
- pnpm add @xmachines/play-xstate xstate
16
+ pnpm add @xmachines/play-xstate @xmachines/play @xmachines/play-atom xstate
17
17
  ```
18
18
 
19
- `xstate ^5.33.0` is a peer dependency. Install it with this package.
19
+ **Peer dependencies.** Install them with the package:
20
+
21
+ - [`@xmachines/play`](../play/README.md) — the core protocol. This package reads `shallowEqualExcept` and `DISPOSE` from it.
22
+ - [`@xmachines/play-atom`](../play-atom/README.md) — the atom primitives. `PlayerActor` holds `currentView` and `currentRoute` as atoms.
23
+ - `xstate` ^5.33.0 — the XState v5 runtime.
24
+
25
+ **Optional peers.** Each capability subpath carries one. Install it when you read that subpath, and not before:
26
+
27
+ ```bash
28
+ pnpm add @xmachines/play-router # @xmachines/play-xstate/routing
29
+ pnpm add @xmachines/play-view # @xmachines/play-xstate/view
30
+ ```
31
+
32
+ - [`@xmachines/play-router`](../play-router/README.md) — the routing capability reads `Routable`, `PlayRouteEvent` and `RouteData` from it.
33
+ - [`@xmachines/play-view`](../play-view/README.md) — the view capability reads `composePlayState`, `PlaySpec` and `Viewable` from it.
20
34
 
21
35
  ---
22
36
 
@@ -43,7 +57,7 @@ const createPlayer = definePlayer({ machine, actor: compose(PlayerActor, withRou
43
57
  const actor = createPlayer();
44
58
  actor.start();
45
59
 
46
- // 4. Observe TC39 Signal-based reactive state
60
+ // 4. Observe atom-based reactive state
47
61
  console.log(actor.currentRoute.get()); // "/"
48
62
  console.log(actor.state.get().value); // "idle"
49
63
 
@@ -132,13 +146,13 @@ console.log(restored.currentRoute.get()); // same route as when saved
132
146
 
133
147
  ### `PlayerActor<TMachine>`
134
148
 
135
- This concrete actor class is an XState v5 actor that exposes reactive TC39 Signals. It holds the protocol of `PlayActor` and nothing else: `state` and `send`.
149
+ This concrete actor class is an XState v5 actor that exposes reactive atoms. It holds the protocol of `PlayActor` and nothing else: `state` and `send`.
136
150
 
137
- #### Signals
151
+ #### Atoms
138
152
 
139
- | Signal | Type | Description |
140
- | ------- | -------------------------------------- | ---------------------------------------------------------------------------- |
141
- | `state` | `Signal.State<SnapshotFrom<TMachine>>` | The current XState snapshot. The actor updates it on every active transition |
153
+ | Atom | Type | Description |
154
+ | ------- | ------------------------------ | ---------------------------------------------------------------------------- |
155
+ | `state` | `Atom<SnapshotFrom<TMachine>>` | The current XState snapshot. The actor updates it on every active transition |
142
156
 
143
157
  ### The capabilities
144
158
 
@@ -154,12 +168,12 @@ pnpm add @xmachines/play-view # for @xmachines/play-xstate/view
154
168
  The main entry point of this package names neither. `@xmachines/play-xstate/routing` also
155
169
  carries the route utilities — `deriveRoute`, `isAbsoluteRoute`, `buildRouteUrl`,
156
170
  `formatPlayRouteTransitions` and the route types — because each one names
157
- `@xmachines/play-router` in its own types.
171
+ [`@xmachines/play-router`](../play-router/README.md) in its own types.
158
172
 
159
- | Capability | Entry point | Adds | Interface |
160
- | ---------- | -------------------------------- | ------------------------------ | -------------------------------------- |
161
- | Routing | `@xmachines/play-xstate/routing` | `currentRoute`, `initialRoute` | `Routable` of `@xmachines/play-router` |
162
- | View | `@xmachines/play-xstate/view` | `currentView` | `Viewable` of `@xmachines/play-view` |
173
+ | Capability | Entry point | Adds | Interface |
174
+ | ---------- | -------------------------------- | ------------------------------ | ------------------------------------------------------------------ |
175
+ | Routing | `@xmachines/play-xstate/routing` | `currentRoute`, `initialRoute` | `Routable` of [`@xmachines/play-router`](../play-router/README.md) |
176
+ | View | `@xmachines/play-xstate/view` | `currentView` | `Viewable` of [`@xmachines/play-view`](../play-view/README.md) |
163
177
 
164
178
  `compose` applies each capability from left to right:
165
179
 
@@ -181,7 +195,7 @@ const createRouted = definePlayer({ machine, actor: compose(PlayerActor, withRou
181
195
  const createBare = definePlayer({ machine });
182
196
  ```
183
197
 
184
- **Compose `withView` after `withRouting`.** An override calls `super.onSnapshot()` first, so the composition order decides the derivation order: the route holds its new value before the view derives from the same transition. A router bridge therefore sees a guard redirect before a renderer sees the view of the state that the guard refused.
198
+ **The composition ORDER decides nothing.** `currentRoute` and `currentView` are computed atoms over `state`, and neither reads the other, so one write for each transition reaches both and the engine evaluates them in topological order. A router bridge therefore sees a guard redirect and a renderer sees the view of the same snapshot, whatever order `compose` applied. A release before this one wrote `currentView` from an `onSnapshot` override, and the order was load-bearing there.
185
199
 
186
200
  **A lifecycle hook receives the bare actor.** `PlayerOptions` is typed before the class is composed, so it cannot name the capabilities, and a narrower hook parameter is refused under `strictFunctionTypes`. A hook that reads `currentRoute` or `currentView` reads them through a binding of the composed type:
187
201
 
@@ -196,11 +210,27 @@ const actor = definePlayer({
196
210
  composed = actor;
197
211
  ```
198
212
 
199
- | Signal | Type | Capability | Description |
200
- | -------------- | --------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
201
- | `currentRoute` | `Signal.Computed<string \| null>` | routing | The URL that comes from the `meta.route` template of the active state and from the context |
202
- | `initialRoute` | `readonly string \| null` | routing | The route of the initial state of the machine. The construction fixes it, and a router bridge uses it to detect a deep link or a restore |
203
- | `currentView` | `Signal.State<PlaySpec \| null>` | view | The view spec from the `meta.view` metadata of the active state, with the context params added |
213
+ | Atom | Type | Capability | Description |
214
+ | -------------- | -------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
215
+ | `currentRoute` | `ReadonlyAtom<string \| null>` | routing | The URL that comes from the `meta.route` template of the active state and from the context |
216
+ | `initialRoute` | `readonly string \| null` | routing | The route of the initial state of the machine. The construction fixes it, and a router bridge uses it to detect a deep link or a restore |
217
+ | `currentView` | `ReadonlyAtom<PlaySpec \| null>` | view | The view spec from the `meta.view` metadata of the active state, with the context params added |
218
+
219
+ `state` is the ONE atom that the actor writes. `currentRoute` and `currentView` are
220
+ COMPUTED over it, so one write for each transition reaches both in one propagation and no
221
+ observer reads the new state beside an old derivation. Each derivation reports a failure
222
+ through the `onError` option and keeps its last good value; it throws never, because it
223
+ runs inside the write.
224
+
225
+ **`currentRoute` notifies on every transition, and `currentView` notifies on a change of
226
+ the view alone.** The two atoms answer two different questions. A router bridge needs the
227
+ answer of the actor to each event that it proposed, and a guard that refuses an inbound
228
+ location and holds the machine where it was derives the SAME path — so `currentRoute`
229
+ compares "different" always, and the bridge learns that the address bar must go back.
230
+ `currentView` gates its emission on the value, and a snapshot that changes no view on the
231
+ screen keeps the previous reference, so a provider below it mounts the UI again not on
232
+ every event. Debounce your own `watchAtom(actor.currentRoute, ...)` callback, or compare
233
+ the path yourself, when you run work that belongs to a change of the route alone.
204
234
 
205
235
  #### Methods
206
236
 
@@ -213,19 +243,19 @@ composed = actor;
213
243
  | `getSnapshot()` | Returns the current XState snapshot |
214
244
  | `[DISPOSE]()` | Stops the actor at the end of a `using` scope. The release is `stop()` |
215
245
 
216
- #### Signal usage example
246
+ #### Atom usage example
217
247
 
218
248
  ```typescript
219
- import { Signal } from "@xmachines/play-signals";
249
+ import { watchAtom } from "@xmachines/play-atom";
220
250
 
221
- const watcher = new Signal.subtle.Watcher(() => {
222
- queueMicrotask(() => {
223
- console.log("Route changed:", actor.currentRoute.get());
224
- });
251
+ const stop = watchAtom(actor.currentRoute, (route) => {
252
+ console.log("Route changed:", route);
225
253
  });
226
254
 
227
- watcher.watch(actor.currentRoute);
228
255
  actor.start();
256
+
257
+ // Later, on teardown
258
+ stop();
229
259
  ```
230
260
 
231
261
  ---
@@ -371,7 +401,7 @@ import type {
371
401
  ```
372
402
 
373
403
  `RouteObject`, `RouteMetadata`, `RouteData`, and `RouteDataResolver` have one
374
- definition, and it lives in `@xmachines/play-router`. `@xmachines/play-xstate/routing`
404
+ definition, and it lives in [`@xmachines/play-router`](../play-router/README.md). `@xmachines/play-xstate/routing`
375
405
  re-exports them, so either import path gives you the same type. The MAIN entry point of
376
406
  this package re-exports them no longer: it would name an optional peer in the types of
377
407
  every consumer, including one that composes no routing.
@@ -435,6 +465,7 @@ The `@xmachines/play-xstate/errors` subpath exports the error classes. The main
435
465
  ```typescript
436
466
  import {
437
467
  MissingRouteParamError, // Required :param absent from context when resolving currentRoute
468
+ InvalidRouteParamError, // A :param carries a dot segment, which a URL resolves away
438
469
  MissingStateIdError, // meta.route declared without a state id field
439
470
  InvalidMachineError, // PlayerActor constructed with a non-object machine
440
471
  InvalidEventError, // actor.send() called with null/undefined/non-object
@@ -444,7 +475,7 @@ import {
444
475
  } from "@xmachines/play-xstate/errors";
445
476
  ```
446
477
 
447
- Every error class extends `PlayError` from `@xmachines/play/errors`. Each class also carries typed detail fields, such as `param`, `template`, and `handler`. Your code therefore reads the details of an error, and it does not parse the message.
478
+ Every error class extends `PlayError` from [`@xmachines/play/errors`](../play/README.md). Each class also carries typed detail fields, such as `param`, `template`, and `handler`. Your code therefore reads the details of an error, and it does not parse the message.
448
479
 
449
480
  ---
450
481
 
@@ -7,9 +7,10 @@
7
7
  * and an application that declares no route loads no routing code.
8
8
  *
9
9
  * {@link compose} applies each capability from left to right, so the LAST one is the
10
- * outermost class. That is also the order in which `onSnapshot` derives: an override calls
11
- * `super.onSnapshot()` first, so `compose(PlayerActor, withRouting, withView)` gives the
12
- * route its new value before the view reads it.
10
+ * outermost class. The ORDER decides no value: a capability that publishes one derives it
11
+ * with a computed atom over `state`, and the engine evaluates every derivation from the
12
+ * one write of a transition, in topological order. `onSnapshot` remains for a capability
13
+ * that must run an EFFECT, and an override of it still calls `super.onSnapshot()` first.
13
14
  *
14
15
  * ## Why the types read this way
15
16
  *
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,CAC5B,QAAQ,SAAS,eAAe,EAChC,aAAa,SAAS,MAAM,GAAG,MAAM,IAClC,KACH,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,EAChC,KAAK,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC,EAC3B,gBAAgB,CAAC,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,KACjD,WAAW,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,MAAM,UAAU,CAAC,QAAQ,SAAS,eAAe,EAAE,MAAM,SAAS,MAAM,IAAI,CACjF,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,KAC7B,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EACvD,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GAC/B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AAC/B,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EAAE,GAAG,SAAS,MAAM,EAC3E,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACpC,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EAAE,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAC/F,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;AAC1C,wBAAgB,OAAO,CACtB,QAAQ,SAAS,eAAe,EAChC,GAAG,SAAS,MAAM,EAClB,GAAG,SAAS,MAAM,EAClB,GAAG,SAAS,MAAM,EAElB,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC"}
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,CAC5B,QAAQ,SAAS,eAAe,EAChC,aAAa,SAAS,MAAM,GAAG,MAAM,IAClC,KACH,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,EAChC,KAAK,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC,EAC3B,gBAAgB,CAAC,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,KACjD,WAAW,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,MAAM,UAAU,CAAC,QAAQ,SAAS,eAAe,EAAE,MAAM,SAAS,MAAM,IAAI,CACjF,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,KAC7B,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EACvD,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GAC/B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AAC/B,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EAAE,GAAG,SAAS,MAAM,EAC3E,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACpC,wBAAgB,OAAO,CAAC,QAAQ,SAAS,eAAe,EAAE,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAC/F,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;AAC1C,wBAAgB,OAAO,CACtB,QAAQ,SAAS,eAAe,EAChC,GAAG,SAAS,MAAM,EAClB,GAAG,SAAS,MAAM,EAClB,GAAG,SAAS,MAAM,EAElB,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,EAC7B,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,GAC3B,iBAAiB,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AA4HA,MAAM,UAAU,OAAO,CACtB,IAAiC,EACjC,GAAG,YAEF;IAED,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;AAC5E,CAAC"}
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AA6HA,MAAM,UAAU,OAAO,CACtB,IAAiC,EACjC,GAAG,YAEF;IAED,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;AAC5E,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -35,6 +35,44 @@ export declare class MissingRouteParamError extends PlayError {
35
35
  readonly template: string;
36
36
  constructor(param: string, template: string);
37
37
  }
38
+ /**
39
+ * `buildRouteUrl()` throws this error when a route parameter carries a value that no path
40
+ * can hold, so the template matches the built URL back never.
41
+ *
42
+ * A dot segment is that value. A URL parser resolves `.` and `..` BEFORE it decodes the
43
+ * percent escapes, and it counts `%2e` as the dot, so every encoding of them resolves
44
+ * away: `/files/..` becomes `/`. The actor would hold the route `/files/..` while the
45
+ * address bar shows `/`, and the two stay out of step for the rest of the session.
46
+ *
47
+ * Give the param a value that names a segment. Machine state that can carry a path from a
48
+ * user belongs behind a check of its own, in the same way that a base path checks the
49
+ * values of its `:param` segments.
50
+ *
51
+ * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_INVALID`
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * import { buildRouteUrl } from "@xmachines/play-xstate/routing";
56
+ * import { InvalidRouteParamError } from "@xmachines/play-xstate/errors";
57
+ *
58
+ * try {
59
+ * buildRouteUrl("/files/:name", { params: { name: ".." }, query: {} });
60
+ * } catch (err) {
61
+ * if (err instanceof InvalidRouteParamError) {
62
+ * console.error(`"${err.value}" cannot stand in "${err.param}"`);
63
+ * }
64
+ * }
65
+ * ```
66
+ */
67
+ export declare class InvalidRouteParamError extends PlayError {
68
+ /** The name of the route parameter that carries the value, for example `"name"`. */
69
+ readonly param: string;
70
+ /** The value that no path can hold, for example `".."`. */
71
+ readonly value: string;
72
+ /** The route template that declares the parameter, for example `"/files/:name"`. */
73
+ readonly template: string;
74
+ constructor(param: string, value: string, template: string);
75
+ }
38
76
  /**
39
77
  * `formatPlayRouteTransitions()` throws this error when a state node declares a
40
78
  * `meta.route` field but no explicit `id` field.
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAsBnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAU3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAW3C;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;;CASjD;AAqBD;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,OAAO,EAAE,MAAM,SAAgB;CAUlD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,wBAAyB,SAAQ,SAAS;IACtD,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,OAAO,EAAE,MAAM,SAA+B;CAUnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC/C,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,MAAM,EAAE,OAAO;CAS3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;gBACzC,KAAK,EAAE,OAAO;CAS1B"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAsBnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAU3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAW1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAW3C;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;;CASjD;AAqBD;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,OAAO,EAAE,MAAM,SAAgB;CAUlD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,wBAAyB,SAAQ,SAAS;IACtD,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,OAAO,EAAE,MAAM,SAA+B;CAUnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC/C,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,MAAM,EAAE,OAAO;CAS3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;gBACzC,KAAK,EAAE,OAAO;CAS1B"}
package/dist/errors.js CHANGED
@@ -61,6 +61,50 @@ export class MissingRouteParamError extends PlayError {
61
61
  this.template = template;
62
62
  }
63
63
  }
64
+ /**
65
+ * `buildRouteUrl()` throws this error when a route parameter carries a value that no path
66
+ * can hold, so the template matches the built URL back never.
67
+ *
68
+ * A dot segment is that value. A URL parser resolves `.` and `..` BEFORE it decodes the
69
+ * percent escapes, and it counts `%2e` as the dot, so every encoding of them resolves
70
+ * away: `/files/..` becomes `/`. The actor would hold the route `/files/..` while the
71
+ * address bar shows `/`, and the two stay out of step for the rest of the session.
72
+ *
73
+ * Give the param a value that names a segment. Machine state that can carry a path from a
74
+ * user belongs behind a check of its own, in the same way that a base path checks the
75
+ * values of its `:param` segments.
76
+ *
77
+ * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_INVALID`
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * import { buildRouteUrl } from "@xmachines/play-xstate/routing";
82
+ * import { InvalidRouteParamError } from "@xmachines/play-xstate/errors";
83
+ *
84
+ * try {
85
+ * buildRouteUrl("/files/:name", { params: { name: ".." }, query: {} });
86
+ * } catch (err) {
87
+ * if (err instanceof InvalidRouteParamError) {
88
+ * console.error(`"${err.value}" cannot stand in "${err.param}"`);
89
+ * }
90
+ * }
91
+ * ```
92
+ */
93
+ export class InvalidRouteParamError extends PlayError {
94
+ /** The name of the route parameter that carries the value, for example `"name"`. */
95
+ param;
96
+ /** The value that no path can hold, for example `".."`. */
97
+ value;
98
+ /** The route template that declares the parameter, for example `"/files/:name"`. */
99
+ template;
100
+ constructor(param, value, template) {
101
+ super("buildRouteUrl", "PLAY_XSTATE_ROUTE_PARAM_INVALID", `Route parameter '${param}' of template '${template}' carries the value '${value}', which resolves away in a URL.`);
102
+ this.name = "InvalidRouteParamError";
103
+ this.param = param;
104
+ this.value = value;
105
+ this.template = template;
106
+ }
107
+ }
64
108
  /**
65
109
  * `formatPlayRouteTransitions()` throws this error when a state node declares a
66
110
  * `meta.route` field but no explicit `id` field.
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,11 +2,11 @@
2
2
  * @xmachines/play-xstate - the XState v5 adapter of the Play Architecture
3
3
  *
4
4
  * This package gives you the definePlayer() API. That function binds an XState state
5
- * machine to the actor base, with the signal lifecycle and the DevTools
5
+ * machine to the actor base, with the atom lifecycle and the DevTools
6
6
  * integration.
7
7
  *
8
8
  * The Play RFC gives this package as the adapter of the logic layer. It converts a
9
- * declarative machine definition into a live actor with a signal-driven
9
+ * declarative machine definition into a live actor with an atom-driven
10
10
  * reactivity.
11
11
  *
12
12
  * @packageDocumentation
package/dist/index.js CHANGED
@@ -2,11 +2,11 @@
2
2
  * @xmachines/play-xstate - the XState v5 adapter of the Play Architecture
3
3
  *
4
4
  * This package gives you the definePlayer() API. That function binds an XState state
5
- * machine to the actor base, with the signal lifecycle and the DevTools
5
+ * machine to the actor base, with the atom lifecycle and the DevTools
6
6
  * integration.
7
7
  *
8
8
  * The Play RFC gives this package as the adapter of the logic layer. It converts a
9
- * declarative machine definition into a live actor with a signal-driven
9
+ * declarative machine definition into a live actor with an atom-driven
10
10
  * reactivity.
11
11
  *
12
12
  * @packageDocumentation
@@ -1,7 +1,7 @@
1
1
  import { Actor, type AnyStateMachine, type AnyMachineSnapshot, type InputFrom, type ActorOptions, type Observer, type Snapshot, type SnapshotFrom, type Subscription, type EventFromLogic } from "xstate";
2
2
  import type { PlayActor } from "@xmachines/play-actor";
3
3
  import { DISPOSE } from "@xmachines/play";
4
- import { Signal } from "@xmachines/play-signals";
4
+ import type { Atom } from "@xmachines/play-atom";
5
5
  import type { PlayerOptions } from "./types.js";
6
6
  /**
7
7
  * Normalizes a failure of the actor for `onError`.
@@ -16,7 +16,7 @@ import type { PlayerOptions } from "./types.js";
16
16
  */
17
17
  export declare const toError: (value: unknown) => Error;
18
18
  /**
19
- * The concrete XState actor. It implements the signal protocol of the Play Architecture
19
+ * The concrete XState actor. It implements the atom protocol of the Play Architecture
20
20
  *
21
21
  * The class extends the `Actor` class of XState directly, and it implements
22
22
  * {@link @xmachines/play-actor!PlayActor}. It gives you the XState v5 integration, and it keeps the
@@ -24,7 +24,7 @@ export declare const toError: (value: unknown) => Error;
24
24
  * The constructor of the base class receives the machine. Therefore a `PlayerActor`
25
25
  * **is** the XState actor, and it is no wrapper around one: every member of the
26
26
  * XState `Actor` class works on the state of this instance, and this class adds the
27
- * reactive state on the TC39 Signals for the observation by the infrastructure.
27
+ * reactive state on the atoms for the observation by the infrastructure.
28
28
  *
29
29
  * **Capabilities:** the class implements both the
30
30
  * {@link @xmachines/play-router!index.Routable} interface and the
@@ -33,7 +33,7 @@ export declare const toError: (value: unknown) => Error;
33
33
  *
34
34
  * **Architectural context:** the class implements **Actor Authority (INV-01)**,
35
35
  * because the guards of the XState machine control every decision of the
36
- * navigation. The infrastructure observes the signals of the actor (`state`,
36
+ * navigation. The infrastructure observes the atoms of the actor (`state`,
37
37
  * `currentRoute`, and `currentView`), but it changes no state directly: every
38
38
  * change goes through the event handlers of the state machine.
39
39
  *
@@ -65,31 +65,29 @@ export declare const toError: (value: unknown) => Error;
65
65
  * const actor = createPlayer();
66
66
  * actor.start();
67
67
  *
68
- * // Observe the signals
68
+ * // Observe the atoms
69
69
  * console.log(actor.currentRoute.get()); // '/'
70
70
  * console.log(actor.currentView.get()?.root); // 'home'
71
71
  * ```
72
72
  *
73
73
  * @example
74
- * The signal lifecycle with a watcher
74
+ * The atom lifecycle with a watch
75
75
  * ```typescript
76
- * import { Signal } from "@xmachines/play-signals";
76
+ * import { watchAtom } from "@xmachines/play-atom";
77
77
  *
78
- * const watcher = new Signal.subtle.Watcher(() => {
79
- * queueMicrotask(() => {
80
- * const pending = watcher.getPending();
81
- * console.log('State changed:', actor.state.get());
82
- * });
78
+ * const stop = watchAtom(actor.state, (snapshot) => {
79
+ * console.log('State changed:', snapshot.value);
83
80
  * });
84
81
  *
85
- * watcher.watch(actor.state);
86
82
  * actor.send({ type: 'play.route', to: '#about' });
87
- * // The watcher schedules its own notification in a microtask
83
+ * // watchAtom delivers the new value from a microtask
84
+ *
85
+ * stop();
88
86
  * ```
89
87
  *
90
88
  * @see [Play RFC](../../docs/rfc/play.md)
91
89
  * @see {@link definePlayer} for the creation through a factory
92
- * @see {@link @xmachines/play-actor!PlayActor} for the signal protocol
90
+ * @see {@link @xmachines/play-actor!PlayActor} for the atom protocol
93
91
  * @see {@link @xmachines/play-router!index.Routable} for the routing capability
94
92
  * @see {@link @xmachines/play-view!index.Viewable} for the view rendering capability
95
93
  *
@@ -99,10 +97,11 @@ export declare const toError: (value: unknown) => Error;
99
97
  * `meta.route`, which is the Stately pattern, for a URL template, and it substitutes
100
98
  * each parameter.
101
99
  *
102
- * **The pattern of the view signal:** the `currentView` signal is a direct
103
- * `Signal.State`, and not a `Signal.Computed`. The propagation to a watcher in
104
- * PlayRenderer is therefore correct. The class derives each view at the entry of a
105
- * state and keeps it, and it computes no view on a read.
100
+ * **The pattern of the view atom:** `withView` of `@xmachines/play-xstate/view` adds
101
+ * `currentView`, and that atom is a COMPUTED atom over `state`. One write for each
102
+ * transition — `state.set(snapshot)` — therefore reaches the view and the route in one
103
+ * flush, and no subscriber reads the new state beside an old derivation. The atom
104
+ * memoizes the result, so a repeated read computes no view again.
106
105
  */
107
106
  export declare class PlayerActor<TMachine extends AnyStateMachine> extends Actor<TMachine> implements PlayActor<ReturnType<TMachine["transition"]>, EventFromLogic<TMachine>> {
108
107
  private playerOptions?;
@@ -162,12 +161,12 @@ export declare class PlayerActor<TMachine extends AnyStateMachine> extends Actor
162
161
  * times.
163
162
  */
164
163
  private nextOnlySubscriptions?;
165
- state: Signal.State<ReturnType<TMachine["transition"]>>;
164
+ state: Atom<ReturnType<TMachine["transition"]>>;
166
165
  /**
167
166
  * Tells you if the current state of the actor accepts the given event.
168
167
  *
169
168
  * The type is the event union of the machine. An unknown event type is therefore a
170
- * compile error. The method evaluates the event against the snapshot signal.
169
+ * compile error. The method evaluates the event against the snapshot atom.
171
170
  *
172
171
  * @example
173
172
  * ```typescript
@@ -248,17 +247,19 @@ export declare class PlayerActor<TMachine extends AnyStateMachine> extends Actor
248
247
  */
249
248
  getPersistedSnapshot(options?: unknown): Snapshot<unknown>;
250
249
  /**
251
- * The point where a capability derives its own signals from a new snapshot.
250
+ * The point where a capability derives its own atoms from a new snapshot.
252
251
  *
253
252
  * The base derives nothing: `PlayActor` asks for `state` and `send`, and this class
254
- * gives exactly those. A capability is a mixin that overrides this method, calls
255
- * `super.onSnapshot(snapshot)` FIRST, and then writes its own signal.
253
+ * gives exactly those.
254
+ *
255
+ * A capability that PUBLISHES a value overrides this method NOT. It derives the value
256
+ * with a computed atom over `state`, as `withRouting` and `withView` both do, and the
257
+ * engine then evaluates every derivation from the one write of a transition, in
258
+ * topological order. The composition order therefore decides no value.
256
259
  *
257
- * That one rule fixes the order, and the order is load-bearing. The view of a state
258
- * reads the route and the state that the same transition produced, and a router bridge
259
- * must see a guard redirect synchronously. `compose(PlayerActor, withRouting, withView)`
260
- * therefore derives the route before the view, because `withView` wraps the class that
261
- * `withRouting` returned.
260
+ * This method remains for a capability that must run an EFFECT on a transition. Such a
261
+ * mixin overrides it and calls `super.onSnapshot(snapshot)` FIRST, so that every
262
+ * capability composed before it runs its own effect first.
262
263
  *
263
264
  * The method runs after `state` holds the new snapshot and before the `onStateChange`
264
265
  * hook of the options.
@@ -1 +1 @@
1
- {"version":3,"file":"player-actor.d.ts","sourceRoot":"","sources":["../src/player-actor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"player-actor.d.ts","sourceRoot":"","sources":["../src/player-actor.ts"],"names":[],"mappings":"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"}