@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.
Files changed (40) hide show
  1. package/README.md +79 -23
  2. package/dist/base-route-map.js +240 -270
  3. package/dist/base-route-map.js.map +1 -1
  4. package/dist/build-tree.js +84 -96
  5. package/dist/build-tree.js.map +1 -1
  6. package/dist/create-route-map-from-tree.js +50 -47
  7. package/dist/create-route-map-from-tree.js.map +1 -1
  8. package/dist/errors.js +124 -133
  9. package/dist/errors.js.map +1 -1
  10. package/dist/find-route.js +88 -105
  11. package/dist/find-route.js.map +1 -1
  12. package/dist/index.js +10 -28
  13. package/dist/provider-lifecycle.js +109 -143
  14. package/dist/provider-lifecycle.js.map +1 -1
  15. package/dist/router-bridge-base.d.ts +5 -5
  16. package/dist/router-bridge-base.d.ts.map +1 -1
  17. package/dist/router-bridge-base.js +1026 -1601
  18. package/dist/router-bridge-base.js.map +1 -1
  19. package/dist/router-sync.js +107 -139
  20. package/dist/router-sync.js.map +1 -1
  21. package/dist/types.d.ts +17 -17
  22. package/dist/types.d.ts.map +1 -1
  23. package/dist/validate-routes.js +58 -66
  24. package/dist/validate-routes.js.map +1 -1
  25. package/dist/xstate/create-route-map.js +36 -35
  26. package/dist/xstate/create-route-map.js.map +1 -1
  27. package/dist/xstate/extract-routes.js +66 -83
  28. package/dist/xstate/extract-routes.js.map +1 -1
  29. package/dist/xstate/index.js +5 -33
  30. package/dist/xstate/machine-to-graph.js +98 -109
  31. package/dist/xstate/machine-to-graph.js.map +1 -1
  32. package/dist/xstate/query.js +190 -212
  33. package/dist/xstate/query.js.map +1 -1
  34. package/package.json +16 -16
  35. package/dist/index.js.map +0 -1
  36. package/dist/types.js +0 -2
  37. package/dist/types.js.map +0 -1
  38. package/dist/xstate/index.js.map +0 -1
  39. package/dist/xstate/machine-types.js +0 -2
  40. 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
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-6.0.0-blue)](https://www.npmjs.com/package/@xmachines/play-router)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-7.0.0-blue)](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
- // A render with a new `region` moves the mount, and it rebuilds the bridge never. A
279
- // render with a new `machineId` gives a different `actor` prop, and THAT rebuilds the
280
- // bridge, which is correct: one actor takes one bridge.
281
- <PlayRouterProvider
282
- actor={actor}
283
- router={router}
284
- routeMap={routeMap}
285
- basePath="/:machineId/play"
286
- basePathParams={{ machineId }}
287
- renderer={(a) => <PlayRenderer actor={a} registry={registry} />}
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 own domain. See the note below. |
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, and this is a change of behaviour.** An earlier release
598
- read `path` alone, so a state could put any name of its own beside it. A state that
599
- carries its own `handler` value now throws an `InvalidRouteHandlerError` at the format
600
- time, and the machine builds never; a state that carries its own `data` value now writes
601
- that value to `context.data`, where the `/context` projection of every view reads it.
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",