@xmachines/play-xstate 2.0.0-alpha.1 → 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 +114 -114
- package/dist/define-player.d.ts +16 -16
- package/dist/define-player.js +16 -16
- package/dist/errors.d.ts +84 -101
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +108 -108
- package/dist/errors.js.map +1 -1
- package/dist/guards/compose.d.ts +70 -77
- package/dist/guards/compose.d.ts.map +1 -1
- package/dist/guards/compose.js +90 -113
- package/dist/guards/compose.js.map +1 -1
- package/dist/guards/helpers.d.ts +22 -18
- package/dist/guards/helpers.d.ts.map +1 -1
- package/dist/guards/helpers.js +23 -19
- package/dist/guards/helpers.js.map +1 -1
- package/dist/guards/index.d.ts +10 -3
- package/dist/guards/index.d.ts.map +1 -1
- package/dist/guards/index.js +10 -3
- package/dist/guards/index.js.map +1 -1
- package/dist/guards/types.d.ts +9 -9
- package/dist/guards/types.d.ts.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -10
- package/dist/index.js.map +1 -1
- package/dist/player-actor.d.ts +197 -113
- package/dist/player-actor.d.ts.map +1 -1
- package/dist/player-actor.js +413 -401
- package/dist/player-actor.js.map +1 -1
- package/dist/routing/build-url.d.ts +19 -21
- package/dist/routing/build-url.d.ts.map +1 -1
- package/dist/routing/build-url.js +70 -71
- package/dist/routing/build-url.js.map +1 -1
- package/dist/routing/derive-current-route.d.ts +51 -13
- package/dist/routing/derive-current-route.d.ts.map +1 -1
- package/dist/routing/derive-current-route.js +69 -60
- package/dist/routing/derive-current-route.js.map +1 -1
- package/dist/routing/derive-initial-route.d.ts +23 -23
- package/dist/routing/derive-initial-route.js +27 -27
- 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 -71
- package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
- package/dist/routing/format-play-route-transitions.js +74 -130
- package/dist/routing/format-play-route-transitions.js.map +1 -1
- package/dist/routing/index.d.ts +4 -8
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -6
- package/dist/routing/index.js.map +1 -1
- package/dist/routing/types.d.ts +12 -11
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/types.d.ts +97 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/view/derive-current-view.d.ts +51 -0
- package/dist/view/derive-current-view.d.ts.map +1 -0
- package/dist/view/derive-current-view.js +119 -0
- package/dist/view/derive-current-view.js.map +1 -0
- package/package.json +22 -21
- package/dist/define-player.typecheck.d.ts +0 -2
- package/dist/define-player.typecheck.d.ts.map +0 -1
- package/dist/define-player.typecheck.js +0 -48
- package/dist/define-player.typecheck.js.map +0 -1
- package/dist/guards/compose.typecheck.d.ts +0 -2
- package/dist/guards/compose.typecheck.d.ts.map +0 -1
- package/dist/guards/compose.typecheck.js +0 -22
- package/dist/guards/compose.typecheck.js.map +0 -1
- package/dist/player-actor.typecheck.d.ts +0 -2
- package/dist/player-actor.typecheck.d.ts.map +0 -1
- package/dist/player-actor.typecheck.js +0 -30
- package/dist/player-actor.typecheck.js.map +0 -1
- package/dist/routing/create-routed-machine.d.ts +0 -71
- package/dist/routing/create-routed-machine.d.ts.map +0 -1
- package/dist/routing/create-routed-machine.js +0 -71
- package/dist/routing/create-routed-machine.js.map +0 -1
- package/dist/routing/play-route-event.typecheck.d.ts +0 -2
- package/dist/routing/play-route-event.typecheck.d.ts.map +0 -1
- package/dist/routing/play-route-event.typecheck.js +0 -43
- package/dist/routing/play-route-event.typecheck.js.map +0 -1
- package/dist/routing/schemas.d.ts +0 -99
- package/dist/routing/schemas.d.ts.map +0 -1
- package/dist/routing/schemas.js +0 -30
- package/dist/routing/schemas.js.map +0 -1
- package/dist/schemas.d.ts +0 -28
- package/dist/schemas.d.ts.map +0 -1
- package/dist/schemas.js +0 -29
- package/dist/schemas.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
<!-- generated-by: gsd-doc-writer -->
|
|
2
|
-
|
|
3
1
|
# @xmachines/play-xstate
|
|
4
2
|
|
|
5
|
-
> XState
|
|
6
|
-
|
|
7
|
-
[](https://opensource.org/licenses/MIT)
|
|
8
|
-
[](https://www.npmjs.com/package/@xmachines/play-xstate)
|
|
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.
|
|
9
4
|
|
|
10
|
-
|
|
5
|
+
[](https://opensource.org/licenses/MIT) [](https://www.npmjs.com/package/@xmachines/play-xstate)
|
|
11
6
|
|
|
12
7
|
---
|
|
13
8
|
|
|
@@ -17,7 +12,7 @@ Part of the [XMachines Play](../../README.md) monorepo.
|
|
|
17
12
|
pnpm add @xmachines/play-xstate xstate
|
|
18
13
|
```
|
|
19
14
|
|
|
20
|
-
`xstate ^
|
|
15
|
+
`xstate ^5.31.0` is a peer dependency. Install it with this package.
|
|
21
16
|
|
|
22
17
|
---
|
|
23
18
|
|
|
@@ -25,18 +20,13 @@ pnpm add @xmachines/play-xstate xstate
|
|
|
25
20
|
|
|
26
21
|
```typescript
|
|
27
22
|
import { setup } from "xstate";
|
|
28
|
-
import { definePlayer
|
|
23
|
+
import { definePlayer } from "@xmachines/play-xstate";
|
|
29
24
|
|
|
30
|
-
// 1. Define your XState
|
|
31
|
-
const machine = setup({
|
|
32
|
-
schemas: {
|
|
33
|
-
events: { activate: emptyEventSchema },
|
|
34
|
-
meta: playMetaSchema, // types meta.route / meta.view on state nodes
|
|
35
|
-
},
|
|
36
|
-
}).createMachine({
|
|
25
|
+
// 1. Define your XState v5 machine
|
|
26
|
+
const machine = setup({}).createMachine({
|
|
37
27
|
initial: "idle",
|
|
38
28
|
states: {
|
|
39
|
-
idle: { meta: { route: "/" }, on: { activate:
|
|
29
|
+
idle: { meta: { route: "/" }, on: { activate: "active" } },
|
|
40
30
|
active: { meta: { route: "/active" } },
|
|
41
31
|
},
|
|
42
32
|
});
|
|
@@ -64,16 +54,16 @@ actor.stop();
|
|
|
64
54
|
|
|
65
55
|
### `definePlayer(config)`
|
|
66
56
|
|
|
67
|
-
|
|
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.
|
|
68
58
|
|
|
69
59
|
```typescript
|
|
70
|
-
import { setup
|
|
60
|
+
import { setup } from "xstate";
|
|
71
61
|
import { definePlayer } from "@xmachines/play-xstate";
|
|
72
62
|
|
|
73
63
|
const machine = setup({
|
|
74
|
-
|
|
75
|
-
context:
|
|
76
|
-
input:
|
|
64
|
+
types: {
|
|
65
|
+
context: {} as { userId: string },
|
|
66
|
+
input: {} as { userId: string },
|
|
77
67
|
},
|
|
78
68
|
}).createMachine({
|
|
79
69
|
context: ({ input }) => ({ userId: input.userId }),
|
|
@@ -89,6 +79,7 @@ const createPlayer = definePlayer({
|
|
|
89
79
|
onTransition: (actor, prev, next) => console.log("transitioned"),
|
|
90
80
|
onStateChange: (actor, state) => console.log("state changed"),
|
|
91
81
|
onError: (actor, err) => console.error(err),
|
|
82
|
+
inspect: (event) => console.log(event.type), // handed to XState's actor constructor — enables @statelyai/inspect
|
|
92
83
|
},
|
|
93
84
|
});
|
|
94
85
|
|
|
@@ -99,17 +90,27 @@ const bob = createPlayer({ userId: "bob" });
|
|
|
99
90
|
|
|
100
91
|
#### `PlayerFactory` signature
|
|
101
92
|
|
|
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.
|
|
96
|
+
|
|
102
97
|
```typescript
|
|
103
|
-
type PlayerFactory<TMachine> =
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
98
|
+
type PlayerFactory<TMachine> =
|
|
99
|
+
undefined extends InputFrom<TMachine>
|
|
100
|
+
? (
|
|
101
|
+
input?: InputFrom<TMachine>,
|
|
102
|
+
options?: PlayerFactoryResumeOptions<TMachine>,
|
|
103
|
+
) => PlayerActor<TMachine>
|
|
104
|
+
: (
|
|
105
|
+
input: InputFrom<TMachine>,
|
|
106
|
+
options?: PlayerFactoryResumeOptions<TMachine>,
|
|
107
|
+
) => PlayerActor<TMachine>;
|
|
107
108
|
```
|
|
108
109
|
|
|
109
110
|
#### Restoring from a snapshot
|
|
110
111
|
|
|
111
112
|
```typescript
|
|
112
|
-
const snapshot = actor.
|
|
113
|
+
const snapshot = actor.getPersistedSnapshot();
|
|
113
114
|
actor.stop();
|
|
114
115
|
|
|
115
116
|
// Restore to the exact saved state
|
|
@@ -118,31 +119,35 @@ restored.start();
|
|
|
118
119
|
console.log(restored.currentRoute.get()); // same route as when saved
|
|
119
120
|
```
|
|
120
121
|
|
|
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.
|
|
125
|
+
|
|
121
126
|
---
|
|
122
127
|
|
|
123
128
|
### `PlayerActor<TMachine>`
|
|
124
129
|
|
|
125
|
-
|
|
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`.
|
|
126
131
|
|
|
127
132
|
#### Signals
|
|
128
133
|
|
|
129
|
-
| Signal | Type | Description
|
|
130
|
-
| -------------- | -------------------------------------- |
|
|
131
|
-
| `state` | `Signal.State<SnapshotFrom<TMachine>>` |
|
|
132
|
-
| `currentRoute` | `Signal.Computed<string \| null>` |
|
|
133
|
-
| `currentView` | `Signal.State<PlaySpec \| null>` |
|
|
134
|
-
| `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 |
|
|
135
140
|
|
|
136
141
|
#### Methods
|
|
137
142
|
|
|
138
|
-
| Method | Description
|
|
139
|
-
| --------------- |
|
|
140
|
-
| `start()` |
|
|
141
|
-
| `stop()` |
|
|
142
|
-
| `send(event)` |
|
|
143
|
-
| `can(event)` | Returns `true`
|
|
144
|
-
| `getSnapshot()` | Returns the current XState snapshot
|
|
145
|
-
| `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()` |
|
|
146
151
|
|
|
147
152
|
#### Signal usage example
|
|
148
153
|
|
|
@@ -163,7 +168,12 @@ actor.start();
|
|
|
163
168
|
|
|
164
169
|
### Guard utilities
|
|
165
170
|
|
|
166
|
-
|
|
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.
|
|
175
|
+
|
|
176
|
+
These composable guard helpers wrap the `and()`, `or()`, and `not()` functions of XState. Use them in a machine `setup({ guards })` definition.
|
|
167
177
|
|
|
168
178
|
```typescript
|
|
169
179
|
import { setup } from "xstate";
|
|
@@ -176,24 +186,20 @@ import {
|
|
|
176
186
|
contextFieldMatches, // guard: context field equals a value
|
|
177
187
|
} from "@xmachines/play-xstate";
|
|
178
188
|
|
|
179
|
-
const canAccessAdmin = composeGuards(["isLoggedIn", "hasAdminRole"]);
|
|
180
|
-
const isAuthenticated = negateGuard("isGuest");
|
|
181
|
-
|
|
182
189
|
const machine = setup({
|
|
183
190
|
guards: {
|
|
184
191
|
isLoggedIn: ({ context }) => !!context.userId,
|
|
185
192
|
hasAdminRole: ({ context }) => context.role === "admin",
|
|
186
|
-
isGuest: ({ context }) => !context.userId,
|
|
187
193
|
},
|
|
188
194
|
}).createMachine({
|
|
189
195
|
on: {
|
|
190
|
-
accessAdmin:
|
|
191
|
-
|
|
192
|
-
|
|
196
|
+
accessAdmin: {
|
|
197
|
+
guard: composeGuards(["isLoggedIn", "hasAdminRole"]),
|
|
198
|
+
target: "adminPanel",
|
|
193
199
|
},
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
accessLogin: {
|
|
201
|
+
guard: negateGuard("isLoggedIn"),
|
|
202
|
+
target: "login",
|
|
197
203
|
},
|
|
198
204
|
},
|
|
199
205
|
// ...
|
|
@@ -204,19 +210,17 @@ const machine = setup({
|
|
|
204
210
|
|
|
205
211
|
### Routing utilities
|
|
206
212
|
|
|
207
|
-
|
|
213
|
+
These helper functions configure the routes of an XState machine declaratively.
|
|
208
214
|
|
|
209
|
-
#### `
|
|
215
|
+
#### `formatPlayRouteTransitions(machineConfig)`
|
|
210
216
|
|
|
211
|
-
|
|
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.
|
|
212
218
|
|
|
213
219
|
```typescript
|
|
214
220
|
import { setup } from "xstate";
|
|
215
|
-
import {
|
|
216
|
-
|
|
217
|
-
const appSetup = setup({/* schemas, guards, ... */});
|
|
221
|
+
import { formatPlayRouteTransitions } from "@xmachines/play-xstate";
|
|
218
222
|
|
|
219
|
-
const
|
|
223
|
+
const config = formatPlayRouteTransitions({
|
|
220
224
|
id: "app",
|
|
221
225
|
states: {
|
|
222
226
|
home: {
|
|
@@ -229,61 +233,58 @@ const machine = createRoutedMachine(appSetup)({
|
|
|
229
233
|
},
|
|
230
234
|
},
|
|
231
235
|
});
|
|
236
|
+
|
|
237
|
+
// config now includes auto-generated play.route handlers:
|
|
238
|
+
// on: { "play.route": [ { target: ".home", guard: e => e.to === "#home" }, ... ] }
|
|
239
|
+
const machine = setup({}).createMachine(config);
|
|
232
240
|
```
|
|
233
241
|
|
|
234
|
-
|
|
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.
|
|
235
243
|
|
|
236
|
-
|
|
244
|
+
#### Other routing exports
|
|
237
245
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
playRouteEventSchema,
|
|
244
|
-
} from "@xmachines/play-xstate";
|
|
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 |
|
|
245
251
|
|
|
246
|
-
|
|
247
|
-
id: "app",
|
|
248
|
-
states: {
|
|
249
|
-
home: {
|
|
250
|
-
id: "home",
|
|
251
|
-
meta: { route: "/home" },
|
|
252
|
-
},
|
|
253
|
-
profile: {
|
|
254
|
-
id: "profile",
|
|
255
|
-
meta: { route: "/users/:userId" },
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
});
|
|
252
|
+
---
|
|
259
253
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
})
|
|
254
|
+
## Inspection
|
|
255
|
+
|
|
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):
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { createBrowserInspector } from "@statelyai/inspect";
|
|
262
|
+
|
|
263
|
+
const { inspect } = createBrowserInspector();
|
|
264
|
+
const createPlayer = definePlayer({ machine, options: { inspect } });
|
|
271
265
|
```
|
|
272
266
|
|
|
273
|
-
|
|
267
|
+
Three points are important:
|
|
274
268
|
|
|
275
|
-
|
|
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.
|
|
276
281
|
|
|
277
|
-
|
|
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)`.
|
|
278
284
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
| `playRouteEventSchema` | Shared `schemas.events` entry for the `play.route` event payload |
|
|
283
|
-
| `emptyEventSchema` | Shared `schemas.events` entry for events that carry no payload |
|
|
284
|
-
| `deriveRoute(meta)` | Extract the route template string from a state's metadata object |
|
|
285
|
-
| `isAbsoluteRoute(route)` | Returns `true` if the route string is an absolute URL path |
|
|
286
|
-
| `buildRouteUrl(template, context)` | Substitute `:param` placeholders in a route template using context values |
|
|
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
|
|
|
@@ -292,12 +293,12 @@ Because the injected `route` configs are static, route transitions keep statical
|
|
|
292
293
|
```typescript
|
|
293
294
|
import type {
|
|
294
295
|
PlayerConfig, // definePlayer() config argument shape
|
|
295
|
-
PlayerOptions, // Lifecycle hooks (onStart, onStop, onTransition, onStateChange, onError)
|
|
296
|
+
PlayerOptions, // Lifecycle hooks (onStart, onStop, onTransition, onStateChange, onError) + inspect
|
|
296
297
|
PlayerFactory, // Factory function returned by definePlayer()
|
|
297
298
|
PlayerFactoryResumeOptions, // { snapshot? } for restoring actor state
|
|
298
|
-
Guard, //
|
|
299
|
-
GuardArray, //
|
|
300
|
-
ComposedGuard, //
|
|
299
|
+
Guard, // deprecated with the guard utilities — removed in the next major
|
|
300
|
+
GuardArray, // deprecated with the guard utilities — removed in the next major
|
|
301
|
+
ComposedGuard, // deprecated with the guard utilities — removed in the next major
|
|
301
302
|
RouteMachineConfig, // Minimal machine config accepted by formatPlayRouteTransitions
|
|
302
303
|
RouteStateNode, // Single state node shape used during route crawling
|
|
303
304
|
RouteContext, // Context shape expected by buildRouteUrl ({ params?, query?, basePath?, hash? })
|
|
@@ -310,23 +311,22 @@ 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 {
|
|
317
318
|
MissingRouteParamError, // Required :param absent from context when resolving currentRoute
|
|
318
|
-
MissingQueryContextError, //
|
|
319
|
+
MissingQueryContextError, // deprecated: no longer thrown
|
|
319
320
|
MissingStateIdError, // meta.route declared without a state id field
|
|
320
321
|
InvalidMachineError, // PlayerActor constructed with a non-object machine
|
|
321
322
|
InvalidEventError, // actor.send() called with null/undefined/non-object
|
|
323
|
+
ActorThrewNonErrorError, // actor failed with a thrown value that is not an Error
|
|
322
324
|
InvalidRouteMetadataError, // meta.route is neither a string nor { path: string }
|
|
323
325
|
EmptyGuardArrayError, // composeGuards/composeGuardsOr called with empty array
|
|
324
|
-
UnresolvableGuardNameError, // string guard name could not be resolved at call time
|
|
325
|
-
InvalidGuardEntryError, // guard entry was neither a predicate nor a name (e.g. undefined)
|
|
326
326
|
} from "@xmachines/play-xstate/errors";
|
|
327
327
|
```
|
|
328
328
|
|
|
329
|
-
|
|
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.
|
|
330
330
|
|
|
331
331
|
---
|
|
332
332
|
|
|
@@ -340,7 +340,7 @@ pnpm --filter @xmachines/play-xstate test
|
|
|
340
340
|
pnpm --filter @xmachines/play-xstate run test:watch
|
|
341
341
|
```
|
|
342
342
|
|
|
343
|
-
|
|
343
|
+
The tests use [Vitest](https://vitest.dev/). They are in `packages/play-xstate/test/`.
|
|
344
344
|
|
|
345
345
|
---
|
|
346
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
|
|
11
|
+
* @typeParam TMachine - The type of the XState v5 state machine
|
|
12
12
|
*
|
|
13
|
-
* @param config -
|
|
14
|
-
* @param config.machine - XState
|
|
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
|
|
10
|
+
* @typeParam TMachine - The type of the XState v5 state machine
|
|
11
11
|
*
|
|
12
|
-
* @param config -
|
|
13
|
-
* @param config.machine - XState
|
|
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;
|