@xmachines/play-router 1.0.0-beta.8 → 1.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/LICENSE +21 -0
- package/README.md +259 -335
- package/dist/base-route-map.d.ts +136 -0
- package/dist/base-route-map.d.ts.map +1 -0
- package/dist/base-route-map.js +182 -0
- package/dist/base-route-map.js.map +1 -0
- package/dist/build-tree.d.ts +7 -0
- package/dist/build-tree.d.ts.map +1 -1
- package/dist/build-tree.js +21 -6
- package/dist/build-tree.js.map +1 -1
- package/dist/create-route-map-from-tree.d.ts +33 -0
- package/dist/create-route-map-from-tree.d.ts.map +1 -0
- package/dist/create-route-map-from-tree.js +43 -0
- package/dist/create-route-map-from-tree.js.map +1 -0
- package/dist/create-route-map.d.ts +29 -33
- package/dist/create-route-map.d.ts.map +1 -1
- package/dist/create-route-map.js +25 -64
- package/dist/create-route-map.js.map +1 -1
- package/dist/errors.d.ts +152 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +186 -0
- package/dist/errors.js.map +1 -0
- package/dist/extract-routes.d.ts +5 -31
- package/dist/extract-routes.d.ts.map +1 -1
- package/dist/extract-routes.js +73 -51
- package/dist/extract-routes.js.map +1 -1
- package/dist/find-route.d.ts +44 -0
- package/dist/find-route.d.ts.map +1 -0
- package/dist/find-route.js +103 -0
- package/dist/find-route.js.map +1 -0
- package/dist/index.d.ts +13 -51
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -133
- package/dist/index.js.map +1 -1
- package/dist/machine-to-graph.d.ts +17 -0
- package/dist/machine-to-graph.d.ts.map +1 -0
- package/dist/machine-to-graph.js +115 -0
- package/dist/machine-to-graph.js.map +1 -0
- package/dist/query.d.ts +49 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +98 -3
- package/dist/query.js.map +1 -1
- package/dist/router-bridge-base.d.ts +196 -32
- package/dist/router-bridge-base.d.ts.map +1 -1
- package/dist/router-bridge-base.js +319 -85
- package/dist/router-bridge-base.js.map +1 -1
- package/dist/router-sync.d.ts +95 -0
- package/dist/router-sync.d.ts.map +1 -0
- package/dist/router-sync.js +161 -0
- package/dist/router-sync.js.map +1 -0
- package/dist/types.d.ts +163 -22
- package/dist/types.d.ts.map +1 -1
- package/dist/url-pattern-utils.d.ts +117 -0
- package/dist/url-pattern-utils.d.ts.map +1 -0
- package/dist/url-pattern-utils.js +176 -0
- package/dist/url-pattern-utils.js.map +1 -0
- package/dist/validate-routes.d.ts +32 -14
- package/dist/validate-routes.d.ts.map +1 -1
- package/dist/validate-routes.js +28 -21
- package/dist/validate-routes.js.map +1 -1
- package/package.json +42 -14
- package/dist/connect-router.d.ts +0 -56
- package/dist/connect-router.d.ts.map +0 -1
- package/dist/connect-router.js +0 -119
- package/dist/connect-router.js.map +0 -1
- package/dist/crawl-machine.d.ts +0 -74
- package/dist/crawl-machine.d.ts.map +0 -1
- package/dist/crawl-machine.js +0 -95
- package/dist/crawl-machine.js.map +0 -1
- package/dist/create-browser-history.d.ts +0 -68
- package/dist/create-browser-history.d.ts.map +0 -1
- package/dist/create-browser-history.js +0 -94
- package/dist/create-browser-history.js.map +0 -1
- package/dist/create-router.d.ts +0 -73
- package/dist/create-router.d.ts.map +0 -1
- package/dist/create-router.js +0 -63
- package/dist/create-router.js.map +0 -1
- package/dist/extract-route.d.ts +0 -25
- package/dist/extract-route.d.ts.map +0 -1
- package/dist/extract-route.js +0 -63
- package/dist/extract-route.js.map +0 -1
package/dist/create-route-map.js
CHANGED
|
@@ -1,73 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { extractMachineRoutes } from "./extract-routes.js";
|
|
2
|
+
import { getRoutableRoutes } from "./query.js";
|
|
3
|
+
import { RouteMap } from "./base-route-map.js";
|
|
2
4
|
/**
|
|
3
|
-
* Create a RouteMap from
|
|
5
|
+
* Create a `RouteMap` from an XState state machine.
|
|
4
6
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
* - Returns formatted state IDs (with # prefix)
|
|
10
|
-
* - Extracts params from matched patterns
|
|
7
|
+
* Extracts all routable states (those with `meta.route`) and builds a bidirectional
|
|
8
|
+
* path ↔ stateId lookup structure. The returned map is used by `RouterBridgeBase`
|
|
9
|
+
* subclasses to translate browser URL changes into `play.route` actor events and
|
|
10
|
+
* vice-versa.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* @param machine - XState v5 state machine with `meta.route` annotations on states.
|
|
13
|
+
* @param options - Optional configuration. Pass `{ cacheSize }` to override the
|
|
14
|
+
* default LRU cache size for parameterized path lookups.
|
|
15
|
+
* @returns A `RouteMap` for passing to any `RouterBridgeBase`-based adapter.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
13
18
|
* ```typescript
|
|
14
|
-
*
|
|
15
|
-
*
|
|
19
|
+
* import { createRouteMap } from '@xmachines/play-router';
|
|
20
|
+
* import { connectRouter } from '@xmachines/play-dom-router';
|
|
16
21
|
*
|
|
17
|
-
* const
|
|
18
|
-
*
|
|
19
|
-
* actor.send({ type: 'play.route', to, params });
|
|
20
|
-
* }
|
|
22
|
+
* const routeMap = createRouteMap(myMachine);
|
|
23
|
+
* const disconnect = connectRouter({ actor, router, routeMap });
|
|
21
24
|
* ```
|
|
22
25
|
*/
|
|
23
|
-
export function createRouteMap(
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// URLPattern expects patterns in format: /settings/:section
|
|
31
|
-
const pattern = new URLPattern({ pathname: node.pattern });
|
|
32
|
-
patternRoutes.push({ pattern, node });
|
|
33
|
-
}
|
|
34
|
-
catch (err) {
|
|
35
|
-
console.warn("[RouteMap] Invalid pattern:", node.pattern, err);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
for (const child of node.children) {
|
|
39
|
-
collectPatterns(child);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
collectPatterns(routeTree.root);
|
|
43
|
-
return {
|
|
44
|
-
resolve(path) {
|
|
45
|
-
// Try exact match first (O(1))
|
|
46
|
-
const exactMatch = routeTree.byPath.get(path);
|
|
47
|
-
if (exactMatch?.routable) {
|
|
48
|
-
return {
|
|
49
|
-
to: `#${exactMatch.id}`,
|
|
50
|
-
params: {},
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
// Try pattern matching (O(n))
|
|
54
|
-
for (const { pattern, node } of patternRoutes) {
|
|
55
|
-
const match = pattern.exec({ pathname: path });
|
|
56
|
-
if (match) {
|
|
57
|
-
// Extract pathname params (e.g., { section: "account" })
|
|
58
|
-
const params = {};
|
|
59
|
-
if (match.pathname.groups) {
|
|
60
|
-
Object.assign(params, match.pathname.groups);
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
to: `#${node.id}`,
|
|
64
|
-
params,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
// No match found
|
|
69
|
-
return { to: null, params: {} };
|
|
70
|
-
},
|
|
71
|
-
};
|
|
26
|
+
export function createRouteMap(machine, options) {
|
|
27
|
+
const routeTree = extractMachineRoutes(machine);
|
|
28
|
+
const routes = getRoutableRoutes(routeTree);
|
|
29
|
+
return new RouteMap(routes.map((node) => ({
|
|
30
|
+
stateId: node.stateId,
|
|
31
|
+
path: node.fullPath,
|
|
32
|
+
})), options);
|
|
72
33
|
}
|
|
73
34
|
//# sourceMappingURL=create-route-map.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-route-map.js","sourceRoot":"","sources":["../src/create-route-map.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"create-route-map.js","sourceRoot":"","sources":["../src/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,qBAAqB,CAAC;AAmB/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,cAAc,CAAC,OAAwB,EAAE,OAAyB;IACjF,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAChD,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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { PlayError } from "@xmachines/play";
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when `RouterBridgeBase.syncActorFromRouter()` fails to process a router
|
|
4
|
+
* location change and send the corresponding `play.route` event to the actor.
|
|
5
|
+
*
|
|
6
|
+
* The `cause` property wraps the original error.
|
|
7
|
+
*
|
|
8
|
+
* **Error code:** `PLAY_ROUTER_SYNC_FAILED`
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { RouterSyncError } from "@xmachines/play-router/errors";
|
|
13
|
+
*
|
|
14
|
+
* try {
|
|
15
|
+
* bridge.connect();
|
|
16
|
+
* } catch (err) {
|
|
17
|
+
* if (err instanceof RouterSyncError) {
|
|
18
|
+
* console.error("Router sync failed:", err.message, err.cause);
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare class RouterSyncError extends PlayError {
|
|
24
|
+
constructor(message: string, options?: ErrorOptions);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Thrown by `RouterBridgeBase.connect()` when a second bridge tries to connect
|
|
28
|
+
* to an actor that already has an active bridge connection.
|
|
29
|
+
*
|
|
30
|
+
* One actor may only be connected to one router bridge at a time. Two bridges
|
|
31
|
+
* sharing the same actor would both receive and process every router navigation
|
|
32
|
+
* event, sending duplicate `play.route` events to the actor and producing
|
|
33
|
+
* conflicting echo-suppression state via `lastSyncedPath`.
|
|
34
|
+
*
|
|
35
|
+
* **How to fix:** Call `bridge.disconnect()` on the first bridge before
|
|
36
|
+
* connecting a second one, or ensure only one `connectRouter()` call is active
|
|
37
|
+
* per actor at any given time.
|
|
38
|
+
*
|
|
39
|
+
* **Error code:** `PLAY_ROUTER_DUPLICATE_BRIDGE`
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* import { DuplicateBridgeError } from "@xmachines/play-router/errors";
|
|
44
|
+
*
|
|
45
|
+
* try {
|
|
46
|
+
* bridge.connect();
|
|
47
|
+
* } catch (err) {
|
|
48
|
+
* if (err instanceof DuplicateBridgeError) {
|
|
49
|
+
* console.error("Actor already has an active router bridge — disconnect first.");
|
|
50
|
+
* }
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare class DuplicateBridgeError extends PlayError {
|
|
55
|
+
constructor();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Thrown by the `RouteMap` constructor when a parameterized route is registered but
|
|
59
|
+
* the `URLPattern` API is not available in the current runtime environment and no
|
|
60
|
+
* polyfill has been loaded.
|
|
61
|
+
*
|
|
62
|
+
* **How to fix:** Load `urlpattern-polyfill` at your application entry point, before
|
|
63
|
+
* any import of `@xmachines/play-router`:
|
|
64
|
+
*
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // app entry point — must run first
|
|
67
|
+
* import "urlpattern-polyfill";
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* URLPattern is natively available on Node.js ≥ 24 and modern browsers
|
|
71
|
+
* (Chrome 95+, Firefox 117+, Safari 16.4+). Use the polyfill on older targets.
|
|
72
|
+
*
|
|
73
|
+
* **Error code:** `PLAY_ROUTE_MAP_URLPATTERN_UNAVAILABLE`
|
|
74
|
+
*/
|
|
75
|
+
export declare class URLPatternUnavailableError extends PlayError {
|
|
76
|
+
constructor();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Thrown by `validateRouteFormat()` when a state declares `meta.route` with an
|
|
80
|
+
* empty string path.
|
|
81
|
+
*
|
|
82
|
+
* **Error code:** `PLAY_ROUTE_EMPTY_PATH`
|
|
83
|
+
*/
|
|
84
|
+
export declare class EmptyRoutePathError extends PlayError {
|
|
85
|
+
/** The state ID whose route path is empty. */
|
|
86
|
+
readonly stateId: string;
|
|
87
|
+
constructor(stateId: string);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Thrown by `validateStateExists()` when a route references a state ID that does
|
|
91
|
+
* not exist in the machine graph.
|
|
92
|
+
*
|
|
93
|
+
* **Error code:** `PLAY_ROUTE_INVALID_STATE_ID`
|
|
94
|
+
*/
|
|
95
|
+
export declare class InvalidStateIdError extends PlayError {
|
|
96
|
+
/** The state ID that was referenced but not found. */
|
|
97
|
+
readonly stateId: string;
|
|
98
|
+
constructor(stateId: string);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Thrown by `detectDuplicateRoutes()` when two or more states share the same URL path.
|
|
102
|
+
*
|
|
103
|
+
* **Error code:** `PLAY_ROUTE_DUPLICATE_PATH`
|
|
104
|
+
*/
|
|
105
|
+
export declare class DuplicateRoutePathError extends PlayError {
|
|
106
|
+
/** Human-readable list of conflicting path → state-ID mappings. */
|
|
107
|
+
readonly duplicates: string[];
|
|
108
|
+
constructor(duplicates: string[]);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Thrown by `machineToGraph()` when an XState state node has an unrecognised
|
|
112
|
+
* `.type` value.
|
|
113
|
+
*
|
|
114
|
+
* **Error code:** `PLAY_ROUTE_UNKNOWN_STATE_TYPE`
|
|
115
|
+
*/
|
|
116
|
+
export declare class UnknownStateTypeError extends PlayError {
|
|
117
|
+
/** The unrecognised state type string. */
|
|
118
|
+
readonly stateType: string;
|
|
119
|
+
/** The ID of the state node with the unknown type. */
|
|
120
|
+
readonly nodeId: string;
|
|
121
|
+
constructor(stateType: string, nodeId: string, validTypes: string[]);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Thrown by the `RouteMap` constructor when a route pattern string cannot be compiled
|
|
125
|
+
* by `URLPattern`. The `pattern` field contains the rejected string; `cause` wraps the
|
|
126
|
+
* original `URLPattern` constructor error.
|
|
127
|
+
*
|
|
128
|
+
* Common causes:
|
|
129
|
+
* - Unmatched parentheses or brackets in the pattern string
|
|
130
|
+
* - Characters that are invalid in a URL pathname pattern
|
|
131
|
+
*
|
|
132
|
+
* **Error code:** `PLAY_ROUTE_MAP_INVALID_PATTERN`
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* import { InvalidRoutePatternError } from "@xmachines/play-router/errors";
|
|
137
|
+
*
|
|
138
|
+
* try {
|
|
139
|
+
* const routeMap = createRouteMap(machine);
|
|
140
|
+
* } catch (err) {
|
|
141
|
+
* if (err instanceof InvalidRoutePatternError) {
|
|
142
|
+
* console.error(`Bad route pattern: "${err.pattern}"`, err.cause);
|
|
143
|
+
* }
|
|
144
|
+
* }
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export declare class InvalidRoutePatternError extends PlayError {
|
|
148
|
+
/** The route pattern string that could not be compiled by URLPattern. */
|
|
149
|
+
readonly pattern: string;
|
|
150
|
+
constructor(pattern: string, options?: ErrorOptions);
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAgB,SAAQ,SAAS;gBACjC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAInD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;;CAUlD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,0BAA2B,SAAQ,SAAS;;CASxD;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAS3B;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IACjD,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAS3B;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;IACrD,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBAElB,UAAU,EAAE,MAAM,EAAE;CAWhC;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;IACnD,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE;CAWnE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,wBAAyB,SAAQ,SAAS;IACtD,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAUnD"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { PlayError } from "@xmachines/play";
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when `RouterBridgeBase.syncActorFromRouter()` fails to process a router
|
|
4
|
+
* location change and send the corresponding `play.route` event to the actor.
|
|
5
|
+
*
|
|
6
|
+
* The `cause` property wraps the original error.
|
|
7
|
+
*
|
|
8
|
+
* **Error code:** `PLAY_ROUTER_SYNC_FAILED`
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { RouterSyncError } from "@xmachines/play-router/errors";
|
|
13
|
+
*
|
|
14
|
+
* try {
|
|
15
|
+
* bridge.connect();
|
|
16
|
+
* } catch (err) {
|
|
17
|
+
* if (err instanceof RouterSyncError) {
|
|
18
|
+
* console.error("Router sync failed:", err.message, err.cause);
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export class RouterSyncError extends PlayError {
|
|
24
|
+
constructor(message, options) {
|
|
25
|
+
super("RouterBridgeBase", "PLAY_ROUTER_SYNC_FAILED", message, options);
|
|
26
|
+
this.name = "RouterSyncError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Thrown by `RouterBridgeBase.connect()` when a second bridge tries to connect
|
|
31
|
+
* to an actor that already has an active bridge connection.
|
|
32
|
+
*
|
|
33
|
+
* One actor may only be connected to one router bridge at a time. Two bridges
|
|
34
|
+
* sharing the same actor would both receive and process every router navigation
|
|
35
|
+
* event, sending duplicate `play.route` events to the actor and producing
|
|
36
|
+
* conflicting echo-suppression state via `lastSyncedPath`.
|
|
37
|
+
*
|
|
38
|
+
* **How to fix:** Call `bridge.disconnect()` on the first bridge before
|
|
39
|
+
* connecting a second one, or ensure only one `connectRouter()` call is active
|
|
40
|
+
* per actor at any given time.
|
|
41
|
+
*
|
|
42
|
+
* **Error code:** `PLAY_ROUTER_DUPLICATE_BRIDGE`
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* import { DuplicateBridgeError } from "@xmachines/play-router/errors";
|
|
47
|
+
*
|
|
48
|
+
* try {
|
|
49
|
+
* bridge.connect();
|
|
50
|
+
* } catch (err) {
|
|
51
|
+
* if (err instanceof DuplicateBridgeError) {
|
|
52
|
+
* console.error("Actor already has an active router bridge — disconnect first.");
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export class DuplicateBridgeError extends PlayError {
|
|
58
|
+
constructor() {
|
|
59
|
+
super("RouterBridgeBase", "PLAY_ROUTER_DUPLICATE_BRIDGE", "An actor can only be connected to one router bridge at a time. " +
|
|
60
|
+
"Call disconnect() on the existing bridge before connecting a new one.");
|
|
61
|
+
this.name = "DuplicateBridgeError";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Thrown by the `RouteMap` constructor when a parameterized route is registered but
|
|
66
|
+
* the `URLPattern` API is not available in the current runtime environment and no
|
|
67
|
+
* polyfill has been loaded.
|
|
68
|
+
*
|
|
69
|
+
* **How to fix:** Load `urlpattern-polyfill` at your application entry point, before
|
|
70
|
+
* any import of `@xmachines/play-router`:
|
|
71
|
+
*
|
|
72
|
+
* ```typescript
|
|
73
|
+
* // app entry point — must run first
|
|
74
|
+
* import "urlpattern-polyfill";
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* URLPattern is natively available on Node.js ≥ 24 and modern browsers
|
|
78
|
+
* (Chrome 95+, Firefox 117+, Safari 16.4+). Use the polyfill on older targets.
|
|
79
|
+
*
|
|
80
|
+
* **Error code:** `PLAY_ROUTE_MAP_URLPATTERN_UNAVAILABLE`
|
|
81
|
+
*/
|
|
82
|
+
export class URLPatternUnavailableError extends PlayError {
|
|
83
|
+
constructor() {
|
|
84
|
+
super("RouteMap", "PLAY_ROUTE_MAP_URLPATTERN_UNAVAILABLE", "URLPattern is not available. Load a polyfill (e.g. urlpattern-polyfill) before using @xmachines/play-router on Node < 24 or older browsers.");
|
|
85
|
+
this.name = "URLPatternUnavailableError";
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Thrown by `validateRouteFormat()` when a state declares `meta.route` with an
|
|
90
|
+
* empty string path.
|
|
91
|
+
*
|
|
92
|
+
* **Error code:** `PLAY_ROUTE_EMPTY_PATH`
|
|
93
|
+
*/
|
|
94
|
+
export class EmptyRoutePathError extends PlayError {
|
|
95
|
+
/** The state ID whose route path is empty. */
|
|
96
|
+
stateId;
|
|
97
|
+
constructor(stateId) {
|
|
98
|
+
super("RouteMap", "PLAY_ROUTE_EMPTY_PATH", `Empty route path in state "${stateId}": routes must have a non-empty path`);
|
|
99
|
+
this.name = "EmptyRoutePathError";
|
|
100
|
+
this.stateId = stateId;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Thrown by `validateStateExists()` when a route references a state ID that does
|
|
105
|
+
* not exist in the machine graph.
|
|
106
|
+
*
|
|
107
|
+
* **Error code:** `PLAY_ROUTE_INVALID_STATE_ID`
|
|
108
|
+
*/
|
|
109
|
+
export class InvalidStateIdError extends PlayError {
|
|
110
|
+
/** The state ID that was referenced but not found. */
|
|
111
|
+
stateId;
|
|
112
|
+
constructor(stateId) {
|
|
113
|
+
super("RouteMap", "PLAY_ROUTE_INVALID_STATE_ID", `Route references non-existent state ID: ${stateId}`);
|
|
114
|
+
this.name = "InvalidStateIdError";
|
|
115
|
+
this.stateId = stateId;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Thrown by `detectDuplicateRoutes()` when two or more states share the same URL path.
|
|
120
|
+
*
|
|
121
|
+
* **Error code:** `PLAY_ROUTE_DUPLICATE_PATH`
|
|
122
|
+
*/
|
|
123
|
+
export class DuplicateRoutePathError extends PlayError {
|
|
124
|
+
/** Human-readable list of conflicting path → state-ID mappings. */
|
|
125
|
+
duplicates;
|
|
126
|
+
constructor(duplicates) {
|
|
127
|
+
super("RouteMap", "PLAY_ROUTE_DUPLICATE_PATH", `Duplicate route paths detected:\n${duplicates.join("\n")}\n\n` +
|
|
128
|
+
`Each route path must map to exactly one state.\n` +
|
|
129
|
+
`Use different paths (e.g., /dashboard vs /) or conditional rendering within a single state.`);
|
|
130
|
+
this.name = "DuplicateRoutePathError";
|
|
131
|
+
this.duplicates = duplicates;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Thrown by `machineToGraph()` when an XState state node has an unrecognised
|
|
136
|
+
* `.type` value.
|
|
137
|
+
*
|
|
138
|
+
* **Error code:** `PLAY_ROUTE_UNKNOWN_STATE_TYPE`
|
|
139
|
+
*/
|
|
140
|
+
export class UnknownStateTypeError extends PlayError {
|
|
141
|
+
/** The unrecognised state type string. */
|
|
142
|
+
stateType;
|
|
143
|
+
/** The ID of the state node with the unknown type. */
|
|
144
|
+
nodeId;
|
|
145
|
+
constructor(stateType, nodeId, validTypes) {
|
|
146
|
+
super("machineToGraph", "PLAY_ROUTE_UNKNOWN_STATE_TYPE", `Unknown XState state type "${stateType}" on node "${nodeId}". ` +
|
|
147
|
+
`Expected one of: ${validTypes.join(", ")}.`);
|
|
148
|
+
this.name = "UnknownStateTypeError";
|
|
149
|
+
this.stateType = stateType;
|
|
150
|
+
this.nodeId = nodeId;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Thrown by the `RouteMap` constructor when a route pattern string cannot be compiled
|
|
155
|
+
* by `URLPattern`. The `pattern` field contains the rejected string; `cause` wraps the
|
|
156
|
+
* original `URLPattern` constructor error.
|
|
157
|
+
*
|
|
158
|
+
* Common causes:
|
|
159
|
+
* - Unmatched parentheses or brackets in the pattern string
|
|
160
|
+
* - Characters that are invalid in a URL pathname pattern
|
|
161
|
+
*
|
|
162
|
+
* **Error code:** `PLAY_ROUTE_MAP_INVALID_PATTERN`
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* import { InvalidRoutePatternError } from "@xmachines/play-router/errors";
|
|
167
|
+
*
|
|
168
|
+
* try {
|
|
169
|
+
* const routeMap = createRouteMap(machine);
|
|
170
|
+
* } catch (err) {
|
|
171
|
+
* if (err instanceof InvalidRoutePatternError) {
|
|
172
|
+
* console.error(`Bad route pattern: "${err.pattern}"`, err.cause);
|
|
173
|
+
* }
|
|
174
|
+
* }
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export class InvalidRoutePatternError extends PlayError {
|
|
178
|
+
/** The route pattern string that could not be compiled by URLPattern. */
|
|
179
|
+
pattern;
|
|
180
|
+
constructor(pattern, options) {
|
|
181
|
+
super("RouteMap", "PLAY_ROUTE_MAP_INVALID_PATTERN", `Invalid route pattern: "${pattern}"`, options);
|
|
182
|
+
this.name = "InvalidRoutePatternError";
|
|
183
|
+
this.pattern = pattern;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/extract-routes.d.ts
CHANGED
|
@@ -3,39 +3,13 @@ import type { RouteTree } from "./types.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Extract complete route tree from state machine graph
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* and
|
|
6
|
+
* Converts the XState machine to a @statelyai/graph Graph via machineToGraph(),
|
|
7
|
+
* then walks graph nodes to extract route metadata, validate route references,
|
|
8
|
+
* and build a hierarchical RouteTree. The graph is attached to the returned
|
|
9
|
+
* RouteTree for downstream transition-aware queries.
|
|
9
10
|
*
|
|
10
11
|
* @param machine - XState v5 state machine
|
|
11
|
-
* @returns Route tree with root, byStateId map,
|
|
12
|
-
* @throws {Error} If route references non-existent state
|
|
13
|
-
* @throws {Error} If route path is malformed (doesn't start with /)
|
|
14
|
-
* @throws {Error} If parallel states define conflicting routes
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* import { createMachine } from 'xstate';
|
|
19
|
-
* import { extractMachineRoutes } from '@xmachines/play-router';
|
|
20
|
-
*
|
|
21
|
-
* const machine = createMachine({
|
|
22
|
-
* initial: 'home',
|
|
23
|
-
* states: {
|
|
24
|
-
* home: { id: 'home', meta: { route: '/' } },
|
|
25
|
-
* dashboard: {
|
|
26
|
-
* id: 'dashboard',
|
|
27
|
-
* meta: { route: '/dashboard' },
|
|
28
|
-
* initial: 'overview',
|
|
29
|
-
* states: {
|
|
30
|
-
* overview: { id: 'overview', meta: { route: '/overview' } }
|
|
31
|
-
* }
|
|
32
|
-
* }
|
|
33
|
-
* }
|
|
34
|
-
* });
|
|
35
|
-
*
|
|
36
|
-
* const tree = extractMachineRoutes(machine);
|
|
37
|
-
* console.log(tree.byPath.get('/dashboard/overview'));
|
|
38
|
-
* ```
|
|
12
|
+
* @returns Route tree with root, byStateId map, byPath map, and graph
|
|
39
13
|
*/
|
|
40
14
|
export declare const extractMachineRoutes: (machine: AnyStateMachine) => RouteTree;
|
|
41
15
|
//# sourceMappingURL=extract-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-routes.d.ts","sourceRoot":"","sources":["../src/extract-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"extract-routes.d.ts","sourceRoot":"","sources":["../src/extract-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,KAAK,EAAE,SAAS,EAA6C,MAAM,YAAY,CAAC;AA2EvF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,eAAe,KAAG,SAmB/D,CAAC"}
|
package/dist/extract-routes.js
CHANGED
|
@@ -1,61 +1,83 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { detectDuplicateRoutes } from "./validate-routes.js";
|
|
1
|
+
import { machineToGraph } from "./machine-to-graph.js";
|
|
2
|
+
import { validateRouteFormat, validateStateExists } from "./validate-routes.js";
|
|
4
3
|
import { buildRouteTree } from "./build-tree.js";
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Crawls machine starting from root, visits all state nodes (including nested
|
|
9
|
-
* and parallel), extracts meta.route metadata, validates route references,
|
|
10
|
-
* and builds hierarchical tree.
|
|
5
|
+
* Build statePath for a graph node by walking the parentId chain.
|
|
11
6
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* @throws {Error} If route references non-existent state
|
|
15
|
-
* @throws {Error} If route path is malformed (doesn't start with /)
|
|
16
|
-
* @throws {Error} If parallel states define conflicting routes
|
|
7
|
+
* Produces an array of stateId segments from root to this node (excluding root),
|
|
8
|
+
* matching the format expected by buildRouteTree's parent lookup.
|
|
17
9
|
*
|
|
18
|
-
* @
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
|
|
10
|
+
* @param graphNode - The node to build a path for
|
|
11
|
+
* @param graphNodeMap - Map from node id to GraphNode for O(1) parent lookup
|
|
12
|
+
* @returns Array of stateId segments (e.g. ["dashboard", "overview"])
|
|
13
|
+
*/
|
|
14
|
+
const buildStatePath = (graphNode, graphNodeMap) => {
|
|
15
|
+
const path = [];
|
|
16
|
+
let current = graphNode;
|
|
17
|
+
while (current && current.parentId !== undefined && current.parentId !== null) {
|
|
18
|
+
path.unshift(current.data.stateId);
|
|
19
|
+
current = graphNodeMap.get(current.parentId);
|
|
20
|
+
}
|
|
21
|
+
return path;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Extract route info from a graph node's MachineNodeData.
|
|
25
|
+
* Returns null if the node has no route (not routable).
|
|
26
|
+
*/
|
|
27
|
+
const extractRouteFromNode = (graphNode, stateIds, graphNodeMap) => {
|
|
28
|
+
const { stateId, route, meta } = graphNode.data;
|
|
29
|
+
// Node has no route — not routable
|
|
30
|
+
if (!route)
|
|
31
|
+
return null;
|
|
32
|
+
// Validate format (must start with /)
|
|
33
|
+
validateRouteFormat(route, stateId);
|
|
34
|
+
// Validate state exists in graph (redundant but guards against corruption)
|
|
35
|
+
validateStateExists(stateId, stateIds);
|
|
36
|
+
// Build statePath from parentId chain (works for both explicit IDs and auto-generated)
|
|
37
|
+
const statePath = buildStatePath(graphNode, graphNodeMap);
|
|
38
|
+
const pattern = route.includes(":") ? route : undefined;
|
|
39
|
+
// Reconstruct original metadata shape from graph data
|
|
40
|
+
const metadata = meta && typeof meta === "object" && "route" in meta
|
|
41
|
+
? meta["route"]
|
|
42
|
+
: route;
|
|
43
|
+
const result = {
|
|
44
|
+
stateId,
|
|
45
|
+
statePath,
|
|
46
|
+
routePath: route,
|
|
47
|
+
isAbsolute: route.startsWith("/"),
|
|
48
|
+
routable: true,
|
|
49
|
+
metadata,
|
|
50
|
+
};
|
|
51
|
+
if (pattern)
|
|
52
|
+
result.pattern = pattern;
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Extract complete route tree from state machine graph
|
|
22
57
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* dashboard: {
|
|
28
|
-
* id: 'dashboard',
|
|
29
|
-
* meta: { route: '/dashboard' },
|
|
30
|
-
* initial: 'overview',
|
|
31
|
-
* states: {
|
|
32
|
-
* overview: { id: 'overview', meta: { route: '/overview' } }
|
|
33
|
-
* }
|
|
34
|
-
* }
|
|
35
|
-
* }
|
|
36
|
-
* });
|
|
58
|
+
* Converts the XState machine to a @statelyai/graph Graph via machineToGraph(),
|
|
59
|
+
* then walks graph nodes to extract route metadata, validate route references,
|
|
60
|
+
* and build a hierarchical RouteTree. The graph is attached to the returned
|
|
61
|
+
* RouteTree for downstream transition-aware queries.
|
|
37
62
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* ```
|
|
63
|
+
* @param machine - XState v5 state machine
|
|
64
|
+
* @returns Route tree with root, byStateId map, byPath map, and graph
|
|
41
65
|
*/
|
|
42
66
|
export const extractMachineRoutes = (machine) => {
|
|
43
|
-
// 1.
|
|
44
|
-
const
|
|
45
|
-
// 2. Build state map for
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// 5. Build hierarchical tree
|
|
59
|
-
return buildRouteTree(routes);
|
|
67
|
+
// 1. Convert machine to graph
|
|
68
|
+
const graph = machineToGraph(machine);
|
|
69
|
+
// 2. Build state ID set for validation and node map for O(1) parent lookup
|
|
70
|
+
const stateIds = new Set(graph.nodes.map((n) => n.data.stateId));
|
|
71
|
+
const graphNodeMap = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
72
|
+
// 3. Extract routes from graph nodes
|
|
73
|
+
const routes = graph.nodes
|
|
74
|
+
.map((node) => extractRouteFromNode(node, stateIds, graphNodeMap))
|
|
75
|
+
.filter((r) => r !== null);
|
|
76
|
+
// 4. Build hierarchical tree and attach graph.
|
|
77
|
+
// Duplicate-route detection happens inside buildRouteTree, AFTER relative
|
|
78
|
+
// routes are resolved to full paths — raw route strings are not comparable
|
|
79
|
+
// (two relative "settings" routes under different parents are distinct).
|
|
80
|
+
const tree = buildRouteTree(routes);
|
|
81
|
+
return { ...tree, graph };
|
|
60
82
|
};
|
|
61
83
|
//# sourceMappingURL=extract-routes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-routes.js","sourceRoot":"","sources":["../src/extract-routes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extract-routes.js","sourceRoot":"","sources":["../src/extract-routes.ts"],"names":[],"mappings":"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"}
|