@tanstack/router-core 1.167.1 → 1.167.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/dist/cjs/Matches.cjs +15 -12
  2. package/dist/cjs/Matches.cjs.map +1 -1
  3. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  4. package/dist/cjs/config.cjs +9 -8
  5. package/dist/cjs/config.cjs.map +1 -1
  6. package/dist/cjs/defer.cjs +37 -21
  7. package/dist/cjs/defer.cjs.map +1 -1
  8. package/dist/cjs/index.cjs +87 -89
  9. package/dist/cjs/isServer/client.cjs +5 -3
  10. package/dist/cjs/isServer/client.cjs.map +1 -1
  11. package/dist/cjs/isServer/development.cjs +5 -3
  12. package/dist/cjs/isServer/development.cjs.map +1 -1
  13. package/dist/cjs/isServer/server.cjs +5 -3
  14. package/dist/cjs/isServer/server.cjs.map +1 -1
  15. package/dist/cjs/link.cjs +5 -4
  16. package/dist/cjs/link.cjs.map +1 -1
  17. package/dist/cjs/load-matches.cjs +619 -766
  18. package/dist/cjs/load-matches.cjs.map +1 -1
  19. package/dist/cjs/lru-cache.cjs +67 -64
  20. package/dist/cjs/lru-cache.cjs.map +1 -1
  21. package/dist/cjs/new-process-route-tree.cjs +707 -792
  22. package/dist/cjs/new-process-route-tree.cjs.map +1 -1
  23. package/dist/cjs/not-found.cjs +20 -7
  24. package/dist/cjs/not-found.cjs.map +1 -1
  25. package/dist/cjs/path.cjs +221 -232
  26. package/dist/cjs/path.cjs.map +1 -1
  27. package/dist/cjs/qss.cjs +62 -28
  28. package/dist/cjs/qss.cjs.map +1 -1
  29. package/dist/cjs/redirect.cjs +44 -30
  30. package/dist/cjs/redirect.cjs.map +1 -1
  31. package/dist/cjs/rewrite.cjs +56 -56
  32. package/dist/cjs/rewrite.cjs.map +1 -1
  33. package/dist/cjs/root.cjs +6 -4
  34. package/dist/cjs/root.cjs.map +1 -1
  35. package/dist/cjs/route.cjs +96 -105
  36. package/dist/cjs/route.cjs.map +1 -1
  37. package/dist/cjs/router.cjs +1153 -1524
  38. package/dist/cjs/router.cjs.map +1 -1
  39. package/dist/cjs/scroll-restoration.cjs +189 -207
  40. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  41. package/dist/cjs/searchMiddleware.cjs +48 -37
  42. package/dist/cjs/searchMiddleware.cjs.map +1 -1
  43. package/dist/cjs/searchParams.cjs +57 -45
  44. package/dist/cjs/searchParams.cjs.map +1 -1
  45. package/dist/cjs/ssr/client.cjs +6 -8
  46. package/dist/cjs/ssr/constants.cjs +6 -5
  47. package/dist/cjs/ssr/constants.cjs.map +1 -1
  48. package/dist/cjs/ssr/createRequestHandler.cjs +41 -59
  49. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  50. package/dist/cjs/ssr/handlerCallback.cjs +5 -4
  51. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -1
  52. package/dist/cjs/ssr/headers.cjs +17 -26
  53. package/dist/cjs/ssr/headers.cjs.map +1 -1
  54. package/dist/cjs/ssr/json.cjs +8 -4
  55. package/dist/cjs/ssr/json.cjs.map +1 -1
  56. package/dist/cjs/ssr/serializer/RawStream.cjs +268 -268
  57. package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -1
  58. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs +31 -32
  59. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -1
  60. package/dist/cjs/ssr/serializer/seroval-plugins.cjs +12 -12
  61. package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -1
  62. package/dist/cjs/ssr/serializer/transformer.cjs +45 -41
  63. package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
  64. package/dist/cjs/ssr/server.cjs +12 -14
  65. package/dist/cjs/ssr/ssr-client.cjs +173 -211
  66. package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
  67. package/dist/cjs/ssr/ssr-match-id.cjs +6 -5
  68. package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -1
  69. package/dist/cjs/ssr/ssr-server.cjs +266 -300
  70. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  71. package/dist/cjs/ssr/transformStreamWithRouter.cjs +317 -337
  72. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
  73. package/dist/cjs/ssr/tsrScript.cjs +6 -4
  74. package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
  75. package/dist/cjs/utils/batch.cjs +13 -13
  76. package/dist/cjs/utils/batch.cjs.map +1 -1
  77. package/dist/cjs/utils.cjs +274 -208
  78. package/dist/cjs/utils.cjs.map +1 -1
  79. package/dist/esm/Matches.js +16 -13
  80. package/dist/esm/Matches.js.map +1 -1
  81. package/dist/esm/config.js +10 -9
  82. package/dist/esm/config.js.map +1 -1
  83. package/dist/esm/defer.js +37 -22
  84. package/dist/esm/defer.js.map +1 -1
  85. package/dist/esm/index.js +12 -82
  86. package/dist/esm/isServer/client.js +6 -5
  87. package/dist/esm/isServer/client.js.map +1 -1
  88. package/dist/esm/isServer/development.js +6 -5
  89. package/dist/esm/isServer/development.js.map +1 -1
  90. package/dist/esm/isServer/server.js +6 -5
  91. package/dist/esm/isServer/server.js.map +1 -1
  92. package/dist/esm/link.js +6 -5
  93. package/dist/esm/link.js.map +1 -1
  94. package/dist/esm/load-matches.js +614 -765
  95. package/dist/esm/load-matches.js.map +1 -1
  96. package/dist/esm/lru-cache.js +68 -65
  97. package/dist/esm/lru-cache.js.map +1 -1
  98. package/dist/esm/new-process-route-tree.js +705 -797
  99. package/dist/esm/new-process-route-tree.js.map +1 -1
  100. package/dist/esm/not-found.js +21 -9
  101. package/dist/esm/not-found.js.map +1 -1
  102. package/dist/esm/path.js +220 -241
  103. package/dist/esm/path.js.map +1 -1
  104. package/dist/esm/qss.js +63 -30
  105. package/dist/esm/qss.js.map +1 -1
  106. package/dist/esm/redirect.js +45 -34
  107. package/dist/esm/redirect.js.map +1 -1
  108. package/dist/esm/rewrite.js +57 -60
  109. package/dist/esm/rewrite.js.map +1 -1
  110. package/dist/esm/root.js +7 -5
  111. package/dist/esm/root.js.map +1 -1
  112. package/dist/esm/route.js +92 -105
  113. package/dist/esm/route.js.map +1 -1
  114. package/dist/esm/router.js +1147 -1527
  115. package/dist/esm/router.js.map +1 -1
  116. package/dist/esm/scroll-restoration.js +188 -213
  117. package/dist/esm/scroll-restoration.js.map +1 -1
  118. package/dist/esm/searchMiddleware.js +48 -38
  119. package/dist/esm/searchMiddleware.js.map +1 -1
  120. package/dist/esm/searchParams.js +57 -48
  121. package/dist/esm/searchParams.js.map +1 -1
  122. package/dist/esm/ssr/client.js +1 -6
  123. package/dist/esm/ssr/constants.js +7 -7
  124. package/dist/esm/ssr/constants.js.map +1 -1
  125. package/dist/esm/ssr/createRequestHandler.js +39 -58
  126. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  127. package/dist/esm/ssr/handlerCallback.js +6 -5
  128. package/dist/esm/ssr/handlerCallback.js.map +1 -1
  129. package/dist/esm/ssr/headers.js +16 -26
  130. package/dist/esm/ssr/headers.js.map +1 -1
  131. package/dist/esm/ssr/json.js +9 -5
  132. package/dist/esm/ssr/json.js.map +1 -1
  133. package/dist/esm/ssr/serializer/RawStream.js +267 -273
  134. package/dist/esm/ssr/serializer/RawStream.js.map +1 -1
  135. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js +31 -32
  136. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -1
  137. package/dist/esm/ssr/serializer/seroval-plugins.js +10 -11
  138. package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -1
  139. package/dist/esm/ssr/serializer/transformer.js +44 -43
  140. package/dist/esm/ssr/serializer/transformer.js.map +1 -1
  141. package/dist/esm/ssr/server.js +2 -12
  142. package/dist/esm/ssr/ssr-client.js +169 -209
  143. package/dist/esm/ssr/ssr-client.js.map +1 -1
  144. package/dist/esm/ssr/ssr-match-id.js +7 -7
  145. package/dist/esm/ssr/ssr-match-id.js.map +1 -1
  146. package/dist/esm/ssr/ssr-server.js +262 -300
  147. package/dist/esm/ssr/ssr-server.js.map +1 -1
  148. package/dist/esm/ssr/transformStreamWithRouter.js +315 -338
  149. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
  150. package/dist/esm/ssr/tsrScript.js +6 -5
  151. package/dist/esm/ssr/tsrScript.js.map +1 -1
  152. package/dist/esm/utils/batch.js +13 -14
  153. package/dist/esm/utils/batch.js.map +1 -1
  154. package/dist/esm/utils.js +273 -224
  155. package/dist/esm/utils.js.map +1 -1
  156. package/package.json +2 -2
  157. package/dist/cjs/index.cjs.map +0 -1
  158. package/dist/cjs/ssr/client.cjs.map +0 -1
  159. package/dist/cjs/ssr/server.cjs.map +0 -1
  160. package/dist/esm/index.js.map +0 -1
  161. package/dist/esm/ssr/client.js.map +0 -1
  162. package/dist/esm/ssr/server.js.map +0 -1
@@ -1,838 +1,753 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const invariant = require("tiny-invariant");
4
- const lruCache = require("./lru-cache.cjs");
5
- const utils = require("./utils.cjs");
6
- const SEGMENT_TYPE_PATHNAME = 0;
7
- const SEGMENT_TYPE_PARAM = 1;
8
- const SEGMENT_TYPE_WILDCARD = 2;
9
- const SEGMENT_TYPE_OPTIONAL_PARAM = 3;
10
- const SEGMENT_TYPE_INDEX = 4;
11
- const SEGMENT_TYPE_PATHLESS = 5;
1
+ const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
2
+ const require_utils = require("./utils.cjs");
3
+ const require_lru_cache = require("./lru-cache.cjs");
4
+ let tiny_invariant = require("tiny-invariant");
5
+ tiny_invariant = require_runtime.__toESM(tiny_invariant);
6
+ var SEGMENT_TYPE_INDEX = 4;
7
+ var SEGMENT_TYPE_PATHLESS = 5;
12
8
  function getOpenAndCloseBraces(part) {
13
- const openBrace = part.indexOf("{");
14
- if (openBrace === -1) return null;
15
- const closeBrace = part.indexOf("}", openBrace);
16
- if (closeBrace === -1) return null;
17
- const afterOpen = openBrace + 1;
18
- if (afterOpen >= part.length) return null;
19
- return [openBrace, closeBrace];
9
+ const openBrace = part.indexOf("{");
10
+ if (openBrace === -1) return null;
11
+ const closeBrace = part.indexOf("}", openBrace);
12
+ if (closeBrace === -1) return null;
13
+ if (openBrace + 1 >= part.length) return null;
14
+ return [openBrace, closeBrace];
20
15
  }
16
+ /**
17
+ * Populates the `output` array with the parsed representation of the given `segment` string.
18
+ *
19
+ * Usage:
20
+ * ```ts
21
+ * let output
22
+ * let cursor = 0
23
+ * while (cursor < path.length) {
24
+ * output = parseSegment(path, cursor, output)
25
+ * const end = output[5]
26
+ * cursor = end + 1
27
+ * ```
28
+ *
29
+ * `output` is stored outside to avoid allocations during repeated calls. It doesn't need to be typed
30
+ * or initialized, it will be done automatically.
31
+ */
21
32
  function parseSegment(path, start, output = new Uint16Array(6)) {
22
- const next = path.indexOf("/", start);
23
- const end = next === -1 ? path.length : next;
24
- const part = path.substring(start, end);
25
- if (!part || !part.includes("$")) {
26
- output[0] = SEGMENT_TYPE_PATHNAME;
27
- output[1] = start;
28
- output[2] = start;
29
- output[3] = end;
30
- output[4] = end;
31
- output[5] = end;
32
- return output;
33
- }
34
- if (part === "$") {
35
- const total = path.length;
36
- output[0] = SEGMENT_TYPE_WILDCARD;
37
- output[1] = start;
38
- output[2] = start;
39
- output[3] = total;
40
- output[4] = total;
41
- output[5] = total;
42
- return output;
43
- }
44
- if (part.charCodeAt(0) === 36) {
45
- output[0] = SEGMENT_TYPE_PARAM;
46
- output[1] = start;
47
- output[2] = start + 1;
48
- output[3] = end;
49
- output[4] = end;
50
- output[5] = end;
51
- return output;
52
- }
53
- const braces = getOpenAndCloseBraces(part);
54
- if (braces) {
55
- const [openBrace, closeBrace] = braces;
56
- const firstChar = part.charCodeAt(openBrace + 1);
57
- if (firstChar === 45) {
58
- if (openBrace + 2 < part.length && part.charCodeAt(openBrace + 2) === 36) {
59
- const paramStart = openBrace + 3;
60
- const paramEnd = closeBrace;
61
- if (paramStart < paramEnd) {
62
- output[0] = SEGMENT_TYPE_OPTIONAL_PARAM;
63
- output[1] = start + openBrace;
64
- output[2] = start + paramStart;
65
- output[3] = start + paramEnd;
66
- output[4] = start + closeBrace + 1;
67
- output[5] = end;
68
- return output;
69
- }
70
- }
71
- } else if (firstChar === 36) {
72
- const dollarPos = openBrace + 1;
73
- const afterDollar = openBrace + 2;
74
- if (afterDollar === closeBrace) {
75
- output[0] = SEGMENT_TYPE_WILDCARD;
76
- output[1] = start + openBrace;
77
- output[2] = start + dollarPos;
78
- output[3] = start + afterDollar;
79
- output[4] = start + closeBrace + 1;
80
- output[5] = path.length;
81
- return output;
82
- }
83
- output[0] = SEGMENT_TYPE_PARAM;
84
- output[1] = start + openBrace;
85
- output[2] = start + afterDollar;
86
- output[3] = start + closeBrace;
87
- output[4] = start + closeBrace + 1;
88
- output[5] = end;
89
- return output;
90
- }
91
- }
92
- output[0] = SEGMENT_TYPE_PATHNAME;
93
- output[1] = start;
94
- output[2] = start;
95
- output[3] = end;
96
- output[4] = end;
97
- output[5] = end;
98
- return output;
33
+ const next = path.indexOf("/", start);
34
+ const end = next === -1 ? path.length : next;
35
+ const part = path.substring(start, end);
36
+ if (!part || !part.includes("$")) {
37
+ output[0] = 0;
38
+ output[1] = start;
39
+ output[2] = start;
40
+ output[3] = end;
41
+ output[4] = end;
42
+ output[5] = end;
43
+ return output;
44
+ }
45
+ if (part === "$") {
46
+ const total = path.length;
47
+ output[0] = 2;
48
+ output[1] = start;
49
+ output[2] = start;
50
+ output[3] = total;
51
+ output[4] = total;
52
+ output[5] = total;
53
+ return output;
54
+ }
55
+ if (part.charCodeAt(0) === 36) {
56
+ output[0] = 1;
57
+ output[1] = start;
58
+ output[2] = start + 1;
59
+ output[3] = end;
60
+ output[4] = end;
61
+ output[5] = end;
62
+ return output;
63
+ }
64
+ const braces = getOpenAndCloseBraces(part);
65
+ if (braces) {
66
+ const [openBrace, closeBrace] = braces;
67
+ const firstChar = part.charCodeAt(openBrace + 1);
68
+ if (firstChar === 45) {
69
+ if (openBrace + 2 < part.length && part.charCodeAt(openBrace + 2) === 36) {
70
+ const paramStart = openBrace + 3;
71
+ const paramEnd = closeBrace;
72
+ if (paramStart < paramEnd) {
73
+ output[0] = 3;
74
+ output[1] = start + openBrace;
75
+ output[2] = start + paramStart;
76
+ output[3] = start + paramEnd;
77
+ output[4] = start + closeBrace + 1;
78
+ output[5] = end;
79
+ return output;
80
+ }
81
+ }
82
+ } else if (firstChar === 36) {
83
+ const dollarPos = openBrace + 1;
84
+ const afterDollar = openBrace + 2;
85
+ if (afterDollar === closeBrace) {
86
+ output[0] = 2;
87
+ output[1] = start + openBrace;
88
+ output[2] = start + dollarPos;
89
+ output[3] = start + afterDollar;
90
+ output[4] = start + closeBrace + 1;
91
+ output[5] = path.length;
92
+ return output;
93
+ }
94
+ output[0] = 1;
95
+ output[1] = start + openBrace;
96
+ output[2] = start + afterDollar;
97
+ output[3] = start + closeBrace;
98
+ output[4] = start + closeBrace + 1;
99
+ output[5] = end;
100
+ return output;
101
+ }
102
+ }
103
+ output[0] = 0;
104
+ output[1] = start;
105
+ output[2] = start;
106
+ output[3] = end;
107
+ output[4] = end;
108
+ output[5] = end;
109
+ return output;
99
110
  }
111
+ /**
112
+ * Recursively parses the segments of the given route tree and populates a segment trie.
113
+ *
114
+ * @param data A reusable Uint16Array for parsing segments. (non important, we're just avoiding allocations)
115
+ * @param route The current route to parse.
116
+ * @param start The starting index for parsing within the route's full path.
117
+ * @param node The current segment node in the trie to populate.
118
+ * @param onRoute Callback invoked for each route processed.
119
+ */
100
120
  function parseSegments(defaultCaseSensitive, data, route, start, node, depth, onRoute) {
101
- onRoute?.(route);
102
- let cursor = start;
103
- {
104
- const path = route.fullPath ?? route.from;
105
- const length = path.length;
106
- const caseSensitive = route.options?.caseSensitive ?? defaultCaseSensitive;
107
- const skipOnParamError = !!(route.options?.params?.parse && route.options?.skipRouteOnParseError?.params);
108
- while (cursor < length) {
109
- const segment = parseSegment(path, cursor, data);
110
- let nextNode;
111
- const start2 = cursor;
112
- const end = segment[5];
113
- cursor = end + 1;
114
- depth++;
115
- const kind = segment[0];
116
- switch (kind) {
117
- case SEGMENT_TYPE_PATHNAME: {
118
- const value = path.substring(segment[2], segment[3]);
119
- if (caseSensitive) {
120
- const existingNode = node.static?.get(value);
121
- if (existingNode) {
122
- nextNode = existingNode;
123
- } else {
124
- node.static ??= /* @__PURE__ */ new Map();
125
- const next = createStaticNode(
126
- route.fullPath ?? route.from
127
- );
128
- next.parent = node;
129
- next.depth = depth;
130
- nextNode = next;
131
- node.static.set(value, next);
132
- }
133
- } else {
134
- const name = value.toLowerCase();
135
- const existingNode = node.staticInsensitive?.get(name);
136
- if (existingNode) {
137
- nextNode = existingNode;
138
- } else {
139
- node.staticInsensitive ??= /* @__PURE__ */ new Map();
140
- const next = createStaticNode(
141
- route.fullPath ?? route.from
142
- );
143
- next.parent = node;
144
- next.depth = depth;
145
- nextNode = next;
146
- node.staticInsensitive.set(name, next);
147
- }
148
- }
149
- break;
150
- }
151
- case SEGMENT_TYPE_PARAM: {
152
- const prefix_raw = path.substring(start2, segment[1]);
153
- const suffix_raw = path.substring(segment[4], end);
154
- const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
155
- const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
156
- const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
157
- const existingNode = !skipOnParamError && node.dynamic?.find(
158
- (s) => !s.skipOnParamError && s.caseSensitive === actuallyCaseSensitive && s.prefix === prefix && s.suffix === suffix
159
- );
160
- if (existingNode) {
161
- nextNode = existingNode;
162
- } else {
163
- const next = createDynamicNode(
164
- SEGMENT_TYPE_PARAM,
165
- route.fullPath ?? route.from,
166
- actuallyCaseSensitive,
167
- prefix,
168
- suffix
169
- );
170
- nextNode = next;
171
- next.depth = depth;
172
- next.parent = node;
173
- node.dynamic ??= [];
174
- node.dynamic.push(next);
175
- }
176
- break;
177
- }
178
- case SEGMENT_TYPE_OPTIONAL_PARAM: {
179
- const prefix_raw = path.substring(start2, segment[1]);
180
- const suffix_raw = path.substring(segment[4], end);
181
- const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
182
- const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
183
- const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
184
- const existingNode = !skipOnParamError && node.optional?.find(
185
- (s) => !s.skipOnParamError && s.caseSensitive === actuallyCaseSensitive && s.prefix === prefix && s.suffix === suffix
186
- );
187
- if (existingNode) {
188
- nextNode = existingNode;
189
- } else {
190
- const next = createDynamicNode(
191
- SEGMENT_TYPE_OPTIONAL_PARAM,
192
- route.fullPath ?? route.from,
193
- actuallyCaseSensitive,
194
- prefix,
195
- suffix
196
- );
197
- nextNode = next;
198
- next.parent = node;
199
- next.depth = depth;
200
- node.optional ??= [];
201
- node.optional.push(next);
202
- }
203
- break;
204
- }
205
- case SEGMENT_TYPE_WILDCARD: {
206
- const prefix_raw = path.substring(start2, segment[1]);
207
- const suffix_raw = path.substring(segment[4], end);
208
- const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
209
- const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
210
- const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
211
- const next = createDynamicNode(
212
- SEGMENT_TYPE_WILDCARD,
213
- route.fullPath ?? route.from,
214
- actuallyCaseSensitive,
215
- prefix,
216
- suffix
217
- );
218
- nextNode = next;
219
- next.parent = node;
220
- next.depth = depth;
221
- node.wildcard ??= [];
222
- node.wildcard.push(next);
223
- }
224
- }
225
- node = nextNode;
226
- }
227
- if (skipOnParamError && route.children && !route.isRoot && route.id && route.id.charCodeAt(route.id.lastIndexOf("/") + 1) === 95) {
228
- const pathlessNode = createStaticNode(
229
- route.fullPath ?? route.from
230
- );
231
- pathlessNode.kind = SEGMENT_TYPE_PATHLESS;
232
- pathlessNode.parent = node;
233
- depth++;
234
- pathlessNode.depth = depth;
235
- node.pathless ??= [];
236
- node.pathless.push(pathlessNode);
237
- node = pathlessNode;
238
- }
239
- const isLeaf = (route.path || !route.children) && !route.isRoot;
240
- if (isLeaf && path.endsWith("/")) {
241
- const indexNode = createStaticNode(
242
- route.fullPath ?? route.from
243
- );
244
- indexNode.kind = SEGMENT_TYPE_INDEX;
245
- indexNode.parent = node;
246
- depth++;
247
- indexNode.depth = depth;
248
- node.index = indexNode;
249
- node = indexNode;
250
- }
251
- node.parse = route.options?.params?.parse ?? null;
252
- node.skipOnParamError = skipOnParamError;
253
- node.parsingPriority = route.options?.skipRouteOnParseError?.priority ?? 0;
254
- if (isLeaf && !node.route) {
255
- node.route = route;
256
- node.fullPath = route.fullPath ?? route.from;
257
- }
258
- }
259
- if (route.children)
260
- for (const child of route.children) {
261
- parseSegments(
262
- defaultCaseSensitive,
263
- data,
264
- child,
265
- cursor,
266
- node,
267
- depth,
268
- onRoute
269
- );
270
- }
121
+ onRoute?.(route);
122
+ let cursor = start;
123
+ {
124
+ const path = route.fullPath ?? route.from;
125
+ const length = path.length;
126
+ const caseSensitive = route.options?.caseSensitive ?? defaultCaseSensitive;
127
+ const skipOnParamError = !!(route.options?.params?.parse && route.options?.skipRouteOnParseError?.params);
128
+ while (cursor < length) {
129
+ const segment = parseSegment(path, cursor, data);
130
+ let nextNode;
131
+ const start = cursor;
132
+ const end = segment[5];
133
+ cursor = end + 1;
134
+ depth++;
135
+ switch (segment[0]) {
136
+ case 0: {
137
+ const value = path.substring(segment[2], segment[3]);
138
+ if (caseSensitive) {
139
+ const existingNode = node.static?.get(value);
140
+ if (existingNode) nextNode = existingNode;
141
+ else {
142
+ node.static ??= /* @__PURE__ */ new Map();
143
+ const next = createStaticNode(route.fullPath ?? route.from);
144
+ next.parent = node;
145
+ next.depth = depth;
146
+ nextNode = next;
147
+ node.static.set(value, next);
148
+ }
149
+ } else {
150
+ const name = value.toLowerCase();
151
+ const existingNode = node.staticInsensitive?.get(name);
152
+ if (existingNode) nextNode = existingNode;
153
+ else {
154
+ node.staticInsensitive ??= /* @__PURE__ */ new Map();
155
+ const next = createStaticNode(route.fullPath ?? route.from);
156
+ next.parent = node;
157
+ next.depth = depth;
158
+ nextNode = next;
159
+ node.staticInsensitive.set(name, next);
160
+ }
161
+ }
162
+ break;
163
+ }
164
+ case 1: {
165
+ const prefix_raw = path.substring(start, segment[1]);
166
+ const suffix_raw = path.substring(segment[4], end);
167
+ const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
168
+ const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
169
+ const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
170
+ const existingNode = !skipOnParamError && node.dynamic?.find((s) => !s.skipOnParamError && s.caseSensitive === actuallyCaseSensitive && s.prefix === prefix && s.suffix === suffix);
171
+ if (existingNode) nextNode = existingNode;
172
+ else {
173
+ const next = createDynamicNode(1, route.fullPath ?? route.from, actuallyCaseSensitive, prefix, suffix);
174
+ nextNode = next;
175
+ next.depth = depth;
176
+ next.parent = node;
177
+ node.dynamic ??= [];
178
+ node.dynamic.push(next);
179
+ }
180
+ break;
181
+ }
182
+ case 3: {
183
+ const prefix_raw = path.substring(start, segment[1]);
184
+ const suffix_raw = path.substring(segment[4], end);
185
+ const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
186
+ const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
187
+ const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
188
+ const existingNode = !skipOnParamError && node.optional?.find((s) => !s.skipOnParamError && s.caseSensitive === actuallyCaseSensitive && s.prefix === prefix && s.suffix === suffix);
189
+ if (existingNode) nextNode = existingNode;
190
+ else {
191
+ const next = createDynamicNode(3, route.fullPath ?? route.from, actuallyCaseSensitive, prefix, suffix);
192
+ nextNode = next;
193
+ next.parent = node;
194
+ next.depth = depth;
195
+ node.optional ??= [];
196
+ node.optional.push(next);
197
+ }
198
+ break;
199
+ }
200
+ case 2: {
201
+ const prefix_raw = path.substring(start, segment[1]);
202
+ const suffix_raw = path.substring(segment[4], end);
203
+ const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
204
+ const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
205
+ const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
206
+ const next = createDynamicNode(2, route.fullPath ?? route.from, actuallyCaseSensitive, prefix, suffix);
207
+ nextNode = next;
208
+ next.parent = node;
209
+ next.depth = depth;
210
+ node.wildcard ??= [];
211
+ node.wildcard.push(next);
212
+ }
213
+ }
214
+ node = nextNode;
215
+ }
216
+ if (skipOnParamError && route.children && !route.isRoot && route.id && route.id.charCodeAt(route.id.lastIndexOf("/") + 1) === 95) {
217
+ const pathlessNode = createStaticNode(route.fullPath ?? route.from);
218
+ pathlessNode.kind = SEGMENT_TYPE_PATHLESS;
219
+ pathlessNode.parent = node;
220
+ depth++;
221
+ pathlessNode.depth = depth;
222
+ node.pathless ??= [];
223
+ node.pathless.push(pathlessNode);
224
+ node = pathlessNode;
225
+ }
226
+ const isLeaf = (route.path || !route.children) && !route.isRoot;
227
+ if (isLeaf && path.endsWith("/")) {
228
+ const indexNode = createStaticNode(route.fullPath ?? route.from);
229
+ indexNode.kind = SEGMENT_TYPE_INDEX;
230
+ indexNode.parent = node;
231
+ depth++;
232
+ indexNode.depth = depth;
233
+ node.index = indexNode;
234
+ node = indexNode;
235
+ }
236
+ node.parse = route.options?.params?.parse ?? null;
237
+ node.skipOnParamError = skipOnParamError;
238
+ node.parsingPriority = route.options?.skipRouteOnParseError?.priority ?? 0;
239
+ if (isLeaf && !node.route) {
240
+ node.route = route;
241
+ node.fullPath = route.fullPath ?? route.from;
242
+ }
243
+ }
244
+ if (route.children) for (const child of route.children) parseSegments(defaultCaseSensitive, data, child, cursor, node, depth, onRoute);
271
245
  }
272
246
  function sortDynamic(a, b) {
273
- if (a.skipOnParamError && !b.skipOnParamError) return -1;
274
- if (!a.skipOnParamError && b.skipOnParamError) return 1;
275
- if (a.skipOnParamError && b.skipOnParamError && (a.parsingPriority || b.parsingPriority))
276
- return b.parsingPriority - a.parsingPriority;
277
- if (a.prefix && b.prefix && a.prefix !== b.prefix) {
278
- if (a.prefix.startsWith(b.prefix)) return -1;
279
- if (b.prefix.startsWith(a.prefix)) return 1;
280
- }
281
- if (a.suffix && b.suffix && a.suffix !== b.suffix) {
282
- if (a.suffix.endsWith(b.suffix)) return -1;
283
- if (b.suffix.endsWith(a.suffix)) return 1;
284
- }
285
- if (a.prefix && !b.prefix) return -1;
286
- if (!a.prefix && b.prefix) return 1;
287
- if (a.suffix && !b.suffix) return -1;
288
- if (!a.suffix && b.suffix) return 1;
289
- if (a.caseSensitive && !b.caseSensitive) return -1;
290
- if (!a.caseSensitive && b.caseSensitive) return 1;
291
- return 0;
247
+ if (a.skipOnParamError && !b.skipOnParamError) return -1;
248
+ if (!a.skipOnParamError && b.skipOnParamError) return 1;
249
+ if (a.skipOnParamError && b.skipOnParamError && (a.parsingPriority || b.parsingPriority)) return b.parsingPriority - a.parsingPriority;
250
+ if (a.prefix && b.prefix && a.prefix !== b.prefix) {
251
+ if (a.prefix.startsWith(b.prefix)) return -1;
252
+ if (b.prefix.startsWith(a.prefix)) return 1;
253
+ }
254
+ if (a.suffix && b.suffix && a.suffix !== b.suffix) {
255
+ if (a.suffix.endsWith(b.suffix)) return -1;
256
+ if (b.suffix.endsWith(a.suffix)) return 1;
257
+ }
258
+ if (a.prefix && !b.prefix) return -1;
259
+ if (!a.prefix && b.prefix) return 1;
260
+ if (a.suffix && !b.suffix) return -1;
261
+ if (!a.suffix && b.suffix) return 1;
262
+ if (a.caseSensitive && !b.caseSensitive) return -1;
263
+ if (!a.caseSensitive && b.caseSensitive) return 1;
264
+ return 0;
292
265
  }
293
266
  function sortTreeNodes(node) {
294
- if (node.pathless) {
295
- for (const child of node.pathless) {
296
- sortTreeNodes(child);
297
- }
298
- }
299
- if (node.static) {
300
- for (const child of node.static.values()) {
301
- sortTreeNodes(child);
302
- }
303
- }
304
- if (node.staticInsensitive) {
305
- for (const child of node.staticInsensitive.values()) {
306
- sortTreeNodes(child);
307
- }
308
- }
309
- if (node.dynamic?.length) {
310
- node.dynamic.sort(sortDynamic);
311
- for (const child of node.dynamic) {
312
- sortTreeNodes(child);
313
- }
314
- }
315
- if (node.optional?.length) {
316
- node.optional.sort(sortDynamic);
317
- for (const child of node.optional) {
318
- sortTreeNodes(child);
319
- }
320
- }
321
- if (node.wildcard?.length) {
322
- node.wildcard.sort(sortDynamic);
323
- for (const child of node.wildcard) {
324
- sortTreeNodes(child);
325
- }
326
- }
267
+ if (node.pathless) for (const child of node.pathless) sortTreeNodes(child);
268
+ if (node.static) for (const child of node.static.values()) sortTreeNodes(child);
269
+ if (node.staticInsensitive) for (const child of node.staticInsensitive.values()) sortTreeNodes(child);
270
+ if (node.dynamic?.length) {
271
+ node.dynamic.sort(sortDynamic);
272
+ for (const child of node.dynamic) sortTreeNodes(child);
273
+ }
274
+ if (node.optional?.length) {
275
+ node.optional.sort(sortDynamic);
276
+ for (const child of node.optional) sortTreeNodes(child);
277
+ }
278
+ if (node.wildcard?.length) {
279
+ node.wildcard.sort(sortDynamic);
280
+ for (const child of node.wildcard) sortTreeNodes(child);
281
+ }
327
282
  }
328
283
  function createStaticNode(fullPath) {
329
- return {
330
- kind: SEGMENT_TYPE_PATHNAME,
331
- depth: 0,
332
- pathless: null,
333
- index: null,
334
- static: null,
335
- staticInsensitive: null,
336
- dynamic: null,
337
- optional: null,
338
- wildcard: null,
339
- route: null,
340
- fullPath,
341
- parent: null,
342
- parse: null,
343
- skipOnParamError: false,
344
- parsingPriority: 0
345
- };
284
+ return {
285
+ kind: 0,
286
+ depth: 0,
287
+ pathless: null,
288
+ index: null,
289
+ static: null,
290
+ staticInsensitive: null,
291
+ dynamic: null,
292
+ optional: null,
293
+ wildcard: null,
294
+ route: null,
295
+ fullPath,
296
+ parent: null,
297
+ parse: null,
298
+ skipOnParamError: false,
299
+ parsingPriority: 0
300
+ };
346
301
  }
302
+ /**
303
+ * Keys must be declared in the same order as in `SegmentNode` type,
304
+ * to ensure they are represented as the same object class in the engine.
305
+ */
347
306
  function createDynamicNode(kind, fullPath, caseSensitive, prefix, suffix) {
348
- return {
349
- kind,
350
- depth: 0,
351
- pathless: null,
352
- index: null,
353
- static: null,
354
- staticInsensitive: null,
355
- dynamic: null,
356
- optional: null,
357
- wildcard: null,
358
- route: null,
359
- fullPath,
360
- parent: null,
361
- parse: null,
362
- skipOnParamError: false,
363
- parsingPriority: 0,
364
- caseSensitive,
365
- prefix,
366
- suffix
367
- };
307
+ return {
308
+ kind,
309
+ depth: 0,
310
+ pathless: null,
311
+ index: null,
312
+ static: null,
313
+ staticInsensitive: null,
314
+ dynamic: null,
315
+ optional: null,
316
+ wildcard: null,
317
+ route: null,
318
+ fullPath,
319
+ parent: null,
320
+ parse: null,
321
+ skipOnParamError: false,
322
+ parsingPriority: 0,
323
+ caseSensitive,
324
+ prefix,
325
+ suffix
326
+ };
368
327
  }
369
328
  function processRouteMasks(routeList, processedTree) {
370
- const segmentTree = createStaticNode("/");
371
- const data = new Uint16Array(6);
372
- for (const route of routeList) {
373
- parseSegments(false, data, route, 1, segmentTree, 0);
374
- }
375
- sortTreeNodes(segmentTree);
376
- processedTree.masksTree = segmentTree;
377
- processedTree.flatCache = lruCache.createLRUCache(1e3);
329
+ const segmentTree = createStaticNode("/");
330
+ const data = new Uint16Array(6);
331
+ for (const route of routeList) parseSegments(false, data, route, 1, segmentTree, 0);
332
+ sortTreeNodes(segmentTree);
333
+ processedTree.masksTree = segmentTree;
334
+ processedTree.flatCache = require_lru_cache.createLRUCache(1e3);
378
335
  }
336
+ /**
337
+ * Take an arbitrary list of routes, create a tree from them (if it hasn't been created already), and match a path against it.
338
+ */
379
339
  function findFlatMatch(path, processedTree) {
380
- path ||= "/";
381
- const cached = processedTree.flatCache.get(path);
382
- if (cached) return cached;
383
- const result = findMatch(path, processedTree.masksTree);
384
- processedTree.flatCache.set(path, result);
385
- return result;
340
+ path ||= "/";
341
+ const cached = processedTree.flatCache.get(path);
342
+ if (cached) return cached;
343
+ const result = findMatch(path, processedTree.masksTree);
344
+ processedTree.flatCache.set(path, result);
345
+ return result;
386
346
  }
347
+ /**
348
+ * @deprecated keep until v2 so that `router.matchRoute` can keep not caring about the actual route tree
349
+ */
387
350
  function findSingleMatch(from, caseSensitive, fuzzy, path, processedTree) {
388
- from ||= "/";
389
- path ||= "/";
390
- const key = caseSensitive ? `case\0${from}` : from;
391
- let tree = processedTree.singleCache.get(key);
392
- if (!tree) {
393
- tree = createStaticNode("/");
394
- const data = new Uint16Array(6);
395
- parseSegments(caseSensitive, data, { from }, 1, tree, 0);
396
- processedTree.singleCache.set(key, tree);
397
- }
398
- return findMatch(path, tree, fuzzy);
351
+ from ||= "/";
352
+ path ||= "/";
353
+ const key = caseSensitive ? `case\0${from}` : from;
354
+ let tree = processedTree.singleCache.get(key);
355
+ if (!tree) {
356
+ tree = createStaticNode("/");
357
+ parseSegments(caseSensitive, new Uint16Array(6), { from }, 1, tree, 0);
358
+ processedTree.singleCache.set(key, tree);
359
+ }
360
+ return findMatch(path, tree, fuzzy);
399
361
  }
400
362
  function findRouteMatch(path, processedTree, fuzzy = false) {
401
- const key = fuzzy ? path : `nofuzz\0${path}`;
402
- const cached = processedTree.matchCache.get(key);
403
- if (cached !== void 0) return cached;
404
- path ||= "/";
405
- let result;
406
- try {
407
- result = findMatch(
408
- path,
409
- processedTree.segmentTree,
410
- fuzzy
411
- );
412
- } catch (err) {
413
- if (err instanceof URIError) {
414
- result = null;
415
- } else {
416
- throw err;
417
- }
418
- }
419
- if (result) result.branch = buildRouteBranch(result.route);
420
- processedTree.matchCache.set(key, result);
421
- return result;
363
+ const key = fuzzy ? path : `nofuzz\0${path}`;
364
+ const cached = processedTree.matchCache.get(key);
365
+ if (cached !== void 0) return cached;
366
+ path ||= "/";
367
+ let result;
368
+ try {
369
+ result = findMatch(path, processedTree.segmentTree, fuzzy);
370
+ } catch (err) {
371
+ if (err instanceof URIError) result = null;
372
+ else throw err;
373
+ }
374
+ if (result) result.branch = buildRouteBranch(result.route);
375
+ processedTree.matchCache.set(key, result);
376
+ return result;
422
377
  }
378
+ /** Trim trailing slashes (except preserving root '/'). */
423
379
  function trimPathRight(path) {
424
- return path === "/" ? path : path.replace(/\/{1,}$/, "");
380
+ return path === "/" ? path : path.replace(/\/{1,}$/, "");
425
381
  }
382
+ /**
383
+ * Processes a route tree into a segment trie for efficient path matching.
384
+ * Also builds lookup maps for routes by ID and by trimmed full path.
385
+ */
426
386
  function processRouteTree(routeTree, caseSensitive = false, initRoute) {
427
- const segmentTree = createStaticNode(routeTree.fullPath);
428
- const data = new Uint16Array(6);
429
- const routesById = {};
430
- const routesByPath = {};
431
- let index = 0;
432
- parseSegments(caseSensitive, data, routeTree, 1, segmentTree, 0, (route) => {
433
- initRoute?.(route, index);
434
- invariant(
435
- !(route.id in routesById),
436
- `Duplicate routes found with id: ${String(route.id)}`
437
- );
438
- routesById[route.id] = route;
439
- if (index !== 0 && route.path) {
440
- const trimmedFullPath = trimPathRight(route.fullPath);
441
- if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith("/")) {
442
- routesByPath[trimmedFullPath] = route;
443
- }
444
- }
445
- index++;
446
- });
447
- sortTreeNodes(segmentTree);
448
- const processedTree = {
449
- segmentTree,
450
- singleCache: lruCache.createLRUCache(1e3),
451
- matchCache: lruCache.createLRUCache(1e3),
452
- flatCache: null,
453
- masksTree: null
454
- };
455
- return {
456
- processedTree,
457
- routesById,
458
- routesByPath
459
- };
387
+ const segmentTree = createStaticNode(routeTree.fullPath);
388
+ const data = new Uint16Array(6);
389
+ const routesById = {};
390
+ const routesByPath = {};
391
+ let index = 0;
392
+ parseSegments(caseSensitive, data, routeTree, 1, segmentTree, 0, (route) => {
393
+ initRoute?.(route, index);
394
+ (0, tiny_invariant.default)(!(route.id in routesById), `Duplicate routes found with id: ${String(route.id)}`);
395
+ routesById[route.id] = route;
396
+ if (index !== 0 && route.path) {
397
+ const trimmedFullPath = trimPathRight(route.fullPath);
398
+ if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith("/")) routesByPath[trimmedFullPath] = route;
399
+ }
400
+ index++;
401
+ });
402
+ sortTreeNodes(segmentTree);
403
+ return {
404
+ processedTree: {
405
+ segmentTree,
406
+ singleCache: require_lru_cache.createLRUCache(1e3),
407
+ matchCache: require_lru_cache.createLRUCache(1e3),
408
+ flatCache: null,
409
+ masksTree: null
410
+ },
411
+ routesById,
412
+ routesByPath
413
+ };
460
414
  }
461
415
  function findMatch(path, segmentTree, fuzzy = false) {
462
- const parts = path.split("/");
463
- const leaf = getNodeMatch(path, parts, segmentTree, fuzzy);
464
- if (!leaf) return null;
465
- const [rawParams] = extractParams(path, parts, leaf);
466
- return {
467
- route: leaf.node.route,
468
- rawParams,
469
- parsedParams: leaf.parsedParams
470
- };
416
+ const parts = path.split("/");
417
+ const leaf = getNodeMatch(path, parts, segmentTree, fuzzy);
418
+ if (!leaf) return null;
419
+ const [rawParams] = extractParams(path, parts, leaf);
420
+ return {
421
+ route: leaf.node.route,
422
+ rawParams,
423
+ parsedParams: leaf.parsedParams
424
+ };
471
425
  }
426
+ /**
427
+ * This function is "resumable":
428
+ * - the `leaf` input can contain `extract` and `rawParams` properties from a previous `extractParams` call
429
+ * - the returned `state` can be passed back as `extract` in a future call to continue extracting params from where we left off
430
+ *
431
+ * Inputs are *not* mutated.
432
+ */
472
433
  function extractParams(path, parts, leaf) {
473
- const list = buildBranch(leaf.node);
474
- let nodeParts = null;
475
- const rawParams = /* @__PURE__ */ Object.create(null);
476
- let partIndex = leaf.extract?.part ?? 0;
477
- let nodeIndex = leaf.extract?.node ?? 0;
478
- let pathIndex = leaf.extract?.path ?? 0;
479
- let segmentCount = leaf.extract?.segment ?? 0;
480
- for (; nodeIndex < list.length; partIndex++, nodeIndex++, pathIndex++, segmentCount++) {
481
- const node = list[nodeIndex];
482
- if (node.kind === SEGMENT_TYPE_INDEX) break;
483
- if (node.kind === SEGMENT_TYPE_PATHLESS) {
484
- segmentCount--;
485
- partIndex--;
486
- pathIndex--;
487
- continue;
488
- }
489
- const part = parts[partIndex];
490
- const currentPathIndex = pathIndex;
491
- if (part) pathIndex += part.length;
492
- if (node.kind === SEGMENT_TYPE_PARAM) {
493
- nodeParts ??= leaf.node.fullPath.split("/");
494
- const nodePart = nodeParts[segmentCount];
495
- const preLength = node.prefix?.length ?? 0;
496
- const isCurlyBraced = nodePart.charCodeAt(preLength) === 123;
497
- if (isCurlyBraced) {
498
- const sufLength = node.suffix?.length ?? 0;
499
- const name = nodePart.substring(
500
- preLength + 2,
501
- nodePart.length - sufLength - 1
502
- );
503
- const value = part.substring(preLength, part.length - sufLength);
504
- rawParams[name] = decodeURIComponent(value);
505
- } else {
506
- const name = nodePart.substring(1);
507
- rawParams[name] = decodeURIComponent(part);
508
- }
509
- } else if (node.kind === SEGMENT_TYPE_OPTIONAL_PARAM) {
510
- if (leaf.skipped & 1 << nodeIndex) {
511
- partIndex--;
512
- pathIndex = currentPathIndex - 1;
513
- continue;
514
- }
515
- nodeParts ??= leaf.node.fullPath.split("/");
516
- const nodePart = nodeParts[segmentCount];
517
- const preLength = node.prefix?.length ?? 0;
518
- const sufLength = node.suffix?.length ?? 0;
519
- const name = nodePart.substring(
520
- preLength + 3,
521
- nodePart.length - sufLength - 1
522
- );
523
- const value = node.suffix || node.prefix ? part.substring(preLength, part.length - sufLength) : part;
524
- if (value) rawParams[name] = decodeURIComponent(value);
525
- } else if (node.kind === SEGMENT_TYPE_WILDCARD) {
526
- const n = node;
527
- const value = path.substring(
528
- currentPathIndex + (n.prefix?.length ?? 0),
529
- path.length - (n.suffix?.length ?? 0)
530
- );
531
- const splat = decodeURIComponent(value);
532
- rawParams["*"] = splat;
533
- rawParams._splat = splat;
534
- break;
535
- }
536
- }
537
- if (leaf.rawParams) Object.assign(rawParams, leaf.rawParams);
538
- return [
539
- rawParams,
540
- {
541
- part: partIndex,
542
- node: nodeIndex,
543
- path: pathIndex,
544
- segment: segmentCount
545
- }
546
- ];
434
+ const list = buildBranch(leaf.node);
435
+ let nodeParts = null;
436
+ const rawParams = Object.create(null);
437
+ /** which segment of the path we're currently processing */
438
+ let partIndex = leaf.extract?.part ?? 0;
439
+ /** which node of the route tree branch we're currently processing */
440
+ let nodeIndex = leaf.extract?.node ?? 0;
441
+ /** index of the 1st character of the segment we're processing in the path string */
442
+ let pathIndex = leaf.extract?.path ?? 0;
443
+ /** which fullPath segment we're currently processing */
444
+ let segmentCount = leaf.extract?.segment ?? 0;
445
+ for (; nodeIndex < list.length; partIndex++, nodeIndex++, pathIndex++, segmentCount++) {
446
+ const node = list[nodeIndex];
447
+ if (node.kind === SEGMENT_TYPE_INDEX) break;
448
+ if (node.kind === SEGMENT_TYPE_PATHLESS) {
449
+ segmentCount--;
450
+ partIndex--;
451
+ pathIndex--;
452
+ continue;
453
+ }
454
+ const part = parts[partIndex];
455
+ const currentPathIndex = pathIndex;
456
+ if (part) pathIndex += part.length;
457
+ if (node.kind === 1) {
458
+ nodeParts ??= leaf.node.fullPath.split("/");
459
+ const nodePart = nodeParts[segmentCount];
460
+ const preLength = node.prefix?.length ?? 0;
461
+ if (nodePart.charCodeAt(preLength) === 123) {
462
+ const sufLength = node.suffix?.length ?? 0;
463
+ const name = nodePart.substring(preLength + 2, nodePart.length - sufLength - 1);
464
+ const value = part.substring(preLength, part.length - sufLength);
465
+ rawParams[name] = decodeURIComponent(value);
466
+ } else {
467
+ const name = nodePart.substring(1);
468
+ rawParams[name] = decodeURIComponent(part);
469
+ }
470
+ } else if (node.kind === 3) {
471
+ if (leaf.skipped & 1 << nodeIndex) {
472
+ partIndex--;
473
+ pathIndex = currentPathIndex - 1;
474
+ continue;
475
+ }
476
+ nodeParts ??= leaf.node.fullPath.split("/");
477
+ const nodePart = nodeParts[segmentCount];
478
+ const preLength = node.prefix?.length ?? 0;
479
+ const sufLength = node.suffix?.length ?? 0;
480
+ const name = nodePart.substring(preLength + 3, nodePart.length - sufLength - 1);
481
+ const value = node.suffix || node.prefix ? part.substring(preLength, part.length - sufLength) : part;
482
+ if (value) rawParams[name] = decodeURIComponent(value);
483
+ } else if (node.kind === 2) {
484
+ const n = node;
485
+ const value = path.substring(currentPathIndex + (n.prefix?.length ?? 0), path.length - (n.suffix?.length ?? 0));
486
+ const splat = decodeURIComponent(value);
487
+ rawParams["*"] = splat;
488
+ rawParams._splat = splat;
489
+ break;
490
+ }
491
+ }
492
+ if (leaf.rawParams) Object.assign(rawParams, leaf.rawParams);
493
+ return [rawParams, {
494
+ part: partIndex,
495
+ node: nodeIndex,
496
+ path: pathIndex,
497
+ segment: segmentCount
498
+ }];
547
499
  }
548
500
  function buildRouteBranch(route) {
549
- const list = [route];
550
- while (route.parentRoute) {
551
- route = route.parentRoute;
552
- list.push(route);
553
- }
554
- list.reverse();
555
- return list;
501
+ const list = [route];
502
+ while (route.parentRoute) {
503
+ route = route.parentRoute;
504
+ list.push(route);
505
+ }
506
+ list.reverse();
507
+ return list;
556
508
  }
557
509
  function buildBranch(node) {
558
- const list = Array(node.depth + 1);
559
- do {
560
- list[node.depth] = node;
561
- node = node.parent;
562
- } while (node);
563
- return list;
510
+ const list = Array(node.depth + 1);
511
+ do {
512
+ list[node.depth] = node;
513
+ node = node.parent;
514
+ } while (node);
515
+ return list;
564
516
  }
565
517
  function getNodeMatch(path, parts, segmentTree, fuzzy) {
566
- if (path === "/" && segmentTree.index)
567
- return { node: segmentTree.index, skipped: 0 };
568
- const trailingSlash = !utils.last(parts);
569
- const pathIsIndex = trailingSlash && path !== "/";
570
- const partsLength = parts.length - (trailingSlash ? 1 : 0);
571
- const stack = [
572
- {
573
- node: segmentTree,
574
- index: 1,
575
- skipped: 0,
576
- depth: 1,
577
- statics: 1,
578
- dynamics: 0,
579
- optionals: 0
580
- }
581
- ];
582
- let wildcardMatch = null;
583
- let bestFuzzy = null;
584
- let bestMatch = null;
585
- while (stack.length) {
586
- const frame = stack.pop();
587
- const { node, index, skipped, depth, statics, dynamics, optionals } = frame;
588
- let { extract, rawParams, parsedParams } = frame;
589
- if (node.skipOnParamError) {
590
- const result = validateMatchParams(path, parts, frame);
591
- if (!result) continue;
592
- rawParams = frame.rawParams;
593
- extract = frame.extract;
594
- parsedParams = frame.parsedParams;
595
- }
596
- if (fuzzy && node.route && node.kind !== SEGMENT_TYPE_INDEX && isFrameMoreSpecific(bestFuzzy, frame)) {
597
- bestFuzzy = frame;
598
- }
599
- const isBeyondPath = index === partsLength;
600
- if (isBeyondPath) {
601
- if (node.route && !pathIsIndex && isFrameMoreSpecific(bestMatch, frame)) {
602
- bestMatch = frame;
603
- }
604
- if (!node.optional && !node.wildcard && !node.index && !node.pathless)
605
- continue;
606
- }
607
- const part = isBeyondPath ? void 0 : parts[index];
608
- let lowerPart;
609
- if (isBeyondPath && node.index) {
610
- const indexFrame = {
611
- node: node.index,
612
- index,
613
- skipped,
614
- depth: depth + 1,
615
- statics,
616
- dynamics,
617
- optionals,
618
- extract,
619
- rawParams,
620
- parsedParams
621
- };
622
- let indexValid = true;
623
- if (node.index.skipOnParamError) {
624
- const result = validateMatchParams(path, parts, indexFrame);
625
- if (!result) indexValid = false;
626
- }
627
- if (indexValid) {
628
- if (statics === partsLength && !dynamics && !optionals && !skipped) {
629
- return indexFrame;
630
- }
631
- if (isFrameMoreSpecific(bestMatch, indexFrame)) {
632
- bestMatch = indexFrame;
633
- }
634
- }
635
- }
636
- if (node.wildcard && isFrameMoreSpecific(wildcardMatch, frame)) {
637
- for (const segment of node.wildcard) {
638
- const { prefix, suffix } = segment;
639
- if (prefix) {
640
- if (isBeyondPath) continue;
641
- const casePart = segment.caseSensitive ? part : lowerPart ??= part.toLowerCase();
642
- if (!casePart.startsWith(prefix)) continue;
643
- }
644
- if (suffix) {
645
- if (isBeyondPath) continue;
646
- const end = parts.slice(index).join("/").slice(-suffix.length);
647
- const casePart = segment.caseSensitive ? end : end.toLowerCase();
648
- if (casePart !== suffix) continue;
649
- }
650
- const frame2 = {
651
- node: segment,
652
- index: partsLength,
653
- skipped,
654
- depth,
655
- statics,
656
- dynamics,
657
- optionals,
658
- extract,
659
- rawParams,
660
- parsedParams
661
- };
662
- if (segment.skipOnParamError) {
663
- const result = validateMatchParams(path, parts, frame2);
664
- if (!result) continue;
665
- }
666
- wildcardMatch = frame2;
667
- break;
668
- }
669
- }
670
- if (node.optional) {
671
- const nextSkipped = skipped | 1 << depth;
672
- const nextDepth = depth + 1;
673
- for (let i = node.optional.length - 1; i >= 0; i--) {
674
- const segment = node.optional[i];
675
- stack.push({
676
- node: segment,
677
- index,
678
- skipped: nextSkipped,
679
- depth: nextDepth,
680
- statics,
681
- dynamics,
682
- optionals,
683
- extract,
684
- rawParams,
685
- parsedParams
686
- });
687
- }
688
- if (!isBeyondPath) {
689
- for (let i = node.optional.length - 1; i >= 0; i--) {
690
- const segment = node.optional[i];
691
- const { prefix, suffix } = segment;
692
- if (prefix || suffix) {
693
- const casePart = segment.caseSensitive ? part : lowerPart ??= part.toLowerCase();
694
- if (prefix && !casePart.startsWith(prefix)) continue;
695
- if (suffix && !casePart.endsWith(suffix)) continue;
696
- }
697
- stack.push({
698
- node: segment,
699
- index: index + 1,
700
- skipped,
701
- depth: nextDepth,
702
- statics,
703
- dynamics,
704
- optionals: optionals + 1,
705
- extract,
706
- rawParams,
707
- parsedParams
708
- });
709
- }
710
- }
711
- }
712
- if (!isBeyondPath && node.dynamic && part) {
713
- for (let i = node.dynamic.length - 1; i >= 0; i--) {
714
- const segment = node.dynamic[i];
715
- const { prefix, suffix } = segment;
716
- if (prefix || suffix) {
717
- const casePart = segment.caseSensitive ? part : lowerPart ??= part.toLowerCase();
718
- if (prefix && !casePart.startsWith(prefix)) continue;
719
- if (suffix && !casePart.endsWith(suffix)) continue;
720
- }
721
- stack.push({
722
- node: segment,
723
- index: index + 1,
724
- skipped,
725
- depth: depth + 1,
726
- statics,
727
- dynamics: dynamics + 1,
728
- optionals,
729
- extract,
730
- rawParams,
731
- parsedParams
732
- });
733
- }
734
- }
735
- if (!isBeyondPath && node.staticInsensitive) {
736
- const match = node.staticInsensitive.get(
737
- lowerPart ??= part.toLowerCase()
738
- );
739
- if (match) {
740
- stack.push({
741
- node: match,
742
- index: index + 1,
743
- skipped,
744
- depth: depth + 1,
745
- statics: statics + 1,
746
- dynamics,
747
- optionals,
748
- extract,
749
- rawParams,
750
- parsedParams
751
- });
752
- }
753
- }
754
- if (!isBeyondPath && node.static) {
755
- const match = node.static.get(part);
756
- if (match) {
757
- stack.push({
758
- node: match,
759
- index: index + 1,
760
- skipped,
761
- depth: depth + 1,
762
- statics: statics + 1,
763
- dynamics,
764
- optionals,
765
- extract,
766
- rawParams,
767
- parsedParams
768
- });
769
- }
770
- }
771
- if (node.pathless) {
772
- const nextDepth = depth + 1;
773
- for (let i = node.pathless.length - 1; i >= 0; i--) {
774
- const segment = node.pathless[i];
775
- stack.push({
776
- node: segment,
777
- index,
778
- skipped,
779
- depth: nextDepth,
780
- statics,
781
- dynamics,
782
- optionals,
783
- extract,
784
- rawParams,
785
- parsedParams
786
- });
787
- }
788
- }
789
- }
790
- if (bestMatch && wildcardMatch) {
791
- return isFrameMoreSpecific(wildcardMatch, bestMatch) ? bestMatch : wildcardMatch;
792
- }
793
- if (bestMatch) return bestMatch;
794
- if (wildcardMatch) return wildcardMatch;
795
- if (fuzzy && bestFuzzy) {
796
- let sliceIndex = bestFuzzy.index;
797
- for (let i = 0; i < bestFuzzy.index; i++) {
798
- sliceIndex += parts[i].length;
799
- }
800
- const splat = sliceIndex === path.length ? "/" : path.slice(sliceIndex);
801
- bestFuzzy.rawParams ??= /* @__PURE__ */ Object.create(null);
802
- bestFuzzy.rawParams["**"] = decodeURIComponent(splat);
803
- return bestFuzzy;
804
- }
805
- return null;
518
+ if (path === "/" && segmentTree.index) return {
519
+ node: segmentTree.index,
520
+ skipped: 0
521
+ };
522
+ const trailingSlash = !require_utils.last(parts);
523
+ const pathIsIndex = trailingSlash && path !== "/";
524
+ const partsLength = parts.length - (trailingSlash ? 1 : 0);
525
+ const stack = [{
526
+ node: segmentTree,
527
+ index: 1,
528
+ skipped: 0,
529
+ depth: 1,
530
+ statics: 1,
531
+ dynamics: 0,
532
+ optionals: 0
533
+ }];
534
+ let wildcardMatch = null;
535
+ let bestFuzzy = null;
536
+ let bestMatch = null;
537
+ while (stack.length) {
538
+ const frame = stack.pop();
539
+ const { node, index, skipped, depth, statics, dynamics, optionals } = frame;
540
+ let { extract, rawParams, parsedParams } = frame;
541
+ if (node.skipOnParamError) {
542
+ if (!validateMatchParams(path, parts, frame)) continue;
543
+ rawParams = frame.rawParams;
544
+ extract = frame.extract;
545
+ parsedParams = frame.parsedParams;
546
+ }
547
+ if (fuzzy && node.route && node.kind !== SEGMENT_TYPE_INDEX && isFrameMoreSpecific(bestFuzzy, frame)) bestFuzzy = frame;
548
+ const isBeyondPath = index === partsLength;
549
+ if (isBeyondPath) {
550
+ if (node.route && !pathIsIndex && isFrameMoreSpecific(bestMatch, frame)) bestMatch = frame;
551
+ if (!node.optional && !node.wildcard && !node.index && !node.pathless) continue;
552
+ }
553
+ const part = isBeyondPath ? void 0 : parts[index];
554
+ let lowerPart;
555
+ if (isBeyondPath && node.index) {
556
+ const indexFrame = {
557
+ node: node.index,
558
+ index,
559
+ skipped,
560
+ depth: depth + 1,
561
+ statics,
562
+ dynamics,
563
+ optionals,
564
+ extract,
565
+ rawParams,
566
+ parsedParams
567
+ };
568
+ let indexValid = true;
569
+ if (node.index.skipOnParamError) {
570
+ if (!validateMatchParams(path, parts, indexFrame)) indexValid = false;
571
+ }
572
+ if (indexValid) {
573
+ if (statics === partsLength && !dynamics && !optionals && !skipped) return indexFrame;
574
+ if (isFrameMoreSpecific(bestMatch, indexFrame)) bestMatch = indexFrame;
575
+ }
576
+ }
577
+ if (node.wildcard && isFrameMoreSpecific(wildcardMatch, frame)) for (const segment of node.wildcard) {
578
+ const { prefix, suffix } = segment;
579
+ if (prefix) {
580
+ if (isBeyondPath) continue;
581
+ if (!(segment.caseSensitive ? part : lowerPart ??= part.toLowerCase()).startsWith(prefix)) continue;
582
+ }
583
+ if (suffix) {
584
+ if (isBeyondPath) continue;
585
+ const end = parts.slice(index).join("/").slice(-suffix.length);
586
+ if ((segment.caseSensitive ? end : end.toLowerCase()) !== suffix) continue;
587
+ }
588
+ const frame = {
589
+ node: segment,
590
+ index: partsLength,
591
+ skipped,
592
+ depth,
593
+ statics,
594
+ dynamics,
595
+ optionals,
596
+ extract,
597
+ rawParams,
598
+ parsedParams
599
+ };
600
+ if (segment.skipOnParamError) {
601
+ if (!validateMatchParams(path, parts, frame)) continue;
602
+ }
603
+ wildcardMatch = frame;
604
+ break;
605
+ }
606
+ if (node.optional) {
607
+ const nextSkipped = skipped | 1 << depth;
608
+ const nextDepth = depth + 1;
609
+ for (let i = node.optional.length - 1; i >= 0; i--) {
610
+ const segment = node.optional[i];
611
+ stack.push({
612
+ node: segment,
613
+ index,
614
+ skipped: nextSkipped,
615
+ depth: nextDepth,
616
+ statics,
617
+ dynamics,
618
+ optionals,
619
+ extract,
620
+ rawParams,
621
+ parsedParams
622
+ });
623
+ }
624
+ if (!isBeyondPath) for (let i = node.optional.length - 1; i >= 0; i--) {
625
+ const segment = node.optional[i];
626
+ const { prefix, suffix } = segment;
627
+ if (prefix || suffix) {
628
+ const casePart = segment.caseSensitive ? part : lowerPart ??= part.toLowerCase();
629
+ if (prefix && !casePart.startsWith(prefix)) continue;
630
+ if (suffix && !casePart.endsWith(suffix)) continue;
631
+ }
632
+ stack.push({
633
+ node: segment,
634
+ index: index + 1,
635
+ skipped,
636
+ depth: nextDepth,
637
+ statics,
638
+ dynamics,
639
+ optionals: optionals + 1,
640
+ extract,
641
+ rawParams,
642
+ parsedParams
643
+ });
644
+ }
645
+ }
646
+ if (!isBeyondPath && node.dynamic && part) for (let i = node.dynamic.length - 1; i >= 0; i--) {
647
+ const segment = node.dynamic[i];
648
+ const { prefix, suffix } = segment;
649
+ if (prefix || suffix) {
650
+ const casePart = segment.caseSensitive ? part : lowerPart ??= part.toLowerCase();
651
+ if (prefix && !casePart.startsWith(prefix)) continue;
652
+ if (suffix && !casePart.endsWith(suffix)) continue;
653
+ }
654
+ stack.push({
655
+ node: segment,
656
+ index: index + 1,
657
+ skipped,
658
+ depth: depth + 1,
659
+ statics,
660
+ dynamics: dynamics + 1,
661
+ optionals,
662
+ extract,
663
+ rawParams,
664
+ parsedParams
665
+ });
666
+ }
667
+ if (!isBeyondPath && node.staticInsensitive) {
668
+ const match = node.staticInsensitive.get(lowerPart ??= part.toLowerCase());
669
+ if (match) stack.push({
670
+ node: match,
671
+ index: index + 1,
672
+ skipped,
673
+ depth: depth + 1,
674
+ statics: statics + 1,
675
+ dynamics,
676
+ optionals,
677
+ extract,
678
+ rawParams,
679
+ parsedParams
680
+ });
681
+ }
682
+ if (!isBeyondPath && node.static) {
683
+ const match = node.static.get(part);
684
+ if (match) stack.push({
685
+ node: match,
686
+ index: index + 1,
687
+ skipped,
688
+ depth: depth + 1,
689
+ statics: statics + 1,
690
+ dynamics,
691
+ optionals,
692
+ extract,
693
+ rawParams,
694
+ parsedParams
695
+ });
696
+ }
697
+ if (node.pathless) {
698
+ const nextDepth = depth + 1;
699
+ for (let i = node.pathless.length - 1; i >= 0; i--) {
700
+ const segment = node.pathless[i];
701
+ stack.push({
702
+ node: segment,
703
+ index,
704
+ skipped,
705
+ depth: nextDepth,
706
+ statics,
707
+ dynamics,
708
+ optionals,
709
+ extract,
710
+ rawParams,
711
+ parsedParams
712
+ });
713
+ }
714
+ }
715
+ }
716
+ if (bestMatch && wildcardMatch) return isFrameMoreSpecific(wildcardMatch, bestMatch) ? bestMatch : wildcardMatch;
717
+ if (bestMatch) return bestMatch;
718
+ if (wildcardMatch) return wildcardMatch;
719
+ if (fuzzy && bestFuzzy) {
720
+ let sliceIndex = bestFuzzy.index;
721
+ for (let i = 0; i < bestFuzzy.index; i++) sliceIndex += parts[i].length;
722
+ const splat = sliceIndex === path.length ? "/" : path.slice(sliceIndex);
723
+ bestFuzzy.rawParams ??= Object.create(null);
724
+ bestFuzzy.rawParams["**"] = decodeURIComponent(splat);
725
+ return bestFuzzy;
726
+ }
727
+ return null;
806
728
  }
807
729
  function validateMatchParams(path, parts, frame) {
808
- try {
809
- const [rawParams, state] = extractParams(path, parts, frame);
810
- frame.rawParams = rawParams;
811
- frame.extract = state;
812
- const parsed = frame.node.parse(rawParams);
813
- frame.parsedParams = Object.assign(
814
- /* @__PURE__ */ Object.create(null),
815
- frame.parsedParams,
816
- parsed
817
- );
818
- return true;
819
- } catch {
820
- return null;
821
- }
730
+ try {
731
+ const [rawParams, state] = extractParams(path, parts, frame);
732
+ frame.rawParams = rawParams;
733
+ frame.extract = state;
734
+ const parsed = frame.node.parse(rawParams);
735
+ frame.parsedParams = Object.assign(Object.create(null), frame.parsedParams, parsed);
736
+ return true;
737
+ } catch {
738
+ return null;
739
+ }
822
740
  }
823
741
  function isFrameMoreSpecific(prev, next) {
824
- if (!prev) return true;
825
- return next.statics > prev.statics || next.statics === prev.statics && (next.dynamics > prev.dynamics || next.dynamics === prev.dynamics && (next.optionals > prev.optionals || next.optionals === prev.optionals && ((next.node.kind === SEGMENT_TYPE_INDEX) > (prev.node.kind === SEGMENT_TYPE_INDEX) || next.node.kind === SEGMENT_TYPE_INDEX === (prev.node.kind === SEGMENT_TYPE_INDEX) && next.depth > prev.depth)));
742
+ if (!prev) return true;
743
+ return next.statics > prev.statics || next.statics === prev.statics && (next.dynamics > prev.dynamics || next.dynamics === prev.dynamics && (next.optionals > prev.optionals || next.optionals === prev.optionals && ((next.node.kind === SEGMENT_TYPE_INDEX) > (prev.node.kind === SEGMENT_TYPE_INDEX) || next.node.kind === SEGMENT_TYPE_INDEX === (prev.node.kind === SEGMENT_TYPE_INDEX) && next.depth > prev.depth)));
826
744
  }
827
- exports.SEGMENT_TYPE_OPTIONAL_PARAM = SEGMENT_TYPE_OPTIONAL_PARAM;
828
- exports.SEGMENT_TYPE_PARAM = SEGMENT_TYPE_PARAM;
829
- exports.SEGMENT_TYPE_PATHNAME = SEGMENT_TYPE_PATHNAME;
830
- exports.SEGMENT_TYPE_WILDCARD = SEGMENT_TYPE_WILDCARD;
745
+ //#endregion
831
746
  exports.findFlatMatch = findFlatMatch;
832
747
  exports.findRouteMatch = findRouteMatch;
833
748
  exports.findSingleMatch = findSingleMatch;
834
749
  exports.parseSegment = parseSegment;
835
750
  exports.processRouteMasks = processRouteMasks;
836
751
  exports.processRouteTree = processRouteTree;
837
- exports.trimPathRight = trimPathRight;
838
- //# sourceMappingURL=new-process-route-tree.cjs.map
752
+
753
+ //# sourceMappingURL=new-process-route-tree.cjs.map