@xmachines/play-xstate 1.0.0 → 2.0.0-alpha.1
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 +77 -24
- package/dist/define-player.d.ts +3 -3
- package/dist/define-player.js +3 -3
- package/dist/define-player.typecheck.js +10 -10
- package/dist/define-player.typecheck.js.map +1 -1
- package/dist/errors.d.ts +38 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +45 -0
- package/dist/errors.js.map +1 -1
- package/dist/guards/compose.d.ts +59 -41
- package/dist/guards/compose.d.ts.map +1 -1
- package/dist/guards/compose.js +97 -69
- package/dist/guards/compose.js.map +1 -1
- package/dist/guards/compose.typecheck.d.ts +2 -0
- package/dist/guards/compose.typecheck.d.ts.map +1 -0
- package/dist/guards/compose.typecheck.js +22 -0
- package/dist/guards/compose.typecheck.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/player-actor.d.ts +3 -3
- package/dist/player-actor.d.ts.map +1 -1
- package/dist/player-actor.js +15 -9
- package/dist/player-actor.js.map +1 -1
- package/dist/player-actor.typecheck.js +8 -5
- package/dist/player-actor.typecheck.js.map +1 -1
- package/dist/routing/create-routed-machine.d.ts +71 -0
- package/dist/routing/create-routed-machine.d.ts.map +1 -0
- package/dist/routing/create-routed-machine.js +71 -0
- package/dist/routing/create-routed-machine.js.map +1 -0
- package/dist/routing/derive-initial-route.d.ts +1 -1
- package/dist/routing/derive-initial-route.js +1 -1
- package/dist/routing/format-play-route-transitions.d.ts +54 -11
- package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
- package/dist/routing/format-play-route-transitions.js +125 -52
- package/dist/routing/format-play-route-transitions.js.map +1 -1
- package/dist/routing/index.d.ts +4 -0
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +2 -0
- package/dist/routing/index.js.map +1 -1
- package/dist/routing/play-route-event.typecheck.d.ts +2 -0
- package/dist/routing/play-route-event.typecheck.d.ts.map +1 -0
- package/dist/routing/play-route-event.typecheck.js +43 -0
- package/dist/routing/play-route-event.typecheck.js.map +1 -0
- package/dist/routing/schemas.d.ts +99 -0
- package/dist/routing/schemas.d.ts.map +1 -0
- package/dist/routing/schemas.js +30 -0
- package/dist/routing/schemas.js.map +1 -0
- package/dist/schemas.d.ts +28 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +29 -0
- package/dist/schemas.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# @xmachines/play-xstate
|
|
4
4
|
|
|
5
|
-
> XState
|
|
5
|
+
> XState v6 adapter for the XMachines Play Architecture — bind state machines to the actor base with signal-driven reactivity and router integration.
|
|
6
6
|
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
[](https://www.npmjs.com/package/@xmachines/play-xstate)
|
|
@@ -17,7 +17,7 @@ Part of the [XMachines Play](../../README.md) monorepo.
|
|
|
17
17
|
pnpm add @xmachines/play-xstate xstate
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
`xstate ^
|
|
20
|
+
`xstate ^6.0.0-alpha.19` is a peer dependency and must be installed alongside this package.
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -25,13 +25,18 @@ pnpm add @xmachines/play-xstate xstate
|
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
27
|
import { setup } from "xstate";
|
|
28
|
-
import { definePlayer } from "@xmachines/play-xstate";
|
|
28
|
+
import { definePlayer, emptyEventSchema, playMetaSchema } from "@xmachines/play-xstate";
|
|
29
29
|
|
|
30
|
-
// 1. Define your XState
|
|
31
|
-
const machine = setup({
|
|
30
|
+
// 1. Define your XState v6 machine
|
|
31
|
+
const machine = setup({
|
|
32
|
+
schemas: {
|
|
33
|
+
events: { activate: emptyEventSchema },
|
|
34
|
+
meta: playMetaSchema, // types meta.route / meta.view on state nodes
|
|
35
|
+
},
|
|
36
|
+
}).createMachine({
|
|
32
37
|
initial: "idle",
|
|
33
38
|
states: {
|
|
34
|
-
idle: { meta: { route: "/" } },
|
|
39
|
+
idle: { meta: { route: "/" }, on: { activate: { target: "active" } } },
|
|
35
40
|
active: { meta: { route: "/active" } },
|
|
36
41
|
},
|
|
37
42
|
});
|
|
@@ -59,16 +64,16 @@ actor.stop();
|
|
|
59
64
|
|
|
60
65
|
### `definePlayer(config)`
|
|
61
66
|
|
|
62
|
-
Creates a `PlayerFactory` from an XState
|
|
67
|
+
Creates a `PlayerFactory` from an XState v6 machine. The factory pattern enables multiple independent actor instances from a single configuration — useful for multi-user scenarios, SSR, or testing.
|
|
63
68
|
|
|
64
69
|
```typescript
|
|
65
|
-
import { setup } from "xstate";
|
|
70
|
+
import { setup, types } from "xstate";
|
|
66
71
|
import { definePlayer } from "@xmachines/play-xstate";
|
|
67
72
|
|
|
68
73
|
const machine = setup({
|
|
69
|
-
|
|
70
|
-
context: {
|
|
71
|
-
input: {
|
|
74
|
+
schemas: {
|
|
75
|
+
context: types<{ userId: string }>(),
|
|
76
|
+
input: types<{ userId: string }>(),
|
|
72
77
|
},
|
|
73
78
|
}).createMachine({
|
|
74
79
|
context: ({ input }) => ({ userId: input.userId }),
|
|
@@ -117,7 +122,7 @@ console.log(restored.currentRoute.get()); // same route as when saved
|
|
|
117
122
|
|
|
118
123
|
### `PlayerActor<TMachine>`
|
|
119
124
|
|
|
120
|
-
Concrete actor class that wraps an XState
|
|
125
|
+
Concrete actor class that wraps an XState v6 actor and exposes TC39 Signal-based reactive signals. Implements both `Routable` and `Viewable` interfaces from `@xmachines/play-actor`.
|
|
121
126
|
|
|
122
127
|
#### Signals
|
|
123
128
|
|
|
@@ -158,7 +163,7 @@ actor.start();
|
|
|
158
163
|
|
|
159
164
|
### Guard utilities
|
|
160
165
|
|
|
161
|
-
Composable guard helpers that
|
|
166
|
+
Composable guard helpers that combine predicates with AND, OR, and NOT logic. Each helper returns a plain predicate — call it inside a transition function with the transition arguments and return early to block the transition. String guard names are resolved against the named guards declared in `setup({ guards })`.
|
|
162
167
|
|
|
163
168
|
```typescript
|
|
164
169
|
import { setup } from "xstate";
|
|
@@ -171,20 +176,24 @@ import {
|
|
|
171
176
|
contextFieldMatches, // guard: context field equals a value
|
|
172
177
|
} from "@xmachines/play-xstate";
|
|
173
178
|
|
|
179
|
+
const canAccessAdmin = composeGuards(["isLoggedIn", "hasAdminRole"]);
|
|
180
|
+
const isAuthenticated = negateGuard("isGuest");
|
|
181
|
+
|
|
174
182
|
const machine = setup({
|
|
175
183
|
guards: {
|
|
176
184
|
isLoggedIn: ({ context }) => !!context.userId,
|
|
177
185
|
hasAdminRole: ({ context }) => context.role === "admin",
|
|
186
|
+
isGuest: ({ context }) => !context.userId,
|
|
178
187
|
},
|
|
179
188
|
}).createMachine({
|
|
180
189
|
on: {
|
|
181
|
-
accessAdmin: {
|
|
182
|
-
|
|
183
|
-
target: "adminPanel"
|
|
190
|
+
accessAdmin: (args) => {
|
|
191
|
+
if (!canAccessAdmin(args)) return;
|
|
192
|
+
return { target: "adminPanel" };
|
|
184
193
|
},
|
|
185
|
-
accessDashboard: {
|
|
186
|
-
|
|
187
|
-
target: "dashboard"
|
|
194
|
+
accessDashboard: (args) => {
|
|
195
|
+
if (!isAuthenticated(args)) return;
|
|
196
|
+
return { target: "dashboard" };
|
|
188
197
|
},
|
|
189
198
|
},
|
|
190
199
|
// ...
|
|
@@ -197,13 +206,42 @@ const machine = setup({
|
|
|
197
206
|
|
|
198
207
|
Helper functions for declarative route configuration in XState machines.
|
|
199
208
|
|
|
209
|
+
#### `createRoutedMachine(setup)`
|
|
210
|
+
|
|
211
|
+
The recommended entry point: returns a `createMachine` with the same signature as the setup's own — full contextual typing for the config — that wires routing up at runtime.
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { setup } from "xstate";
|
|
215
|
+
import { createRoutedMachine } from "@xmachines/play-xstate";
|
|
216
|
+
|
|
217
|
+
const appSetup = setup({/* schemas, guards, ... */});
|
|
218
|
+
|
|
219
|
+
const machine = createRoutedMachine(appSetup)({
|
|
220
|
+
id: "app",
|
|
221
|
+
states: {
|
|
222
|
+
home: {
|
|
223
|
+
id: "home",
|
|
224
|
+
meta: { route: "/home" },
|
|
225
|
+
},
|
|
226
|
+
profile: {
|
|
227
|
+
id: "profile",
|
|
228
|
+
meta: { route: "/users/:userId" },
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
200
234
|
#### `formatPlayRouteTransitions(machineConfig)`
|
|
201
235
|
|
|
202
|
-
Crawls machine states with `meta.route` and
|
|
236
|
+
The underlying transform. Crawls machine states with `meta.route` and wires them to XState v6's native routing: each routed state gets a native `route: {}` config (targetable via the built-in `xstate.route` event and visible to graph tooling), and one root `play.route` forwarder navigates those targets in a single atomic transition — patching `params`/`query` into context — while re-raising `xstate.route` only for states that declare their own `route` config. Unknown targets fall through to user-defined `play.route` fallbacks (e.g. a 404 route); one `play.route` send is one atomic transition, so exit actions see the old `params` and entry actions the new ones.
|
|
203
237
|
|
|
204
238
|
```typescript
|
|
205
239
|
import { setup } from "xstate";
|
|
206
|
-
import {
|
|
240
|
+
import {
|
|
241
|
+
formatPlayRouteTransitions,
|
|
242
|
+
playMetaSchema,
|
|
243
|
+
playRouteEventSchema,
|
|
244
|
+
} from "@xmachines/play-xstate";
|
|
207
245
|
|
|
208
246
|
const config = formatPlayRouteTransitions({
|
|
209
247
|
id: "app",
|
|
@@ -219,17 +257,30 @@ const config = formatPlayRouteTransitions({
|
|
|
219
257
|
},
|
|
220
258
|
});
|
|
221
259
|
|
|
222
|
-
// config now
|
|
223
|
-
//
|
|
224
|
-
|
|
260
|
+
// config now carries native route configs plus the play.route forwarder:
|
|
261
|
+
// states: { home: { ..., route: {} }, profile: { ..., route: {} } }
|
|
262
|
+
// on: { "play.route": [forwarder, ...userFallbacks] }
|
|
263
|
+
// The forwarder navigates injected-route targets directly (atomically);
|
|
264
|
+
// xstate.route is raised only for states declaring their own route config.
|
|
265
|
+
const machine = setup({
|
|
266
|
+
schemas: {
|
|
267
|
+
events: { "play.route": playRouteEventSchema },
|
|
268
|
+
meta: playMetaSchema,
|
|
269
|
+
},
|
|
270
|
+
}).createMachine(config);
|
|
225
271
|
```
|
|
226
272
|
|
|
273
|
+
Because the injected `route` configs are static, route transitions keep statically-known targets — `machineToGraph()` sees real edges to every routed state, so reachability queries work.
|
|
274
|
+
|
|
227
275
|
> **Note:** Every state with `meta.route` must also have an explicit `id` field; omitting it throws `MissingStateIdError` at machine-definition time.
|
|
228
276
|
|
|
229
277
|
#### Other routing exports
|
|
230
278
|
|
|
231
279
|
| Export | Description |
|
|
232
280
|
| ---------------------------------- | ------------------------------------------------------------------------- |
|
|
281
|
+
| `playMetaSchema` | Shared `schemas.meta` declaration for `meta.route` / `meta.view` metadata |
|
|
282
|
+
| `playRouteEventSchema` | Shared `schemas.events` entry for the `play.route` event payload |
|
|
283
|
+
| `emptyEventSchema` | Shared `schemas.events` entry for events that carry no payload |
|
|
233
284
|
| `deriveRoute(meta)` | Extract the route template string from a state's metadata object |
|
|
234
285
|
| `isAbsoluteRoute(route)` | Returns `true` if the route string is an absolute URL path |
|
|
235
286
|
| `buildRouteUrl(template, context)` | Substitute `:param` placeholders in a route template using context values |
|
|
@@ -270,6 +321,8 @@ import {
|
|
|
270
321
|
InvalidEventError, // actor.send() called with null/undefined/non-object
|
|
271
322
|
InvalidRouteMetadataError, // meta.route is neither a string nor { path: string }
|
|
272
323
|
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)
|
|
273
326
|
} from "@xmachines/play-xstate/errors";
|
|
274
327
|
```
|
|
275
328
|
|
package/dist/define-player.d.ts
CHANGED
|
@@ -3,15 +3,15 @@ import type { PlayerConfig, PlayerFactory } from "./types.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Create a player factory from an XState machine
|
|
5
5
|
*
|
|
6
|
-
* Factory pattern that accepts an XState
|
|
6
|
+
* Factory pattern that accepts an XState v6 machine,
|
|
7
7
|
* returning a function that creates {@link PlayerActor} instances. This enables
|
|
8
8
|
* creating multiple actor instances from a single configuration, useful for
|
|
9
9
|
* testing, multi-instance scenarios, or server-side rendering.
|
|
10
10
|
*
|
|
11
|
-
* @typeParam TMachine - XState
|
|
11
|
+
* @typeParam TMachine - XState v6 state machine type
|
|
12
12
|
*
|
|
13
13
|
* @param config - Player configuration object
|
|
14
|
-
* @param config.machine - XState
|
|
14
|
+
* @param config.machine - XState v6 state machine
|
|
15
15
|
* @param config.options - Optional lifecycle hooks (onStart, onTransition, etc.)
|
|
16
16
|
*
|
|
17
17
|
* @returns Factory function that creates actor instances with optional input context
|
package/dist/define-player.js
CHANGED
|
@@ -2,15 +2,15 @@ import { PlayerActor } from "./player-actor.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Create a player factory from an XState machine
|
|
4
4
|
*
|
|
5
|
-
* Factory pattern that accepts an XState
|
|
5
|
+
* Factory pattern that accepts an XState v6 machine,
|
|
6
6
|
* returning a function that creates {@link PlayerActor} instances. This enables
|
|
7
7
|
* creating multiple actor instances from a single configuration, useful for
|
|
8
8
|
* testing, multi-instance scenarios, or server-side rendering.
|
|
9
9
|
*
|
|
10
|
-
* @typeParam TMachine - XState
|
|
10
|
+
* @typeParam TMachine - XState v6 state machine type
|
|
11
11
|
*
|
|
12
12
|
* @param config - Player configuration object
|
|
13
|
-
* @param config.machine - XState
|
|
13
|
+
* @param config.machine - XState v6 state machine
|
|
14
14
|
* @param config.options - Optional lifecycle hooks (onStart, onTransition, etc.)
|
|
15
15
|
*
|
|
16
16
|
* @returns Factory function that creates actor instances with optional input context
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { setup } from "xstate";
|
|
1
|
+
import { setup, types } from "xstate";
|
|
2
|
+
import { emptyEventSchema } from "./schemas.js";
|
|
2
3
|
import { definePlayer } from "./define-player.js";
|
|
3
4
|
const machine = setup({
|
|
4
|
-
|
|
5
|
-
context:
|
|
6
|
-
input:
|
|
7
|
-
events: {
|
|
5
|
+
schemas: {
|
|
6
|
+
context: types(),
|
|
7
|
+
input: types(),
|
|
8
|
+
events: {
|
|
9
|
+
inc: emptyEventSchema,
|
|
10
|
+
},
|
|
8
11
|
},
|
|
9
12
|
}).createMachine({
|
|
10
13
|
context: ({ input }) => ({ count: input.count }),
|
|
@@ -12,11 +15,8 @@ const machine = setup({
|
|
|
12
15
|
states: {
|
|
13
16
|
active: {
|
|
14
17
|
on: {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
context.count += 1;
|
|
18
|
-
},
|
|
19
|
-
},
|
|
18
|
+
// XState v6: transitions are functions returning a context patch.
|
|
19
|
+
inc: ({ context }) => ({ context: { count: context.count + 1 } }),
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-player.typecheck.js","sourceRoot":"","sources":["../src/define-player.typecheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"define-player.typecheck.js","sourceRoot":"","sources":["../src/define-player.typecheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKlD,MAAM,OAAO,GAAG,KAAK,CAAC;IACrB,OAAO,EAAE;QACR,OAAO,EAAE,KAAK,EAAqB;QACnC,KAAK,EAAE,KAAK,EAAqB;QACjC,MAAM,EAAE;YACP,GAAG,EAAE,gBAAgB;SACrB;KACD;CACD,CAAC,CAAC,aAAa,CAAC;IAChB,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAChD,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE;QACP,MAAM,EAAE;YACP,EAAE,EAAE;gBACH,kEAAkE;gBAClE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC;aACjE;SACD;KACD;CACD,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,YAAY,CAAC;IACjC,OAAO;IACP,OAAO,EAAE;QACR,YAAY,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE;YAK7C,MAAM,WAAW,GAA4B,KAAK,CAAC;YACnD,MAAM,UAAU,GAA2B,KAAK,CAAC;YACjD,MAAM,UAAU,GAA2B,KAAK,CAAC;YAEjD,KAAK,WAAW,CAAC;YACjB,KAAK,UAAU,CAAC;YAChB,KAAK,UAAU,CAAC;QACjB,CAAC;KACD;CACD,CAAC,CAAC;AAEH,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;AACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;AACrC,MAAM,aAAa,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;AAI/D,MAAM,YAAY,GAA6B,KAAK,CAAC;AACrD,MAAM,oBAAoB,GAAqC,KAAK,CAAC;AACrE,KAAK,YAAY,CAAC;AAClB,KAAK,oBAAoB,CAAC;AAE1B,gEAAgE;AAChE,YAAY,CAAC,SAAS,CAAC,CAAC;AAExB,oEAAoE;AACpE,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -137,6 +137,44 @@ export declare class EmptyGuardArrayError extends PlayError {
|
|
|
137
137
|
readonly combinator: "and" | "or";
|
|
138
138
|
constructor(combinator: "and" | "or");
|
|
139
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* The guard-composition helper a composed guard was built by. Threaded into
|
|
142
|
+
* guard errors so `PlayError.scope` names the actual origin.
|
|
143
|
+
*/
|
|
144
|
+
export type GuardCombinator = "composeGuards" | "composeGuardsOr" | "negateGuard";
|
|
145
|
+
/**
|
|
146
|
+
* Thrown when a composed guard cannot resolve a string guard name at call time.
|
|
147
|
+
*
|
|
148
|
+
* String names in `composeGuards`/`composeGuardsOr`/`negateGuard` resolve
|
|
149
|
+
* against `args.guards` — the named guards from `setup({ guards })` that
|
|
150
|
+
* XState v6 provides to transition functions, `always`, entry/exit actions
|
|
151
|
+
* (since 6.0.0-alpha.20), and function-form route resolvers. Resolution fails
|
|
152
|
+
* when the name was never declared or when the composed guard is called
|
|
153
|
+
* without transition arguments.
|
|
154
|
+
*
|
|
155
|
+
* **Error code:** `PLAY_XSTATE_UNRESOLVABLE_GUARD_NAME`
|
|
156
|
+
*/
|
|
157
|
+
export declare class UnresolvableGuardNameError extends PlayError {
|
|
158
|
+
/** The guard name that could not be resolved. */
|
|
159
|
+
readonly guardName: string;
|
|
160
|
+
constructor(guardName: string, origin: GuardCombinator);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Thrown when a composed guard evaluates an entry that is neither a predicate
|
|
164
|
+
* function nor a guard name — typically `null`/`undefined` from a typo'd
|
|
165
|
+
* import or an optional lookup.
|
|
166
|
+
*
|
|
167
|
+
* XState v5 failed loudly when evaluating such entries; silently treating them
|
|
168
|
+
* as never-passing would turn `negateGuard(undefined)` into an always-allow.
|
|
169
|
+
* Composition stays lazy (no throw at compose time); evaluation throws.
|
|
170
|
+
*
|
|
171
|
+
* **Error code:** `PLAY_XSTATE_INVALID_GUARD_ENTRY`
|
|
172
|
+
*/
|
|
173
|
+
export declare class InvalidGuardEntryError extends PlayError {
|
|
174
|
+
/** `typeof` of the invalid entry (e.g. `"undefined"`, `"object"` for null). */
|
|
175
|
+
readonly entryType: string;
|
|
176
|
+
constructor(entryType: string, origin: GuardCombinator);
|
|
177
|
+
}
|
|
140
178
|
/**
|
|
141
179
|
* Thrown by `PlayerActor.send()` when the event argument is not a plain object.
|
|
142
180
|
*
|
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;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,0FAA0F;IAC1F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAU3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,wBAAyB,SAAQ,SAAS;;CAWtD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAW3C;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;;CASjD;AAED;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,OAAO,EAAE,MAAM,SAAgB;CAUlD;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IAClD,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,KAAK,GAAG,IAAI,CAAC;gBAEtB,UAAU,EAAE,KAAK,GAAG,IAAI;CASpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC/C,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,MAAM,EAAE,OAAO;CAS3B"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,0FAA0F;IAC1F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAU3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,wBAAyB,SAAQ,SAAS;;CAWtD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAW3C;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;;CASjD;AAED;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,OAAO,EAAE,MAAM,SAAgB;CAUlD;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IAClD,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,KAAK,GAAG,IAAI,CAAC;gBAEtB,UAAU,EAAE,KAAK,GAAG,IAAI;CASpC;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG,iBAAiB,GAAG,aAAa,CAAC;AAElF;;;;;;;;;;;GAWG;AACH,qBAAa,0BAA2B,SAAQ,SAAS;IACxD,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe;CAWtD;AAED;;;;;;;;;;GAUG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe;CAWtD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC/C,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,MAAM,EAAE,OAAO;CAS3B"}
|
package/dist/errors.js
CHANGED
|
@@ -165,6 +165,51 @@ export class EmptyGuardArrayError extends PlayError {
|
|
|
165
165
|
this.combinator = combinator;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Thrown when a composed guard cannot resolve a string guard name at call time.
|
|
170
|
+
*
|
|
171
|
+
* String names in `composeGuards`/`composeGuardsOr`/`negateGuard` resolve
|
|
172
|
+
* against `args.guards` — the named guards from `setup({ guards })` that
|
|
173
|
+
* XState v6 provides to transition functions, `always`, entry/exit actions
|
|
174
|
+
* (since 6.0.0-alpha.20), and function-form route resolvers. Resolution fails
|
|
175
|
+
* when the name was never declared or when the composed guard is called
|
|
176
|
+
* without transition arguments.
|
|
177
|
+
*
|
|
178
|
+
* **Error code:** `PLAY_XSTATE_UNRESOLVABLE_GUARD_NAME`
|
|
179
|
+
*/
|
|
180
|
+
export class UnresolvableGuardNameError extends PlayError {
|
|
181
|
+
/** The guard name that could not be resolved. */
|
|
182
|
+
guardName;
|
|
183
|
+
constructor(guardName, origin) {
|
|
184
|
+
super(origin, "PLAY_XSTATE_UNRESOLVABLE_GUARD_NAME", `Guard "${guardName}" is not a function. Either the name was never declared ` +
|
|
185
|
+
`in setup({ guards }) or the composed guard was called without ` +
|
|
186
|
+
`transition arguments.`);
|
|
187
|
+
this.name = "UnresolvableGuardNameError";
|
|
188
|
+
this.guardName = guardName;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Thrown when a composed guard evaluates an entry that is neither a predicate
|
|
193
|
+
* function nor a guard name — typically `null`/`undefined` from a typo'd
|
|
194
|
+
* import or an optional lookup.
|
|
195
|
+
*
|
|
196
|
+
* XState v5 failed loudly when evaluating such entries; silently treating them
|
|
197
|
+
* as never-passing would turn `negateGuard(undefined)` into an always-allow.
|
|
198
|
+
* Composition stays lazy (no throw at compose time); evaluation throws.
|
|
199
|
+
*
|
|
200
|
+
* **Error code:** `PLAY_XSTATE_INVALID_GUARD_ENTRY`
|
|
201
|
+
*/
|
|
202
|
+
export class InvalidGuardEntryError extends PlayError {
|
|
203
|
+
/** `typeof` of the invalid entry (e.g. `"undefined"`, `"object"` for null). */
|
|
204
|
+
entryType;
|
|
205
|
+
constructor(entryType, origin) {
|
|
206
|
+
super(origin, "PLAY_XSTATE_INVALID_GUARD_ENTRY", `Guard entry of type "${entryType}" is neither a predicate function nor a ` +
|
|
207
|
+
`guard name. Check for typo'd imports or optional lookups that resolved ` +
|
|
208
|
+
`to null/undefined.`);
|
|
209
|
+
this.name = "InvalidGuardEntryError";
|
|
210
|
+
this.entryType = entryType;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
168
213
|
/**
|
|
169
214
|
* Thrown by `PlayerActor.send()` when the event argument is not a plain object.
|
|
170
215
|
*
|
package/dist/errors.js.map
CHANGED
|
@@ -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/guards/compose.d.ts
CHANGED
|
@@ -1,33 +1,50 @@
|
|
|
1
|
-
import type { GuardPredicate } from "xstate";
|
|
2
1
|
import type { Guard, GuardArray } from "./types.js";
|
|
3
|
-
import type { MachineContext, EventObject, ParameterizedObject } from "xstate";
|
|
4
2
|
/**
|
|
5
|
-
*
|
|
3
|
+
* Composed guard: a plain predicate over transition arguments.
|
|
6
4
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* XState v6 removed guard objects and the `and()`/`or()`/`not()` creators —
|
|
6
|
+
* guards are now plain functions evaluated inside transition functions. A
|
|
7
|
+
* composed guard is therefore just another predicate with the same shape as
|
|
8
|
+
* {@link Guard}, callable anywhere transition args are available.
|
|
9
|
+
*
|
|
10
|
+
* String guard names are resolved against `args.guards` (the named guards
|
|
11
|
+
* declared in `setup({ guards })`, which XState v6 passes to every transition
|
|
12
|
+
* function). Resolving a name outside a transition function — or a name that
|
|
13
|
+
* was never declared — throws `UnresolvableGuardNameError` immediately.
|
|
14
|
+
*
|
|
15
|
+
* String names work in `on` transitions, `always`, entry/exit actions (since
|
|
16
|
+
* xstate 6.0.0-alpha.20 populates `guards` there), and function-form route
|
|
17
|
+
* resolvers.
|
|
9
18
|
*
|
|
10
19
|
* @public
|
|
11
20
|
*/
|
|
12
|
-
export type ComposedGuard =
|
|
21
|
+
export type ComposedGuard = (args: unknown) => boolean;
|
|
13
22
|
/**
|
|
14
|
-
* Compose guards with AND logic
|
|
23
|
+
* Compose guards with AND logic.
|
|
15
24
|
*
|
|
16
25
|
* Combines multiple guard predicates using AND semantics—all guards must pass for
|
|
17
|
-
* the composition to succeed.
|
|
18
|
-
* type inference and machine serialization.
|
|
26
|
+
* the composition to succeed. Evaluation is short-circuiting, left to right.
|
|
19
27
|
*
|
|
20
28
|
* **Architectural Context:** Supports **Actor Authority (INV-01)** by enabling
|
|
21
29
|
* declarative guard composition in state machine transitions. Guards enforce business
|
|
22
30
|
* logic rules that determine whether navigation or actions are valid.
|
|
23
31
|
*
|
|
24
|
-
*
|
|
32
|
+
* **XState v6:** the composed value is a plain predicate. Call it inside a
|
|
33
|
+
* transition function and return early to block the transition:
|
|
34
|
+
*
|
|
35
|
+
* @typeParam TContext - State machine context type (defaults to `any` so the
|
|
36
|
+
* documented inline-predicate examples compile without annotations)
|
|
37
|
+
* @typeParam TEvent - Event type
|
|
38
|
+
*
|
|
39
|
+
* @typeParam TContext - State machine context type (defaults to `any` so the
|
|
40
|
+
* documented inline-predicate examples compile without annotations)
|
|
25
41
|
* @typeParam TEvent - Event type
|
|
26
42
|
*
|
|
27
|
-
* @param guards - Array of guard predicates or guard names (string references
|
|
28
|
-
*
|
|
43
|
+
* @param guards - Array of guard predicates or guard names (string references
|
|
44
|
+
* resolved against `args.guards` from `setup({ guards })`)
|
|
45
|
+
* @returns Predicate returning `true` only when every guard passes
|
|
29
46
|
*
|
|
30
|
-
* @throws {
|
|
47
|
+
* @throws {EmptyGuardArrayError} If guards array is empty
|
|
31
48
|
*
|
|
32
49
|
* @example
|
|
33
50
|
* AND composition with named guards
|
|
@@ -35,6 +52,8 @@ export type ComposedGuard = GuardPredicate<MachineContext, EventObject, unknown,
|
|
|
35
52
|
* import { setup } from "xstate";
|
|
36
53
|
* import { composeGuards } from "@xmachines/play-xstate";
|
|
37
54
|
*
|
|
55
|
+
* const canAccessAdmin = composeGuards(['isLoggedIn', 'hasPermission']);
|
|
56
|
+
*
|
|
38
57
|
* const machine = setup({
|
|
39
58
|
* guards: {
|
|
40
59
|
* isLoggedIn: ({ context }) => !!context.userId,
|
|
@@ -42,10 +61,9 @@ export type ComposedGuard = GuardPredicate<MachineContext, EventObject, unknown,
|
|
|
42
61
|
* }
|
|
43
62
|
* }).createMachine({
|
|
44
63
|
* on: {
|
|
45
|
-
* accessAdmin: {
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* target: 'adminPanel'
|
|
64
|
+
* accessAdmin: (args) => {
|
|
65
|
+
* if (!canAccessAdmin(args)) return;
|
|
66
|
+
* return { target: 'adminPanel' };
|
|
49
67
|
* }
|
|
50
68
|
* }
|
|
51
69
|
* });
|
|
@@ -56,10 +74,10 @@ export type ComposedGuard = GuardPredicate<MachineContext, EventObject, unknown,
|
|
|
56
74
|
* ```typescript
|
|
57
75
|
* import { composeGuards } from "@xmachines/play-xstate";
|
|
58
76
|
*
|
|
59
|
-
*
|
|
77
|
+
* const isEligible = composeGuards([
|
|
60
78
|
* ({ context }) => context.age >= 18,
|
|
61
79
|
* ({ context }) => context.verified
|
|
62
|
-
* ])
|
|
80
|
+
* ]);
|
|
63
81
|
* ```
|
|
64
82
|
*
|
|
65
83
|
* @see {@link composeGuardsOr} for OR composition
|
|
@@ -67,19 +85,16 @@ export type ComposedGuard = GuardPredicate<MachineContext, EventObject, unknown,
|
|
|
67
85
|
*/
|
|
68
86
|
export declare const composeGuards: <TContext = any, TEvent = any>(guards: GuardArray<TContext, TEvent>) => ComposedGuard;
|
|
69
87
|
/**
|
|
70
|
-
* Compose guards with OR logic
|
|
88
|
+
* Compose guards with OR logic.
|
|
71
89
|
*
|
|
72
90
|
* Combines multiple guard predicates using OR semantics—at least one guard must pass
|
|
73
|
-
* for the composition to succeed.
|
|
74
|
-
* type inference.
|
|
75
|
-
*
|
|
76
|
-
* @typeParam TContext - State machine context type
|
|
77
|
-
* @typeParam TEvent - Event type
|
|
91
|
+
* for the composition to succeed. Evaluation is short-circuiting, left to right.
|
|
78
92
|
*
|
|
79
|
-
* @param guards - Array of guard predicates or guard names
|
|
80
|
-
*
|
|
93
|
+
* @param guards - Array of guard predicates or guard names (string references
|
|
94
|
+
* resolved against `args.guards` from `setup({ guards })`)
|
|
95
|
+
* @returns Predicate returning `true` when any guard passes
|
|
81
96
|
*
|
|
82
|
-
* @throws {
|
|
97
|
+
* @throws {EmptyGuardArrayError} If guards array is empty
|
|
83
98
|
*
|
|
84
99
|
* @example
|
|
85
100
|
* OR composition with named guards
|
|
@@ -87,6 +102,8 @@ export declare const composeGuards: <TContext = any, TEvent = any>(guards: Guard
|
|
|
87
102
|
* import { setup } from "xstate";
|
|
88
103
|
* import { composeGuardsOr } from "@xmachines/play-xstate";
|
|
89
104
|
*
|
|
105
|
+
* const canDelete = composeGuardsOr(['isOwner', 'isAdmin']);
|
|
106
|
+
*
|
|
90
107
|
* const machine = setup({
|
|
91
108
|
* guards: {
|
|
92
109
|
* isOwner: ({ context }) => context.role === 'owner',
|
|
@@ -94,10 +111,9 @@ export declare const composeGuards: <TContext = any, TEvent = any>(guards: Guard
|
|
|
94
111
|
* }
|
|
95
112
|
* }).createMachine({
|
|
96
113
|
* on: {
|
|
97
|
-
* deleteResource: {
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* actions: 'delete'
|
|
114
|
+
* deleteResource: (args, enq) => {
|
|
115
|
+
* if (!canDelete(args)) return;
|
|
116
|
+
* enq(() => deleteIt());
|
|
101
117
|
* }
|
|
102
118
|
* }
|
|
103
119
|
* });
|
|
@@ -108,16 +124,17 @@ export declare const composeGuards: <TContext = any, TEvent = any>(guards: Guard
|
|
|
108
124
|
*/
|
|
109
125
|
export declare const composeGuardsOr: <TContext = any, TEvent = any>(guards: GuardArray<TContext, TEvent>) => ComposedGuard;
|
|
110
126
|
/**
|
|
111
|
-
* Negate a guard
|
|
127
|
+
* Negate a guard.
|
|
112
128
|
*
|
|
113
129
|
* Inverts a guard's result—if the guard passes, NOT fails; if guard fails, NOT passes.
|
|
114
|
-
* Uses XState's built-in `not()` helper for proper serialization.
|
|
115
130
|
*
|
|
116
|
-
* @typeParam TContext - State machine context type
|
|
131
|
+
* @typeParam TContext - State machine context type (defaults to `any` so
|
|
132
|
+
* inline predicates compile without annotations)
|
|
117
133
|
* @typeParam TEvent - Event type
|
|
118
134
|
*
|
|
119
|
-
* @param guard - Guard predicate or guard name
|
|
120
|
-
*
|
|
135
|
+
* @param guard - Guard predicate or guard name (resolved against `args.guards`
|
|
136
|
+
* from `setup({ guards })`) to negate
|
|
137
|
+
* @returns Predicate returning the inverted guard result
|
|
121
138
|
*
|
|
122
139
|
* @example
|
|
123
140
|
* NOT composition with named guard
|
|
@@ -125,16 +142,17 @@ export declare const composeGuardsOr: <TContext = any, TEvent = any>(guards: Gua
|
|
|
125
142
|
* import { setup } from "xstate";
|
|
126
143
|
* import { negateGuard } from "@xmachines/play-xstate";
|
|
127
144
|
*
|
|
145
|
+
* const isAuthenticated = negateGuard('isGuest');
|
|
146
|
+
*
|
|
128
147
|
* const machine = setup({
|
|
129
148
|
* guards: {
|
|
130
149
|
* isGuest: ({ context }) => !context.userId
|
|
131
150
|
* }
|
|
132
151
|
* }).createMachine({
|
|
133
152
|
* on: {
|
|
134
|
-
* accessDashboard: {
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
* target: 'dashboard'
|
|
153
|
+
* accessDashboard: (args) => {
|
|
154
|
+
* if (!isAuthenticated(args)) return;
|
|
155
|
+
* return { target: 'dashboard' };
|
|
138
156
|
* }
|
|
139
157
|
* }
|
|
140
158
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/guards/compose.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/guards/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;AAqCvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH,eAAO,MAAM,aAAa,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACzD,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,aAgBF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,eAAO,MAAM,eAAe,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAC3D,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,aAgBF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,eAAO,MAAM,WAAW,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACvD,OAAO,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,KACrC,aAGF,CAAC"}
|