@xmachines/play-router 2.0.0 → 2.1.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 +93 -76
- package/dist/base-route-map.d.ts +63 -57
- package/dist/base-route-map.d.ts.map +1 -1
- package/dist/base-route-map.js +65 -59
- package/dist/base-route-map.js.map +1 -1
- package/dist/build-tree.d.ts +13 -12
- package/dist/build-tree.d.ts.map +1 -1
- package/dist/build-tree.js +30 -28
- package/dist/build-tree.js.map +1 -1
- package/dist/create-route-map-from-tree.d.ts +15 -15
- package/dist/create-route-map-from-tree.js +15 -15
- package/dist/create-route-map.d.ts +18 -16
- package/dist/create-route-map.d.ts.map +1 -1
- package/dist/create-route-map.js +10 -9
- package/dist/create-route-map.js.map +1 -1
- package/dist/errors.d.ts +40 -38
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +40 -38
- package/dist/errors.js.map +1 -1
- package/dist/extract-routes.d.ts +8 -7
- package/dist/extract-routes.d.ts.map +1 -1
- package/dist/extract-routes.js +31 -27
- package/dist/extract-routes.js.map +1 -1
- package/dist/find-route.d.ts +18 -15
- package/dist/find-route.d.ts.map +1 -1
- package/dist/find-route.js +42 -38
- package/dist/find-route.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -10
- package/dist/index.js.map +1 -1
- package/dist/machine-to-graph.d.ts +3 -2
- package/dist/machine-to-graph.d.ts.map +1 -1
- package/dist/machine-to-graph.js +20 -19
- package/dist/machine-to-graph.js.map +1 -1
- package/dist/query.d.ts +39 -37
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +62 -57
- package/dist/query.js.map +1 -1
- package/dist/router-bridge-base.d.ts +208 -190
- package/dist/router-bridge-base.d.ts.map +1 -1
- package/dist/router-bridge-base.js +235 -211
- package/dist/router-bridge-base.js.map +1 -1
- package/dist/router-sync.d.ts +41 -35
- package/dist/router-sync.d.ts.map +1 -1
- package/dist/router-sync.js +53 -45
- package/dist/router-sync.js.map +1 -1
- package/dist/types.d.ts +165 -147
- package/dist/types.d.ts.map +1 -1
- package/dist/url-pattern-utils.d.ts +53 -47
- package/dist/url-pattern-utils.d.ts.map +1 -1
- package/dist/url-pattern-utils.js +61 -55
- package/dist/url-pattern-utils.js.map +1 -1
- package/dist/validate-routes.d.ts +32 -31
- package/dist/validate-routes.d.ts.map +1 -1
- package/dist/validate-routes.js +30 -29
- package/dist/validate-routes.js.map +1 -1
- package/package.json +6 -5
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The shared URLPattern utilities — an internal module. index.ts does not export it
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* This module holds the common URLPattern work of four files:
|
|
5
5
|
* - `create-route-map.ts`
|
|
6
6
|
* - `base-route-map.ts`
|
|
7
7
|
* - `find-route.ts`
|
|
8
8
|
* - `router-bridge-base.ts`
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* The module reads URLPattern from globalThis. A consumer must load a polyfill in an
|
|
11
|
+
* environment without the native API: Node < 24, and an older browser.
|
|
12
12
|
*
|
|
13
13
|
* @internal
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* The minimal structural type of the part of URLPattern that this package uses.
|
|
17
|
+
* The package therefore needs no hard dependency on the complete type declaration of
|
|
18
|
+
* URLPattern.
|
|
18
19
|
*/
|
|
19
20
|
export type URLPatternLike = {
|
|
20
21
|
exec(input: {
|
|
@@ -28,39 +29,42 @@ export type URLPatternLike = {
|
|
|
28
29
|
pathname: string;
|
|
29
30
|
}): boolean;
|
|
30
31
|
};
|
|
31
|
-
/**
|
|
32
|
+
/** The constructor type of a URLPatternLike instance. */
|
|
32
33
|
export type URLPatternCtor = new (init: {
|
|
33
34
|
pathname: string;
|
|
34
35
|
}) => URLPatternLike;
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
37
|
+
* Returns the URLPattern constructor of `globalThis`, or `undefined` when it is
|
|
38
|
+
* absent: in Node < 24, and in an older browser without a polyfill.
|
|
38
39
|
*/
|
|
39
40
|
export declare function getURLPatternCtor(): URLPatternCtor | undefined;
|
|
40
41
|
/**
|
|
41
|
-
*
|
|
42
|
+
* Tells you if a route path is a parameterized pattern, and not a concrete URL.
|
|
42
43
|
*
|
|
43
|
-
* A pattern
|
|
44
|
-
* wildcard
|
|
45
|
-
*
|
|
44
|
+
* A pattern holds a `:param` segment, which is necessary or optional, or the `*`
|
|
45
|
+
* wildcard, or both. Each of them needs a URLPattern match, and each of them carries
|
|
46
|
+
* no concrete value. Therefore the code can push such a path to a browser URL
|
|
47
|
+
* never.
|
|
46
48
|
*
|
|
47
|
-
* This is THE single source of truth
|
|
48
|
-
* `RouteMap`
|
|
49
|
-
* `RouterBridgeBase.resolveNavigationPath`
|
|
50
|
-
* two
|
|
49
|
+
* This function is THE single source of truth of the question "is this path a
|
|
50
|
+
* pattern?". `RouteMap` uses it for its decision between the static map and the
|
|
51
|
+
* index of the pattern buckets, and `RouterBridgeBase.resolveNavigationPath` uses it
|
|
52
|
+
* to skip a route of no navigation. The two tests therefore cannot move apart.
|
|
51
53
|
*
|
|
52
|
-
* @param path - URL path or route pattern
|
|
53
|
-
* @returns `true`
|
|
54
|
+
* @param path - The string of a URL path or of a route pattern, for example `/profile/:userId` or `/docs/*`
|
|
55
|
+
* @returns `true` when the path holds a `:param` or a `*` pattern syntax
|
|
54
56
|
*/
|
|
55
57
|
export declare function isParameterizedPattern(path: string): boolean;
|
|
56
58
|
/**
|
|
57
|
-
*
|
|
59
|
+
* Normalizes a route path, so that each of its parameter names is a valid URLPattern
|
|
60
|
+
* identifier.
|
|
58
61
|
*
|
|
59
|
-
* URLPattern requires
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* the
|
|
62
|
+
* URLPattern requires a valid JS identifier as a parameter name, and such an
|
|
63
|
+
* identifier holds no hyphen. Therefore the function replaces a name with a hyphen,
|
|
64
|
+
* for example `:cat-id`, with the equivalent name with an underscore (`:cat_id`),
|
|
65
|
+
* for the compilation step of URLPattern. A caller that needs the values of the
|
|
66
|
+
* captured groups, and not a test of the match alone, must map each normalized group
|
|
67
|
+
* name back to the original param name with {@link getNormalizedParamNameMap}.
|
|
64
68
|
*
|
|
65
69
|
* @example
|
|
66
70
|
* normalizeParamNames("/docs/:cat-id/:page-num?")
|
|
@@ -68,11 +72,11 @@ export declare function isParameterizedPattern(path: string): boolean;
|
|
|
68
72
|
*/
|
|
69
73
|
export declare function normalizeParamNames(path: string): string;
|
|
70
74
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
75
|
+
* Builds the map from each normalized URLPattern group name back to the original
|
|
76
|
+
* param name, which holds a hyphen, of a route pattern.
|
|
73
77
|
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
78
|
+
* The map holds only the params that {@link normalizeParamNames} rewrote. A param
|
|
79
|
+
* with a valid identifier keeps its own name, and it needs no entry.
|
|
76
80
|
*
|
|
77
81
|
* @example
|
|
78
82
|
* getNormalizedParamNameMap("/docs/:cat-id/:plain")
|
|
@@ -80,36 +84,38 @@ export declare function normalizeParamNames(path: string): string;
|
|
|
80
84
|
*/
|
|
81
85
|
export declare function getNormalizedParamNameMap(path: string): Map<string, string>;
|
|
82
86
|
/**
|
|
83
|
-
*
|
|
87
|
+
* Compiles a route pattern into a `URLPattern`, and it uses the cache of the module
|
|
88
|
+
* level again.
|
|
84
89
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* (`:cat_id`).
|
|
88
|
-
* back
|
|
90
|
+
* {@link normalizeParamNames} normalizes the pattern before the compilation. A param
|
|
91
|
+
* name with a hyphen (`:cat-id`) therefore becomes a valid URLPattern identifier
|
|
92
|
+
* (`:cat_id`). A caller that reads the values of the groups must map each normalized
|
|
93
|
+
* name back with {@link getNormalizedParamNameMap}.
|
|
89
94
|
*
|
|
90
|
-
*
|
|
91
|
-
* that
|
|
95
|
+
* An error of the compilation from the URLPattern constructor goes to the caller
|
|
96
|
+
* without a change. A caller that needs a typed error wraps this function in an
|
|
97
|
+
* `InvalidRoutePatternError`.
|
|
92
98
|
*
|
|
93
|
-
* @param pattern -
|
|
94
|
-
* @param Ctor - URLPattern constructor
|
|
99
|
+
* @param pattern - The string of the route pattern, for example `/profile/:userId`
|
|
100
|
+
* @param Ctor - The URLPattern constructor, from {@link getURLPatternCtor}
|
|
95
101
|
*/
|
|
96
102
|
export declare function getCompiledPattern(pattern: string, Ctor: URLPatternCtor): URLPatternLike;
|
|
97
103
|
/**
|
|
98
|
-
*
|
|
104
|
+
* Computes the key of the bucket index of a path or of a pattern.
|
|
99
105
|
*
|
|
100
|
-
* The key is the first path segment
|
|
101
|
-
*
|
|
102
|
-
* The root path `"/"`
|
|
106
|
+
* The key is the first path segment, for example `"settings"` of `"/settings/:id"`.
|
|
107
|
+
* A first segment with a parameter (`:lang`) goes into the `"*"` wildcard bucket.
|
|
108
|
+
* The root path `"/"` gives the key `"/"`.
|
|
103
109
|
*
|
|
104
|
-
* @param path - URL path or route pattern
|
|
110
|
+
* @param path - The string of a URL path or of a route pattern
|
|
105
111
|
*/
|
|
106
112
|
export declare function getIndexKey(path: string): string;
|
|
107
113
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
114
|
+
* Joins the bucket of the named segment and the wildcard bucket of one index key.
|
|
115
|
+
* The order of the insertion stays, through the `order` field.
|
|
110
116
|
*
|
|
111
|
-
* @param patternBuckets -
|
|
112
|
-
* @param indexKey -
|
|
117
|
+
* @param patternBuckets - The map from a bucket key to its ordered pattern entries
|
|
118
|
+
* @param indexKey - The key of the first segment, from `getIndexKey`
|
|
113
119
|
*/
|
|
114
120
|
export declare function getCandidates<T extends {
|
|
115
121
|
order: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-pattern-utils.d.ts","sourceRoot":"","sources":["../src/url-pattern-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH
|
|
1
|
+
{"version":3,"file":"url-pattern-utils.d.ts","sourceRoot":"","sources":["../src/url-pattern-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,IAAI,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG;QAClC,QAAQ,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;SAAE,CAAC;KACzD,GAAG,IAAI,CAAC;IACT,IAAI,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;CAC3C,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,cAAc,GAAG,KAAK,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,cAAc,CAAC;AAEhF;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CAE9D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AASD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAO3E;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,cAAc,CAWxF;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMhD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EACxD,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAChC,QAAQ,EAAE,MAAM,GACd,CAAC,EAAE,CA2BL"}
|
|
@@ -1,56 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The shared URLPattern utilities — an internal module. index.ts does not export it
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* This module holds the common URLPattern work of four files:
|
|
5
5
|
* - `create-route-map.ts`
|
|
6
6
|
* - `base-route-map.ts`
|
|
7
7
|
* - `find-route.ts`
|
|
8
8
|
* - `router-bridge-base.ts`
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* The module reads URLPattern from globalThis. A consumer must load a polyfill in an
|
|
11
|
+
* environment without the native API: Node < 24, and an older browser.
|
|
12
12
|
*
|
|
13
13
|
* @internal
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Returns the URLPattern constructor of `globalThis`, or `undefined` when it is
|
|
17
|
+
* absent: in Node < 24, and in an older browser without a polyfill.
|
|
18
18
|
*/
|
|
19
19
|
export function getURLPatternCtor() {
|
|
20
20
|
return globalThis["URLPattern"];
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Tells you if a route path is a parameterized pattern, and not a concrete URL.
|
|
24
24
|
*
|
|
25
|
-
* A pattern
|
|
26
|
-
* wildcard
|
|
27
|
-
*
|
|
25
|
+
* A pattern holds a `:param` segment, which is necessary or optional, or the `*`
|
|
26
|
+
* wildcard, or both. Each of them needs a URLPattern match, and each of them carries
|
|
27
|
+
* no concrete value. Therefore the code can push such a path to a browser URL
|
|
28
|
+
* never.
|
|
28
29
|
*
|
|
29
|
-
* This is THE single source of truth
|
|
30
|
-
* `RouteMap`
|
|
31
|
-
* `RouterBridgeBase.resolveNavigationPath`
|
|
32
|
-
* two
|
|
30
|
+
* This function is THE single source of truth of the question "is this path a
|
|
31
|
+
* pattern?". `RouteMap` uses it for its decision between the static map and the
|
|
32
|
+
* index of the pattern buckets, and `RouterBridgeBase.resolveNavigationPath` uses it
|
|
33
|
+
* to skip a route of no navigation. The two tests therefore cannot move apart.
|
|
33
34
|
*
|
|
34
|
-
* @param path - URL path or route pattern
|
|
35
|
-
* @returns `true`
|
|
35
|
+
* @param path - The string of a URL path or of a route pattern, for example `/profile/:userId` or `/docs/*`
|
|
36
|
+
* @returns `true` when the path holds a `:param` or a `*` pattern syntax
|
|
36
37
|
*/
|
|
37
38
|
export function isParameterizedPattern(path) {
|
|
38
39
|
return path.includes(":") || path.includes("*");
|
|
39
40
|
}
|
|
40
41
|
/**
|
|
41
|
-
*
|
|
42
|
-
* URLPattern requires
|
|
43
|
-
*
|
|
42
|
+
* The expression matches a `:param` name with a hyphen, for example `:cat-id` or
|
|
43
|
+
* `:page-num?`. URLPattern requires a valid JS identifier as a parameter name.
|
|
44
|
+
* Therefore the code must rewrite a name with a hyphen before the compilation.
|
|
44
45
|
*/
|
|
45
46
|
const HYPHENATED_PARAM_RE = /:([A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)+)(\??)/g;
|
|
46
47
|
/**
|
|
47
|
-
*
|
|
48
|
+
* Normalizes a route path, so that each of its parameter names is a valid URLPattern
|
|
49
|
+
* identifier.
|
|
48
50
|
*
|
|
49
|
-
* URLPattern requires
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* the
|
|
51
|
+
* URLPattern requires a valid JS identifier as a parameter name, and such an
|
|
52
|
+
* identifier holds no hyphen. Therefore the function replaces a name with a hyphen,
|
|
53
|
+
* for example `:cat-id`, with the equivalent name with an underscore (`:cat_id`),
|
|
54
|
+
* for the compilation step of URLPattern. A caller that needs the values of the
|
|
55
|
+
* captured groups, and not a test of the match alone, must map each normalized group
|
|
56
|
+
* name back to the original param name with {@link getNormalizedParamNameMap}.
|
|
54
57
|
*
|
|
55
58
|
* @example
|
|
56
59
|
* normalizeParamNames("/docs/:cat-id/:page-num?")
|
|
@@ -62,11 +65,11 @@ export function normalizeParamNames(path) {
|
|
|
62
65
|
});
|
|
63
66
|
}
|
|
64
67
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
68
|
+
* Builds the map from each normalized URLPattern group name back to the original
|
|
69
|
+
* param name, which holds a hyphen, of a route pattern.
|
|
67
70
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
71
|
+
* The map holds only the params that {@link normalizeParamNames} rewrote. A param
|
|
72
|
+
* with a valid identifier keeps its own name, and it needs no entry.
|
|
70
73
|
*
|
|
71
74
|
* @example
|
|
72
75
|
* getNormalizedParamNameMap("/docs/:cat-id/:plain")
|
|
@@ -81,30 +84,33 @@ export function getNormalizedParamNameMap(path) {
|
|
|
81
84
|
return nameMap;
|
|
82
85
|
}
|
|
83
86
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
87
|
+
* The cache of the compiled URLPattern instances at the module level. The key is the
|
|
88
|
+
* string of the pattern.
|
|
89
|
+
*
|
|
90
|
+
* The code compiles a route pattern on every lookup path of a navigation
|
|
91
|
+
* (`extractRouteParams` and `findRouteByPath`), and also one time for each
|
|
92
|
+
* `RouteMap` construction. A new compilation of the same route pattern each time is
|
|
93
|
+
* lost work. The number of the different route patterns of the route maps of the
|
|
94
|
+
* application limits the growth of the cache. The cache goes away when the
|
|
95
|
+
* URLPattern constructor changes, and a test changes `globalThis.URLPattern`.
|
|
92
96
|
*/
|
|
93
97
|
const compiledPatternCache = new Map();
|
|
94
98
|
let compiledPatternCtor;
|
|
95
99
|
/**
|
|
96
|
-
*
|
|
100
|
+
* Compiles a route pattern into a `URLPattern`, and it uses the cache of the module
|
|
101
|
+
* level again.
|
|
97
102
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* (`:cat_id`).
|
|
101
|
-
* back
|
|
103
|
+
* {@link normalizeParamNames} normalizes the pattern before the compilation. A param
|
|
104
|
+
* name with a hyphen (`:cat-id`) therefore becomes a valid URLPattern identifier
|
|
105
|
+
* (`:cat_id`). A caller that reads the values of the groups must map each normalized
|
|
106
|
+
* name back with {@link getNormalizedParamNameMap}.
|
|
102
107
|
*
|
|
103
|
-
*
|
|
104
|
-
* that
|
|
108
|
+
* An error of the compilation from the URLPattern constructor goes to the caller
|
|
109
|
+
* without a change. A caller that needs a typed error wraps this function in an
|
|
110
|
+
* `InvalidRoutePatternError`.
|
|
105
111
|
*
|
|
106
|
-
* @param pattern -
|
|
107
|
-
* @param Ctor - URLPattern constructor
|
|
112
|
+
* @param pattern - The string of the route pattern, for example `/profile/:userId`
|
|
113
|
+
* @param Ctor - The URLPattern constructor, from {@link getURLPatternCtor}
|
|
108
114
|
*/
|
|
109
115
|
export function getCompiledPattern(pattern, Ctor) {
|
|
110
116
|
if (Ctor !== compiledPatternCtor) {
|
|
@@ -119,13 +125,13 @@ export function getCompiledPattern(pattern, Ctor) {
|
|
|
119
125
|
return compiled;
|
|
120
126
|
}
|
|
121
127
|
/**
|
|
122
|
-
*
|
|
128
|
+
* Computes the key of the bucket index of a path or of a pattern.
|
|
123
129
|
*
|
|
124
|
-
* The key is the first path segment
|
|
125
|
-
*
|
|
126
|
-
* The root path `"/"`
|
|
130
|
+
* The key is the first path segment, for example `"settings"` of `"/settings/:id"`.
|
|
131
|
+
* A first segment with a parameter (`:lang`) goes into the `"*"` wildcard bucket.
|
|
132
|
+
* The root path `"/"` gives the key `"/"`.
|
|
127
133
|
*
|
|
128
|
-
* @param path - URL path or route pattern
|
|
134
|
+
* @param path - The string of a URL path or of a route pattern
|
|
129
135
|
*/
|
|
130
136
|
export function getIndexKey(path) {
|
|
131
137
|
const trimmed = path.startsWith("/") ? path.slice(1) : path;
|
|
@@ -137,11 +143,11 @@ export function getIndexKey(path) {
|
|
|
137
143
|
return segment;
|
|
138
144
|
}
|
|
139
145
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
146
|
+
* Joins the bucket of the named segment and the wildcard bucket of one index key.
|
|
147
|
+
* The order of the insertion stays, through the `order` field.
|
|
142
148
|
*
|
|
143
|
-
* @param patternBuckets -
|
|
144
|
-
* @param indexKey -
|
|
149
|
+
* @param patternBuckets - The map from a bucket key to its ordered pattern entries
|
|
150
|
+
* @param indexKey - The key of the first segment, from `getIndexKey`
|
|
145
151
|
*/
|
|
146
152
|
export function getCandidates(patternBuckets, indexKey) {
|
|
147
153
|
const bucket = patternBuckets.get(indexKey) ?? [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-pattern-utils.js","sourceRoot":"","sources":["../src/url-pattern-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"url-pattern-utils.js","sourceRoot":"","sources":["../src/url-pattern-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,57 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A route entry with its RESOLVED
|
|
3
|
-
*
|
|
2
|
+
* A route entry with its RESOLVED complete path, which is the path after the tree
|
|
3
|
+
* construction put the path of the parent before each relative route.
|
|
4
4
|
*
|
|
5
5
|
* `RouteNode` satisfies this shape structurally.
|
|
6
6
|
*/
|
|
7
7
|
export interface ResolvedRoutePath {
|
|
8
|
-
/**
|
|
8
|
+
/** The identifier of the state that owns the route, for example `"app.dashboard.settings"`. */
|
|
9
9
|
stateId: string;
|
|
10
|
-
/**
|
|
10
|
+
/** The resolved absolute route path, for example `"/dashboard/settings"`. */
|
|
11
11
|
fullPath: string;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Checks the format of a route path
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* and relative
|
|
18
|
-
*
|
|
16
|
+
* The function requires a string that is not empty. It accepts an absolute path
|
|
17
|
+
* ("/foo") and also a relative path ("foo" or "child/nested"). A relative route
|
|
18
|
+
* receives the path prefix of its parent state during the construction of the tree.
|
|
19
19
|
*
|
|
20
|
-
* @param routePath -
|
|
21
|
-
* @param stateId -
|
|
22
|
-
* @throws {EmptyRoutePathError}
|
|
20
|
+
* @param routePath - The route path to check: absolute or relative
|
|
21
|
+
* @param stateId - The identifier of the state, for the error message
|
|
22
|
+
* @throws {EmptyRoutePathError} When the route path is empty
|
|
23
23
|
*/
|
|
24
24
|
export declare const validateRouteFormat: (routePath: string, stateId: string) => void;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Checks that the set of the state IDs holds a state
|
|
27
27
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* The function requires each state ID of a reference in the machine graph. This
|
|
29
|
+
* check at the build time therefore stops a broken route reference.
|
|
30
30
|
*
|
|
31
|
-
* @param stateId -
|
|
32
|
-
* @param stateIds -
|
|
33
|
-
* @throws {InvalidStateIdError}
|
|
31
|
+
* @param stateId - The identifier of the state to check
|
|
32
|
+
* @param stateIds - The set of every known state ID of the machine graph
|
|
33
|
+
* @throws {InvalidStateIdError} When the set does not hold the state ID
|
|
34
34
|
*/
|
|
35
35
|
export declare const validateStateExists: (stateId: string, stateIds: Set<string>) => void;
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Finds each duplicate route path
|
|
38
38
|
*
|
|
39
|
-
* THROWS ERROR when
|
|
39
|
+
* The function THROWS AN ERROR when more than one state holds the same RESOLVED
|
|
40
|
+
* complete path.
|
|
40
41
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* strings: two relative `"settings"` routes
|
|
44
|
-
*
|
|
45
|
-
* route
|
|
46
|
-
*
|
|
42
|
+
* The detection works on the resolved complete paths, after `buildRouteTree` put the
|
|
43
|
+
* path of each parent before its relative routes. It does not work on the raw route
|
|
44
|
+
* strings: two relative `"settings"` routes below two different parents resolve to
|
|
45
|
+
* two different complete paths, and they are valid; a relative route and an absolute
|
|
46
|
+
* route that resolve to the same URL are a real collision, and the function refuses
|
|
47
|
+
* them. `buildRouteTree` calls this function when the complete paths are known.
|
|
47
48
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* direct URL
|
|
51
|
-
* conditional
|
|
49
|
+
* The reason: a routing on the URL requires one state for each URL. Two states at
|
|
50
|
+
* the same path make the browser navigation ambiguous, for the BACK button and for a
|
|
51
|
+
* direct URL. Use a different path for each state, or use one state with a
|
|
52
|
+
* conditional render.
|
|
52
53
|
*
|
|
53
|
-
* @param routes -
|
|
54
|
-
* @throws {DuplicateRoutePathError}
|
|
54
|
+
* @param routes - The array of the route entries with their resolved complete paths, for example the `RouteNode` objects
|
|
55
|
+
* @throws {DuplicateRoutePathError} When the function finds two resolved route paths that are equal
|
|
55
56
|
*/
|
|
56
57
|
export declare const detectDuplicateRoutes: (routes: ResolvedRoutePath[]) => void;
|
|
57
58
|
//# sourceMappingURL=validate-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-routes.d.ts","sourceRoot":"","sources":["../src/validate-routes.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IACjC
|
|
1
|
+
{"version":3,"file":"validate-routes.d.ts","sourceRoot":"","sources":["../src/validate-routes.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IACjC,+FAA+F;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,GAAI,WAAW,MAAM,EAAE,SAAS,MAAM,KAAG,IAIxE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM,EAAE,UAAU,GAAG,CAAC,MAAM,CAAC,KAAG,IAI5E,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ,iBAAiB,EAAE,KAAG,IAqBnE,CAAC"}
|
package/dist/validate-routes.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { EmptyRoutePathError, InvalidStateIdError, DuplicateRoutePathError } from "./errors.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Checks the format of a route path
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* and relative
|
|
7
|
-
*
|
|
5
|
+
* The function requires a string that is not empty. It accepts an absolute path
|
|
6
|
+
* ("/foo") and also a relative path ("foo" or "child/nested"). A relative route
|
|
7
|
+
* receives the path prefix of its parent state during the construction of the tree.
|
|
8
8
|
*
|
|
9
|
-
* @param routePath -
|
|
10
|
-
* @param stateId -
|
|
11
|
-
* @throws {EmptyRoutePathError}
|
|
9
|
+
* @param routePath - The route path to check: absolute or relative
|
|
10
|
+
* @param stateId - The identifier of the state, for the error message
|
|
11
|
+
* @throws {EmptyRoutePathError} When the route path is empty
|
|
12
12
|
*/
|
|
13
13
|
export const validateRouteFormat = (routePath, stateId) => {
|
|
14
14
|
if (!routePath) {
|
|
@@ -16,14 +16,14 @@ export const validateRouteFormat = (routePath, stateId) => {
|
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Checks that the set of the state IDs holds a state
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* The function requires each state ID of a reference in the machine graph. This
|
|
22
|
+
* check at the build time therefore stops a broken route reference.
|
|
23
23
|
*
|
|
24
|
-
* @param stateId -
|
|
25
|
-
* @param stateIds -
|
|
26
|
-
* @throws {InvalidStateIdError}
|
|
24
|
+
* @param stateId - The identifier of the state to check
|
|
25
|
+
* @param stateIds - The set of every known state ID of the machine graph
|
|
26
|
+
* @throws {InvalidStateIdError} When the set does not hold the state ID
|
|
27
27
|
*/
|
|
28
28
|
export const validateStateExists = (stateId, stateIds) => {
|
|
29
29
|
if (!stateIds.has(stateId)) {
|
|
@@ -31,34 +31,35 @@ export const validateStateExists = (stateId, stateIds) => {
|
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* Finds each duplicate route path
|
|
35
35
|
*
|
|
36
|
-
* THROWS ERROR when
|
|
36
|
+
* The function THROWS AN ERROR when more than one state holds the same RESOLVED
|
|
37
|
+
* complete path.
|
|
37
38
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* strings: two relative `"settings"` routes
|
|
41
|
-
*
|
|
42
|
-
* route
|
|
43
|
-
*
|
|
39
|
+
* The detection works on the resolved complete paths, after `buildRouteTree` put the
|
|
40
|
+
* path of each parent before its relative routes. It does not work on the raw route
|
|
41
|
+
* strings: two relative `"settings"` routes below two different parents resolve to
|
|
42
|
+
* two different complete paths, and they are valid; a relative route and an absolute
|
|
43
|
+
* route that resolve to the same URL are a real collision, and the function refuses
|
|
44
|
+
* them. `buildRouteTree` calls this function when the complete paths are known.
|
|
44
45
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* direct URL
|
|
48
|
-
* conditional
|
|
46
|
+
* The reason: a routing on the URL requires one state for each URL. Two states at
|
|
47
|
+
* the same path make the browser navigation ambiguous, for the BACK button and for a
|
|
48
|
+
* direct URL. Use a different path for each state, or use one state with a
|
|
49
|
+
* conditional render.
|
|
49
50
|
*
|
|
50
|
-
* @param routes -
|
|
51
|
-
* @throws {DuplicateRoutePathError}
|
|
51
|
+
* @param routes - The array of the route entries with their resolved complete paths, for example the `RouteNode` objects
|
|
52
|
+
* @throws {DuplicateRoutePathError} When the function finds two resolved route paths that are equal
|
|
52
53
|
*/
|
|
53
54
|
export const detectDuplicateRoutes = (routes) => {
|
|
54
55
|
const routeMap = new Map();
|
|
55
|
-
// Build map
|
|
56
|
+
// Build the map from each resolved complete path to its state IDs
|
|
56
57
|
for (const route of routes) {
|
|
57
58
|
const stateIds = routeMap.get(route.fullPath) || [];
|
|
58
59
|
stateIds.push(route.stateId);
|
|
59
60
|
routeMap.set(route.fullPath, stateIds);
|
|
60
61
|
}
|
|
61
|
-
//
|
|
62
|
+
// Find each duplicate, and throw an error
|
|
62
63
|
const duplicates = [];
|
|
63
64
|
for (const [routePath, stateIds] of routeMap.entries()) {
|
|
64
65
|
if (stateIds.length > 1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-routes.js","sourceRoot":"","sources":["../src/validate-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAehG;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,SAAiB,EAAE,OAAe,EAAQ,EAAE;IAC/E,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,MAAM,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;AACF,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAe,EAAE,QAAqB,EAAQ,EAAE;IACnF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;AACF,CAAC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"validate-routes.js","sourceRoot":"","sources":["../src/validate-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAehG;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,SAAiB,EAAE,OAAe,EAAQ,EAAE;IAC/E,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,MAAM,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;AACF,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAe,EAAE,QAAqB,EAAQ,EAAE;IACnF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;AACF,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAA2B,EAAQ,EAAE;IAC1E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE7C,kEAAkE;IAClE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,0CAA0C;IAC1C,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,UAAU,CAAC,IAAI,CAAC,KAAK,SAAS,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7D,CAAC;IACF,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;AACF,CAAC,CAAC"}
|