@tanstack/router-core 1.121.0-alpha.27 → 1.121.0-alpha.28

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 (165) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +31 -1
  3. package/dist/cjs/RouterProvider.d.cts +2 -1
  4. package/dist/cjs/defer.cjs +1 -1
  5. package/dist/cjs/defer.cjs.map +1 -1
  6. package/dist/cjs/global.d.cts +7 -0
  7. package/dist/cjs/index.cjs +1 -2
  8. package/dist/cjs/index.cjs.map +1 -1
  9. package/dist/cjs/index.d.cts +6 -6
  10. package/dist/cjs/link.cjs.map +1 -1
  11. package/dist/cjs/link.d.cts +12 -0
  12. package/dist/cjs/lru-cache.cjs +62 -0
  13. package/dist/cjs/lru-cache.cjs.map +1 -0
  14. package/dist/cjs/lru-cache.d.cts +5 -0
  15. package/dist/cjs/not-found.cjs +1 -1
  16. package/dist/cjs/not-found.cjs.map +1 -1
  17. package/dist/cjs/path.cjs +316 -148
  18. package/dist/cjs/path.cjs.map +1 -1
  19. package/dist/cjs/path.d.cts +18 -24
  20. package/dist/cjs/qss.cjs.map +1 -1
  21. package/dist/cjs/redirect.cjs +3 -0
  22. package/dist/cjs/redirect.cjs.map +1 -1
  23. package/dist/cjs/route.cjs +6 -12
  24. package/dist/cjs/route.cjs.map +1 -1
  25. package/dist/cjs/route.d.cts +29 -9
  26. package/dist/cjs/router.cjs +453 -272
  27. package/dist/cjs/router.cjs.map +1 -1
  28. package/dist/cjs/router.d.cts +55 -85
  29. package/dist/cjs/scroll-restoration.cjs +20 -13
  30. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  31. package/dist/cjs/scroll-restoration.d.cts +9 -1
  32. package/dist/cjs/searchMiddleware.cjs.map +1 -1
  33. package/dist/cjs/searchParams.cjs.map +1 -1
  34. package/dist/cjs/ssr/client.cjs +10 -0
  35. package/dist/cjs/ssr/client.cjs.map +1 -0
  36. package/dist/cjs/ssr/client.d.cts +5 -0
  37. package/dist/cjs/ssr/createRequestHandler.cjs +50 -0
  38. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -0
  39. package/dist/cjs/ssr/createRequestHandler.d.cts +9 -0
  40. package/dist/cjs/ssr/handlerCallback.cjs +7 -0
  41. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -0
  42. package/dist/cjs/ssr/handlerCallback.d.cts +9 -0
  43. package/dist/cjs/ssr/headers.cjs +39 -0
  44. package/dist/cjs/ssr/headers.cjs.map +1 -0
  45. package/dist/cjs/ssr/headers.d.cts +5 -0
  46. package/dist/cjs/ssr/json.cjs +14 -0
  47. package/dist/cjs/ssr/json.cjs.map +1 -0
  48. package/dist/cjs/ssr/json.d.cts +4 -0
  49. package/dist/cjs/ssr/seroval-plugins.cjs +34 -0
  50. package/dist/cjs/ssr/seroval-plugins.cjs.map +1 -0
  51. package/dist/cjs/ssr/seroval-plugins.d.cts +10 -0
  52. package/dist/cjs/ssr/server.cjs +13 -0
  53. package/dist/cjs/ssr/server.cjs.map +1 -0
  54. package/dist/cjs/ssr/server.d.cts +6 -0
  55. package/dist/cjs/ssr/ssr-client.cjs +159 -0
  56. package/dist/cjs/ssr/ssr-client.cjs.map +1 -0
  57. package/dist/cjs/ssr/ssr-client.d.cts +29 -0
  58. package/dist/cjs/ssr/ssr-server.cjs +107 -0
  59. package/dist/cjs/ssr/ssr-server.cjs.map +1 -0
  60. package/dist/cjs/ssr/ssr-server.d.cts +18 -0
  61. package/dist/cjs/ssr/transformStreamWithRouter.cjs +183 -0
  62. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -0
  63. package/dist/cjs/ssr/transformStreamWithRouter.d.cts +6 -0
  64. package/dist/cjs/ssr/tsrScript.cjs +4 -0
  65. package/dist/cjs/ssr/tsrScript.cjs.map +1 -0
  66. package/dist/cjs/ssr/tsrScript.d.cts +0 -0
  67. package/dist/cjs/utils.cjs +7 -25
  68. package/dist/cjs/utils.cjs.map +1 -1
  69. package/dist/cjs/utils.d.cts +1 -6
  70. package/dist/esm/Matches.d.ts +31 -1
  71. package/dist/esm/Matches.js.map +1 -1
  72. package/dist/esm/RouterProvider.d.ts +2 -1
  73. package/dist/esm/defer.js +1 -1
  74. package/dist/esm/defer.js.map +1 -1
  75. package/dist/esm/global.d.ts +7 -0
  76. package/dist/esm/index.d.ts +6 -6
  77. package/dist/esm/index.js +2 -3
  78. package/dist/esm/link.d.ts +12 -0
  79. package/dist/esm/link.js.map +1 -1
  80. package/dist/esm/lru-cache.d.ts +5 -0
  81. package/dist/esm/lru-cache.js +62 -0
  82. package/dist/esm/lru-cache.js.map +1 -0
  83. package/dist/esm/not-found.js +1 -1
  84. package/dist/esm/not-found.js.map +1 -1
  85. package/dist/esm/path.d.ts +18 -24
  86. package/dist/esm/path.js +316 -148
  87. package/dist/esm/path.js.map +1 -1
  88. package/dist/esm/qss.js.map +1 -1
  89. package/dist/esm/redirect.js +3 -0
  90. package/dist/esm/redirect.js.map +1 -1
  91. package/dist/esm/route.d.ts +29 -9
  92. package/dist/esm/route.js +6 -12
  93. package/dist/esm/route.js.map +1 -1
  94. package/dist/esm/router.d.ts +55 -85
  95. package/dist/esm/router.js +462 -281
  96. package/dist/esm/router.js.map +1 -1
  97. package/dist/esm/scroll-restoration.d.ts +9 -1
  98. package/dist/esm/scroll-restoration.js +20 -13
  99. package/dist/esm/scroll-restoration.js.map +1 -1
  100. package/dist/esm/searchMiddleware.js.map +1 -1
  101. package/dist/esm/searchParams.js.map +1 -1
  102. package/dist/esm/ssr/client.d.ts +5 -0
  103. package/dist/esm/ssr/client.js +10 -0
  104. package/dist/esm/ssr/client.js.map +1 -0
  105. package/dist/esm/ssr/createRequestHandler.d.ts +9 -0
  106. package/dist/esm/ssr/createRequestHandler.js +50 -0
  107. package/dist/esm/ssr/createRequestHandler.js.map +1 -0
  108. package/dist/esm/ssr/handlerCallback.d.ts +9 -0
  109. package/dist/esm/ssr/handlerCallback.js +7 -0
  110. package/dist/esm/ssr/handlerCallback.js.map +1 -0
  111. package/dist/esm/ssr/headers.d.ts +5 -0
  112. package/dist/esm/ssr/headers.js +39 -0
  113. package/dist/esm/ssr/headers.js.map +1 -0
  114. package/dist/esm/ssr/json.d.ts +4 -0
  115. package/dist/esm/ssr/json.js +14 -0
  116. package/dist/esm/ssr/json.js.map +1 -0
  117. package/dist/esm/ssr/seroval-plugins.d.ts +10 -0
  118. package/dist/esm/ssr/seroval-plugins.js +34 -0
  119. package/dist/esm/ssr/seroval-plugins.js.map +1 -0
  120. package/dist/esm/ssr/server.d.ts +6 -0
  121. package/dist/esm/ssr/server.js +13 -0
  122. package/dist/esm/ssr/server.js.map +1 -0
  123. package/dist/esm/ssr/ssr-client.d.ts +29 -0
  124. package/dist/esm/ssr/ssr-client.js +159 -0
  125. package/dist/esm/ssr/ssr-client.js.map +1 -0
  126. package/dist/esm/ssr/ssr-server.d.ts +18 -0
  127. package/dist/esm/ssr/ssr-server.js +107 -0
  128. package/dist/esm/ssr/ssr-server.js.map +1 -0
  129. package/dist/esm/ssr/transformStreamWithRouter.d.ts +6 -0
  130. package/dist/esm/ssr/transformStreamWithRouter.js +183 -0
  131. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -0
  132. package/dist/esm/ssr/tsrScript.d.ts +0 -0
  133. package/dist/esm/ssr/tsrScript.js +5 -0
  134. package/dist/esm/ssr/tsrScript.js.map +1 -0
  135. package/dist/esm/utils.d.ts +1 -6
  136. package/dist/esm/utils.js +8 -26
  137. package/dist/esm/utils.js.map +1 -1
  138. package/package.json +29 -2
  139. package/src/Matches.ts +40 -1
  140. package/src/RouterProvider.ts +2 -1
  141. package/src/global.ts +9 -0
  142. package/src/index.ts +12 -20
  143. package/src/link.ts +12 -0
  144. package/src/lru-cache.ts +68 -0
  145. package/src/path.ts +424 -174
  146. package/src/redirect.ts +3 -0
  147. package/src/route.ts +44 -13
  148. package/src/router.ts +580 -312
  149. package/src/scroll-restoration.ts +30 -18
  150. package/src/ssr/client.ts +5 -0
  151. package/src/ssr/createRequestHandler.ts +74 -0
  152. package/src/ssr/handlerCallback.ts +15 -0
  153. package/src/ssr/headers.ts +51 -0
  154. package/src/ssr/json.ts +18 -0
  155. package/src/ssr/seroval-plugins.ts +43 -0
  156. package/src/ssr/server.ts +10 -0
  157. package/src/ssr/ssr-client.ts +242 -0
  158. package/src/ssr/ssr-server.ts +132 -0
  159. package/src/ssr/transformStreamWithRouter.ts +259 -0
  160. package/src/ssr/tsrScript.ts +7 -0
  161. package/src/utils.ts +10 -39
  162. package/src/vite-env.d.ts +4 -0
  163. package/dist/cjs/serializer.d.cts +0 -22
  164. package/dist/esm/serializer.d.ts +0 -22
  165. package/src/serializer.ts +0 -32
package/dist/esm/path.js CHANGED
@@ -1,4 +1,8 @@
1
1
  import { last } from "./utils.js";
2
+ const SEGMENT_TYPE_PATHNAME = 0;
3
+ const SEGMENT_TYPE_PARAM = 1;
4
+ const SEGMENT_TYPE_WILDCARD = 2;
5
+ const SEGMENT_TYPE_OPTIONAL_PARAM = 3;
2
6
  function joinPaths(paths) {
3
7
  return cleanPath(
4
8
  paths.filter((val) => {
@@ -19,7 +23,7 @@ function trimPath(path) {
19
23
  return trimPathRight(trimPathLeft(path));
20
24
  }
21
25
  function removeTrailingSlash(value, basepath) {
22
- if ((value == null ? void 0 : value.endsWith("/")) && value !== "/" && value !== `${basepath}/`) {
26
+ if (value?.endsWith("/") && value !== "/" && value !== `${basepath}/`) {
23
27
  return value.slice(0, -1);
24
28
  }
25
29
  return value;
@@ -27,83 +31,108 @@ function removeTrailingSlash(value, basepath) {
27
31
  function exactPathTest(pathName1, pathName2, basepath) {
28
32
  return removeTrailingSlash(pathName1, basepath) === removeTrailingSlash(pathName2, basepath);
29
33
  }
34
+ function segmentToString(segment) {
35
+ const { type, value } = segment;
36
+ if (type === SEGMENT_TYPE_PATHNAME) {
37
+ return value;
38
+ }
39
+ const { prefixSegment, suffixSegment } = segment;
40
+ if (type === SEGMENT_TYPE_PARAM) {
41
+ const param = value.substring(1);
42
+ if (prefixSegment && suffixSegment) {
43
+ return `${prefixSegment}{$${param}}${suffixSegment}`;
44
+ } else if (prefixSegment) {
45
+ return `${prefixSegment}{$${param}}`;
46
+ } else if (suffixSegment) {
47
+ return `{$${param}}${suffixSegment}`;
48
+ }
49
+ }
50
+ if (type === SEGMENT_TYPE_OPTIONAL_PARAM) {
51
+ const param = value.substring(1);
52
+ if (prefixSegment && suffixSegment) {
53
+ return `${prefixSegment}{-$${param}}${suffixSegment}`;
54
+ } else if (prefixSegment) {
55
+ return `${prefixSegment}{-$${param}}`;
56
+ } else if (suffixSegment) {
57
+ return `{-$${param}}${suffixSegment}`;
58
+ }
59
+ return `{-$${param}}`;
60
+ }
61
+ if (type === SEGMENT_TYPE_WILDCARD) {
62
+ if (prefixSegment && suffixSegment) {
63
+ return `${prefixSegment}{$}${suffixSegment}`;
64
+ } else if (prefixSegment) {
65
+ return `${prefixSegment}{$}`;
66
+ } else if (suffixSegment) {
67
+ return `{$}${suffixSegment}`;
68
+ }
69
+ }
70
+ return value;
71
+ }
30
72
  function resolvePath({
31
73
  basepath,
32
74
  base,
33
75
  to,
34
76
  trailingSlash = "never",
35
- caseSensitive
77
+ caseSensitive,
78
+ parseCache
36
79
  }) {
37
- var _a, _b;
38
80
  base = removeBasepath(basepath, base, caseSensitive);
39
81
  to = removeBasepath(basepath, to, caseSensitive);
40
- let baseSegments = parsePathname(base);
41
- const toSegments = parsePathname(to);
42
- if (baseSegments.length > 1 && ((_a = last(baseSegments)) == null ? void 0 : _a.value) === "/") {
82
+ let baseSegments = parsePathname(base, parseCache).slice();
83
+ const toSegments = parsePathname(to, parseCache);
84
+ if (baseSegments.length > 1 && last(baseSegments)?.value === "/") {
43
85
  baseSegments.pop();
44
86
  }
45
- toSegments.forEach((toSegment, index) => {
46
- if (toSegment.value === "/") {
87
+ for (let index = 0, length = toSegments.length; index < length; index++) {
88
+ const toSegment = toSegments[index];
89
+ const value = toSegment.value;
90
+ if (value === "/") {
47
91
  if (!index) {
48
92
  baseSegments = [toSegment];
49
- } else if (index === toSegments.length - 1) {
93
+ } else if (index === length - 1) {
50
94
  baseSegments.push(toSegment);
51
95
  } else ;
52
- } else if (toSegment.value === "..") {
96
+ } else if (value === "..") {
53
97
  baseSegments.pop();
54
- } else if (toSegment.value === ".") ;
98
+ } else if (value === ".") ;
55
99
  else {
56
100
  baseSegments.push(toSegment);
57
101
  }
58
- });
102
+ }
59
103
  if (baseSegments.length > 1) {
60
- if (((_b = last(baseSegments)) == null ? void 0 : _b.value) === "/") {
104
+ if (last(baseSegments).value === "/") {
61
105
  if (trailingSlash === "never") {
62
106
  baseSegments.pop();
63
107
  }
64
108
  } else if (trailingSlash === "always") {
65
- baseSegments.push({ type: "pathname", value: "/" });
109
+ baseSegments.push({ type: SEGMENT_TYPE_PATHNAME, value: "/" });
66
110
  }
67
111
  }
68
- const segmentValues = baseSegments.map((segment) => {
69
- if (segment.type === "param") {
70
- const param = segment.value.substring(1);
71
- if (segment.prefixSegment && segment.suffixSegment) {
72
- return `${segment.prefixSegment}{$${param}}${segment.suffixSegment}`;
73
- } else if (segment.prefixSegment) {
74
- return `${segment.prefixSegment}{$${param}}`;
75
- } else if (segment.suffixSegment) {
76
- return `{$${param}}${segment.suffixSegment}`;
77
- }
78
- }
79
- if (segment.type === "wildcard") {
80
- if (segment.prefixSegment && segment.suffixSegment) {
81
- return `${segment.prefixSegment}{$}${segment.suffixSegment}`;
82
- } else if (segment.prefixSegment) {
83
- return `${segment.prefixSegment}{$}`;
84
- } else if (segment.suffixSegment) {
85
- return `{$}${segment.suffixSegment}`;
86
- }
87
- }
88
- return segment.value;
89
- });
112
+ const segmentValues = baseSegments.map(segmentToString);
90
113
  const joined = joinPaths([basepath, ...segmentValues]);
91
- return cleanPath(joined);
114
+ return joined;
92
115
  }
116
+ const parsePathname = (pathname, cache) => {
117
+ if (!pathname) return [];
118
+ const cached = cache?.get(pathname);
119
+ if (cached) return cached;
120
+ const parsed = baseParsePathname(pathname);
121
+ cache?.set(pathname, parsed);
122
+ return parsed;
123
+ };
93
124
  const PARAM_RE = /^\$.{1,}$/;
94
125
  const PARAM_W_CURLY_BRACES_RE = /^(.*?)\{(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/;
126
+ const OPTIONAL_PARAM_W_CURLY_BRACES_RE = /^(.*?)\{-(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/;
95
127
  const WILDCARD_RE = /^\$$/;
96
128
  const WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\{\$\}(.*)$/;
97
- function parsePathname(pathname) {
98
- if (!pathname) {
99
- return [];
100
- }
129
+ function baseParsePathname(pathname) {
101
130
  pathname = cleanPath(pathname);
102
131
  const segments = [];
103
132
  if (pathname.slice(0, 1) === "/") {
104
133
  pathname = pathname.substring(1);
105
134
  segments.push({
106
- type: "pathname",
135
+ type: SEGMENT_TYPE_PATHNAME,
107
136
  value: "/"
108
137
  });
109
138
  }
@@ -118,19 +147,34 @@ function parsePathname(pathname) {
118
147
  const prefix = wildcardBracesMatch[1];
119
148
  const suffix = wildcardBracesMatch[2];
120
149
  return {
121
- type: "wildcard",
150
+ type: SEGMENT_TYPE_WILDCARD,
122
151
  value: "$",
123
152
  prefixSegment: prefix || void 0,
124
153
  suffixSegment: suffix || void 0
125
154
  };
126
155
  }
156
+ const optionalParamBracesMatch = part.match(
157
+ OPTIONAL_PARAM_W_CURLY_BRACES_RE
158
+ );
159
+ if (optionalParamBracesMatch) {
160
+ const prefix = optionalParamBracesMatch[1];
161
+ const paramName = optionalParamBracesMatch[2];
162
+ const suffix = optionalParamBracesMatch[3];
163
+ return {
164
+ type: SEGMENT_TYPE_OPTIONAL_PARAM,
165
+ value: paramName,
166
+ // Now just $paramName (no prefix)
167
+ prefixSegment: prefix || void 0,
168
+ suffixSegment: suffix || void 0
169
+ };
170
+ }
127
171
  const paramBracesMatch = part.match(PARAM_W_CURLY_BRACES_RE);
128
172
  if (paramBracesMatch) {
129
173
  const prefix = paramBracesMatch[1];
130
174
  const paramName = paramBracesMatch[2];
131
175
  const suffix = paramBracesMatch[3];
132
176
  return {
133
- type: "param",
177
+ type: SEGMENT_TYPE_PARAM,
134
178
  value: "" + paramName,
135
179
  prefixSegment: prefix || void 0,
136
180
  suffixSegment: suffix || void 0
@@ -139,7 +183,7 @@ function parsePathname(pathname) {
139
183
  if (PARAM_RE.test(part)) {
140
184
  const paramName = part.substring(1);
141
185
  return {
142
- type: "param",
186
+ type: SEGMENT_TYPE_PARAM,
143
187
  value: "$" + paramName,
144
188
  prefixSegment: void 0,
145
189
  suffixSegment: void 0
@@ -147,14 +191,14 @@ function parsePathname(pathname) {
147
191
  }
148
192
  if (WILDCARD_RE.test(part)) {
149
193
  return {
150
- type: "wildcard",
194
+ type: SEGMENT_TYPE_WILDCARD,
151
195
  value: "$",
152
196
  prefixSegment: void 0,
153
197
  suffixSegment: void 0
154
198
  };
155
199
  }
156
200
  return {
157
- type: "pathname",
201
+ type: SEGMENT_TYPE_PATHNAME,
158
202
  value: part.includes("%25") ? part.split("%25").map((segment) => decodeURI(segment)).join("%25") : decodeURI(part)
159
203
  };
160
204
  })
@@ -162,7 +206,7 @@ function parsePathname(pathname) {
162
206
  if (pathname.slice(-1) === "/") {
163
207
  pathname = pathname.substring(1);
164
208
  segments.push({
165
- type: "pathname",
209
+ type: SEGMENT_TYPE_PATHNAME,
166
210
  value: "/"
167
211
  });
168
212
  }
@@ -173,13 +217,14 @@ function interpolatePath({
173
217
  params,
174
218
  leaveWildcards,
175
219
  leaveParams,
176
- decodeCharMap
220
+ decodeCharMap,
221
+ parseCache
177
222
  }) {
178
- const interpolatedPathSegments = parsePathname(path);
223
+ const interpolatedPathSegments = parsePathname(path, parseCache);
179
224
  function encodeParam(key) {
180
225
  const value = params[key];
181
226
  const isValueString = typeof value === "string";
182
- if (["*", "_splat"].includes(key)) {
227
+ if (key === "*" || key === "_splat") {
183
228
  return isValueString ? encodeURI(value) : value;
184
229
  } else {
185
230
  return isValueString ? encodePathParam(value, decodeCharMap) : value;
@@ -189,17 +234,30 @@ function interpolatePath({
189
234
  const usedParams = {};
190
235
  const interpolatedPath = joinPaths(
191
236
  interpolatedPathSegments.map((segment) => {
192
- if (segment.type === "wildcard") {
237
+ if (segment.type === SEGMENT_TYPE_PATHNAME) {
238
+ return segment.value;
239
+ }
240
+ if (segment.type === SEGMENT_TYPE_WILDCARD) {
193
241
  usedParams._splat = params._splat;
194
242
  const segmentPrefix = segment.prefixSegment || "";
195
243
  const segmentSuffix = segment.suffixSegment || "";
244
+ if (!("_splat" in params)) {
245
+ isMissingParams = true;
246
+ if (leaveWildcards) {
247
+ return `${segmentPrefix}${segment.value}${segmentSuffix}`;
248
+ }
249
+ if (segmentPrefix || segmentSuffix) {
250
+ return `${segmentPrefix}${segmentSuffix}`;
251
+ }
252
+ return void 0;
253
+ }
196
254
  const value = encodeParam("_splat");
197
255
  if (leaveWildcards) {
198
256
  return `${segmentPrefix}${segment.value}${value ?? ""}${segmentSuffix}`;
199
257
  }
200
258
  return `${segmentPrefix}${value}${segmentSuffix}`;
201
259
  }
202
- if (segment.type === "param") {
260
+ if (segment.type === SEGMENT_TYPE_PARAM) {
203
261
  const key = segment.value.substring(1);
204
262
  if (!isMissingParams && !(key in params)) {
205
263
  isMissingParams = true;
@@ -213,6 +271,29 @@ function interpolatePath({
213
271
  }
214
272
  return `${segmentPrefix}${encodeParam(key) ?? "undefined"}${segmentSuffix}`;
215
273
  }
274
+ if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {
275
+ const key = segment.value.substring(1);
276
+ const segmentPrefix = segment.prefixSegment || "";
277
+ const segmentSuffix = segment.suffixSegment || "";
278
+ if (!(key in params) || params[key] == null) {
279
+ if (leaveWildcards) {
280
+ return `${segmentPrefix}${key}${segmentSuffix}`;
281
+ }
282
+ if (segmentPrefix || segmentSuffix) {
283
+ return `${segmentPrefix}${segmentSuffix}`;
284
+ }
285
+ return void 0;
286
+ }
287
+ usedParams[key] = params[key];
288
+ if (leaveParams) {
289
+ const value = encodeParam(segment.value);
290
+ return `${segmentPrefix}${segment.value}${value ?? ""}${segmentSuffix}`;
291
+ }
292
+ if (leaveWildcards) {
293
+ return `${segmentPrefix}${key}${encodeParam(key) ?? ""}${segmentSuffix}`;
294
+ }
295
+ return `${segmentPrefix}${encodeParam(key) ?? ""}${segmentSuffix}`;
296
+ }
216
297
  return segment.value;
217
298
  })
218
299
  );
@@ -227,8 +308,13 @@ function encodePathParam(value, decodeCharMap) {
227
308
  }
228
309
  return encoded;
229
310
  }
230
- function matchPathname(basepath, currentPathname, matchLocation) {
231
- const pathParams = matchByPath(basepath, currentPathname, matchLocation);
311
+ function matchPathname(basepath, currentPathname, matchLocation, parseCache) {
312
+ const pathParams = matchByPath(
313
+ basepath,
314
+ currentPathname,
315
+ matchLocation,
316
+ parseCache
317
+ );
232
318
  if (matchLocation.to && !pathParams) {
233
319
  return;
234
320
  }
@@ -263,111 +349,156 @@ function removeBasepath(basepath, pathname, caseSensitive = false) {
263
349
  return pathname;
264
350
  }
265
351
  }
266
- function matchByPath(basepath, from, matchLocation) {
352
+ function matchByPath(basepath, from, {
353
+ to,
354
+ fuzzy,
355
+ caseSensitive
356
+ }, parseCache) {
267
357
  if (basepath !== "/" && !from.startsWith(basepath)) {
268
358
  return void 0;
269
359
  }
270
- from = removeBasepath(basepath, from, matchLocation.caseSensitive);
271
- const to = removeBasepath(
272
- basepath,
273
- `${matchLocation.to ?? "$"}`,
274
- matchLocation.caseSensitive
360
+ from = removeBasepath(basepath, from, caseSensitive);
361
+ to = removeBasepath(basepath, `${to ?? "$"}`, caseSensitive);
362
+ const baseSegments = parsePathname(
363
+ from.startsWith("/") ? from : `/${from}`,
364
+ parseCache
365
+ );
366
+ const routeSegments = parsePathname(
367
+ to.startsWith("/") ? to : `/${to}`,
368
+ parseCache
275
369
  );
276
- const baseSegments = parsePathname(from);
277
- const routeSegments = parsePathname(to);
278
- if (!from.startsWith("/")) {
279
- baseSegments.unshift({
280
- type: "pathname",
281
- value: "/"
282
- });
283
- }
284
- if (!to.startsWith("/")) {
285
- routeSegments.unshift({
286
- type: "pathname",
287
- value: "/"
288
- });
289
- }
290
370
  const params = {};
291
- const isMatch = (() => {
292
- var _a;
293
- for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
294
- const baseSegment = baseSegments[i];
295
- const routeSegment = routeSegments[i];
296
- const isLastBaseSegment = i >= baseSegments.length - 1;
297
- const isLastRouteSegment = i >= routeSegments.length - 1;
298
- if (routeSegment) {
299
- if (routeSegment.type === "wildcard") {
300
- const remainingBaseSegments = baseSegments.slice(i);
301
- let _splat;
302
- if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
303
- if (!baseSegment) return false;
304
- const prefix = routeSegment.prefixSegment || "";
305
- const suffix = routeSegment.suffixSegment || "";
306
- const baseValue = baseSegment.value;
307
- if ("prefixSegment" in routeSegment) {
308
- if (!baseValue.startsWith(prefix)) {
309
- return false;
310
- }
311
- }
312
- if ("suffixSegment" in routeSegment) {
313
- if (!((_a = baseSegments[baseSegments.length - 1]) == null ? void 0 : _a.value.endsWith(suffix))) {
314
- return false;
315
- }
316
- }
317
- let rejoinedSplat = decodeURI(
318
- joinPaths(remainingBaseSegments.map((d) => d.value))
319
- );
320
- if (prefix && rejoinedSplat.startsWith(prefix)) {
321
- rejoinedSplat = rejoinedSplat.slice(prefix.length);
371
+ const result = isMatch(
372
+ baseSegments,
373
+ routeSegments,
374
+ params,
375
+ fuzzy,
376
+ caseSensitive
377
+ );
378
+ return result ? params : void 0;
379
+ }
380
+ function isMatch(baseSegments, routeSegments, params, fuzzy, caseSensitive) {
381
+ let baseIndex = 0;
382
+ let routeIndex = 0;
383
+ while (baseIndex < baseSegments.length || routeIndex < routeSegments.length) {
384
+ const baseSegment = baseSegments[baseIndex];
385
+ const routeSegment = routeSegments[routeIndex];
386
+ if (routeSegment) {
387
+ if (routeSegment.type === SEGMENT_TYPE_WILDCARD) {
388
+ const remainingBaseSegments = baseSegments.slice(baseIndex);
389
+ let _splat;
390
+ if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
391
+ if (!baseSegment) return false;
392
+ const prefix = routeSegment.prefixSegment || "";
393
+ const suffix = routeSegment.suffixSegment || "";
394
+ const baseValue = baseSegment.value;
395
+ if ("prefixSegment" in routeSegment) {
396
+ if (!baseValue.startsWith(prefix)) {
397
+ return false;
322
398
  }
323
- if (suffix && rejoinedSplat.endsWith(suffix)) {
324
- rejoinedSplat = rejoinedSplat.slice(
325
- 0,
326
- rejoinedSplat.length - suffix.length
327
- );
399
+ }
400
+ if ("suffixSegment" in routeSegment) {
401
+ if (!baseSegments[baseSegments.length - 1]?.value.endsWith(suffix)) {
402
+ return false;
328
403
  }
329
- _splat = rejoinedSplat;
330
- } else {
331
- _splat = decodeURI(
332
- joinPaths(remainingBaseSegments.map((d) => d.value))
404
+ }
405
+ let rejoinedSplat = decodeURI(
406
+ joinPaths(remainingBaseSegments.map((d) => d.value))
407
+ );
408
+ if (prefix && rejoinedSplat.startsWith(prefix)) {
409
+ rejoinedSplat = rejoinedSplat.slice(prefix.length);
410
+ }
411
+ if (suffix && rejoinedSplat.endsWith(suffix)) {
412
+ rejoinedSplat = rejoinedSplat.slice(
413
+ 0,
414
+ rejoinedSplat.length - suffix.length
333
415
  );
334
416
  }
335
- params["*"] = _splat;
336
- params["_splat"] = _splat;
337
- return true;
417
+ _splat = rejoinedSplat;
418
+ } else {
419
+ _splat = decodeURI(
420
+ joinPaths(remainingBaseSegments.map((d) => d.value))
421
+ );
338
422
  }
339
- if (routeSegment.type === "pathname") {
340
- if (routeSegment.value === "/" && !(baseSegment == null ? void 0 : baseSegment.value)) {
341
- return true;
342
- }
343
- if (baseSegment) {
344
- if (matchLocation.caseSensitive) {
345
- if (routeSegment.value !== baseSegment.value) {
346
- return false;
347
- }
348
- } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
423
+ params["*"] = _splat;
424
+ params["_splat"] = _splat;
425
+ return true;
426
+ }
427
+ if (routeSegment.type === SEGMENT_TYPE_PATHNAME) {
428
+ if (routeSegment.value === "/" && !baseSegment?.value) {
429
+ routeIndex++;
430
+ continue;
431
+ }
432
+ if (baseSegment) {
433
+ if (caseSensitive) {
434
+ if (routeSegment.value !== baseSegment.value) {
349
435
  return false;
350
436
  }
437
+ } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
438
+ return false;
351
439
  }
440
+ baseIndex++;
441
+ routeIndex++;
442
+ continue;
443
+ } else {
444
+ return false;
352
445
  }
446
+ }
447
+ if (routeSegment.type === SEGMENT_TYPE_PARAM) {
353
448
  if (!baseSegment) {
354
449
  return false;
355
450
  }
356
- if (routeSegment.type === "param") {
357
- if (baseSegment.value === "/") {
451
+ if (baseSegment.value === "/") {
452
+ return false;
453
+ }
454
+ let _paramValue = "";
455
+ let matched = false;
456
+ if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
457
+ const prefix = routeSegment.prefixSegment || "";
458
+ const suffix = routeSegment.suffixSegment || "";
459
+ const baseValue = baseSegment.value;
460
+ if (prefix && !baseValue.startsWith(prefix)) {
358
461
  return false;
359
462
  }
360
- let _paramValue;
361
- if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
362
- const prefix = routeSegment.prefixSegment || "";
363
- const suffix = routeSegment.suffixSegment || "";
364
- const baseValue = baseSegment.value;
365
- if (prefix && !baseValue.startsWith(prefix)) {
366
- return false;
367
- }
368
- if (suffix && !baseValue.endsWith(suffix)) {
369
- return false;
370
- }
463
+ if (suffix && !baseValue.endsWith(suffix)) {
464
+ return false;
465
+ }
466
+ let paramValue = baseValue;
467
+ if (prefix && paramValue.startsWith(prefix)) {
468
+ paramValue = paramValue.slice(prefix.length);
469
+ }
470
+ if (suffix && paramValue.endsWith(suffix)) {
471
+ paramValue = paramValue.slice(0, paramValue.length - suffix.length);
472
+ }
473
+ _paramValue = decodeURIComponent(paramValue);
474
+ matched = true;
475
+ } else {
476
+ _paramValue = decodeURIComponent(baseSegment.value);
477
+ matched = true;
478
+ }
479
+ if (matched) {
480
+ params[routeSegment.value.substring(1)] = _paramValue;
481
+ baseIndex++;
482
+ }
483
+ routeIndex++;
484
+ continue;
485
+ }
486
+ if (routeSegment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {
487
+ if (!baseSegment) {
488
+ routeIndex++;
489
+ continue;
490
+ }
491
+ if (baseSegment.value === "/") {
492
+ routeIndex++;
493
+ continue;
494
+ }
495
+ let _paramValue = "";
496
+ let matched = false;
497
+ if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
498
+ const prefix = routeSegment.prefixSegment || "";
499
+ const suffix = routeSegment.suffixSegment || "";
500
+ const baseValue = baseSegment.value;
501
+ if ((!prefix || baseValue.startsWith(prefix)) && (!suffix || baseValue.endsWith(suffix))) {
371
502
  let paramValue = baseValue;
372
503
  if (prefix && paramValue.startsWith(prefix)) {
373
504
  paramValue = paramValue.slice(prefix.length);
@@ -379,22 +510,59 @@ function matchByPath(basepath, from, matchLocation) {
379
510
  );
380
511
  }
381
512
  _paramValue = decodeURIComponent(paramValue);
382
- } else {
513
+ matched = true;
514
+ }
515
+ } else {
516
+ let shouldMatchOptional = true;
517
+ for (let lookAhead = routeIndex + 1; lookAhead < routeSegments.length; lookAhead++) {
518
+ const futureRouteSegment = routeSegments[lookAhead];
519
+ if (futureRouteSegment?.type === SEGMENT_TYPE_PATHNAME && futureRouteSegment.value === baseSegment.value) {
520
+ shouldMatchOptional = false;
521
+ break;
522
+ }
523
+ if (futureRouteSegment?.type === SEGMENT_TYPE_PARAM || futureRouteSegment?.type === SEGMENT_TYPE_WILDCARD) {
524
+ if (baseSegments.length < routeSegments.length) {
525
+ shouldMatchOptional = false;
526
+ }
527
+ break;
528
+ }
529
+ }
530
+ if (shouldMatchOptional) {
383
531
  _paramValue = decodeURIComponent(baseSegment.value);
532
+ matched = true;
384
533
  }
534
+ }
535
+ if (matched) {
385
536
  params[routeSegment.value.substring(1)] = _paramValue;
537
+ baseIndex++;
386
538
  }
539
+ routeIndex++;
540
+ continue;
387
541
  }
388
- if (!isLastBaseSegment && isLastRouteSegment) {
389
- params["**"] = joinPaths(baseSegments.slice(i + 1).map((d) => d.value));
390
- return !!matchLocation.fuzzy && (routeSegment == null ? void 0 : routeSegment.value) !== "/";
542
+ }
543
+ if (baseIndex < baseSegments.length && routeIndex >= routeSegments.length) {
544
+ params["**"] = joinPaths(
545
+ baseSegments.slice(baseIndex).map((d) => d.value)
546
+ );
547
+ return !!fuzzy && routeSegments[routeSegments.length - 1]?.value !== "/";
548
+ }
549
+ if (routeIndex < routeSegments.length && baseIndex >= baseSegments.length) {
550
+ for (let i = routeIndex; i < routeSegments.length; i++) {
551
+ if (routeSegments[i]?.type !== SEGMENT_TYPE_OPTIONAL_PARAM) {
552
+ return false;
553
+ }
391
554
  }
555
+ break;
392
556
  }
393
- return true;
394
- })();
395
- return isMatch ? params : void 0;
557
+ break;
558
+ }
559
+ return true;
396
560
  }
397
561
  export {
562
+ SEGMENT_TYPE_OPTIONAL_PARAM,
563
+ SEGMENT_TYPE_PARAM,
564
+ SEGMENT_TYPE_PATHNAME,
565
+ SEGMENT_TYPE_WILDCARD,
398
566
  cleanPath,
399
567
  exactPathTest,
400
568
  interpolatePath,