@xmachines/play-router 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -23
- package/dist/base-route-map.js +240 -270
- package/dist/base-route-map.js.map +1 -1
- package/dist/build-tree.js +84 -96
- package/dist/build-tree.js.map +1 -1
- package/dist/create-route-map-from-tree.js +50 -47
- package/dist/create-route-map-from-tree.js.map +1 -1
- package/dist/errors.js +124 -133
- package/dist/errors.js.map +1 -1
- package/dist/find-route.js +88 -105
- package/dist/find-route.js.map +1 -1
- package/dist/index.js +10 -28
- package/dist/provider-lifecycle.js +109 -143
- package/dist/provider-lifecycle.js.map +1 -1
- package/dist/router-bridge-base.d.ts +5 -5
- package/dist/router-bridge-base.d.ts.map +1 -1
- package/dist/router-bridge-base.js +1026 -1601
- package/dist/router-bridge-base.js.map +1 -1
- package/dist/router-sync.js +107 -139
- package/dist/router-sync.js.map +1 -1
- package/dist/types.d.ts +17 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/validate-routes.js +58 -66
- package/dist/validate-routes.js.map +1 -1
- package/dist/xstate/create-route-map.js +36 -35
- package/dist/xstate/create-route-map.js.map +1 -1
- package/dist/xstate/extract-routes.js +66 -83
- package/dist/xstate/extract-routes.js.map +1 -1
- package/dist/xstate/index.js +5 -33
- package/dist/xstate/machine-to-graph.js +98 -109
- package/dist/xstate/machine-to-graph.js.map +1 -1
- package/dist/xstate/query.js +190 -212
- package/dist/xstate/query.js.map +1 -1
- package/package.json +16 -16
- package/dist/index.js.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/xstate/index.js.map +0 -1
- package/dist/xstate/machine-types.js +0 -2
- package/dist/xstate/machine-types.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Route tree extraction from XState v5 state machines. Part of [@xmachines/play](../play/README.md) Universal Player Architecture.
|
|
4
4
|
|
|
5
|
-
[](https://opensource.org/licenses/MIT) [](https://opensource.org/licenses/MIT) [](https://www.npmjs.com/package/@xmachines/play-router)
|
|
6
6
|
|
|
7
7
|
This package extracts the routes from a machine graph and looks them up in both directions. The Actor therefore keeps the authority over the navigation.
|
|
8
8
|
|
|
@@ -97,8 +97,10 @@ routeMap.getPathByStateId("profile"); // "/profile/:userId"
|
|
|
97
97
|
```typescript
|
|
98
98
|
import { definePlayer } from "@xmachines/play-xstate";
|
|
99
99
|
import type { PlayRouteEvent } from "@xmachines/play-router";
|
|
100
|
+
import type { AnyStateMachine } from "xstate";
|
|
101
|
+
|
|
102
|
+
declare const machine: AnyStateMachine; // your routable machine (states carry meta.route)
|
|
100
103
|
|
|
101
|
-
// machine: your routable machine (states carry meta.route)
|
|
102
104
|
const actor = definePlayer({ machine })();
|
|
103
105
|
actor.start();
|
|
104
106
|
|
|
@@ -136,6 +138,18 @@ a `load` function of SvelteKit — and the `meta.route` tree of the machine give
|
|
|
136
138
|
everything below `/:machineId/play`.
|
|
137
139
|
|
|
138
140
|
```typescript
|
|
141
|
+
import {
|
|
142
|
+
connectRouter,
|
|
143
|
+
type RoutableActor,
|
|
144
|
+
type RouteLookupContract,
|
|
145
|
+
type VanillaRouter,
|
|
146
|
+
} from "@xmachines/play-dom-router";
|
|
147
|
+
|
|
148
|
+
declare const actor: RoutableActor;
|
|
149
|
+
declare const router: VanillaRouter;
|
|
150
|
+
declare const routeMap: RouteLookupContract;
|
|
151
|
+
declare const machineId: string;
|
|
152
|
+
|
|
139
153
|
// The route of the host is /$machineId/play/$ and its loader resolved machineId.
|
|
140
154
|
const disconnect = connectRouter({
|
|
141
155
|
actor,
|
|
@@ -199,6 +213,10 @@ the machine cannot shadow it.
|
|
|
199
213
|
Read the resolved mount from the bridge instead, where it cannot go stale:
|
|
200
214
|
|
|
201
215
|
```typescript
|
|
216
|
+
import type { MountableRouterBridge } from "@xmachines/play-router";
|
|
217
|
+
|
|
218
|
+
declare const bridge: MountableRouterBridge;
|
|
219
|
+
|
|
202
220
|
bridge.basePath; // "/abc123/play"
|
|
203
221
|
bridge.basePathParams; // { machineId: "abc123" }
|
|
204
222
|
```
|
|
@@ -242,6 +260,11 @@ a rebuild.
|
|
|
242
260
|
`setBasePath()` moves WHERE an actor is mounted, and never WHICH actor is mounted:
|
|
243
261
|
|
|
244
262
|
```typescript
|
|
263
|
+
import type { MountableRouterBridge } from "@xmachines/play-router";
|
|
264
|
+
|
|
265
|
+
declare const bridge: MountableRouterBridge;
|
|
266
|
+
declare const machineId: string;
|
|
267
|
+
|
|
245
268
|
// The host moved this actor from one region of its URL space to another.
|
|
246
269
|
bridge.setBasePath("/:region/:machineId/play", { region: "us", machineId });
|
|
247
270
|
```
|
|
@@ -275,17 +298,40 @@ props**, wired to `setBasePath()`. They need no stable reference, unlike `actor`
|
|
|
275
298
|
`router`, and `routeMap`, and they rebuild the bridge never:
|
|
276
299
|
|
|
277
300
|
```tsx
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
301
|
+
import { RouterProvider, type createBrowserRouter } from "react-router";
|
|
302
|
+
import {
|
|
303
|
+
PlayRouterProvider,
|
|
304
|
+
type RoutableActor,
|
|
305
|
+
type RouteMap,
|
|
306
|
+
} from "@xmachines/play-react-router";
|
|
307
|
+
|
|
308
|
+
declare const router: ReturnType<typeof createBrowserRouter>;
|
|
309
|
+
|
|
310
|
+
interface MountProps {
|
|
311
|
+
region: string;
|
|
312
|
+
machineId: string;
|
|
313
|
+
/** The actor of `machineId`. Keep one actor for each machine id. */
|
|
314
|
+
actor: RoutableActor;
|
|
315
|
+
/** The route map of the machine of `machineId`. Keep one for each machine. */
|
|
316
|
+
routeMap: RouteMap;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function Mount({ region, machineId, actor, routeMap }: MountProps) {
|
|
320
|
+
// A render with a new `region` moves the mount, and it rebuilds the bridge never. A
|
|
321
|
+
// render with a new `machineId` comes with the actor of that machine, a different
|
|
322
|
+
// `actor` prop, and THAT rebuilds the bridge, which is correct: one actor takes one
|
|
323
|
+
// bridge.
|
|
324
|
+
return (
|
|
325
|
+
<PlayRouterProvider
|
|
326
|
+
actor={actor}
|
|
327
|
+
router={router}
|
|
328
|
+
routeMap={routeMap}
|
|
329
|
+
basePath="/:region/:machineId/play"
|
|
330
|
+
basePathParams={{ region, machineId }}
|
|
331
|
+
renderer={(_, currentRouter) => <RouterProvider router={currentRouter} />}
|
|
332
|
+
/>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
289
335
|
```
|
|
290
336
|
|
|
291
337
|
To register the routes of the machine in a host router that declares real route
|
|
@@ -293,6 +339,10 @@ objects, ask for the list — and drop it again when the machine unloads:
|
|
|
293
339
|
|
|
294
340
|
```typescript
|
|
295
341
|
import { extractMachineRoutes, getRouteMappings } from "@xmachines/play-router/xstate";
|
|
342
|
+
import type { AnyStateMachine } from "xstate";
|
|
343
|
+
|
|
344
|
+
declare const machine: AnyStateMachine; // your routable machine
|
|
345
|
+
declare const machineId: string; // the loader of the host resolved it
|
|
296
346
|
|
|
297
347
|
const tree = extractMachineRoutes(machine);
|
|
298
348
|
|
|
@@ -335,6 +385,7 @@ Extend `RouterBridgeBase`, then implement the three abstract methods for your fr
|
|
|
335
385
|
import { RouterBridgeBase } from "@xmachines/play-router";
|
|
336
386
|
import { createRouteMap } from "@xmachines/play-router/xstate";
|
|
337
387
|
import type { RoutableActor } from "@xmachines/play-router";
|
|
388
|
+
import type { AnyStateMachine } from "xstate";
|
|
338
389
|
|
|
339
390
|
// Shape of your framework's router — adjust to its real API
|
|
340
391
|
type MyRouter = {
|
|
@@ -380,6 +431,10 @@ export class MyRouterBridge extends RouterBridgeBase {
|
|
|
380
431
|
|
|
381
432
|
// Usage — myRouter: your framework's router instance;
|
|
382
433
|
// machine/actor: your routable machine and its started actor
|
|
434
|
+
declare const myRouter: MyRouter;
|
|
435
|
+
declare const machine: AnyStateMachine;
|
|
436
|
+
declare const actor: RoutableActor;
|
|
437
|
+
|
|
383
438
|
const routeMap = createRouteMap(machine);
|
|
384
439
|
const bridge = new MyRouterBridge(myRouter, actor, routeMap);
|
|
385
440
|
bridge.connect();
|
|
@@ -539,8 +594,10 @@ props that a framework decides, which is why it is a type parameter.
|
|
|
539
594
|
|
|
540
595
|
```typescript
|
|
541
596
|
import { RouterSyncError, DuplicateBridgeError } from "@xmachines/play-router/errors";
|
|
597
|
+
import type { RouterBridge } from "@xmachines/play-router";
|
|
598
|
+
|
|
599
|
+
declare const bridge: RouterBridge; // the bridge of the adapter example above
|
|
542
600
|
|
|
543
|
-
// bridge from the adapter example above
|
|
544
601
|
try {
|
|
545
602
|
bridge.connect();
|
|
546
603
|
} catch (err) {
|
|
@@ -558,7 +615,7 @@ try {
|
|
|
558
615
|
|
|
559
616
|
Declare the route of an XState state node in its `meta.route` field:
|
|
560
617
|
|
|
561
|
-
```typescript
|
|
618
|
+
```typescript fragment
|
|
562
619
|
states: {
|
|
563
620
|
home: {
|
|
564
621
|
id: "home",
|
|
@@ -588,24 +645,23 @@ breadcrumb. It also carries three fields that the routing layer reads:
|
|
|
588
645
|
| --------- | -------- | ------------------------------------------------------------------------------- |
|
|
589
646
|
| `path` | required | The template of the route path |
|
|
590
647
|
| `handler` | `"root"` | Where the generated `play.route` transition sits: `"root"`, `"local"`, `"both"` |
|
|
591
|
-
| `reenter` | `false` | Whether the transition re-enters its
|
|
648
|
+
| `reenter` | `false` | Whether the transition re-enters its domain |
|
|
592
649
|
| `data` | none | The extra data of the route: a literal value, or a function of the event |
|
|
593
650
|
|
|
594
651
|
[`@xmachines/play-xstate`](../play-xstate/README.md) reads `handler`, `reenter`, and `data` when it generates the
|
|
595
652
|
transitions. See the README of that package for what each value does.
|
|
596
653
|
|
|
597
|
-
**The four names are RESERVED
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
Give such a field another name.
|
|
654
|
+
**The four names are RESERVED.** The routing layer reads each of them, so a field of
|
|
655
|
+
your own under one of these names changes the machine. An unknown `handler` value throws
|
|
656
|
+
an `InvalidRouteHandlerError` at the format time, and the machine builds never. A `data`
|
|
657
|
+
value goes to `context.data`, where the `/context` projection of every view reads it.
|
|
658
|
+
Give a field of your own another name.
|
|
603
659
|
|
|
604
660
|
### Relative vs absolute paths
|
|
605
661
|
|
|
606
662
|
A child route that starts with `/` is absolute, and it does not inherit the path of its parent. A child route without the first `/` is relative to its nearest routable ancestor:
|
|
607
663
|
|
|
608
|
-
```typescript
|
|
664
|
+
```typescript fragment
|
|
609
665
|
states: {
|
|
610
666
|
dashboard: {
|
|
611
667
|
id: "dashboard",
|