@xmachines/play-xstate 2.0.0 → 2.1.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 +66 -65
- package/dist/define-player.d.ts +16 -16
- package/dist/define-player.js +16 -16
- package/dist/errors.d.ts +57 -50
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +63 -55
- package/dist/errors.js.map +1 -1
- package/dist/guards/compose.d.ts +53 -50
- package/dist/guards/compose.d.ts.map +1 -1
- package/dist/guards/compose.js +67 -63
- package/dist/guards/compose.js.map +1 -1
- package/dist/guards/helpers.d.ts +22 -22
- package/dist/guards/helpers.js +23 -23
- package/dist/guards/index.d.ts +9 -9
- package/dist/guards/index.js +9 -9
- package/dist/guards/types.d.ts +9 -8
- package/dist/guards/types.d.ts.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/player-actor.d.ts +162 -146
- package/dist/player-actor.d.ts.map +1 -1
- package/dist/player-actor.js +269 -241
- package/dist/player-actor.js.map +1 -1
- package/dist/routing/build-url.d.ts +19 -16
- package/dist/routing/build-url.d.ts.map +1 -1
- package/dist/routing/build-url.js +62 -59
- package/dist/routing/build-url.js.map +1 -1
- package/dist/routing/derive-current-route.d.ts +42 -36
- package/dist/routing/derive-current-route.d.ts.map +1 -1
- package/dist/routing/derive-current-route.js +57 -49
- package/dist/routing/derive-current-route.js.map +1 -1
- package/dist/routing/derive-initial-route.d.ts +23 -20
- package/dist/routing/derive-initial-route.d.ts.map +1 -1
- package/dist/routing/derive-initial-route.js +27 -24
- package/dist/routing/derive-initial-route.js.map +1 -1
- package/dist/routing/derive-route.d.ts +38 -37
- package/dist/routing/derive-route.d.ts.map +1 -1
- package/dist/routing/derive-route.js +45 -42
- package/dist/routing/derive-route.js.map +1 -1
- package/dist/routing/format-play-route-transitions.d.ts +34 -28
- package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
- package/dist/routing/format-play-route-transitions.js +32 -28
- package/dist/routing/format-play-route-transitions.js.map +1 -1
- package/dist/routing/index.d.ts +3 -3
- package/dist/routing/index.js +3 -3
- package/dist/routing/types.d.ts +12 -11
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/types.d.ts +64 -60
- package/dist/types.d.ts.map +1 -1
- package/dist/view/derive-current-view.d.ts +42 -40
- package/dist/view/derive-current-view.d.ts.map +1 -1
- package/dist/view/derive-current-view.js +51 -47
- package/dist/view/derive-current-view.js.map +1 -1
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# @xmachines/play-xstate
|
|
2
2
|
|
|
3
|
-
> XState v5 adapter for the XMachines Play Architecture
|
|
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.
|
|
4
4
|
|
|
5
|
-
[](https://opensource.org/licenses/MIT) [ monorepo.
|
|
5
|
+
[](https://opensource.org/licenses/MIT) [](https://www.npmjs.com/package/@xmachines/play-xstate)
|
|
8
6
|
|
|
9
7
|
---
|
|
10
8
|
|
|
@@ -14,7 +12,7 @@ Part of the [XMachines Play](../../README.md) monorepo.
|
|
|
14
12
|
pnpm add @xmachines/play-xstate xstate
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
`xstate ^5.31.0` is a peer dependency
|
|
15
|
+
`xstate ^5.31.0` is a peer dependency. Install it with this package.
|
|
18
16
|
|
|
19
17
|
---
|
|
20
18
|
|
|
@@ -28,7 +26,7 @@ import { definePlayer } from "@xmachines/play-xstate";
|
|
|
28
26
|
const machine = setup({}).createMachine({
|
|
29
27
|
initial: "idle",
|
|
30
28
|
states: {
|
|
31
|
-
idle: { meta: { route: "/" } },
|
|
29
|
+
idle: { meta: { route: "/" }, on: { activate: "active" } },
|
|
32
30
|
active: { meta: { route: "/active" } },
|
|
33
31
|
},
|
|
34
32
|
});
|
|
@@ -56,7 +54,7 @@ actor.stop();
|
|
|
56
54
|
|
|
57
55
|
### `definePlayer(config)`
|
|
58
56
|
|
|
59
|
-
|
|
57
|
+
This function creates a `PlayerFactory` from an XState v5 machine. One configuration can therefore make more than one independent actor instance. This helps with a multi-user application, with SSR, and with a test.
|
|
60
58
|
|
|
61
59
|
```typescript
|
|
62
60
|
import { setup } from "xstate";
|
|
@@ -92,9 +90,9 @@ const bob = createPlayer({ userId: "bob" });
|
|
|
92
90
|
|
|
93
91
|
#### `PlayerFactory` signature
|
|
94
92
|
|
|
95
|
-
`input`
|
|
96
|
-
cannot be `undefined
|
|
97
|
-
|
|
93
|
+
The `input` argument follows the rule of `createActor` in XState. If the input type of a
|
|
94
|
+
machine cannot be `undefined`, the first argument of the factory is necessary. An absent
|
|
95
|
+
input is then a compile error, not an actor that stops in an error status.
|
|
98
96
|
|
|
99
97
|
```typescript
|
|
100
98
|
type PlayerFactory<TMachine> =
|
|
@@ -121,35 +119,35 @@ restored.start();
|
|
|
121
119
|
console.log(restored.currentRoute.get()); // same route as when saved
|
|
122
120
|
```
|
|
123
121
|
|
|
124
|
-
> **Note:**
|
|
125
|
-
>
|
|
126
|
-
> with invoked or spawned
|
|
122
|
+
> **Note:** persist the state with `getPersistedSnapshot()`, not with
|
|
123
|
+
> `getSnapshot()`. `createActor` accepts that form only, and it is the only form
|
|
124
|
+
> that restores a machine with an invoked child or a spawned child.
|
|
127
125
|
|
|
128
126
|
---
|
|
129
127
|
|
|
130
128
|
### `PlayerActor<TMachine>`
|
|
131
129
|
|
|
132
|
-
|
|
130
|
+
This concrete actor class is an XState v5 actor that also exposes reactive TC39 Signals. It implements both the `Routable` interface and the `Viewable` interface from `@xmachines/play-actor`.
|
|
133
131
|
|
|
134
132
|
#### Signals
|
|
135
133
|
|
|
136
|
-
| Signal | Type | Description
|
|
137
|
-
| -------------- | -------------------------------------- |
|
|
138
|
-
| `state` | `Signal.State<SnapshotFrom<TMachine>>` |
|
|
139
|
-
| `currentRoute` | `Signal.Computed<string \| null>` |
|
|
140
|
-
| `currentView` | `Signal.State<PlaySpec \| null>` |
|
|
141
|
-
| `initialRoute` | `readonly string \| null` |
|
|
134
|
+
| Signal | Type | Description |
|
|
135
|
+
| -------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
136
|
+
| `state` | `Signal.State<SnapshotFrom<TMachine>>` | The current XState snapshot. The actor updates it on every active transition |
|
|
137
|
+
| `currentRoute` | `Signal.Computed<string \| null>` | The URL that comes from the `meta.route` template of the active state and from the context |
|
|
138
|
+
| `currentView` | `Signal.State<PlaySpec \| null>` | The view spec from the `meta.view` metadata of the active state, with the context params added |
|
|
139
|
+
| `initialRoute` | `readonly string \| null` | The route of the initial state of the machine. The constructor fixes it, and a router bridge uses it to detect a deep link or a restore |
|
|
142
140
|
|
|
143
141
|
#### Methods
|
|
144
142
|
|
|
145
|
-
| Method | Description
|
|
146
|
-
| --------------- |
|
|
147
|
-
| `start()` |
|
|
148
|
-
| `stop()` |
|
|
149
|
-
| `send(event)` |
|
|
150
|
-
| `can(event)` | Returns `true`
|
|
151
|
-
| `getSnapshot()` | Returns the current XState snapshot
|
|
152
|
-
| `dispose()` |
|
|
143
|
+
| Method | Description |
|
|
144
|
+
| --------------- | ------------------------------------------------------------------------- |
|
|
145
|
+
| `start()` | Starts the actor and calls the `onStart` hook |
|
|
146
|
+
| `stop()` | Stops the actor, cleans up the subscriptions, and calls the `onStop` hook |
|
|
147
|
+
| `send(event)` | Sends a typed event to the machine and calls the `onTransition` hook |
|
|
148
|
+
| `can(event)` | Returns `true` when the current state accepts the given event |
|
|
149
|
+
| `getSnapshot()` | Returns the current XState snapshot |
|
|
150
|
+
| `dispose()` | The alias of `stop()` |
|
|
153
151
|
|
|
154
152
|
#### Signal usage example
|
|
155
153
|
|
|
@@ -170,11 +168,12 @@ actor.start();
|
|
|
170
168
|
|
|
171
169
|
### Guard utilities
|
|
172
170
|
|
|
173
|
-
> **Deprecated:**
|
|
174
|
-
> combinators
|
|
175
|
-
>
|
|
171
|
+
> **Deprecated:** these guard helpers wrap the `and()`, `or()`, and `not()`
|
|
172
|
+
> combinators of XState, but they do not compose with a guard slot that
|
|
173
|
+
> `setup()` types. Use the combinators of XState directly. The next major
|
|
174
|
+
> version removes this module.
|
|
176
175
|
|
|
177
|
-
|
|
176
|
+
These composable guard helpers wrap the `and()`, `or()`, and `not()` functions of XState. Use them in a machine `setup({ guards })` definition.
|
|
178
177
|
|
|
179
178
|
```typescript
|
|
180
179
|
import { setup } from "xstate";
|
|
@@ -198,9 +197,9 @@ const machine = setup({
|
|
|
198
197
|
guard: composeGuards(["isLoggedIn", "hasAdminRole"]),
|
|
199
198
|
target: "adminPanel",
|
|
200
199
|
},
|
|
201
|
-
|
|
202
|
-
guard: negateGuard("
|
|
203
|
-
target: "
|
|
200
|
+
accessLogin: {
|
|
201
|
+
guard: negateGuard("isLoggedIn"),
|
|
202
|
+
target: "login",
|
|
204
203
|
},
|
|
205
204
|
},
|
|
206
205
|
// ...
|
|
@@ -211,11 +210,11 @@ const machine = setup({
|
|
|
211
210
|
|
|
212
211
|
### Routing utilities
|
|
213
212
|
|
|
214
|
-
|
|
213
|
+
These helper functions configure the routes of an XState machine declaratively.
|
|
215
214
|
|
|
216
215
|
#### `formatPlayRouteTransitions(machineConfig)`
|
|
217
216
|
|
|
218
|
-
|
|
217
|
+
This function reads each machine state that has a `meta.route` field. It then generates the `play.route` event handlers at the root level. You therefore write no repetitive routing transition.
|
|
219
218
|
|
|
220
219
|
```typescript
|
|
221
220
|
import { setup } from "xstate";
|
|
@@ -240,23 +239,23 @@ const config = formatPlayRouteTransitions({
|
|
|
240
239
|
const machine = setup({}).createMachine(config);
|
|
241
240
|
```
|
|
242
241
|
|
|
243
|
-
> **Note:**
|
|
242
|
+
> **Note:** every state with a `meta.route` field must also have an explicit `id` field. A state without an `id` field throws `MissingStateIdError` when you define the machine.
|
|
244
243
|
|
|
245
244
|
#### Other routing exports
|
|
246
245
|
|
|
247
|
-
| Export | Description
|
|
248
|
-
| ---------------------------------- |
|
|
249
|
-
| `deriveRoute(meta)` |
|
|
250
|
-
| `isAbsoluteRoute(route)` | Returns `true`
|
|
251
|
-
| `buildRouteUrl(template, context)` |
|
|
246
|
+
| Export | Description |
|
|
247
|
+
| ---------------------------------- | --------------------------------------------------------------------------- |
|
|
248
|
+
| `deriveRoute(meta)` | Reads the route template string from the metadata object of a state |
|
|
249
|
+
| `isAbsoluteRoute(route)` | Returns `true` when the route string is an absolute URL path |
|
|
250
|
+
| `buildRouteUrl(template, context)` | Replaces each `:param` placeholder of a route template with a context value |
|
|
252
251
|
|
|
253
252
|
---
|
|
254
253
|
|
|
255
254
|
## Inspection
|
|
256
255
|
|
|
257
|
-
`options.inspect`
|
|
258
|
-
inspection tool
|
|
259
|
-
|
|
256
|
+
The factory gives `options.inspect` to `createActor` of XState without a change.
|
|
257
|
+
Therefore every XState inspection tool works with a `PlayerActor`, and this
|
|
258
|
+
includes [`@statelyai/inspect`](https://stately.ai/docs/inspector):
|
|
260
259
|
|
|
261
260
|
```typescript
|
|
262
261
|
import { createBrowserInspector } from "@statelyai/inspect";
|
|
@@ -265,25 +264,27 @@ const { inspect } = createBrowserInspector();
|
|
|
265
264
|
const createPlayer = definePlayer({ machine, options: { inspect } });
|
|
266
265
|
```
|
|
267
266
|
|
|
268
|
-
Three
|
|
267
|
+
Three points are important:
|
|
269
268
|
|
|
270
|
-
-
|
|
271
|
-
reports to the same observer.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
269
|
+
- **`inspect` is an option of the factory, not of one instance.** Every actor of a
|
|
270
|
+
factory reports to the same observer. Separate the actors by root:
|
|
271
|
+
`event.rootId === actor.sessionId` covers the complete tree of an actor, with its
|
|
272
|
+
children.
|
|
273
|
+
- **`inspect` is the only path that sees the construction.** `actor.system.inspect(fn)`
|
|
274
|
+
attaches later, and it sees only the events after that moment. It therefore misses the
|
|
275
|
+
`@xstate.actor` registration, and an inspector needs that registration to draw the
|
|
276
|
+
machine.
|
|
277
|
+
- **A `PlayerActor` is the actor.** Its own events carry `actorRef === playerActor`, so
|
|
278
|
+
you can recognize a player by its identity. Note one point: `@xstate.actor` fires from
|
|
279
|
+
inside the constructor, and `state`, `currentRoute`, `currentView`, and `initialRoute`
|
|
280
|
+
do not exist yet. A read of one of them there throws.
|
|
280
281
|
|
|
281
|
-
For an inspector
|
|
282
|
-
function: `inspect: (event) => currentInspector?.(event)`.
|
|
282
|
+
For an inspector that you create after the factory, such as a dev-tools switch, give the
|
|
283
|
+
factory a function that forwards each event: `inspect: (event) => currentInspector?.(event)`.
|
|
283
284
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
The [inspector guide](../docs/guides/inspector.md) gives the complete procedure: a late
|
|
286
|
+
attachment with a replay, a WebSocket inspection without a browser, and the points to
|
|
287
|
+
consider in production.
|
|
287
288
|
|
|
288
289
|
---
|
|
289
290
|
|
|
@@ -310,7 +311,7 @@ import type {
|
|
|
310
311
|
|
|
311
312
|
## Error Classes
|
|
312
313
|
|
|
313
|
-
|
|
314
|
+
The `@xmachines/play-xstate/errors` subpath exports the error classes. The main bundle therefore stays small.
|
|
314
315
|
|
|
315
316
|
```typescript
|
|
316
317
|
import {
|
|
@@ -325,7 +326,7 @@ import {
|
|
|
325
326
|
} from "@xmachines/play-xstate/errors";
|
|
326
327
|
```
|
|
327
328
|
|
|
328
|
-
|
|
329
|
+
Every error class extends `PlayError` from `@xmachines/play`. Each class also carries typed detail fields, such as `param`, `template`, and `combinator`. Your code therefore reads the details of an error, and it does not parse the message.
|
|
329
330
|
|
|
330
331
|
---
|
|
331
332
|
|
|
@@ -339,7 +340,7 @@ pnpm --filter @xmachines/play-xstate test
|
|
|
339
340
|
pnpm --filter @xmachines/play-xstate run test:watch
|
|
340
341
|
```
|
|
341
342
|
|
|
342
|
-
|
|
343
|
+
The tests use [Vitest](https://vitest.dev/). They are in `packages/play-xstate/test/`.
|
|
343
344
|
|
|
344
345
|
---
|
|
345
346
|
|
package/dist/define-player.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { AnyStateMachine } from "xstate";
|
|
2
2
|
import type { PlayerConfig, PlayerFactory } from "./types.js";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Creates a player factory from an XState machine
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* This factory function accepts an XState v5 machine. It returns a function that
|
|
7
|
+
* makes {@link PlayerActor} instances. One configuration can therefore make more
|
|
8
|
+
* than one actor instance, and this helps with a test, with an application of
|
|
9
|
+
* several instances, and with a render on the server.
|
|
10
10
|
*
|
|
11
|
-
* @typeParam TMachine - XState v5 state machine
|
|
11
|
+
* @typeParam TMachine - The type of the XState v5 state machine
|
|
12
12
|
*
|
|
13
|
-
* @param config -
|
|
14
|
-
* @param config.machine - XState v5 state machine
|
|
15
|
-
* @param config.options -
|
|
13
|
+
* @param config - The configuration object of the player
|
|
14
|
+
* @param config.machine - The XState v5 state machine
|
|
15
|
+
* @param config.options - The optional lifecycle hooks: onStart, onTransition, and the others
|
|
16
16
|
*
|
|
17
|
-
* @returns
|
|
17
|
+
* @returns The factory function. It makes an actor instance, with an optional input context
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
|
-
*
|
|
20
|
+
* A basic player factory
|
|
21
21
|
* ```typescript
|
|
22
22
|
* import { setup } from "xstate";
|
|
23
23
|
* import { definePlayer } from "@xmachines/play-xstate";
|
|
@@ -36,25 +36,25 @@ import type { PlayerConfig, PlayerFactory } from "./types.js";
|
|
|
36
36
|
* ```
|
|
37
37
|
*
|
|
38
38
|
* @example
|
|
39
|
-
*
|
|
39
|
+
* More than one actor instance from one factory
|
|
40
40
|
* ```typescript
|
|
41
41
|
* const createPlayer = definePlayer({ machine });
|
|
42
42
|
*
|
|
43
|
-
* // Create
|
|
43
|
+
* // Create an actor for each user
|
|
44
44
|
* const alice = createPlayer({ userId: 'alice' });
|
|
45
45
|
* const bob = createPlayer({ userId: 'bob' });
|
|
46
46
|
*
|
|
47
47
|
* alice.start();
|
|
48
48
|
* bob.start();
|
|
49
49
|
*
|
|
50
|
-
* //
|
|
50
|
+
* // The two state machines are independent
|
|
51
51
|
* console.log(alice.state.get() !== bob.state.get());
|
|
52
52
|
* ```
|
|
53
53
|
*
|
|
54
54
|
* @see [Play RFC](../../docs/rfc/play.md)
|
|
55
55
|
* @see {@link PlayerActor} for the concrete actor implementation
|
|
56
|
-
* @see {@link PlayerConfig} for configuration options
|
|
57
|
-
* @see {@link PlayerFactory} for factory function
|
|
56
|
+
* @see {@link PlayerConfig} for the configuration options
|
|
57
|
+
* @see {@link PlayerFactory} for the signature of the factory function
|
|
58
58
|
*/
|
|
59
59
|
export declare const definePlayer: <TMachine extends AnyStateMachine>(config: PlayerConfig<TMachine>) => PlayerFactory<TMachine>;
|
|
60
60
|
//# sourceMappingURL=define-player.d.ts.map
|
package/dist/define-player.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { PlayerActor } from "./player-actor.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Creates a player factory from an XState machine
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* This factory function accepts an XState v5 machine. It returns a function that
|
|
6
|
+
* makes {@link PlayerActor} instances. One configuration can therefore make more
|
|
7
|
+
* than one actor instance, and this helps with a test, with an application of
|
|
8
|
+
* several instances, and with a render on the server.
|
|
9
9
|
*
|
|
10
|
-
* @typeParam TMachine - XState v5 state machine
|
|
10
|
+
* @typeParam TMachine - The type of the XState v5 state machine
|
|
11
11
|
*
|
|
12
|
-
* @param config -
|
|
13
|
-
* @param config.machine - XState v5 state machine
|
|
14
|
-
* @param config.options -
|
|
12
|
+
* @param config - The configuration object of the player
|
|
13
|
+
* @param config.machine - The XState v5 state machine
|
|
14
|
+
* @param config.options - The optional lifecycle hooks: onStart, onTransition, and the others
|
|
15
15
|
*
|
|
16
|
-
* @returns
|
|
16
|
+
* @returns The factory function. It makes an actor instance, with an optional input context
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
|
-
*
|
|
19
|
+
* A basic player factory
|
|
20
20
|
* ```typescript
|
|
21
21
|
* import { setup } from "xstate";
|
|
22
22
|
* import { definePlayer } from "@xmachines/play-xstate";
|
|
@@ -35,25 +35,25 @@ import { PlayerActor } from "./player-actor.js";
|
|
|
35
35
|
* ```
|
|
36
36
|
*
|
|
37
37
|
* @example
|
|
38
|
-
*
|
|
38
|
+
* More than one actor instance from one factory
|
|
39
39
|
* ```typescript
|
|
40
40
|
* const createPlayer = definePlayer({ machine });
|
|
41
41
|
*
|
|
42
|
-
* // Create
|
|
42
|
+
* // Create an actor for each user
|
|
43
43
|
* const alice = createPlayer({ userId: 'alice' });
|
|
44
44
|
* const bob = createPlayer({ userId: 'bob' });
|
|
45
45
|
*
|
|
46
46
|
* alice.start();
|
|
47
47
|
* bob.start();
|
|
48
48
|
*
|
|
49
|
-
* //
|
|
49
|
+
* // The two state machines are independent
|
|
50
50
|
* console.log(alice.state.get() !== bob.state.get());
|
|
51
51
|
* ```
|
|
52
52
|
*
|
|
53
53
|
* @see [Play RFC](../../docs/rfc/play.md)
|
|
54
54
|
* @see {@link PlayerActor} for the concrete actor implementation
|
|
55
|
-
* @see {@link PlayerConfig} for configuration options
|
|
56
|
-
* @see {@link PlayerFactory} for factory function
|
|
55
|
+
* @see {@link PlayerConfig} for the configuration options
|
|
56
|
+
* @see {@link PlayerFactory} for the signature of the factory function
|
|
57
57
|
*/
|
|
58
58
|
export const definePlayer = (config) => {
|
|
59
59
|
const { machine, options } = config;
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { PlayError } from "@xmachines/play";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* `buildRouteUrl()` throws this error when the context of the actor does not hold a
|
|
4
|
+
* necessary route parameter.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Read the `param` field and the `template` field to identify the parameter that is
|
|
7
|
+
* absent. Your code therefore parses no `.message` string.
|
|
8
8
|
*
|
|
9
9
|
* **Error code:** `PLAY_XSTATE_ROUTE_PARAM_MISSING`
|
|
10
10
|
*
|
|
11
|
-
* Note: `actor.currentRoute.get()`
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Note: `actor.currentRoute.get()` shows this error never. The route derivation
|
|
12
|
+
* catches it, and it returns `null` for the temporary case during a transition. The
|
|
13
|
+
* error leaves a direct `buildRouteUrl()` call only.
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```typescript
|
|
@@ -29,23 +29,23 @@ import { PlayError } from "@xmachines/play";
|
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
31
|
export declare class MissingRouteParamError extends PlayError {
|
|
32
|
-
/** The name of the route parameter that was
|
|
32
|
+
/** The name of the route parameter that was absent, for example `"userId"`. */
|
|
33
33
|
readonly param: string;
|
|
34
|
-
/** The route template that
|
|
34
|
+
/** The route template that needs the absent parameter, for example `"/profile/:userId"`. */
|
|
35
35
|
readonly template: string;
|
|
36
36
|
constructor(param: string, template: string);
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
* @deprecated
|
|
40
|
-
* field as `query: {}
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* and
|
|
44
|
-
*
|
|
45
|
-
*
|
|
39
|
+
* @deprecated Nothing throws this error now. `buildRouteUrl` reads an absent `query`
|
|
40
|
+
* field as `query: {}`. The generated `play.route` transitions assign `query` on
|
|
41
|
+
* every navigation, and the loss that this error guarded against therefore cannot
|
|
42
|
+
* happen through the route derivation. A machine that handles `play.route` itself
|
|
43
|
+
* and wants the query must assign `event.query` to its context itself. This class
|
|
44
|
+
* stays in the exports, so that an `instanceof` handler that exists now still
|
|
45
|
+
* compiles. Remove such a handler when you have the time.
|
|
46
46
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
47
|
+
* `buildRouteUrl()` threw this error before, when the context had a `params` field,
|
|
48
|
+
* which means a context that knows the routing, but no `query` field.
|
|
49
49
|
*
|
|
50
50
|
* **Error code:** `PLAY_XSTATE_MISSING_QUERY_CONTEXT`
|
|
51
51
|
*/
|
|
@@ -53,23 +53,24 @@ export declare class MissingQueryContextError extends PlayError {
|
|
|
53
53
|
constructor();
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
57
|
-
* but
|
|
56
|
+
* `formatPlayRouteTransitions()` throws this error when a state node declares a
|
|
57
|
+
* `meta.route` field but no explicit `id` field.
|
|
58
58
|
*
|
|
59
|
-
* Without `id`, the function
|
|
60
|
-
* state
|
|
61
|
-
* the state
|
|
62
|
-
*
|
|
59
|
+
* Without an `id`, the function can generate no `play.route` guard that targets the
|
|
60
|
+
* state: the guard compares `event.to` with `#<id>`. An absent `id` therefore makes
|
|
61
|
+
* the state unreachable through the routing, and nothing says so. This error shows
|
|
62
|
+
* the fault of the configuration at the moment of the machine definition, and the
|
|
63
|
+
* function skips no state in silence.
|
|
63
64
|
*
|
|
64
65
|
* **Error code:** `PLAY_XSTATE_MISSING_STATE_ID`
|
|
65
66
|
*
|
|
66
67
|
* @example
|
|
67
68
|
* ```typescript
|
|
68
|
-
* // Bad — meta.route without id:
|
|
69
|
+
* // Bad — a meta.route field without an id field:
|
|
69
70
|
* states: {
|
|
70
71
|
* profile: {
|
|
71
72
|
* meta: { route: "/profile/:username" },
|
|
72
|
-
* // ←
|
|
73
|
+
* // ← the id: "profile" field is absent
|
|
73
74
|
* }
|
|
74
75
|
* }
|
|
75
76
|
*
|
|
@@ -83,15 +84,16 @@ export declare class MissingQueryContextError extends PlayError {
|
|
|
83
84
|
* ```
|
|
84
85
|
*/
|
|
85
86
|
export declare class MissingStateIdError extends PlayError {
|
|
86
|
-
/** The state key
|
|
87
|
+
/** The state key, which is the position in the tree of the states, without an explicit `id` field. */
|
|
87
88
|
readonly stateKey: string;
|
|
88
|
-
/** The route template
|
|
89
|
+
/** The route template of the state, for example `"/profile/:username"`. */
|
|
89
90
|
readonly route: string;
|
|
90
91
|
constructor(stateKey: string, route: string);
|
|
91
92
|
}
|
|
92
93
|
/**
|
|
93
|
-
*
|
|
94
|
-
* valid XState machine object
|
|
94
|
+
* The `PlayerActor` constructor throws this error when the `machine` argument is not
|
|
95
|
+
* a valid XState machine object, which means that it is null, undefined, or not an
|
|
96
|
+
* object.
|
|
95
97
|
*
|
|
96
98
|
* **Error code:** `PLAY_XSTATE_INVALID_MACHINE`
|
|
97
99
|
*/
|
|
@@ -99,35 +101,38 @@ export declare class InvalidMachineError extends PlayError {
|
|
|
99
101
|
constructor();
|
|
100
102
|
}
|
|
101
103
|
/**
|
|
102
|
-
*
|
|
103
|
-
* string
|
|
104
|
+
* `normalizeRoute()` throws this error when the `meta.route` value of a state is not
|
|
105
|
+
* a string and not an object with a `path` property.
|
|
104
106
|
*
|
|
105
107
|
* **Error code:** `PLAY_XSTATE_INVALID_ROUTE_METADATA`
|
|
106
108
|
*/
|
|
107
109
|
export declare class InvalidRouteMetadataError extends PlayError {
|
|
108
|
-
/** The
|
|
110
|
+
/** The invalid route value, as a string, for the debug work. */
|
|
109
111
|
readonly detail: string;
|
|
110
112
|
constructor(route: unknown, source?: string);
|
|
111
113
|
}
|
|
112
114
|
/**
|
|
113
|
-
*
|
|
114
|
-
* guards
|
|
115
|
+
* `composeGuards()` and `composeGuardsOr()` throw this error for an empty array of
|
|
116
|
+
* guards. A composition of zero guards has no meaning.
|
|
115
117
|
*
|
|
116
118
|
* **Error code:** `PLAY_XSTATE_EMPTY_GUARD_ARRAY`
|
|
117
119
|
*/
|
|
118
120
|
export declare class EmptyGuardArrayError extends PlayError {
|
|
119
|
-
/** The combinator
|
|
121
|
+
/** The combinator of the call with the empty array: `"and"` or `"or"`. */
|
|
120
122
|
readonly combinator: "and" | "or";
|
|
121
123
|
constructor(combinator: "and" | "or");
|
|
122
124
|
}
|
|
123
125
|
/**
|
|
124
|
-
*
|
|
126
|
+
* `PlayerActor.send()` throws this error when the event argument is not a plain
|
|
127
|
+
* object.
|
|
125
128
|
*
|
|
126
|
-
* `PlayEvent`
|
|
127
|
-
* a string,
|
|
129
|
+
* A `PlayEvent` needs the shape `{ type: string, ...fields }`. A `null` value, an
|
|
130
|
+
* `undefined` value, a string, and every other value that is not an object are an
|
|
131
|
+
* error of the programmer.
|
|
128
132
|
*
|
|
129
|
-
* The
|
|
130
|
-
* TypeScript
|
|
133
|
+
* The error holds the value in question in its readonly class field `detail`, for
|
|
134
|
+
* the debug work. A TypeScript consumer reads `err.detail` directly, with no unsafe
|
|
135
|
+
* cast.
|
|
131
136
|
*
|
|
132
137
|
* **Error code:** `PLAY_XSTATE_INVALID_EVENT`
|
|
133
138
|
*
|
|
@@ -139,25 +144,27 @@ export declare class EmptyGuardArrayError extends PlayError {
|
|
|
139
144
|
* actor.send(null as any);
|
|
140
145
|
* } catch (err) {
|
|
141
146
|
* if (err instanceof InvalidEventError) {
|
|
142
|
-
* // err.detail
|
|
147
|
+
* // err.detail has the type `unknown`, and it needs no cast
|
|
143
148
|
* console.error("Invalid event passed to actor.send():", err.detail);
|
|
144
149
|
* }
|
|
145
150
|
* }
|
|
146
151
|
* ```
|
|
147
152
|
*/
|
|
148
153
|
export declare class InvalidEventError extends PlayError {
|
|
149
|
-
/** The
|
|
154
|
+
/** The value in question, from the `send()` call. */
|
|
150
155
|
readonly detail: unknown;
|
|
151
156
|
constructor(detail: unknown);
|
|
152
157
|
}
|
|
153
158
|
/**
|
|
154
|
-
*
|
|
155
|
-
* not an `Error
|
|
159
|
+
* The actor gives this error to `PlayerOptions.onError` when it failed with a value
|
|
160
|
+
* that is not an `Error`, for example after a machine action ran
|
|
161
|
+
* `throw { code: 42 }`.
|
|
156
162
|
*
|
|
157
|
-
* An actor error that *is* an `Error` reaches `onError`
|
|
158
|
-
* identity the machine
|
|
159
|
-
* carries a
|
|
160
|
-
* `"[object Object]"`. The
|
|
163
|
+
* An actor error that *is* an `Error` reaches `onError` without a change, and it
|
|
164
|
+
* keeps the identity of the machine. This case alone builds a new error. The new
|
|
165
|
+
* error therefore carries a code that your code can match, and not a
|
|
166
|
+
* `String(value)` message such as `"[object Object]"`. The `cause` field holds the
|
|
167
|
+
* value from the throw.
|
|
161
168
|
*
|
|
162
169
|
* **Error code:** `PLAY_XSTATE_NON_ERROR_THROWN`
|
|
163
170
|
*
|
|
@@ -170,7 +177,7 @@ export declare class InvalidEventError extends PlayError {
|
|
|
170
177
|
* options: {
|
|
171
178
|
* onError: (actor, err) => {
|
|
172
179
|
* if (err instanceof ActorThrewNonErrorError) {
|
|
173
|
-
* // err.cause is the value the machine
|
|
180
|
+
* // err.cause is the value that the machine threw
|
|
174
181
|
* console.error("Machine threw a non-Error:", err.cause);
|
|
175
182
|
* }
|
|
176
183
|
* },
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAsB5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;;;;;;;;;;;;;GAaG;AACH,qBAAa,wBAAyB,SAAQ,SAAS;;CAWtD;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;AAED;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,OAAO,EAAE,MAAM,SAAgB;CAUlD;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IAClD,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,KAAK,GAAG,IAAI,CAAC;gBAEtB,UAAU,EAAE,KAAK,GAAG,IAAI;CASpC;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"}
|