@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.
- package/README.md +111 -116
- package/dist/base-route-map.d.ts +24 -13
- package/dist/base-route-map.d.ts.map +1 -1
- package/dist/base-route-map.js +116 -27
- package/dist/base-route-map.js.map +1 -1
- package/dist/build-tree.d.ts +16 -1
- package/dist/build-tree.d.ts.map +1 -1
- package/dist/build-tree.js +22 -4
- package/dist/build-tree.js.map +1 -1
- package/dist/create-route-map-from-tree.d.ts +13 -7
- package/dist/create-route-map-from-tree.d.ts.map +1 -1
- package/dist/create-route-map-from-tree.js +14 -6
- package/dist/create-route-map-from-tree.js.map +1 -1
- package/dist/errors.d.ts +2 -134
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +11 -151
- package/dist/errors.js.map +1 -1
- package/dist/find-route.d.ts +13 -1
- package/dist/find-route.d.ts.map +1 -1
- package/dist/find-route.js +33 -26
- package/dist/find-route.js.map +1 -1
- package/dist/index.d.ts +8 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -12
- package/dist/index.js.map +1 -1
- package/dist/provider-lifecycle.d.ts +18 -6
- package/dist/provider-lifecycle.d.ts.map +1 -1
- package/dist/provider-lifecycle.js +10 -5
- package/dist/provider-lifecycle.js.map +1 -1
- package/dist/router-bridge-base.d.ts +73 -38
- package/dist/router-bridge-base.d.ts.map +1 -1
- package/dist/router-bridge-base.js +304 -124
- package/dist/router-bridge-base.js.map +1 -1
- package/dist/router-sync.d.ts +3 -27
- package/dist/router-sync.d.ts.map +1 -1
- package/dist/router-sync.js +27 -45
- package/dist/router-sync.js.map +1 -1
- package/dist/types.d.ts +206 -102
- package/dist/types.d.ts.map +1 -1
- package/dist/xstate/create-route-map.d.ts +30 -0
- package/dist/xstate/create-route-map.d.ts.map +1 -0
- package/dist/{create-route-map.js → xstate/create-route-map.js} +11 -6
- package/dist/xstate/create-route-map.js.map +1 -0
- package/dist/{extract-routes.d.ts → xstate/extract-routes.d.ts} +4 -2
- package/dist/xstate/extract-routes.d.ts.map +1 -0
- package/dist/{extract-routes.js → xstate/extract-routes.js} +11 -6
- package/dist/xstate/extract-routes.js.map +1 -0
- package/dist/xstate/index.d.ts +35 -0
- package/dist/xstate/index.d.ts.map +1 -0
- package/dist/xstate/index.js +33 -0
- package/dist/xstate/index.js.map +1 -0
- package/dist/{machine-to-graph.d.ts → xstate/machine-to-graph.d.ts} +1 -1
- package/dist/xstate/machine-to-graph.d.ts.map +1 -0
- package/dist/{machine-to-graph.js → xstate/machine-to-graph.js} +2 -2
- package/dist/xstate/machine-to-graph.js.map +1 -0
- package/dist/xstate/machine-types.d.ts +42 -0
- package/dist/xstate/machine-types.d.ts.map +1 -0
- package/dist/xstate/machine-types.js +2 -0
- package/dist/xstate/machine-types.js.map +1 -0
- package/dist/{query.d.ts → xstate/query.d.ts} +6 -4
- package/dist/xstate/query.d.ts.map +1 -0
- package/dist/{query.js → xstate/query.js} +3 -2
- package/dist/xstate/query.js.map +1 -0
- package/package.json +30 -21
- package/dist/base-path.d.ts +0 -209
- package/dist/base-path.d.ts.map +0 -1
- package/dist/base-path.js +0 -418
- package/dist/base-path.js.map +0 -1
- package/dist/create-route-map.d.ts +0 -44
- package/dist/create-route-map.d.ts.map +0 -1
- package/dist/create-route-map.js.map +0 -1
- package/dist/extract-routes.d.ts.map +0 -1
- package/dist/extract-routes.js.map +0 -1
- package/dist/framework-params.d.ts +0 -144
- package/dist/framework-params.d.ts.map +0 -1
- package/dist/framework-params.js +0 -291
- package/dist/framework-params.js.map +0 -1
- package/dist/machine-to-graph.d.ts.map +0 -1
- package/dist/machine-to-graph.js.map +0 -1
- package/dist/query.d.ts.map +0 -1
- package/dist/query.js.map +0 -1
- package/dist/url-pattern-utils.d.ts +0 -93
- package/dist/url-pattern-utils.d.ts.map +0 -1
- package/dist/url-pattern-utils.js +0 -233
- package/dist/url-pattern-utils.js.map +0 -1
package/dist/base-route-map.js
CHANGED
|
@@ -10,9 +10,8 @@
|
|
|
10
10
|
* segment, and that number is much smaller than the number of all the routes. The
|
|
11
11
|
* class matches a parameterized route with URLPattern.
|
|
12
12
|
*/
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import { URLPatternUnavailableError, InvalidRoutePatternError } from "./errors.js";
|
|
13
|
+
import { createPatternCache, getCandidates, getCompiledPattern, getIndexKey, parsePattern, splitLocation, } from "@xmachines/play-url";
|
|
14
|
+
import { InvalidRoutePatternError } from "./errors.js";
|
|
16
15
|
/**
|
|
17
16
|
* The canonical key of a stateId: the bare form, without a `#` at its start.
|
|
18
17
|
*
|
|
@@ -25,6 +24,65 @@ import { URLPatternUnavailableError, InvalidRoutePatternError } from "./errors.j
|
|
|
25
24
|
function canonicalStateIdKey(stateId) {
|
|
26
25
|
return stateId.startsWith("#") ? stateId.slice(1) : stateId;
|
|
27
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The bound of the path cache that a map builds for itself.
|
|
29
|
+
*
|
|
30
|
+
* `createPatternCache` keeps two generations, so the cache holds between this number and
|
|
31
|
+
* twice it. A caller that wants another bound passes a cache: `createPatternCache(5000)`
|
|
32
|
+
* builds one. A separate size option would configure THIS cache alone and say so nowhere,
|
|
33
|
+
* and it would do nothing at all beside a cache that the caller passed.
|
|
34
|
+
*/
|
|
35
|
+
const DEFAULT_PATH_CACHE_SIZE = 500;
|
|
36
|
+
/**
|
|
37
|
+
* The id of one route table: a digest of its mappings, in order.
|
|
38
|
+
*
|
|
39
|
+
* It is the key space that each ROUTE TABLE owns inside a shared path cache. An entry of
|
|
40
|
+
* that cache says which state a path resolves to, and the answer is a pure function of
|
|
41
|
+
* the mappings and the path: two maps built from the SAME mappings resolve every path the
|
|
42
|
+
* same way, and two maps built from different mappings do not. A map with no route for
|
|
43
|
+
* `/settings/x` writes `null`, and a map that DOES hold `/settings/:s` then read that
|
|
44
|
+
* `null` and reported no state for a route of its own.
|
|
45
|
+
*
|
|
46
|
+
* The key therefore names the TABLE, and not the instance. An instance counter kept the
|
|
47
|
+
* two apart as well, and it also gave a server that rebuilds its map for each request a
|
|
48
|
+
* cache that answered nothing: every request opened a key space of its own, and the dead
|
|
49
|
+
* keys of the last one evicted the live entries of this one.
|
|
50
|
+
*
|
|
51
|
+
* Two maps built from the same mappings share the id, which is what a server that
|
|
52
|
+
* rebuilds its map for each request needs, and two maps built from different mappings do
|
|
53
|
+
* not — a map with no route for a path writes `null` for it, and a map that HOLDS one
|
|
54
|
+
* must not read that.
|
|
55
|
+
*
|
|
56
|
+
* A REGISTER of the serialized tables answered this before, and it kept every table
|
|
57
|
+
* string it had seen for the life of the process: a per-tenant table of fifty routes is a
|
|
58
|
+
* few kilobytes, and a bounded register of them still retained megabytes in exactly the
|
|
59
|
+
* per-request case that the cache exists for. A digest retains nothing.
|
|
60
|
+
*
|
|
61
|
+
* ## The collision
|
|
62
|
+
*
|
|
63
|
+
* Two DIFFERENT tables that share a digest share a key space, and the negative entries of
|
|
64
|
+
* one then answer for the other. The digest is 64 bits over the full signature, so a
|
|
65
|
+
* process that built ten thousand distinct route tables carries a chance of about 3 in
|
|
66
|
+
* 10^12 of one collision — far below the chance of the bit flip that would corrupt the
|
|
67
|
+
* cache anyway. This library already identifies by digest: an XMachines id is a Git OID.
|
|
68
|
+
*/
|
|
69
|
+
function routeTableId(mappings) {
|
|
70
|
+
// FNV-1a, in two 32-bit halves, because a bitwise operator of JavaScript truncates to
|
|
71
|
+
// 32 bits and `BigInt` costs an allocation for each character.
|
|
72
|
+
let hashLow = 0x811c9dc5;
|
|
73
|
+
let hashHigh = 0x811c9dc5;
|
|
74
|
+
for (const { stateId, path } of mappings) {
|
|
75
|
+
// The ORDER is significant: it gives the priority when more than one pattern matches,
|
|
76
|
+
// so the separators below keep `[{a, /x}, {b, /y}]` apart from `[{a, /x/b}, {/y}]`.
|
|
77
|
+
const entry = `${stateId}\u0000${path}\u0001`;
|
|
78
|
+
for (let index = 0; index < entry.length; index += 1) {
|
|
79
|
+
const code = entry.charCodeAt(index);
|
|
80
|
+
hashLow = Math.imul(hashLow ^ code, 0x01000193) >>> 0;
|
|
81
|
+
hashHigh = Math.imul(hashHigh ^ (code + index), 0x01000193) >>> 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return `${hashLow.toString(36)}.${hashHigh.toString(36)}`;
|
|
85
|
+
}
|
|
28
86
|
/**
|
|
29
87
|
* The shared base class of the route map for both directions.
|
|
30
88
|
*
|
|
@@ -35,14 +93,21 @@ function canonicalStateIdKey(stateId) {
|
|
|
35
93
|
* - A static path, without a `:param` → a `Map` lookup in O(1)
|
|
36
94
|
* - A dynamic path → a scan of the bucket index in O(k), with `URLPattern`, where
|
|
37
95
|
* `k` is the number of the routes with the same first path segment
|
|
38
|
-
* - The class keeps each result of a first match in an LRU cache. The default
|
|
39
|
-
*
|
|
96
|
+
* - The class keeps each result of a first match in an LRU cache. The default cache
|
|
97
|
+
* holds between 500 and 1000 entries, and the `pathCache` constructor option
|
|
98
|
+
* replaces it
|
|
40
99
|
*
|
|
41
|
-
* **The syntax of a pattern
|
|
100
|
+
* **The syntax of a pattern:** the whole URLPattern pathname grammar. The forms used most
|
|
101
|
+
* often are:
|
|
42
102
|
* - `:param` — a necessary segment. It matches exactly one segment without a `/`
|
|
43
103
|
* - `:param?` — an optional segment. It matches zero segments or one segment without a `/`
|
|
44
104
|
* - `*` — a wildcard. It matches each number of segments, as URLPattern defines
|
|
45
105
|
*
|
|
106
|
+
* A `{…}` group, a `:param(\d+)` constraint, a `+` modifier and a `\:` escape are read
|
|
107
|
+
* too. The [routing guide](../../docs/guides/routing.md) states every form, the prefix
|
|
108
|
+
* rule, and the one divergence from the standard: a param name of this library can hold a
|
|
109
|
+
* hyphen.
|
|
110
|
+
*
|
|
46
111
|
* **The forms of a stateId:** you can register a stateId, and you can look one up,
|
|
47
112
|
* in the form `"#stateId"` or in the form `"stateId"`. `RouteMap` makes the
|
|
48
113
|
* canonical form itself. `getStateIdByPath` returns the stateId exactly as you
|
|
@@ -75,6 +140,16 @@ export class RouteMap {
|
|
|
75
140
|
pathToStateId;
|
|
76
141
|
patternBuckets;
|
|
77
142
|
pathMatchCache;
|
|
143
|
+
/** The key space of this ROUTE TABLE inside {@link pathMatchCache}, which a caller may share. */
|
|
144
|
+
pathCacheKey;
|
|
145
|
+
/**
|
|
146
|
+
* The caches that every parse and every compilation of this map reads.
|
|
147
|
+
*
|
|
148
|
+
* Each default stays SHARED on purpose. A map that built one of its own would keep its
|
|
149
|
+
* patterns out of the cache that `find-route.ts` and `router-sync.ts` read, so the same
|
|
150
|
+
* pattern would parse two times. A caller that wants the isolation passes a cache.
|
|
151
|
+
*/
|
|
152
|
+
compileOptions;
|
|
78
153
|
/**
|
|
79
154
|
* Builds a route map from an array of the mappings between a state ID and a path.
|
|
80
155
|
*
|
|
@@ -85,35 +160,44 @@ export class RouteMap {
|
|
|
85
160
|
*
|
|
86
161
|
* @param mappings - The array of the `{ stateId, path }` entries. The order gives the
|
|
87
162
|
* priority when more than one pattern can match the same path.
|
|
88
|
-
* @param options -
|
|
89
|
-
* `
|
|
90
|
-
* lookups in the cache. The default is `500`. Raise it for an application with
|
|
91
|
-
* many different values in a parameterized URL, for example a page of a user
|
|
92
|
-
* profile with thousands of different IDs. After an eviction, the path goes to the
|
|
93
|
-
* bucket pattern scan in O(k) again, which is correct but slower. The smallest
|
|
94
|
-
* effective value is `1`, because QuickLRU requires it.
|
|
163
|
+
* @param options - See {@link RouteMapOptions}. A map holds TWO caches, so no option is
|
|
164
|
+
* named `cache`: each one names the cache that it carries.
|
|
95
165
|
*/
|
|
96
|
-
constructor(mappings,
|
|
166
|
+
constructor(mappings, options = {}) {
|
|
167
|
+
const { pathCache, ...compileOptions } = options;
|
|
168
|
+
this.compileOptions = compileOptions;
|
|
97
169
|
this.stateIdToPath = new Map();
|
|
98
170
|
this.pathToStateId = new Map();
|
|
99
171
|
this.patternBuckets = new Map();
|
|
100
|
-
this.pathMatchCache =
|
|
172
|
+
this.pathMatchCache =
|
|
173
|
+
pathCache ?? createPatternCache(DEFAULT_PATH_CACHE_SIZE);
|
|
174
|
+
// A map that BUILDS its own cache owns every key in it, and a prefix would only make
|
|
175
|
+
// each key longer. A map that RECEIVES one shares it, so its keys carry the prefix.
|
|
176
|
+
if (pathCache === undefined) {
|
|
177
|
+
this.pathCacheKey = (path) => path;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
const prefix = `${routeTableId(mappings)}\u0002`;
|
|
181
|
+
this.pathCacheKey = (path) => prefix + path;
|
|
182
|
+
}
|
|
101
183
|
let patternOrder = 0;
|
|
102
184
|
for (const { stateId, path } of mappings) {
|
|
103
185
|
// The key is the canonical bare form. Therefore getPathByStateId accepts
|
|
104
186
|
// "#stateId" and also "stateId". The map keeps the registered form for its return
|
|
105
187
|
// values.
|
|
106
188
|
this.stateIdToPath.set(canonicalStateIdKey(stateId), path);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
189
|
+
// ONE parse answers both questions: is the path a pattern, and which bucket does
|
|
190
|
+
// it belong to. The key comes from that parse, and not from a split of the raw
|
|
191
|
+
// string. A pattern such as `/books{/:id}?` keeps the literal first segment
|
|
192
|
+
// `books`, and a split on `/` read the key `books{` and put the route in a bucket
|
|
193
|
+
// that the path `/books/1` reaches never.
|
|
194
|
+
const parsed = parsePattern(path, this.compileOptions);
|
|
195
|
+
if (parsed.parameterized) {
|
|
196
|
+
const bucketKey = parsed.indexKey;
|
|
113
197
|
const bucket = this.patternBuckets.get(bucketKey) ?? [];
|
|
114
198
|
try {
|
|
115
199
|
bucket.push({
|
|
116
|
-
pattern: getCompiledPattern(path,
|
|
200
|
+
pattern: getCompiledPattern(path, this.compileOptions),
|
|
117
201
|
stateId,
|
|
118
202
|
order: patternOrder++,
|
|
119
203
|
});
|
|
@@ -150,23 +234,28 @@ export class RouteMap {
|
|
|
150
234
|
* ```
|
|
151
235
|
*/
|
|
152
236
|
getStateIdByPath(path) {
|
|
153
|
-
// Remove the query string and the hash fragment before the match
|
|
154
|
-
|
|
237
|
+
// Remove the query string and the hash fragment before the match. `splitLocation` is
|
|
238
|
+
// the ONE answer to "where does a pathname end", and `RouterBridgeBase`,
|
|
239
|
+
// `framework-params.ts` and `sanitizePathname` read it too, so the four cannot
|
|
240
|
+
// disagree. Two splits allocated two arrays of every part on the hottest lookup of
|
|
241
|
+
// the library, and this function then read one element of each.
|
|
242
|
+
const cleanPath = splitLocation(path).pathname;
|
|
155
243
|
const exactMatch = this.pathToStateId.get(cleanPath);
|
|
156
244
|
if (exactMatch !== undefined)
|
|
157
245
|
return exactMatch;
|
|
158
|
-
const
|
|
246
|
+
const cacheKey = this.pathCacheKey(cleanPath);
|
|
247
|
+
const cachedMatch = this.pathMatchCache.get(cacheKey);
|
|
159
248
|
if (cachedMatch !== undefined)
|
|
160
249
|
return cachedMatch;
|
|
161
250
|
const candidates = getCandidates(this.patternBuckets, getIndexKey(cleanPath));
|
|
162
251
|
for (const { pattern, stateId } of candidates) {
|
|
163
252
|
const match = pattern.exec({ pathname: cleanPath });
|
|
164
253
|
if (match) {
|
|
165
|
-
this.pathMatchCache.set(
|
|
254
|
+
this.pathMatchCache.set(cacheKey, stateId);
|
|
166
255
|
return stateId;
|
|
167
256
|
}
|
|
168
257
|
}
|
|
169
|
-
this.pathMatchCache.set(
|
|
258
|
+
this.pathMatchCache.set(cacheKey, null);
|
|
170
259
|
return null;
|
|
171
260
|
}
|
|
172
261
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-route-map.js","sourceRoot":"","sources":["../src/base-route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"base-route-map.js","sourceRoot":"","sources":["../src/base-route-map.ts"],"names":[],"mappings":"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"}
|
package/dist/build-tree.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import type { RouteInfo, RouteTree } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The ID and the state ID of the synthetic root node of every `RouteTree`.
|
|
4
|
+
*
|
|
5
|
+
* `buildRouteTree` always makes this node, and no state of a machine declares it. It
|
|
6
|
+
* gives the tree one parent for each absolute route, and it holds `routable: false`.
|
|
7
|
+
*
|
|
8
|
+
* A consumer that walks a tree must SKIP this node. `createRouteMapFromTree` skips it,
|
|
9
|
+
* and `getRoutableRoutes` of `@xmachines/play-router/xstate` skips it. A walk that keeps
|
|
10
|
+
* it maps the path `/` to a state that the machine does not hold.
|
|
11
|
+
*/
|
|
12
|
+
export declare const ROOT_NODE_ID = "__root__";
|
|
2
13
|
/**
|
|
3
14
|
* Builds the hierarchical route tree from the flat list of the routes
|
|
4
15
|
*
|
|
@@ -13,9 +24,13 @@ import type { RouteInfo, RouteTree } from "./types.js";
|
|
|
13
24
|
* strings that resolve to the same complete path are not: those two overwrite each
|
|
14
25
|
* other in `byPath` in silence.
|
|
15
26
|
*
|
|
27
|
+
* `TGraph` names the type of the graph that a CALLER attaches afterwards. The builder
|
|
28
|
+
* attaches none: it reads a list of routes and writes the maps of the tree.
|
|
29
|
+
* `extractMachineRoutes` of `@xmachines/play-router/xstate` binds it to `MachineGraph`.
|
|
30
|
+
*
|
|
16
31
|
* @param routes - The flat list of the RouteInfo objects, from the extraction
|
|
17
32
|
* @returns The RouteTree, with its root, its byStateId map, and its byPath map
|
|
18
33
|
* @throws {DuplicateRoutePathError} When two states resolve to the same complete path
|
|
19
34
|
*/
|
|
20
|
-
export declare const buildRouteTree: (routes: RouteInfo[]) => RouteTree
|
|
35
|
+
export declare const buildRouteTree: <TGraph = unknown>(routes: RouteInfo[]) => RouteTree<TGraph>;
|
|
21
36
|
//# sourceMappingURL=build-tree.d.ts.map
|
package/dist/build-tree.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-tree.d.ts","sourceRoot":"","sources":["../src/build-tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"build-tree.d.ts","sourceRoot":"","sources":["../src/build-tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,SAAS,EAAE,MAAM,YAAY,CAAC;AAGlE;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,GAAG,OAAO,EAAE,QAAQ,SAAS,EAAE,KAAG,SAAS,CAAC,MAAM,CA0EtF,CAAC"}
|
package/dist/build-tree.js
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { detectDuplicateRoutes } from "./validate-routes.js";
|
|
2
|
+
/**
|
|
3
|
+
* The ID and the state ID of the synthetic root node of every `RouteTree`.
|
|
4
|
+
*
|
|
5
|
+
* `buildRouteTree` always makes this node, and no state of a machine declares it. It
|
|
6
|
+
* gives the tree one parent for each absolute route, and it holds `routable: false`.
|
|
7
|
+
*
|
|
8
|
+
* A consumer that walks a tree must SKIP this node. `createRouteMapFromTree` skips it,
|
|
9
|
+
* and `getRoutableRoutes` of `@xmachines/play-router/xstate` skips it. A walk that keeps
|
|
10
|
+
* it maps the path `/` to a state that the machine does not hold.
|
|
11
|
+
*/
|
|
12
|
+
export const ROOT_NODE_ID = "__root__";
|
|
2
13
|
/**
|
|
3
14
|
* Builds the hierarchical route tree from the flat list of the routes
|
|
4
15
|
*
|
|
@@ -13,6 +24,10 @@ import { detectDuplicateRoutes } from "./validate-routes.js";
|
|
|
13
24
|
* strings that resolve to the same complete path are not: those two overwrite each
|
|
14
25
|
* other in `byPath` in silence.
|
|
15
26
|
*
|
|
27
|
+
* `TGraph` names the type of the graph that a CALLER attaches afterwards. The builder
|
|
28
|
+
* attaches none: it reads a list of routes and writes the maps of the tree.
|
|
29
|
+
* `extractMachineRoutes` of `@xmachines/play-router/xstate` binds it to `MachineGraph`.
|
|
30
|
+
*
|
|
16
31
|
* @param routes - The flat list of the RouteInfo objects, from the extraction
|
|
17
32
|
* @returns The RouteTree, with its root, its byStateId map, and its byPath map
|
|
18
33
|
* @throws {DuplicateRoutePathError} When two states resolve to the same complete path
|
|
@@ -20,10 +35,10 @@ import { detectDuplicateRoutes } from "./validate-routes.js";
|
|
|
20
35
|
export const buildRouteTree = (routes) => {
|
|
21
36
|
// 1. Create the root node
|
|
22
37
|
const root = {
|
|
23
|
-
id:
|
|
38
|
+
id: ROOT_NODE_ID,
|
|
24
39
|
path: "/",
|
|
25
40
|
fullPath: "/",
|
|
26
|
-
stateId:
|
|
41
|
+
stateId: ROOT_NODE_ID,
|
|
27
42
|
routable: false, // The root is a state without a route
|
|
28
43
|
children: [],
|
|
29
44
|
parent: null,
|
|
@@ -44,8 +59,11 @@ export const buildRouteTree = (routes) => {
|
|
|
44
59
|
let parentNode = root;
|
|
45
60
|
for (let i = route.statePath.length - 2; i >= 0; i--) {
|
|
46
61
|
const parentStateId = route.statePath[i]; // nosemgrep: gitlab.eslint.detect-object-injection
|
|
47
|
-
if (
|
|
48
|
-
|
|
62
|
+
if (parentStateId === undefined)
|
|
63
|
+
continue;
|
|
64
|
+
const candidate = byStateId.get(parentStateId);
|
|
65
|
+
if (candidate !== undefined) {
|
|
66
|
+
parentNode = candidate;
|
|
49
67
|
break;
|
|
50
68
|
}
|
|
51
69
|
}
|
package/dist/build-tree.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-tree.js","sourceRoot":"","sources":["../src/build-tree.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D
|
|
1
|
+
{"version":3,"file":"build-tree.js","sourceRoot":"","sources":["../src/build-tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { RouteTree } from "./types.js";
|
|
1
|
+
import type { RouteTree, RouteMapOptions } from "./types.js";
|
|
2
2
|
import { RouteMap } from "./base-route-map.js";
|
|
3
|
-
import type { RouteMapOptions } from "./create-route-map.js";
|
|
4
3
|
/**
|
|
5
4
|
* Creates a `RouteMap` from the node structure of a `RouteTree`.
|
|
6
5
|
*
|
|
7
|
-
* A framework router adapter uses this function when it
|
|
8
|
-
* `extractMachineRoutes()`, and not when it calls
|
|
6
|
+
* A framework router adapter uses this function when it holds a `RouteTree`, for example
|
|
7
|
+
* from `extractMachineRoutes()` of `@xmachines/play-router/xstate`, and not when it calls
|
|
8
|
+
* `createRouteMap()` of that package directly.
|
|
9
9
|
*
|
|
10
10
|
* The function walks every node, and it collects the pairs
|
|
11
11
|
* `{ stateId: node.id, path: node.fullPath }`. `node.fullPath` is always the
|
|
@@ -13,18 +13,24 @@ import type { RouteMapOptions } from "./create-route-map.js";
|
|
|
13
13
|
* that path for the match of a browser URL. `createRouteMap(machine)` behaves in the
|
|
14
14
|
* same way, because it also uses `node.fullPath`.
|
|
15
15
|
*
|
|
16
|
+
* The walk SKIPS the synthetic root node. `buildRouteTree` makes that node to hold each
|
|
17
|
+
* absolute route, and no state of a machine declares it. `createRouteMap` skips it as
|
|
18
|
+
* well, through `getRoutableRoutes`, and the two functions therefore answer the same map
|
|
19
|
+
* for the same tree.
|
|
20
|
+
*
|
|
16
21
|
* @param routeTree - A `RouteTree`, as `extractMachineRoutes()` returns it.
|
|
17
|
-
* @param options - The optional configuration, for example `{
|
|
22
|
+
* @param options - The optional configuration, for example `{ pathCache }` to replace the LRU cache of the resolved paths.
|
|
18
23
|
* @returns A `RouteMap` for each adapter on `RouterBridgeBase`.
|
|
19
24
|
*
|
|
20
25
|
* @example
|
|
21
26
|
* ```typescript
|
|
22
27
|
* // The preferred form — one call for an XState machine:
|
|
23
|
-
* import { createRouteMap } from '@xmachines/play-router';
|
|
28
|
+
* import { createRouteMap } from '@xmachines/play-router/xstate';
|
|
24
29
|
* const routeMap = createRouteMap(machine); // it takes an AnyStateMachine
|
|
25
30
|
*
|
|
26
31
|
* // The two-step form, for a framework adapter that works with a route tree:
|
|
27
|
-
* import {
|
|
32
|
+
* import { createRouteMapFromTree } from '@xmachines/play-router';
|
|
33
|
+
* import { extractMachineRoutes } from '@xmachines/play-router/xstate';
|
|
28
34
|
* const routeTree = extractMachineRoutes(machine);
|
|
29
35
|
* const routeMap = createRouteMapFromTree(routeTree); // it uses node.fullPath, which is absolute
|
|
30
36
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-route-map-from-tree.d.ts","sourceRoot":"","sources":["../src/create-route-map-from-tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"create-route-map-from-tree.d.ts","sourceRoot":"","sources":["../src/create-route-map-from-tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,eAAe,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAchG"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { RouteMap } from "./base-route-map.js";
|
|
2
|
+
import { ROOT_NODE_ID } from "./build-tree.js";
|
|
2
3
|
/**
|
|
3
4
|
* Creates a `RouteMap` from the node structure of a `RouteTree`.
|
|
4
5
|
*
|
|
5
|
-
* A framework router adapter uses this function when it
|
|
6
|
-
* `extractMachineRoutes()`, and not when it calls
|
|
6
|
+
* A framework router adapter uses this function when it holds a `RouteTree`, for example
|
|
7
|
+
* from `extractMachineRoutes()` of `@xmachines/play-router/xstate`, and not when it calls
|
|
8
|
+
* `createRouteMap()` of that package directly.
|
|
7
9
|
*
|
|
8
10
|
* The function walks every node, and it collects the pairs
|
|
9
11
|
* `{ stateId: node.id, path: node.fullPath }`. `node.fullPath` is always the
|
|
@@ -11,18 +13,24 @@ import { RouteMap } from "./base-route-map.js";
|
|
|
11
13
|
* that path for the match of a browser URL. `createRouteMap(machine)` behaves in the
|
|
12
14
|
* same way, because it also uses `node.fullPath`.
|
|
13
15
|
*
|
|
16
|
+
* The walk SKIPS the synthetic root node. `buildRouteTree` makes that node to hold each
|
|
17
|
+
* absolute route, and no state of a machine declares it. `createRouteMap` skips it as
|
|
18
|
+
* well, through `getRoutableRoutes`, and the two functions therefore answer the same map
|
|
19
|
+
* for the same tree.
|
|
20
|
+
*
|
|
14
21
|
* @param routeTree - A `RouteTree`, as `extractMachineRoutes()` returns it.
|
|
15
|
-
* @param options - The optional configuration, for example `{
|
|
22
|
+
* @param options - The optional configuration, for example `{ pathCache }` to replace the LRU cache of the resolved paths.
|
|
16
23
|
* @returns A `RouteMap` for each adapter on `RouterBridgeBase`.
|
|
17
24
|
*
|
|
18
25
|
* @example
|
|
19
26
|
* ```typescript
|
|
20
27
|
* // The preferred form — one call for an XState machine:
|
|
21
|
-
* import { createRouteMap } from '@xmachines/play-router';
|
|
28
|
+
* import { createRouteMap } from '@xmachines/play-router/xstate';
|
|
22
29
|
* const routeMap = createRouteMap(machine); // it takes an AnyStateMachine
|
|
23
30
|
*
|
|
24
31
|
* // The two-step form, for a framework adapter that works with a route tree:
|
|
25
|
-
* import {
|
|
32
|
+
* import { createRouteMapFromTree } from '@xmachines/play-router';
|
|
33
|
+
* import { extractMachineRoutes } from '@xmachines/play-router/xstate';
|
|
26
34
|
* const routeTree = extractMachineRoutes(machine);
|
|
27
35
|
* const routeMap = createRouteMapFromTree(routeTree); // it uses node.fullPath, which is absolute
|
|
28
36
|
* ```
|
|
@@ -30,7 +38,7 @@ import { RouteMap } from "./base-route-map.js";
|
|
|
30
38
|
export function createRouteMapFromTree(routeTree, options) {
|
|
31
39
|
const routes = [];
|
|
32
40
|
function traverse(node) {
|
|
33
|
-
if (node.id && node.fullPath) {
|
|
41
|
+
if (node.id && node.fullPath && node.id !== ROOT_NODE_ID) {
|
|
34
42
|
routes.push({ stateId: node.id, path: node.fullPath });
|
|
35
43
|
}
|
|
36
44
|
if (node.children) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-route-map-from-tree.js","sourceRoot":"","sources":["../src/create-route-map-from-tree.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"create-route-map-from-tree.js","sourceRoot":"","sources":["../src/create-route-map-from-tree.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAoB,EAAE,OAAyB;IACrF,MAAM,MAAM,GAA6C,EAAE,CAAC;IAE5D,SAAS,QAAQ,CAAC,IAAe;QAChC,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,EAAE,KAAK,YAAY,EAAE,CAAC;YAC1D,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;IACF,CAAC;IAED,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { PlayError } from "@xmachines/play";
|
|
1
|
+
import { PlayError } from "@xmachines/play/errors";
|
|
2
|
+
export { InvalidRoutePatternError, InvalidBasePathError, MissingBasePathParamError, } from "@xmachines/play-url/errors";
|
|
2
3
|
/**
|
|
3
4
|
* The bridge throws this error when `RouterBridgeBase.syncActorFromRouter()`
|
|
4
5
|
* cannot process a location change of the router and send the `play.route` event to
|
|
@@ -55,27 +56,6 @@ export declare class RouterSyncError extends PlayError {
|
|
|
55
56
|
export declare class DuplicateBridgeError extends PlayError {
|
|
56
57
|
constructor();
|
|
57
58
|
}
|
|
58
|
-
/**
|
|
59
|
-
* The `RouteMap` constructor throws this error when the caller registers a
|
|
60
|
-
* parameterized route, the current runtime has no `URLPattern` API, and no polyfill
|
|
61
|
-
* is loaded.
|
|
62
|
-
*
|
|
63
|
-
* **The remedy:** load `urlpattern-polyfill` at the entry point of your application,
|
|
64
|
-
* before each import of `@xmachines/play-router`:
|
|
65
|
-
*
|
|
66
|
-
* ```typescript
|
|
67
|
-
* // the entry point of the application — it must run first
|
|
68
|
-
* import "urlpattern-polyfill";
|
|
69
|
-
* ```
|
|
70
|
-
*
|
|
71
|
-
* URLPattern is native in Node.js ≥ 24 and in a modern browser (Chrome 95+,
|
|
72
|
-
* Firefox 117+, Safari 16.4+). Use the polyfill for an older target.
|
|
73
|
-
*
|
|
74
|
-
* **Error code:** `PLAY_ROUTE_MAP_URLPATTERN_UNAVAILABLE`
|
|
75
|
-
*/
|
|
76
|
-
export declare class URLPatternUnavailableError extends PlayError {
|
|
77
|
-
constructor();
|
|
78
|
-
}
|
|
79
59
|
/**
|
|
80
60
|
* `validateRouteFormat()` throws this error when a state declares a `meta.route`
|
|
81
61
|
* field with an empty string as its path.
|
|
@@ -122,116 +102,4 @@ export declare class UnknownStateTypeError extends PlayError {
|
|
|
122
102
|
readonly nodeId: string;
|
|
123
103
|
constructor(stateType: string, nodeId: string, validTypes: string[]);
|
|
124
104
|
}
|
|
125
|
-
/**
|
|
126
|
-
* The library throws this error when `URLPattern` cannot compile the string of a route
|
|
127
|
-
* pattern. The `pattern` field holds the string in question, and `cause` holds the
|
|
128
|
-
* original error of the `URLPattern` constructor.
|
|
129
|
-
*
|
|
130
|
-
* Every compilation reports through this error, so `extractRouteParams` raises it for a
|
|
131
|
-
* pattern that no `RouteMap` ever held, and not a bare `TypeError`.
|
|
132
|
-
*
|
|
133
|
-
* The common causes:
|
|
134
|
-
* - A parenthesis or a bracket without its pair in the string of the pattern
|
|
135
|
-
* - A character that a URL pathname pattern does not permit
|
|
136
|
-
* - Two params of one pattern that land on the same URLPattern group. A name with a
|
|
137
|
-
* hyphen compiles with an underscore, so `:cat-id` and `:cat_id` are one group. The
|
|
138
|
-
* message names the two params and the group, and `cause` is absent: the library
|
|
139
|
-
* refuses the pattern before URLPattern sees it.
|
|
140
|
-
*
|
|
141
|
-
* **Error code:** `PLAY_ROUTE_MAP_INVALID_PATTERN`
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* ```typescript
|
|
145
|
-
* import { InvalidRoutePatternError } from "@xmachines/play-router/errors";
|
|
146
|
-
*
|
|
147
|
-
* try {
|
|
148
|
-
* const routeMap = createRouteMap(machine);
|
|
149
|
-
* } catch (err) {
|
|
150
|
-
* if (err instanceof InvalidRoutePatternError) {
|
|
151
|
-
* console.error(`Bad route pattern: "${err.pattern}"`, err.cause);
|
|
152
|
-
* }
|
|
153
|
-
* }
|
|
154
|
-
* ```
|
|
155
|
-
*/
|
|
156
|
-
export declare class InvalidRoutePatternError extends PlayError {
|
|
157
|
-
/** The string of the route pattern. URLPattern could not compile it. */
|
|
158
|
-
readonly pattern: string;
|
|
159
|
-
/**
|
|
160
|
-
* @param pattern - The route pattern that URLPattern could not compile.
|
|
161
|
-
* @param options - The standard `cause`, and an optional `reason` that says WHY. Give
|
|
162
|
-
* a reason whenever the library knows it: the pattern alone shows a caller nothing
|
|
163
|
-
* when the fault is a rewrite that the library made, and not the text they wrote.
|
|
164
|
-
*/
|
|
165
|
-
constructor(pattern: string, options?: ErrorOptions & {
|
|
166
|
-
reason?: string;
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Thrown when a `basePath` option resolves to one concrete URL prefix never.
|
|
171
|
-
*
|
|
172
|
-
* A bridge writes a real browser URL from its prefix, so every segment must hold
|
|
173
|
-
* exactly one value. A wildcard segment (`*`), an optional segment (`:section?`), a
|
|
174
|
-
* nameless `:` segment, a query string, and a hash fragment each describe a SET of
|
|
175
|
-
* prefixes instead, or no prefix at all. A `$param` segment is the route-param
|
|
176
|
-
* syntax of TanStack Router: a base path writes a param as `:param`, and it takes
|
|
177
|
-
* the value of that param from `basePathParams`.
|
|
178
|
-
*
|
|
179
|
-
* **How to fix it:** mount on the prefix itself, and let the machine own the rest.
|
|
180
|
-
* For the splat route `/$machineId/play/$` of TanStack, the base path is
|
|
181
|
-
* `"/:machineId/play"` with `basePathParams: { machineId }`.
|
|
182
|
-
*
|
|
183
|
-
* **Error code:** `PLAY_ROUTER_INVALID_BASE_PATH`
|
|
184
|
-
*
|
|
185
|
-
* @example
|
|
186
|
-
* ```typescript
|
|
187
|
-
* import { InvalidBasePathError } from "@xmachines/play-router/errors";
|
|
188
|
-
*
|
|
189
|
-
* try {
|
|
190
|
-
* bridge.setBasePath("/:machineId/play/*");
|
|
191
|
-
* } catch (err) {
|
|
192
|
-
* if (err instanceof InvalidBasePathError) {
|
|
193
|
-
* console.error(`Bad base path: "${err.basePath}"`, err.message);
|
|
194
|
-
* }
|
|
195
|
-
* }
|
|
196
|
-
* ```
|
|
197
|
-
*/
|
|
198
|
-
export declare class InvalidBasePathError extends PlayError {
|
|
199
|
-
/** The `basePath` option of the refusal, exactly as the caller gave it. */
|
|
200
|
-
readonly basePath: string;
|
|
201
|
-
constructor(basePath: string, reason: string);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Thrown when a `:param` segment of a `basePath` has no value in `basePathParams`.
|
|
205
|
-
*
|
|
206
|
-
* A base path can be a pattern, so a host keeps one string that mirrors its own
|
|
207
|
-
* route config. The bridge must still resolve that pattern to a concrete prefix,
|
|
208
|
-
* because it writes a real browser URL, and it removes a literal prefix from every
|
|
209
|
-
* inbound location. Every `:param` therefore needs a value.
|
|
210
|
-
*
|
|
211
|
-
* **How to fix it:** give the value that the host resolved already — a loader of
|
|
212
|
-
* TanStack, or a `useParams()` call, holds it — as `basePathParams: { machineId }`.
|
|
213
|
-
* An empty string counts as an absent value, because it would collapse the segment.
|
|
214
|
-
*
|
|
215
|
-
* **Error code:** `PLAY_ROUTER_MISSING_BASE_PATH_PARAM`
|
|
216
|
-
*
|
|
217
|
-
* @example
|
|
218
|
-
* ```typescript
|
|
219
|
-
* import { MissingBasePathParamError } from "@xmachines/play-router/errors";
|
|
220
|
-
*
|
|
221
|
-
* try {
|
|
222
|
-
* connectRouter({ actor, router, routeMap, basePath: "/:machineId/play" });
|
|
223
|
-
* } catch (err) {
|
|
224
|
-
* if (err instanceof MissingBasePathParamError) {
|
|
225
|
-
* console.error(`basePath needs a value for :${err.param}`);
|
|
226
|
-
* }
|
|
227
|
-
* }
|
|
228
|
-
* ```
|
|
229
|
-
*/
|
|
230
|
-
export declare class MissingBasePathParamError extends PlayError {
|
|
231
|
-
/** The name of the `:param` segment without a value, and without its `:`. */
|
|
232
|
-
readonly param: string;
|
|
233
|
-
/** The `basePath` option that declares the param. */
|
|
234
|
-
readonly basePath: string;
|
|
235
|
-
constructor(param: string, basePath: string);
|
|
236
|
-
}
|
|
237
105
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAWnD,OAAO,EACN,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,GACzB,MAAM,4BAA4B,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,eAAgB,SAAQ,SAAS;gBACjC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAInD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;;CAUlD;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,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAS3B;AAED;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;IACrD,sFAAsF;IACtF,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBAElB,UAAU,EAAE,MAAM,EAAE;CAWhC;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;IACnD,mEAAmE;IACnE,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"}
|