@xmachines/play-router 3.0.0 → 5.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 (85) hide show
  1. package/README.md +111 -116
  2. package/dist/base-route-map.d.ts +24 -13
  3. package/dist/base-route-map.d.ts.map +1 -1
  4. package/dist/base-route-map.js +116 -27
  5. package/dist/base-route-map.js.map +1 -1
  6. package/dist/build-tree.d.ts +16 -1
  7. package/dist/build-tree.d.ts.map +1 -1
  8. package/dist/build-tree.js +22 -4
  9. package/dist/build-tree.js.map +1 -1
  10. package/dist/create-route-map-from-tree.d.ts +13 -7
  11. package/dist/create-route-map-from-tree.d.ts.map +1 -1
  12. package/dist/create-route-map-from-tree.js +14 -6
  13. package/dist/create-route-map-from-tree.js.map +1 -1
  14. package/dist/errors.d.ts +2 -134
  15. package/dist/errors.d.ts.map +1 -1
  16. package/dist/errors.js +11 -151
  17. package/dist/errors.js.map +1 -1
  18. package/dist/find-route.d.ts +13 -1
  19. package/dist/find-route.d.ts.map +1 -1
  20. package/dist/find-route.js +33 -26
  21. package/dist/find-route.js.map +1 -1
  22. package/dist/index.d.ts +8 -18
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +6 -12
  25. package/dist/index.js.map +1 -1
  26. package/dist/provider-lifecycle.d.ts +18 -6
  27. package/dist/provider-lifecycle.d.ts.map +1 -1
  28. package/dist/provider-lifecycle.js +10 -5
  29. package/dist/provider-lifecycle.js.map +1 -1
  30. package/dist/router-bridge-base.d.ts +73 -38
  31. package/dist/router-bridge-base.d.ts.map +1 -1
  32. package/dist/router-bridge-base.js +304 -124
  33. package/dist/router-bridge-base.js.map +1 -1
  34. package/dist/router-sync.d.ts +3 -27
  35. package/dist/router-sync.d.ts.map +1 -1
  36. package/dist/router-sync.js +27 -45
  37. package/dist/router-sync.js.map +1 -1
  38. package/dist/types.d.ts +206 -102
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/xstate/create-route-map.d.ts +30 -0
  41. package/dist/xstate/create-route-map.d.ts.map +1 -0
  42. package/dist/{create-route-map.js → xstate/create-route-map.js} +11 -6
  43. package/dist/xstate/create-route-map.js.map +1 -0
  44. package/dist/{extract-routes.d.ts → xstate/extract-routes.d.ts} +4 -2
  45. package/dist/xstate/extract-routes.d.ts.map +1 -0
  46. package/dist/{extract-routes.js → xstate/extract-routes.js} +11 -6
  47. package/dist/xstate/extract-routes.js.map +1 -0
  48. package/dist/xstate/index.d.ts +35 -0
  49. package/dist/xstate/index.d.ts.map +1 -0
  50. package/dist/xstate/index.js +33 -0
  51. package/dist/xstate/index.js.map +1 -0
  52. package/dist/{machine-to-graph.d.ts → xstate/machine-to-graph.d.ts} +1 -1
  53. package/dist/xstate/machine-to-graph.d.ts.map +1 -0
  54. package/dist/{machine-to-graph.js → xstate/machine-to-graph.js} +2 -2
  55. package/dist/xstate/machine-to-graph.js.map +1 -0
  56. package/dist/xstate/machine-types.d.ts +42 -0
  57. package/dist/xstate/machine-types.d.ts.map +1 -0
  58. package/dist/xstate/machine-types.js +2 -0
  59. package/dist/xstate/machine-types.js.map +1 -0
  60. package/dist/{query.d.ts → xstate/query.d.ts} +6 -4
  61. package/dist/xstate/query.d.ts.map +1 -0
  62. package/dist/{query.js → xstate/query.js} +3 -2
  63. package/dist/xstate/query.js.map +1 -0
  64. package/package.json +30 -21
  65. package/dist/base-path.d.ts +0 -209
  66. package/dist/base-path.d.ts.map +0 -1
  67. package/dist/base-path.js +0 -418
  68. package/dist/base-path.js.map +0 -1
  69. package/dist/create-route-map.d.ts +0 -44
  70. package/dist/create-route-map.d.ts.map +0 -1
  71. package/dist/create-route-map.js.map +0 -1
  72. package/dist/extract-routes.d.ts.map +0 -1
  73. package/dist/extract-routes.js.map +0 -1
  74. package/dist/framework-params.d.ts +0 -144
  75. package/dist/framework-params.d.ts.map +0 -1
  76. package/dist/framework-params.js +0 -291
  77. package/dist/framework-params.js.map +0 -1
  78. package/dist/machine-to-graph.d.ts.map +0 -1
  79. package/dist/machine-to-graph.js.map +0 -1
  80. package/dist/query.d.ts.map +0 -1
  81. package/dist/query.js.map +0 -1
  82. package/dist/url-pattern-utils.d.ts +0 -93
  83. package/dist/url-pattern-utils.d.ts.map +0 -1
  84. package/dist/url-pattern-utils.js +0 -233
  85. package/dist/url-pattern-utils.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,48 +1,146 @@
1
- import type { Graph } from "@statelyai/graph";
2
- import type { BasePathOptions } from "./base-path.js";
3
- import type { Signal } from "@xmachines/play-signals";
4
- import type { PlaySpec } from "@xmachines/play-actor";
1
+ import type { BasePathOptions, CompileOptions, PatternCache } from "@xmachines/play-url";
2
+ import type { ReadonlyAtom } from "@xmachines/play-atom";
5
3
  /**
6
- * The data on each node of the graph that represents the machine.
7
- * It holds the state metadata that the route extraction and the queries need.
4
+ * The type definitions of the routing protocol of @xmachines/play-router
5
+ *
6
+ * PlayRouteEvent, RouterBridge, RouteMetadata, and RouteObject are here. The routing
7
+ * therefore stays separate from the base event protocol of @xmachines/play.
8
8
  */
9
- export interface MachineNodeData {
10
- /** The XState state ID, for example "test.dashboard.overview" */
11
- stateId: string;
12
- /** The state type of XState */
13
- type: "atomic" | "compound" | "parallel" | "final" | "history";
14
- /** The original meta object of the state */
15
- meta?: Record<string, unknown>;
16
- /** The route path of meta.route, in its string form */
17
- route?: string;
18
- }
19
9
  /**
20
- * The data on each edge of the graph that represents the machine.
21
- * It holds the event of the transition and the information of its guard.
10
+ * The resolved extra data of a route. It reaches the consumer on the `data` field of a
11
+ * `play.route` event.
22
12
  */
23
- export interface MachineEdgeData {
24
- /** The event type that starts this transition */
25
- eventType: string;
26
- /**
27
- * The guard as a string, when a guard is present
28
- *
29
- * @deprecated Will be removed in the next major.
30
- */
31
- guardType?: string;
32
- }
13
+ export type RouteData = Record<string, unknown>;
33
14
  /**
34
- * The type definitions of the routing protocol of @xmachines/play-router
15
+ * The function form of {@link RouteObject.data}.
35
16
  *
36
- * PlayRouteEvent, RouterBridge, RouteMetadata, and RouteObject are here. The routing
37
- * therefore stays separate from the base event protocol of @xmachines/play.
17
+ * The signature mirrors `WithDynamicParams` of XState: the resolver reads the context
18
+ * of the machine and the event that asks for the route, and it returns the data.
19
+ *
20
+ * The resolver reads every field of the event, and `event.data` among them: that field
21
+ * carries what the SENDER of the event supplied, and the resolver decides how it
22
+ * combines with what the state declares. The `data` that the resolver RETURNS goes to
23
+ * `context.data`, and it does not go back onto the event.
38
24
  */
25
+ export type RouteDataResolver = (args: {
26
+ context: unknown;
27
+ event: PlayRouteEvent;
28
+ }) => RouteData;
39
29
  /**
40
30
  * A route object, with more metadata.
41
31
  */
42
32
  export interface RouteObject {
43
- /** The template of the route path, for example '/user/:id' */
33
+ /** The template of the route path, for example `"/user/:id"`. */
44
34
  path: string;
45
- /** The additional metadata of the route: a title, a breadcrumb, and so on */
35
+ /**
36
+ * The `reenter` flag of the generated `play.route` transition.
37
+ *
38
+ * The default is `false`, which is also the default of XState.
39
+ *
40
+ * The flag spares the DOMAIN of the transition, and not every ancestor that stays
41
+ * active. Under the default placement `handler: "root"` the domain is the root of
42
+ * the machine, so `false` spares the root alone: each ancestor BETWEEN the root and
43
+ * the target still runs its `exit` and its `entry` actions, because XState re-enters
44
+ * every descendant of the domain that lies on the path to the target. A move between
45
+ * two siblings therefore still runs the `entry` action of their shared parent.
46
+ *
47
+ * {@link RouteObject.handler} is the field that spares those intermediate ancestors:
48
+ * `"local"` and `"both"` move the domain down to the parent of the state. Use the
49
+ * two fields together where an `entry` action must run one time for each state that
50
+ * the actor really enters.
51
+ *
52
+ * Set the field to `true` where the domain must run its `entry` actions again on
53
+ * every route to a descendant.
54
+ *
55
+ * The flag does not decide the destination. The value of the machine after a route
56
+ * is identical under both settings. A route to a state that has children still
57
+ * enters the `initial` child of that state, because the generated transition targets
58
+ * the state by its id, and XState enters the initial child of an id target under
59
+ * both settings.
60
+ *
61
+ * @see [Play RFC](../../docs/rfc/play.md)
62
+ */
63
+ reenter?: boolean;
64
+ /**
65
+ * Where the generated `play.route` transition sits.
66
+ *
67
+ * `"root"` is the default, and it is what XState does: `formatRouteTransitions`
68
+ * installs every route transition on the ROOT of the machine, and each one targets
69
+ * its state by the ID. A route from any state therefore reaches this state. The cost
70
+ * is that the root is the domain of the transition, so XState re-enters each
71
+ * ancestor on the path to the target, and those ancestors run their `entry` actions
72
+ * again although they stay active.
73
+ *
74
+ * `"local"` installs the transition on the PARENT of this state instead, and it
75
+ * targets this state relatively. XState offers the transitions of the deepest active
76
+ * state node first, so the parent answers the event itself and runs its `exit` and
77
+ * its `entry` actions NOT again.
78
+ *
79
+ * `"both"` installs one transition in each place. The local one answers while the
80
+ * parent is active, and the root one answers a route that arrives from outside the
81
+ * parent. Use `"both"` where an ancestor holds an `entry` action that must run one
82
+ * time for each real entry, such as an analytics event or an audit record.
83
+ *
84
+ * CAUTION: `"local"` makes this state reachable by a route ONLY while its parent is
85
+ * active. A `play.route` event that arrives from anywhere else matches no transition
86
+ * and the actor does not move. A browser URL for this state therefore leaves the URL
87
+ * and the actor divergent. Choose `"local"` to SCOPE a route on purpose, for example
88
+ * a step that a person reaches only inside its wizard. Choose `"both"` where the
89
+ * state must stay reachable from everywhere.
90
+ *
91
+ * The field has no effect on a state whose parent IS the root: the root transition
92
+ * of such a state is already local to its parent, so all three values agree.
93
+ */
94
+ handler?: "root" | "local" | "both";
95
+ /**
96
+ * The extra data that the state threads into its `play.route` event.
97
+ *
98
+ * The shape follows `WithDynamicParams` of XState, which is how XState itself
99
+ * parameterizes an action and a guard: the field holds a literal value, OR a
100
+ * function of `{ context, event }` that returns one.
101
+ *
102
+ * ```ts
103
+ * // The literal form. It survives a serialization of the machine.
104
+ * meta: { route: { path: "/doc/:docId", data: { titleKey: "doc.view" } } }
105
+ *
106
+ * // The function form, for a value that depends on the route.
107
+ * meta: {
108
+ * route: {
109
+ * path: "/doc/:docId",
110
+ * data: ({ event }) => ({ title: `Document ${event.params?.docId}` }),
111
+ * },
112
+ * }
113
+ * ```
114
+ *
115
+ * The generated transition resolves the value and assigns it to the `data` field of
116
+ * the context, beside `params` and `query`. The data of a state does NOT merge with
117
+ * the data of its ancestors: each state declares the whole value that its own route
118
+ * carries.
119
+ *
120
+ * This field and {@link PlayRouteEvent.data} are two different things, and they meet
121
+ * in the resolver. This field is what the STATE declares, in its machine.
122
+ * `PlayRouteEvent.data` is what the SENDER of the event supplies, such as a router
123
+ * bridge or the code of an application. A resolver reads `event.data` and returns
124
+ * whatever mix of the two the state needs.
125
+ *
126
+ * CAUTION: the function form holds a function inside `meta`, and a function does not
127
+ * survive `JSON.stringify`. A machine that Stately Studio reads, or that a process
128
+ * sends over a wire, must use the literal form.
129
+ */
130
+ data?: RouteData | RouteDataResolver;
131
+ /**
132
+ * The additional metadata of the route: a title, a breadcrumb, and so on.
133
+ *
134
+ * CAUTION: `path`, `handler`, `reenter` and `data` are RESERVED. The routing layer
135
+ * reads those four names, and a release before this one read `path` alone. A state
136
+ * that carries its own `handler` value now throws an `InvalidRouteHandlerError` from
137
+ * `formatPlayRouteTransitions`, so the machine builds never; a state that carries its
138
+ * own `data` value now writes that value to `context.data`, where the `/context`
139
+ * projection of every view reads it. A `reenter` value is read as the FLAG of the
140
+ * generated transition, and the literal `true` alone turns the reentry on: the
141
+ * default is `false`, and a release before this one generated every transition with
142
+ * `reenter: true`. Give such a field another name.
143
+ */
46
144
  [key: string]: unknown;
47
145
  }
48
146
  /**
@@ -112,7 +210,7 @@ export interface RouteNode {
112
210
  * - byStateId: it maps each state ID to its route node, for the target of a play.route event
113
211
  * - byPath: it maps each URL path to its route node, for the browser navigation
114
212
  */
115
- export interface RouteTree {
213
+ export interface RouteTree<TGraph = unknown> {
116
214
  /** The root node of the routes */
117
215
  root: RouteNode;
118
216
  /**
@@ -127,17 +225,20 @@ export interface RouteTree {
127
225
  byPath: Map<string, RouteNode>;
128
226
  /**
129
227
  * The graph of the state machine, for an advanced query.
130
- * extractMachineRoutes() fills it. Use it for a query of the hierarchy, for a test of
131
- * the reachability, and for a navigation that knows the transitions, through the
132
- * algorithms of @statelyai/graph.
228
+ *
229
+ * `TGraph` carries its type, and this package names none: a route tree is a map from a
230
+ * path to a state, and the graph of a MACHINE belongs to the package that reads a
231
+ * machine. `extractMachineRoutes` of `@xmachines/play-router/xstate` answers
232
+ * `RouteTree<MachineGraph>`, so a consumer of that function loses no type.
133
233
  *
134
234
  * @example
135
235
  * ```typescript
136
236
  * import { getSuccessors, hasPath } from "@statelyai/graph";
237
+ * // `tree` comes from `extractMachineRoutes` of `@xmachines/play-router/xstate`
137
238
  * const successors = getSuccessors(tree.graph!, "myMachine.home");
138
239
  * ```
139
240
  */
140
- graph?: Graph<MachineNodeData, MachineEdgeData>;
241
+ graph?: TGraph;
141
242
  }
142
243
  /**
143
244
  * The routing event, with its parameters and its query
@@ -231,23 +332,43 @@ export interface PlayRouteEvent {
231
332
  readonly to: string;
232
333
  readonly params?: Record<string, string>;
233
334
  readonly query?: Record<string, string>;
335
+ /**
336
+ * The extra data that the SENDER of this event supplies: a router bridge, or the
337
+ * code of an application. It is not what the target state declares — that is
338
+ * {@link RouteObject.data}, and a resolver there reads this field.
339
+ */
340
+ readonly data?: RouteData;
234
341
  readonly match?: unknown;
235
- [key: string]: unknown;
342
+ }
343
+ /**
344
+ * An optional capability: the routing support
345
+ */
346
+ export interface Routable {
347
+ readonly currentRoute: ReadonlyAtom<string | null>;
348
+ readonly initialRoute: string | null;
236
349
  }
237
350
  /**
238
351
  * The minimal actor interface that `RouterBridgeBase` and every framework router
239
352
  * adapter require.
240
353
  *
241
- * This interface, and not `AbstractActor<AnyActorLogic> & Routable`, gives
242
- * `RouterBridgeBase.actor.send` the type that accepts a `PlayRouteEvent` directly.
243
- * It therefore removes the unsafe cast `(actor.send as (e: PlayRouteEvent) => void)`,
244
- * which the weaker `EventObject` constraint of the actor type needed before.
354
+ * It names `send` itself, and it therefore gives `RouterBridgeBase.actor.send` a type that
355
+ * accepts a `PlayRouteEvent` directly. That removes the unsafe cast
356
+ * `(actor.send as (e: PlayRouteEvent) => void)`.
357
+ *
358
+ * It is {@link Routable} with `send`. The two members of the capability are declared once,
359
+ * in `Routable`, and this interface extends it. A copy of them here drifts the day that
360
+ * one of the two files changes.
245
361
  *
246
- * Every `AbstractActor` subclass satisfies this interface structurally, for two
247
- * reasons:
248
- * - `AbstractActor` implements `send(event: TEvent): void`, and `TEvent` accepts each
249
- * `EventObject`. Therefore it always accepts a `PlayRouteEvent`, which is a subtype.
250
- * - `Routable` gives `currentRoute` and `initialRoute`.
362
+ * **It names the view NOWHERE. Routing implies no rendering.** No file of this package,
363
+ * and no file of any of the eight router adapters, ever reads `currentView`. A provider
364
+ * whose renderer callback reads the view binds its own `TActor`, and a constraint keeps
365
+ * the concrete type of the actor whole, so that callback still reads the exact spec of
366
+ * that actor.
367
+ *
368
+ * Every `PlayActor` of `@xmachines/play-actor` that also implements `Routable`, and whose
369
+ * event union holds `PlayRouteEvent`, satisfies this interface structurally. A machine
370
+ * that declares no route event does NOT satisfy it, and that refusal is correct: a bridge
371
+ * cannot navigate an actor that receives no route event.
251
372
  *
252
373
  * @example
253
374
  * ```typescript
@@ -260,84 +381,43 @@ export interface PlayRouteEvent {
260
381
  * }
261
382
  * ```
262
383
  */
263
- export interface RoutableActor {
264
- /** The TC39 Signal of the current URL path of the actor, or of its state ID. */
265
- readonly currentRoute: Signal.Computed<string | null>;
266
- /**
267
- * The route of the initial state of the machine. The constructor fixes it.
268
- * A router bridge compares it with the browser URL. It therefore separates a deep
269
- * link, where the router wins, from a restore of a session, where the actor wins.
270
- */
271
- readonly initialRoute: string | null;
384
+ export interface RoutableActor extends Routable {
272
385
  /** Sends a route navigation event to the actor. */
273
386
  send(event: PlayRouteEvent): void;
274
387
  }
275
- /**
276
- * The complete actor shape of the `PlayRouterProvider` component of each framework
277
- * adapter: `play-solid-router`, `play-vue-router`, `play-react-router`, and each
278
- * adapter on the shared framework router bridge bases.
279
- *
280
- * The shape extends `RoutableActor` with `currentView`, because the provider renders
281
- * the current view spec and also keeps the routes in step. It therefore needs both
282
- * capabilities.
283
- *
284
- * - Use `RoutableActor` when you need the routing alone, for example in a
285
- * `RouterBridgeBase` subclass, or in `connectRouter`.
286
- * - Use `PlayActor` when the component also renders the current view spec, for
287
- * example for the renderer callback parameter of `PlayRouterProvider`, and in
288
- * `PlayRenderer`.
289
- *
290
- * Every `AbstractActor` subclass that implements both `Routable` and `Viewable`
291
- * satisfies this interface structurally.
292
- *
293
- * @example
294
- * ```typescript
295
- * import type { PlayActor } from "@xmachines/play-router";
296
- *
297
- * function MyRouterProvider({ actor }: { actor: PlayActor }) {
298
- * // it reads actor.currentRoute for the routing, and actor.currentView for the render
299
- * }
300
- * ```
301
- */
302
- export interface PlayActor extends RoutableActor {
303
- /** The TC39 Signal of the current view spec of the actor, or `null` when no view is active. */
304
- readonly currentView: Signal.State<PlaySpec | null>;
305
- }
306
388
  /**
307
389
  * The RouterBridge interface of a runtime infrastructure adapter
308
390
  *
309
391
  * The interface defines the connection of the lifecycle between the infrastructure,
310
392
  * for example a framework router, and the Actor. The infrastructure builds a "bridge"
311
- * to the Actor: it observes the signals of the Actor, and it manages its own
393
+ * to the Actor: it observes the atoms of the Actor, and it manages its own
312
394
  * lifecycle accordingly.
313
395
  *
314
396
  * **Architectural context:** the interface implements **Passive Infrastructure
315
397
  * (INV-04)**, because it gives an observation in one direction. The infrastructure
316
- * connects to observe the signals of the Actor (currentRoute, currentView, and
398
+ * connects to observe the atoms of the Actor (currentRoute, currentView, and
317
399
  * state), and it reflects each change. It makes no decision about the state.
318
400
  *
319
401
  * @example
320
402
  * The implementation of a framework router bridge
321
403
  * ```typescript
322
404
  * import type { RouterBridge } from "@xmachines/play-router";
323
- * import { Signal } from "@xmachines/play-signals";
405
+ * import { watchAtom, type Cleanup } from "@xmachines/play-atom";
324
406
  *
325
407
  * class MyRouterBridge implements RouterBridge {
326
- * private watcher: Signal.Watcher | null = null;
408
+ * private stop: Cleanup | null = null;
327
409
  *
328
410
  * async connect(): Promise<void> {
329
- * // Start the observation of the actor.currentRoute signal
330
- * this.watcher = new Signal.subtle.Watcher(() => {
331
- * const route = actor.currentRoute.get();
411
+ * // Start the observation of the actor.currentRoute atom
412
+ * this.stop = watchAtom(actor.currentRoute, (route) => {
332
413
  * if (route) router.navigate(route);
333
414
  * });
334
- * this.watcher.watch(actor.currentRoute);
335
415
  * }
336
416
  *
337
417
  * async disconnect(): Promise<void> {
338
- * // Stop the observation, and clean the watchers up
339
- * this.watcher?.unwatch(actor.currentRoute);
340
- * this.watcher = null;
418
+ * // Stop the observation, and release the subscription
419
+ * this.stop?.();
420
+ * this.stop = null;
341
421
  * }
342
422
  * }
343
423
  * ```
@@ -349,7 +429,7 @@ export interface RouterBridge {
349
429
  * Connects the router bridge to the Actor
350
430
  *
351
431
  * The infrastructure calls it when it must start the observation of the Actor
352
- * signals, and when it must bring its own state, for example the browser URL, in line
432
+ * atoms, and when it must bring its own state, for example the browser URL, in line
353
433
  * with the Actor state.
354
434
  *
355
435
  * @returns The promise that resolves after the connection, or void for a synchronous connection
@@ -358,7 +438,7 @@ export interface RouterBridge {
358
438
  * ```typescript
359
439
  * const bridge: RouterBridge = createBridge(actor, router);
360
440
  * await bridge.connect();
361
- * // The bridge observes the actor.currentRoute signal now
441
+ * // The bridge observes the actor.currentRoute atom now
362
442
  * ```
363
443
  */
364
444
  connect(): void | Promise<void>;
@@ -366,7 +446,7 @@ export interface RouterBridge {
366
446
  * Disconnects the router bridge from the Actor
367
447
  *
368
448
  * The infrastructure calls it when it must stop the observation and free its
369
- * resources, for example a signal watcher and an event listener.
449
+ * resources, for example an atom watcher and an event listener.
370
450
  *
371
451
  * @returns The promise that resolves after the disconnection, or void for a synchronous disconnection
372
452
  *
@@ -462,4 +542,28 @@ export interface LocationLike {
462
542
  readonly pathname: string;
463
543
  readonly search: string;
464
544
  }
545
+ /**
546
+ * The options of `createRouteMap` and of `createRouteMapFromTree`.
547
+ */
548
+ export interface RouteMapOptions extends CompileOptions {
549
+ /**
550
+ * The cache of the state that a VISITED PATH resolves to, or `null` for a path that
551
+ * resolves to none.
552
+ *
553
+ * The default is a cache of this map alone, of 500 entries in each of two generations.
554
+ * Pass one to raise that bound, to share the resolution across maps, or to give it an
555
+ * eviction policy of your own: `createPatternCache(5000)` builds one, and so does any
556
+ * object with a `get` and a `set`.
557
+ *
558
+ * A cache that a caller passes is keyed by the ROUTE TABLE. Two maps built from the
559
+ * same mappings, in the same order, therefore read each other's answers — which is
560
+ * what a server that rebuilds its map for each request wants — and two maps built from
561
+ * different mappings never do, because a map with no route for a path writes `null`
562
+ * for it and a map that holds one must not read that.
563
+ *
564
+ * The keys are the paths that a visitor reaches, so the key space is unbounded: a
565
+ * cache with no bound of its own grows for the life of the process.
566
+ */
567
+ pathCache?: PatternCache<string | null>;
568
+ }
465
569
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { AnyStateMachine } from "xstate";
2
+ import { RouteMap } from "../base-route-map.js";
3
+ import type { RouteMapOptions } from "../types.js";
4
+ /**
5
+ * Creates a `RouteMap` from an XState state machine.
6
+ *
7
+ * The function reads every state with a route, which means each state with a
8
+ * `meta.route` field. It keeps the routable states alone, and it drops the synthetic
9
+ * root of the tree. `createRouteMapFromTree` of the main entry point drops the same
10
+ * node, and the two functions therefore answer the same map for the same machine. It then builds the lookup structure between a path and a
11
+ * stateId, for both directions. A subclass of `RouterBridgeBase` uses the map: it
12
+ * converts each change of the browser URL into a `play.route` actor event, and each
13
+ * actor route into a URL.
14
+ *
15
+ * @param machine - The XState v5 state machine, with a `meta.route` annotation on each state with a route.
16
+ * @param options - The optional configuration. Give `{ pathCache }` to replace the
17
+ * default LRU cache of the parameterized path lookups with one that you own.
18
+ * @returns A `RouteMap` for each adapter on `RouterBridgeBase`.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * import { createRouteMap } from '@xmachines/play-router/xstate';
23
+ * import { connectRouter } from '@xmachines/play-dom-router';
24
+ *
25
+ * const routeMap = createRouteMap(myMachine);
26
+ * const disconnect = connectRouter({ actor, router, routeMap });
27
+ * ```
28
+ */
29
+ export declare function createRouteMap(machine: AnyStateMachine, options?: RouteMapOptions): RouteMap;
30
+ //# sourceMappingURL=create-route-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-route-map.d.ts","sourceRoot":"","sources":["../../src/xstate/create-route-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAa5F"}
@@ -1,23 +1,25 @@
1
1
  import { extractMachineRoutes } from "./extract-routes.js";
2
2
  import { getRoutableRoutes } from "./query.js";
3
- import { RouteMap } from "./base-route-map.js";
3
+ import { RouteMap } from "../base-route-map.js";
4
4
  /**
5
5
  * Creates a `RouteMap` from an XState state machine.
6
6
  *
7
7
  * The function reads every state with a route, which means each state with a
8
- * `meta.route` field. It then builds the lookup structure between a path and a
8
+ * `meta.route` field. It keeps the routable states alone, and it drops the synthetic
9
+ * root of the tree. `createRouteMapFromTree` of the main entry point drops the same
10
+ * node, and the two functions therefore answer the same map for the same machine. It then builds the lookup structure between a path and a
9
11
  * stateId, for both directions. A subclass of `RouterBridgeBase` uses the map: it
10
12
  * converts each change of the browser URL into a `play.route` actor event, and each
11
13
  * actor route into a URL.
12
14
  *
13
15
  * @param machine - The XState v5 state machine, with a `meta.route` annotation on each state with a route.
14
- * @param options - The optional configuration. Give `{ cacheSize }` to change the
15
- * default size of the LRU cache of the parameterized path lookups.
16
+ * @param options - The optional configuration. Give `{ pathCache }` to replace the
17
+ * default LRU cache of the parameterized path lookups with one that you own.
16
18
  * @returns A `RouteMap` for each adapter on `RouterBridgeBase`.
17
19
  *
18
20
  * @example
19
21
  * ```typescript
20
- * import { createRouteMap } from '@xmachines/play-router';
22
+ * import { createRouteMap } from '@xmachines/play-router/xstate';
21
23
  * import { connectRouter } from '@xmachines/play-dom-router';
22
24
  *
23
25
  * const routeMap = createRouteMap(myMachine);
@@ -25,7 +27,10 @@ import { RouteMap } from "./base-route-map.js";
25
27
  * ```
26
28
  */
27
29
  export function createRouteMap(machine, options) {
28
- const routeTree = extractMachineRoutes(machine);
30
+ // The options reach the EXTRACTION too. `extractMachineRoutes` parses the route of
31
+ // every node, so a caller that passes a cache for the isolation of a tenant would
32
+ // otherwise write each of those patterns into the shared default cache.
33
+ const routeTree = extractMachineRoutes(machine, options);
29
34
  const routes = getRoutableRoutes(routeTree);
30
35
  return new RouteMap(routes.map((node) => ({
31
36
  stateId: node.stateId,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-route-map.js","sourceRoot":"","sources":["../../src/xstate/create-route-map.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,cAAc,CAAC,OAAwB,EAAE,OAAyB;IACjF,mFAAmF;IACnF,kFAAkF;IAClF,wEAAwE;IACxE,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC5C,OAAO,IAAI,QAAQ,CAClB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,QAAQ;KACnB,CAAC,CAAC,EACH,OAAO,CACP,CAAC;AACH,CAAC"}
@@ -1,5 +1,7 @@
1
+ import type { ParseOptions } from "@xmachines/play-url";
1
2
  import type { AnyStateMachine } from "xstate";
2
- import type { RouteTree } from "./types.js";
3
+ import type { RouteTree } from "../types.js";
4
+ import { type MachineGraph } from "./machine-to-graph.js";
3
5
  /**
4
6
  * Reads the complete route tree from the graph of a state machine
5
7
  *
@@ -12,5 +14,5 @@ import type { RouteTree } from "./types.js";
12
14
  * @param machine - The XState v5 state machine
13
15
  * @returns The route tree, with its root, its byStateId map, its byPath map, and its graph
14
16
  */
15
- export declare const extractMachineRoutes: (machine: AnyStateMachine) => RouteTree;
17
+ export declare const extractMachineRoutes: (machine: AnyStateMachine, options?: ParseOptions) => RouteTree<MachineGraph>;
16
18
  //# sourceMappingURL=extract-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-routes.d.ts","sourceRoot":"","sources":["../../src/xstate/extract-routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,KAAK,EAAE,SAAS,EAA4B,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAiF1E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,GAChC,SAAS,eAAe,EACxB,UAAU,YAAY,KACpB,SAAS,CAAC,YAAY,CAoBxB,CAAC"}
@@ -1,6 +1,7 @@
1
+ import { parsePattern } from "@xmachines/play-url";
1
2
  import { machineToGraph } from "./machine-to-graph.js";
2
- import { validateRouteFormat, validateStateExists } from "./validate-routes.js";
3
- import { buildRouteTree } from "./build-tree.js";
3
+ import { validateRouteFormat, validateStateExists } from "../validate-routes.js";
4
+ import { buildRouteTree } from "../build-tree.js";
4
5
  /**
5
6
  * Builds the statePath of a graph node, and it walks the chain of the parentId
6
7
  * values.
@@ -26,7 +27,7 @@ const buildStatePath = (graphNode, graphNodeMap) => {
26
27
  * Reads the route information of the MachineNodeData object of a graph node.
27
28
  * The function returns null when the node has no route.
28
29
  */
29
- const extractRouteFromNode = (graphNode, stateIds, graphNodeMap) => {
30
+ const extractRouteFromNode = (graphNode, stateIds, graphNodeMap, options) => {
30
31
  const { stateId, route, meta } = graphNode.data;
31
32
  // The node has no route
32
33
  if (!route)
@@ -37,7 +38,11 @@ const extractRouteFromNode = (graphNode, stateIds, graphNodeMap) => {
37
38
  validateStateExists(stateId, stateIds);
38
39
  // Build the statePath from the chain of the parentId values. This works for an explicit ID and also for a generated one
39
40
  const statePath = buildStatePath(graphNode, graphNodeMap);
40
- const pattern = route.includes(":") ? route : undefined;
41
+ // The parse answers this, and not a search for a ":". `route.includes(":")` was the
42
+ // last expression that read the grammar on its own: it reported no pattern for
43
+ // `/docs/*`, for `/books{/:id}?` and for an escaped literal, so a consumer that reads
44
+ // `node.pattern` learned that a parameterized route is a literal path.
45
+ const pattern = parsePattern(route, options).parameterized ? route : undefined;
41
46
  // Build the original shape of the metadata again, from the data of the graph
42
47
  const metadata = meta && typeof meta === "object" && "route" in meta
43
48
  ? meta["route"]
@@ -66,7 +71,7 @@ const extractRouteFromNode = (graphNode, stateIds, graphNodeMap) => {
66
71
  * @param machine - The XState v5 state machine
67
72
  * @returns The route tree, with its root, its byStateId map, its byPath map, and its graph
68
73
  */
69
- export const extractMachineRoutes = (machine) => {
74
+ export const extractMachineRoutes = (machine, options) => {
70
75
  // 1. Convert the machine into a graph
71
76
  const graph = machineToGraph(machine);
72
77
  // 2. Build the set of the state IDs, for the check, and the node map, for a parent lookup in O(1)
@@ -74,7 +79,7 @@ export const extractMachineRoutes = (machine) => {
74
79
  const graphNodeMap = new Map(graph.nodes.map((n) => [n.id, n]));
75
80
  // 3. Read the routes of the graph nodes
76
81
  const routes = graph.nodes
77
- .map((node) => extractRouteFromNode(node, stateIds, graphNodeMap))
82
+ .map((node) => extractRouteFromNode(node, stateIds, graphNodeMap, options))
78
83
  .filter((r) => r !== null);
79
84
  // 4. Build the hierarchical tree, and attach the graph.
80
85
  // buildRouteTree finds each duplicate route, AFTER it resolved each relative route
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-routes.js","sourceRoot":"","sources":["../../src/xstate/extract-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * `@xmachines/play-router/xstate` - the routes of an XState machine
3
+ *
4
+ * A route of XMachines is a fact about a STATE. This entry point reads that fact out of an
5
+ * XState v5 machine: it walks the machine, collects each `meta.route`, builds the route
6
+ * tree, and answers the questions that the tree can be asked — which routes are reachable,
7
+ * which are navigable from a state, and which path maps to which state id.
8
+ *
9
+ * The MAIN entry point holds what happens AFTERWARDS: the route map, the match of a
10
+ * location, the bridge, and the provider lifecycle. It names no machine, and it reads this
11
+ * module never. `xstate` is therefore an OPTIONAL peer of this package, and a bundler drops
12
+ * `@statelyai/graph` for a consumer that imports this entry point nowhere.
13
+ *
14
+ * This is the same shape as `@xmachines/play-xstate/routing` and
15
+ * `@xmachines/play-xstate/view`: an optional capability behind its own entry point, with
16
+ * its own dependency.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { createRouteMap } from "@xmachines/play-router/xstate";
21
+ * import { connectRouter } from "@xmachines/play-dom-router";
22
+ *
23
+ * const routeMap = createRouteMap(myMachine);
24
+ * ```
25
+ *
26
+ * @packageDocumentation
27
+ * @see [Routing guide](../../../docs/guides/routing.md)
28
+ */
29
+ export { extractMachineRoutes } from "./extract-routes.js";
30
+ export { createRouteMap } from "./create-route-map.js";
31
+ export { machineToGraph } from "./machine-to-graph.js";
32
+ export type { MachineGraph } from "./machine-to-graph.js";
33
+ export type { MachineNodeData, MachineEdgeData } from "./machine-types.js";
34
+ export { getNavigableRoutes, getRoutableRoutes, routeExists, getTransitionReachableRoutes, isRouteReachable, getRouteMappings, } from "./query.js";
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/xstate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,4BAA4B,EAC5B,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,YAAY,CAAC"}