@xmachines/docs 1.0.0-beta.10
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/LICENSE +21 -0
- package/README.md +15 -0
- package/api/@xmachines/play/README.md +130 -0
- package/api/@xmachines/play/type-aliases/PlayEvent.md +81 -0
- package/api/@xmachines/play-actor/README.md +247 -0
- package/api/@xmachines/play-actor/classes/AbstractActor.md +520 -0
- package/api/@xmachines/play-actor/interfaces/Routable.md +29 -0
- package/api/@xmachines/play-actor/interfaces/ViewMetadata.md +17 -0
- package/api/@xmachines/play-actor/interfaces/Viewable.md +12 -0
- package/api/@xmachines/play-catalog/README.md +331 -0
- package/api/@xmachines/play-catalog/functions/defineCatalog.md +98 -0
- package/api/@xmachines/play-catalog/functions/defineComponents.md +134 -0
- package/api/@xmachines/play-catalog/type-aliases/Catalog.md +48 -0
- package/api/@xmachines/play-catalog/type-aliases/ComponentsFor.md +20 -0
- package/api/@xmachines/play-catalog/type-aliases/InferComponentProps.md +65 -0
- package/api/@xmachines/play-catalog/type-aliases/NoExtraKeys.md +17 -0
- package/api/@xmachines/play-react/README.md +423 -0
- package/api/@xmachines/play-react/classes/PlayErrorBoundary.md +613 -0
- package/api/@xmachines/play-react/functions/useSignalEffect.md +68 -0
- package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryProps.md +15 -0
- package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryState.md +14 -0
- package/api/@xmachines/play-react/interfaces/PlayRendererProps.md +15 -0
- package/api/@xmachines/play-react/variables/PlayRenderer.md +64 -0
- package/api/@xmachines/play-react-router/README.md +198 -0
- package/api/@xmachines/play-react-router/classes/ReactRouterBridge.md +321 -0
- package/api/@xmachines/play-react-router/classes/RouteMap.md +137 -0
- package/api/@xmachines/play-react-router/functions/PlayRouterProvider.md +19 -0
- package/api/@xmachines/play-react-router/functions/createRouteMapFromTree.md +35 -0
- package/api/@xmachines/play-react-router/interfaces/PlayRouteEvent.md +119 -0
- package/api/@xmachines/play-react-router/interfaces/PlayRouterProviderProps.md +14 -0
- package/api/@xmachines/play-react-router/interfaces/RouteMapping.md +17 -0
- package/api/@xmachines/play-react-router/interfaces/RouterBridge.md +104 -0
- package/api/@xmachines/play-react-router-demo/README.md +137 -0
- package/api/@xmachines/play-router/README.md +502 -0
- package/api/@xmachines/play-router/classes/BaseRouteMap.md +142 -0
- package/api/@xmachines/play-router/classes/RouterBridgeBase.md +300 -0
- package/api/@xmachines/play-router/functions/buildRouteTree.md +27 -0
- package/api/@xmachines/play-router/functions/connectRouter.md +67 -0
- package/api/@xmachines/play-router/functions/crawlMachine.md +92 -0
- package/api/@xmachines/play-router/functions/createBrowserHistory.md +47 -0
- package/api/@xmachines/play-router/functions/createRouteMap.md +53 -0
- package/api/@xmachines/play-router/functions/createRouter.md +76 -0
- package/api/@xmachines/play-router/functions/detectDuplicateRoutes.md +32 -0
- package/api/@xmachines/play-router/functions/extractMachineRoutes.md +64 -0
- package/api/@xmachines/play-router/functions/extractRoute.md +45 -0
- package/api/@xmachines/play-router/functions/findRouteById.md +37 -0
- package/api/@xmachines/play-router/functions/findRouteByPath.md +39 -0
- package/api/@xmachines/play-router/functions/getNavigableRoutes.md +35 -0
- package/api/@xmachines/play-router/functions/getRoutableRoutes.md +39 -0
- package/api/@xmachines/play-router/functions/routeExists.md +26 -0
- package/api/@xmachines/play-router/functions/validateRouteFormat.md +29 -0
- package/api/@xmachines/play-router/functions/validateStateExists.md +29 -0
- package/api/@xmachines/play-router/interfaces/BaseRouteMapping.md +27 -0
- package/api/@xmachines/play-router/interfaces/BrowserHistory.md +172 -0
- package/api/@xmachines/play-router/interfaces/BrowserWindow.md +69 -0
- package/api/@xmachines/play-router/interfaces/ConnectRouterOptions.md +13 -0
- package/api/@xmachines/play-router/interfaces/PlayRouteEvent.md +119 -0
- package/api/@xmachines/play-router/interfaces/RouteInfo.md +19 -0
- package/api/@xmachines/play-router/interfaces/RouteMap.md +56 -0
- package/api/@xmachines/play-router/interfaces/RouteNode.md +21 -0
- package/api/@xmachines/play-router/interfaces/RouteObject.md +21 -0
- package/api/@xmachines/play-router/interfaces/RouteTree.md +20 -0
- package/api/@xmachines/play-router/interfaces/RouterBridge.md +104 -0
- package/api/@xmachines/play-router/interfaces/StateVisit.md +15 -0
- package/api/@xmachines/play-router/interfaces/VanillaRouter.md +28 -0
- package/api/@xmachines/play-router/type-aliases/RouteMetadata.md +11 -0
- package/api/@xmachines/play-router-demo/README.md +137 -0
- package/api/@xmachines/play-signals/README.md +176 -0
- package/api/@xmachines/play-signals/interfaces/ComputedOptions.md +34 -0
- package/api/@xmachines/play-signals/interfaces/SignalComputed.md +49 -0
- package/api/@xmachines/play-signals/interfaces/SignalOptions.md +35 -0
- package/api/@xmachines/play-signals/interfaces/SignalState.md +68 -0
- package/api/@xmachines/play-signals/interfaces/SignalWatcher.md +97 -0
- package/api/@xmachines/play-signals/namespaces/Signal/README.md +22 -0
- package/api/@xmachines/play-signals/namespaces/Signal/classes/Computed.md +52 -0
- package/api/@xmachines/play-signals/namespaces/Signal/classes/State.md +72 -0
- package/api/@xmachines/play-signals/namespaces/Signal/interfaces/Options.md +19 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/README.md +21 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/classes/Watcher.md +85 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/currentComputed.md +13 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/hasSinks.md +19 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/hasSources.md +19 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/introspectSinks.md +19 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/introspectSources.md +19 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/untrack.md +25 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/variables/unwatched.md +9 -0
- package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/variables/watched.md +9 -0
- package/api/@xmachines/play-signals/namespaces/Signal/variables/isComputed.md +19 -0
- package/api/@xmachines/play-signals/namespaces/Signal/variables/isState.md +19 -0
- package/api/@xmachines/play-signals/namespaces/Signal/variables/isWatcher.md +19 -0
- package/api/@xmachines/play-signals/type-aliases/WatcherNotify.md +32 -0
- package/api/@xmachines/play-solid/README.md +311 -0
- package/api/@xmachines/play-solid/interfaces/PlayRendererProps.md +15 -0
- package/api/@xmachines/play-solid/variables/PlayRenderer.md +70 -0
- package/api/@xmachines/play-solid-router/README.md +666 -0
- package/api/@xmachines/play-solid-router/classes/RouteMap.md +150 -0
- package/api/@xmachines/play-solid-router/classes/SolidRouterBridge.md +347 -0
- package/api/@xmachines/play-solid-router/functions/PlayRouterProvider.md +19 -0
- package/api/@xmachines/play-solid-router/functions/createRouteMap.md +32 -0
- package/api/@xmachines/play-solid-router/interfaces/AbstractActor.md +486 -0
- package/api/@xmachines/play-solid-router/interfaces/PlayRouteEvent.md +119 -0
- package/api/@xmachines/play-solid-router/interfaces/PlayRouterProviderProps.md +14 -0
- package/api/@xmachines/play-solid-router/interfaces/RouteMapping.md +14 -0
- package/api/@xmachines/play-solid-router/interfaces/RouterBridge.md +104 -0
- package/api/@xmachines/play-solid-router/type-aliases/RoutableActor.md +9 -0
- package/api/@xmachines/play-solid-router/type-aliases/SolidRouterHooks.md +51 -0
- package/api/@xmachines/play-solid-router-demo/README.md +127 -0
- package/api/@xmachines/play-tanstack-react-router/README.md +226 -0
- package/api/@xmachines/play-tanstack-react-router/classes/RouteMap.md +137 -0
- package/api/@xmachines/play-tanstack-react-router/classes/TanStackReactRouterBridge.md +348 -0
- package/api/@xmachines/play-tanstack-react-router/functions/PlayRouterProvider.md +19 -0
- package/api/@xmachines/play-tanstack-react-router/functions/createRouteMap.md +53 -0
- package/api/@xmachines/play-tanstack-react-router/functions/createRouteMapFromTree.md +35 -0
- package/api/@xmachines/play-tanstack-react-router/functions/extractParams.md +38 -0
- package/api/@xmachines/play-tanstack-react-router/functions/extractQueryParams.md +33 -0
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouteEvent.md +119 -0
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouterProviderProps.md +14 -0
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapping.md +17 -0
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteNavigateEvent.md +26 -0
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouterBridge.md +104 -0
- package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterInstance.md +9 -0
- package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterLike.md +78 -0
- package/api/@xmachines/play-tanstack-react-router/variables/extractMachineRoutes.md +64 -0
- package/api/@xmachines/play-tanstack-react-router-demo/README.md +126 -0
- package/api/@xmachines/play-tanstack-solid-router/README.md +285 -0
- package/api/@xmachines/play-tanstack-solid-router/classes/RouteMap.md +150 -0
- package/api/@xmachines/play-tanstack-solid-router/classes/SolidRouterBridge.md +343 -0
- package/api/@xmachines/play-tanstack-solid-router/functions/PlayRouterProvider.md +19 -0
- package/api/@xmachines/play-tanstack-solid-router/functions/createRouteMap.md +32 -0
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouteEvent.md +119 -0
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouterProviderProps.md +14 -0
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapping.md +23 -0
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouterBridge.md +104 -0
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/RoutableActor.md +9 -0
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterInstance.md +9 -0
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterLike.md +78 -0
- package/api/@xmachines/play-tanstack-solid-router-demo/README.md +126 -0
- package/api/@xmachines/play-vue/README.md +292 -0
- package/api/@xmachines/play-vue/interfaces/PlayRendererProps.md +14 -0
- package/api/@xmachines/play-vue/variables/PlayRenderer.md +9 -0
- package/api/@xmachines/play-vue-router/README.md +604 -0
- package/api/@xmachines/play-vue-router/classes/RouteMap.md +209 -0
- package/api/@xmachines/play-vue-router/classes/VueBaseRouteMap.md +201 -0
- package/api/@xmachines/play-vue-router/classes/VueRouterBridge.md +360 -0
- package/api/@xmachines/play-vue-router/functions/createRouteMap.md +19 -0
- package/api/@xmachines/play-vue-router/interfaces/PlayRouteEvent.md +119 -0
- package/api/@xmachines/play-vue-router/interfaces/RouteMapping.md +15 -0
- package/api/@xmachines/play-vue-router/interfaces/RouterBridge.md +104 -0
- package/api/@xmachines/play-vue-router/type-aliases/RoutableActor.md +9 -0
- package/api/@xmachines/play-vue-router/variables/PlayRouterProvider.md +67 -0
- package/api/@xmachines/play-vue-router-demo/README.md +133 -0
- package/api/@xmachines/play-xstate/README.md +512 -0
- package/api/@xmachines/play-xstate/classes/PlayerActor.md +527 -0
- package/api/@xmachines/play-xstate/functions/buildRouteUrl.md +43 -0
- package/api/@xmachines/play-xstate/functions/composeGuards.md +79 -0
- package/api/@xmachines/play-xstate/functions/composeGuardsOr.md +67 -0
- package/api/@xmachines/play-xstate/functions/definePlayer.md +127 -0
- package/api/@xmachines/play-xstate/functions/deriveRoute.md +109 -0
- package/api/@xmachines/play-xstate/functions/eventMatches.md +40 -0
- package/api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md +54 -0
- package/api/@xmachines/play-xstate/functions/hasContext.md +42 -0
- package/api/@xmachines/play-xstate/functions/isAbsoluteRoute.md +41 -0
- package/api/@xmachines/play-xstate/functions/mergeViewProps.md +26 -0
- package/api/@xmachines/play-xstate/functions/negateGuard.md +61 -0
- package/api/@xmachines/play-xstate/functions/stateMatches.md +25 -0
- package/api/@xmachines/play-xstate/functions/validateComponentBinding.md +39 -0
- package/api/@xmachines/play-xstate/functions/validateViewProps.md +80 -0
- package/api/@xmachines/play-xstate/interfaces/CatalogEntry.md +16 -0
- package/api/@xmachines/play-xstate/interfaces/PlayerConfig.md +24 -0
- package/api/@xmachines/play-xstate/interfaces/PlayerOptions.md +26 -0
- package/api/@xmachines/play-xstate/interfaces/RouteContext.md +22 -0
- package/api/@xmachines/play-xstate/type-aliases/Catalog.md +21 -0
- package/api/@xmachines/play-xstate/type-aliases/ComposedGuard.md +14 -0
- package/api/@xmachines/play-xstate/type-aliases/Guard.md +34 -0
- package/api/@xmachines/play-xstate/type-aliases/GuardArray.md +20 -0
- package/api/@xmachines/play-xstate/type-aliases/PlayerFactory.md +29 -0
- package/api/@xmachines/play-xstate/type-aliases/RouteMachineConfig.md +45 -0
- package/api/@xmachines/play-xstate/type-aliases/RouteStateNode.md +51 -0
- package/api/@xmachines/play-xstate/type-aliases/ValidationResult.md +17 -0
- package/api/@xmachines/play-xstate/type-aliases/ViewMergeContext.md +35 -0
- package/api/@xmachines/shared/README.md +379 -0
- package/api/@xmachines/shared/functions/defineXmVitestConfig.md +29 -0
- package/api/@xmachines/shared/functions/xmAliases.md +24 -0
- package/api/README.md +25 -0
- package/api/llms.txt +26 -0
- package/examples/README.md +63 -0
- package/examples/basic-state-machine.md +70 -0
- package/examples/form-validation.md +167 -0
- package/examples/multi-router-integration.md +277 -0
- package/examples/routing-patterns.md +260 -0
- package/examples/traffic-light.md +99 -0
- package/guides/README.md +29 -0
- package/guides/getting-started.md +223 -0
- package/guides/installation.md +323 -0
- package/index.d.ts +3 -0
- package/index.js +4 -0
- package/package.json +54 -0
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
[Documentation](../../README.md) / @xmachines/play-router
|
|
2
|
+
|
|
3
|
+
# @xmachines/play-router
|
|
4
|
+
|
|
5
|
+
**Route tree extraction from XState v5 state machines with routing patterns**
|
|
6
|
+
|
|
7
|
+
BFS graph crawling and bidirectional route lookup enabling Actor Authority over navigation.
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`@xmachines/play-router` extracts route trees from XState state machines by crawling the state graph using breadth-first traversal. It extracts `meta.route` paths from state machines and builds hierarchical route trees with bidirectional state ID ↔ path mapping.
|
|
12
|
+
|
|
13
|
+
It also exports `RouterBridgeBase`, the shared base class used by framework adapters to implement `RouterBridge` with consistent actor↔router synchronization behavior.
|
|
14
|
+
|
|
15
|
+
`RouterBridgeBase` is the policy point; framework adapters are thin ports that implement only framework-specific navigate/subscribe/unsubscribe behavior.
|
|
16
|
+
|
|
17
|
+
Per [RFC Play v1](https://gitlab.com/xmachin-es/rfc/-/blob/main/src/play-v1.md), this package implements:
|
|
18
|
+
|
|
19
|
+
- **Actor Authority (INV-01):** Routes derive from machine definitions, not external configuration
|
|
20
|
+
|
|
21
|
+
**Routing:** Supports `meta.route` detection, `play.route` event routing, and pattern matching for dynamic parameters.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install xstate@^5.0.0
|
|
27
|
+
npm install @xmachines/play-router
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Peer dependencies:**
|
|
31
|
+
|
|
32
|
+
- `xstate` ^5.0.0 — State machine runtime
|
|
33
|
+
|
|
34
|
+
**URLPattern polyfill (Node.js < 24 / older browsers):**
|
|
35
|
+
|
|
36
|
+
`@xmachines/play-router` uses the [URLPattern API](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) for dynamic route matching. URLPattern is available natively on Node.js 24+ and modern browsers (Chrome 95+, Firefox 117+, Safari 16.4+).
|
|
37
|
+
|
|
38
|
+
On environments without native support, load a polyfill **before** importing this package:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// Entry point — must run before any @xmachines/play-router import
|
|
42
|
+
import "urlpattern-polyfill";
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Install the polyfill:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install urlpattern-polyfill
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`urlpattern-polyfill` is declared as an optional peer dependency. Package managers will not install it automatically — it is the consumer's responsibility to load it when needed.
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { createMachine } from "xstate";
|
|
57
|
+
import { extractMachineRoutes } from "@xmachines/play-router";
|
|
58
|
+
|
|
59
|
+
// Route pattern (recommended)
|
|
60
|
+
const machine = createMachine({
|
|
61
|
+
id: "app",
|
|
62
|
+
initial: "home",
|
|
63
|
+
states: {
|
|
64
|
+
home: {
|
|
65
|
+
id: "home",
|
|
66
|
+
meta: { route: "/", view: { component: "Home" } },
|
|
67
|
+
},
|
|
68
|
+
dashboard: {
|
|
69
|
+
id: "dashboard",
|
|
70
|
+
meta: { route: "/dashboard", view: { component: "Dashboard" } },
|
|
71
|
+
initial: "overview",
|
|
72
|
+
states: {
|
|
73
|
+
overview: {
|
|
74
|
+
id: "overview",
|
|
75
|
+
meta: { route: "/overview", view: { component: "Overview" } },
|
|
76
|
+
},
|
|
77
|
+
settings: {
|
|
78
|
+
id: "settings",
|
|
79
|
+
meta: { route: "/settings/:section?", view: { component: "Settings" } }, // Optional parameter
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const tree = extractMachineRoutes(machine);
|
|
87
|
+
|
|
88
|
+
// Bidirectional lookup
|
|
89
|
+
console.log(tree.byPath.get("/dashboard/overview")); // RouteNode
|
|
90
|
+
console.log(tree.byId.get("overview")); // RouteNode
|
|
91
|
+
|
|
92
|
+
// Pattern matching for dynamic routes
|
|
93
|
+
const settingsRoute = tree.byPath.get("/settings/profile");
|
|
94
|
+
console.log(settingsRoute?.id); // "settings"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Vanilla Browser Example
|
|
98
|
+
|
|
99
|
+
See `examples/vanilla-demo/` for a complete example using vanilla TypeScript with the browser History API.
|
|
100
|
+
|
|
101
|
+
The demo demonstrates:
|
|
102
|
+
|
|
103
|
+
- **RouteTree extraction** from XState machine meta.route
|
|
104
|
+
- **History API integration** (pushState, popstate)
|
|
105
|
+
- **Bidirectional synchronization** (actor ↔ URL)
|
|
106
|
+
- **Protected route guards** (authentication redirects)
|
|
107
|
+
- **Dynamic route parameters** (/profile/:userId)
|
|
108
|
+
|
|
109
|
+
**Run the demo:**
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
cd packages/play-router/examples/demo
|
|
113
|
+
npm install
|
|
114
|
+
npm run dev
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Open http://localhost:5174/ and explore:
|
|
118
|
+
|
|
119
|
+
1. Login with any username
|
|
120
|
+
2. Navigate between home and profile
|
|
121
|
+
3. Use browser back/forward buttons
|
|
122
|
+
4. Try accessing protected routes directly
|
|
123
|
+
|
|
124
|
+
**Key implementation patterns:**
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// Extract routes from machine
|
|
128
|
+
const routeTree = extractMachineRoutes(authMachine);
|
|
129
|
+
const routeMap = createRouteMap(routeTree);
|
|
130
|
+
|
|
131
|
+
// Actor → URL sync
|
|
132
|
+
const watcher = new Signal.subtle.Watcher(() => {
|
|
133
|
+
queueMicrotask(() => {
|
|
134
|
+
watcher.getPending();
|
|
135
|
+
const route = actor.currentRoute.get();
|
|
136
|
+
if (route) {
|
|
137
|
+
window.history.pushState({}, "", route);
|
|
138
|
+
}
|
|
139
|
+
watcher.watch(actor.currentRoute);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// URL → Actor sync (with pattern matching)
|
|
144
|
+
window.addEventListener("popstate", () => {
|
|
145
|
+
const path = window.location.pathname;
|
|
146
|
+
const { to, params } = routeMap.resolve(path);
|
|
147
|
+
if (to) {
|
|
148
|
+
actor.send({ type: "play.route", to, params });
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Initial URL handling
|
|
153
|
+
const initialPath = window.location.pathname;
|
|
154
|
+
if (initialPath !== "/") {
|
|
155
|
+
const { to, params } = routeMap.resolve(initialPath);
|
|
156
|
+
if (to) {
|
|
157
|
+
actor.send({ type: "play.route", to, params });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
This example shows the core routing concepts without framework dependencies, making it ideal for understanding how @xmachines/play-router integrates with browser History API.
|
|
163
|
+
|
|
164
|
+
## Canonical Watcher Lifecycle
|
|
165
|
+
|
|
166
|
+
Bridge implementations should use one watcher flow:
|
|
167
|
+
|
|
168
|
+
1. `notify`
|
|
169
|
+
2. `queueMicrotask`
|
|
170
|
+
3. `getPending()`
|
|
171
|
+
4. read actor route and sync infrastructure state
|
|
172
|
+
5. re-arm with `watch(...)` or `watch()`
|
|
173
|
+
|
|
174
|
+
Watcher notification is one-shot; re-arm is required.
|
|
175
|
+
|
|
176
|
+
## Bridge Cleanup Contract
|
|
177
|
+
|
|
178
|
+
Bridge teardown must be explicit and deterministic:
|
|
179
|
+
|
|
180
|
+
- `disconnect`/`dispose` must unwatch signal subscriptions and unhook router listeners.
|
|
181
|
+
- Do not rely on GC-only cleanup guidance.
|
|
182
|
+
- Infrastructure remains passive: bridges observe and forward intents, actors decide validity.
|
|
183
|
+
|
|
184
|
+
## API Reference
|
|
185
|
+
|
|
186
|
+
### extractMachineRoutes()
|
|
187
|
+
|
|
188
|
+
Main entry point — crawls state machine, extracts routes, builds tree:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
const tree = extractMachineRoutes(machine: AnyStateMachine): RouteTree;
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Detection:**
|
|
195
|
+
|
|
196
|
+
- States with `meta.route` in meta object
|
|
197
|
+
|
|
198
|
+
**Returns:** `RouteTree` with:
|
|
199
|
+
|
|
200
|
+
- `routes: RouteNode[]` - Array of route nodes
|
|
201
|
+
- `byPath: Map<string, RouteNode>` - URL path → route node
|
|
202
|
+
- `byId: Map<string, RouteNode>` - State ID → route node
|
|
203
|
+
|
|
204
|
+
**Throws:** Error if routes are invalid (malformed paths, missing state IDs, duplicates)
|
|
205
|
+
|
|
206
|
+
**Example:**
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { extractMachineRoutes } from "@xmachines/play-router";
|
|
210
|
+
|
|
211
|
+
const tree = extractMachineRoutes(authMachine);
|
|
212
|
+
|
|
213
|
+
// Query routes
|
|
214
|
+
const loginRoute = tree.byId.get("login");
|
|
215
|
+
console.log(loginRoute?.path); // "/login"
|
|
216
|
+
|
|
217
|
+
const dashboardRoute = tree.byPath.get("/dashboard");
|
|
218
|
+
console.log(dashboardRoute?.id); // "dashboard"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### crawlMachine()
|
|
222
|
+
|
|
223
|
+
Low-level BFS traversal of state machine graph:
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
const visits = crawlMachine(machine: AnyStateMachine): StateVisit[];
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Returns:** Array of state visits in breadth-first order with:
|
|
230
|
+
|
|
231
|
+
- `path: string[]` - State path (e.g., ["dashboard", "settings"])
|
|
232
|
+
- `parent: StateNode | null` - Parent state node
|
|
233
|
+
- `node: StateNode` - Current state node
|
|
234
|
+
|
|
235
|
+
**Example:**
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import { crawlMachine } from "@xmachines/play-router";
|
|
239
|
+
|
|
240
|
+
const visits = crawlMachine(machine);
|
|
241
|
+
visits.forEach((visit) => {
|
|
242
|
+
console.log("State:", visit.path.join("."));
|
|
243
|
+
console.log("Parent:", visit.parent?.id ?? "root");
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Query Utilities
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// Get child routes from state
|
|
251
|
+
const children = getNavigableRoutes(tree, "dashboard");
|
|
252
|
+
|
|
253
|
+
// Check if route exists
|
|
254
|
+
const exists = routeExists(tree, "/profile/:userId");
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Examples
|
|
258
|
+
|
|
259
|
+
### Route Detection
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
import { extractMachineRoutes } from "@xmachines/play-router";
|
|
263
|
+
import { createMachine } from "xstate";
|
|
264
|
+
|
|
265
|
+
const machine = createMachine({
|
|
266
|
+
initial: "home",
|
|
267
|
+
states: {
|
|
268
|
+
home: {
|
|
269
|
+
id: "home",
|
|
270
|
+
meta: { route: "/", view: { component: "Home" } },
|
|
271
|
+
},
|
|
272
|
+
profile: {
|
|
273
|
+
id: "profile",
|
|
274
|
+
meta: { route: "/profile/:userId", view: { component: "Profile" } }, // Parameter pattern
|
|
275
|
+
},
|
|
276
|
+
settings: {
|
|
277
|
+
id: "settings",
|
|
278
|
+
meta: { route: "/settings/:section?", view: { component: "Settings" } }, // Optional parameter
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const tree = extractMachineRoutes(machine);
|
|
284
|
+
|
|
285
|
+
// Bidirectional mapping
|
|
286
|
+
const profileById = tree.byId.get("profile");
|
|
287
|
+
console.log(profileById?.path); // "/profile/:userId"
|
|
288
|
+
|
|
289
|
+
const profileByPath = tree.byPath.get("/profile/user123");
|
|
290
|
+
console.log(profileByPath?.id); // "profile"
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Hierarchical Route Tree
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
import { extractMachineRoutes, getNavigableRoutes } from "@xmachines/play-router";
|
|
297
|
+
|
|
298
|
+
const machine = createMachine({
|
|
299
|
+
initial: "app",
|
|
300
|
+
states: {
|
|
301
|
+
app: {
|
|
302
|
+
id: "app",
|
|
303
|
+
meta: { route: "/", view: { component: "AppShell" } },
|
|
304
|
+
initial: "dashboard",
|
|
305
|
+
states: {
|
|
306
|
+
dashboard: {
|
|
307
|
+
id: "dashboard",
|
|
308
|
+
meta: { route: "/dashboard", view: { component: "Dashboard" } },
|
|
309
|
+
initial: "overview",
|
|
310
|
+
states: {
|
|
311
|
+
overview: {
|
|
312
|
+
id: "overview",
|
|
313
|
+
meta: { route: "/overview", view: { component: "Overview" } },
|
|
314
|
+
},
|
|
315
|
+
analytics: {
|
|
316
|
+
id: "analytics",
|
|
317
|
+
meta: { route: "/analytics", view: { component: "Analytics" } },
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
const tree = extractMachineRoutes(machine);
|
|
327
|
+
|
|
328
|
+
// Get child routes
|
|
329
|
+
const dashboardChildren = getNavigableRoutes(tree, "dashboard");
|
|
330
|
+
console.log(dashboardChildren.map((r) => r.id)); // ["overview", "analytics"]
|
|
331
|
+
|
|
332
|
+
// Route inheritance
|
|
333
|
+
const analyticsRoute = tree.byId.get("analytics");
|
|
334
|
+
console.log(analyticsRoute?.path); // "/dashboard/analytics" (inherited parent path)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Pattern Matching
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { extractMachineRoutes } from "@xmachines/play-router";
|
|
341
|
+
|
|
342
|
+
const machine = createMachine({
|
|
343
|
+
states: {
|
|
344
|
+
user: {
|
|
345
|
+
id: "user",
|
|
346
|
+
meta: { route: "/user/:userId", view: { component: "User" } }, // Required parameter
|
|
347
|
+
},
|
|
348
|
+
settings: {
|
|
349
|
+
id: "settings",
|
|
350
|
+
meta: { route: "/settings/:section?", view: { component: "Settings" } }, // Optional parameter
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
const tree = extractMachineRoutes(machine);
|
|
356
|
+
|
|
357
|
+
// Pattern matching for actual URLs
|
|
358
|
+
const userRoute = tree.byPath.get("/user/user123");
|
|
359
|
+
console.log(userRoute?.id); // "user"
|
|
360
|
+
|
|
361
|
+
const settingsDefault = tree.byPath.get("/settings");
|
|
362
|
+
console.log(settingsDefault?.id); // "settings" (optional param)
|
|
363
|
+
|
|
364
|
+
const settingsProfile = tree.byPath.get("/settings/profile");
|
|
365
|
+
console.log(settingsProfile?.id); // "settings" (with param)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Route Configuration
|
|
369
|
+
|
|
370
|
+
### Route Pattern (Recommended)
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
states: {
|
|
374
|
+
dashboard: {
|
|
375
|
+
id: "dashboard", // Required for bidirectional lookup
|
|
376
|
+
meta: {
|
|
377
|
+
route: "/dashboard", // URL path - marks state as routable
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Alternative Pattern
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
states: {
|
|
387
|
+
dashboard: {
|
|
388
|
+
id: "dashboard",
|
|
389
|
+
meta: {
|
|
390
|
+
route: "/dashboard",
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Route Inheritance
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
states: {
|
|
400
|
+
parent: {
|
|
401
|
+
id: "parent",
|
|
402
|
+
meta: { route: "/parent", view: { component: "Parent" } },
|
|
403
|
+
states: {
|
|
404
|
+
absolute: {
|
|
405
|
+
id: "absolute",
|
|
406
|
+
meta: { route: "/absolute", view: { component: "Absolute" } }, // Starts with / → doesn't inherit
|
|
407
|
+
},
|
|
408
|
+
relative: {
|
|
409
|
+
id: "relative",
|
|
410
|
+
meta: { route: "relative", view: { component: "Relative" } }, // No leading / → inherits parent
|
|
411
|
+
// Final path: "/parent/relative"
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Dynamic Parameters
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
meta: {
|
|
422
|
+
route: "/profile/:userId", // Required parameter
|
|
423
|
+
route: "/settings/:section?", // Optional parameter
|
|
424
|
+
route: "/docs/:category/:page", // Multiple parameters
|
|
425
|
+
view: { component: "AnyView" },
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Parameter substitution:** Values extracted from context or event params (handled by play-xstate adapter).
|
|
430
|
+
|
|
431
|
+
## Architecture
|
|
432
|
+
|
|
433
|
+
This package enables **Actor Authority (INV-01)**:
|
|
434
|
+
|
|
435
|
+
1. **Routes derive from machine:** Business logic defines routes in state machine, not external config
|
|
436
|
+
2. **BFS traversal:** Systematic state discovery ensures all nested states visited
|
|
437
|
+
3. **Bidirectional mapping:** Fast lookup by path (browser URL) or by ID (state machine)
|
|
438
|
+
4. **Build-time validation:** Invalid routes throw errors during extraction, not runtime
|
|
439
|
+
|
|
440
|
+
**Enhancements:**
|
|
441
|
+
|
|
442
|
+
- `meta.route` detection via state metadata
|
|
443
|
+
- Pattern matching for dynamic routes (`:param` and `:param?`)
|
|
444
|
+
- State ID ↔ path bidirectional maps for `play.route` events
|
|
445
|
+
|
|
446
|
+
## Related Packages
|
|
447
|
+
|
|
448
|
+
- **[@xmachines/play-xstate](../play-xstate/README.md)** - XState adapter using route extraction
|
|
449
|
+
- **[@xmachines/play-tanstack-react-router](../play-tanstack-react-router/README.md)** - TanStack Router adapter using route trees
|
|
450
|
+
- **[@xmachines/play-react-router](../play-react-router/README.md)** - React Router v7 adapter using RouterBridgeBase
|
|
451
|
+
- **[@xmachines/play](../play/README.md)** - Protocol types
|
|
452
|
+
|
|
453
|
+
## License
|
|
454
|
+
|
|
455
|
+
Copyright (c) 2016 [Mikael Karon](mailto:mikael@karon.se). All rights reserved.
|
|
456
|
+
|
|
457
|
+
This work is licensed under the terms of the MIT license.
|
|
458
|
+
For a copy, see <https://opensource.org/licenses/MIT>.
|
|
459
|
+
|
|
460
|
+
## Classes
|
|
461
|
+
|
|
462
|
+
- [BaseRouteMap](classes/BaseRouteMap.md)
|
|
463
|
+
- [RouterBridgeBase](classes/RouterBridgeBase.md)
|
|
464
|
+
|
|
465
|
+
## Interfaces
|
|
466
|
+
|
|
467
|
+
- [BaseRouteMapping](interfaces/BaseRouteMapping.md)
|
|
468
|
+
- [BrowserHistory](interfaces/BrowserHistory.md)
|
|
469
|
+
- [BrowserWindow](interfaces/BrowserWindow.md)
|
|
470
|
+
- [ConnectRouterOptions](interfaces/ConnectRouterOptions.md)
|
|
471
|
+
- [PlayRouteEvent](interfaces/PlayRouteEvent.md)
|
|
472
|
+
- [RouteInfo](interfaces/RouteInfo.md)
|
|
473
|
+
- [RouteMap](interfaces/RouteMap.md)
|
|
474
|
+
- [RouteNode](interfaces/RouteNode.md)
|
|
475
|
+
- [RouteObject](interfaces/RouteObject.md)
|
|
476
|
+
- [RouterBridge](interfaces/RouterBridge.md)
|
|
477
|
+
- [RouteTree](interfaces/RouteTree.md)
|
|
478
|
+
- [StateVisit](interfaces/StateVisit.md)
|
|
479
|
+
- [VanillaRouter](interfaces/VanillaRouter.md)
|
|
480
|
+
|
|
481
|
+
## Type Aliases
|
|
482
|
+
|
|
483
|
+
- [RouteMetadata](type-aliases/RouteMetadata.md)
|
|
484
|
+
|
|
485
|
+
## Functions
|
|
486
|
+
|
|
487
|
+
- [buildRouteTree](functions/buildRouteTree.md)
|
|
488
|
+
- [connectRouter](functions/connectRouter.md)
|
|
489
|
+
- [crawlMachine](functions/crawlMachine.md)
|
|
490
|
+
- [createBrowserHistory](functions/createBrowserHistory.md)
|
|
491
|
+
- [createRouteMap](functions/createRouteMap.md)
|
|
492
|
+
- [createRouter](functions/createRouter.md)
|
|
493
|
+
- [detectDuplicateRoutes](functions/detectDuplicateRoutes.md)
|
|
494
|
+
- [extractMachineRoutes](functions/extractMachineRoutes.md)
|
|
495
|
+
- [extractRoute](functions/extractRoute.md)
|
|
496
|
+
- [findRouteById](functions/findRouteById.md)
|
|
497
|
+
- [findRouteByPath](functions/findRouteByPath.md)
|
|
498
|
+
- [getNavigableRoutes](functions/getNavigableRoutes.md)
|
|
499
|
+
- [getRoutableRoutes](functions/getRoutableRoutes.md)
|
|
500
|
+
- [routeExists](functions/routeExists.md)
|
|
501
|
+
- [validateRouteFormat](functions/validateRouteFormat.md)
|
|
502
|
+
- [validateStateExists](functions/validateStateExists.md)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
[Documentation](../../../README.md) / [@xmachines/play-router](../README.md) / BaseRouteMap
|
|
2
|
+
|
|
3
|
+
# Class: BaseRouteMap
|
|
4
|
+
|
|
5
|
+
Defined in: [base-route-map.ts:70](https://gitlab.com/xmachin-es/xmachines-js/-/blob/00a28432ed57807112288436d1ae4387d9f06919/packages/play-router/src/base-route-map.ts#L70)
|
|
6
|
+
|
|
7
|
+
Shared bidirectional route map base class.
|
|
8
|
+
|
|
9
|
+
All framework adapter `RouteMap` classes extend this — they add no logic of their
|
|
10
|
+
own and inherit the full public API from here.
|
|
11
|
+
|
|
12
|
+
**Lookup strategy:**
|
|
13
|
+
|
|
14
|
+
- Static paths (no `:param`) → O(1) `Map` lookup
|
|
15
|
+
- Dynamic paths → O(k) bucket-indexed scan using `RegExp`, where `k` is the number
|
|
16
|
+
of routes sharing the same first path segment
|
|
17
|
+
- Results are cached after the first match
|
|
18
|
+
|
|
19
|
+
**Pattern syntax** (`:param` / `:param?`):
|
|
20
|
+
|
|
21
|
+
- `:param` — required segment, matches exactly one non-`/` segment
|
|
22
|
+
- `:param?` — optional segment, matches zero or one non-`/` segment
|
|
23
|
+
|
|
24
|
+
## Example
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { BaseRouteMap } from "@xmachines/play-router";
|
|
28
|
+
|
|
29
|
+
const map = new BaseRouteMap([
|
|
30
|
+
{ stateId: "home", path: "/" },
|
|
31
|
+
{ stateId: "profile", path: "/profile/:userId" },
|
|
32
|
+
{ stateId: "settings", path: "/settings/:section?" },
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
map.getStateIdByPath("/"); // "home"
|
|
36
|
+
map.getStateIdByPath("/profile/123"); // "profile"
|
|
37
|
+
map.getStateIdByPath("/settings"); // "settings"
|
|
38
|
+
map.getStateIdByPath("/unknown"); // null
|
|
39
|
+
|
|
40
|
+
map.getPathByStateId("profile"); // "/profile/:userId"
|
|
41
|
+
map.getPathByStateId("missing"); // null
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Extended by
|
|
45
|
+
|
|
46
|
+
- [`RouteMap`](../../play-react-router/classes/RouteMap.md)
|
|
47
|
+
- [`RouteMap`](../../play-solid-router/classes/RouteMap.md)
|
|
48
|
+
- [`RouteMap`](../../play-tanstack-react-router/classes/RouteMap.md)
|
|
49
|
+
- [`RouteMap`](../../play-tanstack-solid-router/classes/RouteMap.md)
|
|
50
|
+
- [`VueBaseRouteMap`](../../play-vue-router/classes/VueBaseRouteMap.md)
|
|
51
|
+
|
|
52
|
+
## Constructors
|
|
53
|
+
|
|
54
|
+
### Constructor
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
new BaseRouteMap(mappings): BaseRouteMap;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Defined in: [base-route-map.ts:86](https://gitlab.com/xmachin-es/xmachines-js/-/blob/00a28432ed57807112288436d1ae4387d9f06919/packages/play-router/src/base-route-map.ts#L86)
|
|
61
|
+
|
|
62
|
+
Build a route map from an array of state ID ↔ path mappings.
|
|
63
|
+
|
|
64
|
+
Static paths (no `:param`) are indexed in an O(1) `Map`.
|
|
65
|
+
Parameterized paths are compiled to `RegExp` and grouped into first-segment
|
|
66
|
+
buckets for efficient candidate selection.
|
|
67
|
+
|
|
68
|
+
#### Parameters
|
|
69
|
+
|
|
70
|
+
| Parameter | Type | Description |
|
|
71
|
+
| ---------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| `mappings` | [`BaseRouteMapping`](../interfaces/BaseRouteMapping.md)[] | Array of `{ stateId, path }` entries. Order determines priority when multiple patterns could match the same path. |
|
|
73
|
+
|
|
74
|
+
#### Returns
|
|
75
|
+
|
|
76
|
+
`BaseRouteMap`
|
|
77
|
+
|
|
78
|
+
## Methods
|
|
79
|
+
|
|
80
|
+
### getPathByStateId()
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
getPathByStateId(stateId): string | null;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Defined in: [base-route-map.ts:164](https://gitlab.com/xmachin-es/xmachines-js/-/blob/00a28432ed57807112288436d1ae4387d9f06919/packages/play-router/src/base-route-map.ts#L164)
|
|
87
|
+
|
|
88
|
+
Look up the path pattern registered for a state ID.
|
|
89
|
+
|
|
90
|
+
#### Parameters
|
|
91
|
+
|
|
92
|
+
| Parameter | Type | Description |
|
|
93
|
+
| --------- | -------- | --------------------------------------------------------- |
|
|
94
|
+
| `stateId` | `string` | State machine state ID (e.g., `"profile"`, `"#settings"`) |
|
|
95
|
+
|
|
96
|
+
#### Returns
|
|
97
|
+
|
|
98
|
+
`string` \| `null`
|
|
99
|
+
|
|
100
|
+
The registered path pattern, or `null` if the state ID is unknown
|
|
101
|
+
|
|
102
|
+
#### Example
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
map.getPathByStateId("profile"); // "/profile/:userId"
|
|
106
|
+
map.getPathByStateId("missing"); // null
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### getStateIdByPath()
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
getStateIdByPath(path): string | null;
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Defined in: [base-route-map.ts:130](https://gitlab.com/xmachin-es/xmachines-js/-/blob/00a28432ed57807112288436d1ae4387d9f06919/packages/play-router/src/base-route-map.ts#L130)
|
|
118
|
+
|
|
119
|
+
Resolve a URL path to its mapped state ID.
|
|
120
|
+
|
|
121
|
+
Strips query strings and hash fragments before matching. Tries an O(1) exact
|
|
122
|
+
lookup first, then falls back to bucket-indexed pattern matching. Results are
|
|
123
|
+
cached after the first pattern match.
|
|
124
|
+
|
|
125
|
+
#### Parameters
|
|
126
|
+
|
|
127
|
+
| Parameter | Type | Description |
|
|
128
|
+
| --------- | -------- | ------------------------------------------------------------------------------ |
|
|
129
|
+
| `path` | `string` | URL pathname, optionally including query/hash (e.g., `"/profile/123?ref=nav"`) |
|
|
130
|
+
|
|
131
|
+
#### Returns
|
|
132
|
+
|
|
133
|
+
`string` \| `null`
|
|
134
|
+
|
|
135
|
+
The mapped state ID, or `null` if no route matches
|
|
136
|
+
|
|
137
|
+
#### Example
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
map.getStateIdByPath("/profile/123"); // "profile"
|
|
141
|
+
map.getStateIdByPath("/unknown"); // null
|
|
142
|
+
```
|