@tanstack/router-core 1.121.0-alpha.22 → 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 (170) 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 +2 -4
  21. package/dist/cjs/qss.cjs.map +1 -1
  22. package/dist/cjs/qss.d.cts +9 -0
  23. package/dist/cjs/redirect.cjs +3 -0
  24. package/dist/cjs/redirect.cjs.map +1 -1
  25. package/dist/cjs/route.cjs +6 -12
  26. package/dist/cjs/route.cjs.map +1 -1
  27. package/dist/cjs/route.d.cts +29 -9
  28. package/dist/cjs/router.cjs +454 -272
  29. package/dist/cjs/router.cjs.map +1 -1
  30. package/dist/cjs/router.d.cts +55 -85
  31. package/dist/cjs/scroll-restoration.cjs +20 -13
  32. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  33. package/dist/cjs/scroll-restoration.d.cts +9 -1
  34. package/dist/cjs/searchMiddleware.cjs.map +1 -1
  35. package/dist/cjs/searchParams.cjs.map +1 -1
  36. package/dist/cjs/ssr/client.cjs +10 -0
  37. package/dist/cjs/ssr/client.cjs.map +1 -0
  38. package/dist/cjs/ssr/client.d.cts +5 -0
  39. package/dist/cjs/ssr/createRequestHandler.cjs +50 -0
  40. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -0
  41. package/dist/cjs/ssr/createRequestHandler.d.cts +9 -0
  42. package/dist/cjs/ssr/handlerCallback.cjs +7 -0
  43. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -0
  44. package/dist/cjs/ssr/handlerCallback.d.cts +9 -0
  45. package/dist/cjs/ssr/headers.cjs +39 -0
  46. package/dist/cjs/ssr/headers.cjs.map +1 -0
  47. package/dist/cjs/ssr/headers.d.cts +5 -0
  48. package/dist/cjs/ssr/json.cjs +14 -0
  49. package/dist/cjs/ssr/json.cjs.map +1 -0
  50. package/dist/cjs/ssr/json.d.cts +4 -0
  51. package/dist/cjs/ssr/seroval-plugins.cjs +34 -0
  52. package/dist/cjs/ssr/seroval-plugins.cjs.map +1 -0
  53. package/dist/cjs/ssr/seroval-plugins.d.cts +10 -0
  54. package/dist/cjs/ssr/server.cjs +13 -0
  55. package/dist/cjs/ssr/server.cjs.map +1 -0
  56. package/dist/cjs/ssr/server.d.cts +6 -0
  57. package/dist/cjs/ssr/ssr-client.cjs +159 -0
  58. package/dist/cjs/ssr/ssr-client.cjs.map +1 -0
  59. package/dist/cjs/ssr/ssr-client.d.cts +29 -0
  60. package/dist/cjs/ssr/ssr-server.cjs +107 -0
  61. package/dist/cjs/ssr/ssr-server.cjs.map +1 -0
  62. package/dist/cjs/ssr/ssr-server.d.cts +18 -0
  63. package/dist/cjs/ssr/transformStreamWithRouter.cjs +183 -0
  64. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -0
  65. package/dist/cjs/ssr/transformStreamWithRouter.d.cts +6 -0
  66. package/dist/cjs/ssr/tsrScript.cjs +4 -0
  67. package/dist/cjs/ssr/tsrScript.cjs.map +1 -0
  68. package/dist/cjs/ssr/tsrScript.d.cts +0 -0
  69. package/dist/cjs/utils.cjs +7 -30
  70. package/dist/cjs/utils.cjs.map +1 -1
  71. package/dist/cjs/utils.d.cts +1 -18
  72. package/dist/esm/Matches.d.ts +31 -1
  73. package/dist/esm/Matches.js.map +1 -1
  74. package/dist/esm/RouterProvider.d.ts +2 -1
  75. package/dist/esm/defer.js +1 -1
  76. package/dist/esm/defer.js.map +1 -1
  77. package/dist/esm/global.d.ts +7 -0
  78. package/dist/esm/index.d.ts +6 -6
  79. package/dist/esm/index.js +2 -3
  80. package/dist/esm/link.d.ts +12 -0
  81. package/dist/esm/link.js.map +1 -1
  82. package/dist/esm/lru-cache.d.ts +5 -0
  83. package/dist/esm/lru-cache.js +62 -0
  84. package/dist/esm/lru-cache.js.map +1 -0
  85. package/dist/esm/not-found.js +1 -1
  86. package/dist/esm/not-found.js.map +1 -1
  87. package/dist/esm/path.d.ts +18 -24
  88. package/dist/esm/path.js +316 -148
  89. package/dist/esm/path.js.map +1 -1
  90. package/dist/esm/qss.d.ts +9 -0
  91. package/dist/esm/qss.js +2 -4
  92. package/dist/esm/qss.js.map +1 -1
  93. package/dist/esm/redirect.js +3 -0
  94. package/dist/esm/redirect.js.map +1 -1
  95. package/dist/esm/route.d.ts +29 -9
  96. package/dist/esm/route.js +6 -12
  97. package/dist/esm/route.js.map +1 -1
  98. package/dist/esm/router.d.ts +55 -85
  99. package/dist/esm/router.js +463 -281
  100. package/dist/esm/router.js.map +1 -1
  101. package/dist/esm/scroll-restoration.d.ts +9 -1
  102. package/dist/esm/scroll-restoration.js +20 -13
  103. package/dist/esm/scroll-restoration.js.map +1 -1
  104. package/dist/esm/searchMiddleware.js.map +1 -1
  105. package/dist/esm/searchParams.js.map +1 -1
  106. package/dist/esm/ssr/client.d.ts +5 -0
  107. package/dist/esm/ssr/client.js +10 -0
  108. package/dist/esm/ssr/client.js.map +1 -0
  109. package/dist/esm/ssr/createRequestHandler.d.ts +9 -0
  110. package/dist/esm/ssr/createRequestHandler.js +50 -0
  111. package/dist/esm/ssr/createRequestHandler.js.map +1 -0
  112. package/dist/esm/ssr/handlerCallback.d.ts +9 -0
  113. package/dist/esm/ssr/handlerCallback.js +7 -0
  114. package/dist/esm/ssr/handlerCallback.js.map +1 -0
  115. package/dist/esm/ssr/headers.d.ts +5 -0
  116. package/dist/esm/ssr/headers.js +39 -0
  117. package/dist/esm/ssr/headers.js.map +1 -0
  118. package/dist/esm/ssr/json.d.ts +4 -0
  119. package/dist/esm/ssr/json.js +14 -0
  120. package/dist/esm/ssr/json.js.map +1 -0
  121. package/dist/esm/ssr/seroval-plugins.d.ts +10 -0
  122. package/dist/esm/ssr/seroval-plugins.js +34 -0
  123. package/dist/esm/ssr/seroval-plugins.js.map +1 -0
  124. package/dist/esm/ssr/server.d.ts +6 -0
  125. package/dist/esm/ssr/server.js +13 -0
  126. package/dist/esm/ssr/server.js.map +1 -0
  127. package/dist/esm/ssr/ssr-client.d.ts +29 -0
  128. package/dist/esm/ssr/ssr-client.js +159 -0
  129. package/dist/esm/ssr/ssr-client.js.map +1 -0
  130. package/dist/esm/ssr/ssr-server.d.ts +18 -0
  131. package/dist/esm/ssr/ssr-server.js +107 -0
  132. package/dist/esm/ssr/ssr-server.js.map +1 -0
  133. package/dist/esm/ssr/transformStreamWithRouter.d.ts +6 -0
  134. package/dist/esm/ssr/transformStreamWithRouter.js +183 -0
  135. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -0
  136. package/dist/esm/ssr/tsrScript.d.ts +0 -0
  137. package/dist/esm/ssr/tsrScript.js +5 -0
  138. package/dist/esm/ssr/tsrScript.js.map +1 -0
  139. package/dist/esm/utils.d.ts +1 -18
  140. package/dist/esm/utils.js +8 -31
  141. package/dist/esm/utils.js.map +1 -1
  142. package/package.json +29 -2
  143. package/src/Matches.ts +40 -1
  144. package/src/RouterProvider.ts +2 -1
  145. package/src/global.ts +9 -0
  146. package/src/index.ts +12 -20
  147. package/src/link.ts +12 -0
  148. package/src/lru-cache.ts +68 -0
  149. package/src/path.ts +424 -174
  150. package/src/qss.ts +2 -6
  151. package/src/redirect.ts +3 -0
  152. package/src/route.ts +44 -13
  153. package/src/router.ts +581 -312
  154. package/src/scroll-restoration.ts +30 -18
  155. package/src/ssr/client.ts +5 -0
  156. package/src/ssr/createRequestHandler.ts +74 -0
  157. package/src/ssr/handlerCallback.ts +15 -0
  158. package/src/ssr/headers.ts +51 -0
  159. package/src/ssr/json.ts +18 -0
  160. package/src/ssr/seroval-plugins.ts +43 -0
  161. package/src/ssr/server.ts +10 -0
  162. package/src/ssr/ssr-client.ts +242 -0
  163. package/src/ssr/ssr-server.ts +132 -0
  164. package/src/ssr/transformStreamWithRouter.ts +259 -0
  165. package/src/ssr/tsrScript.ts +7 -0
  166. package/src/utils.ts +10 -56
  167. package/src/vite-env.d.ts +4 -0
  168. package/dist/cjs/serializer.d.cts +0 -22
  169. package/dist/esm/serializer.d.ts +0 -22
  170. package/src/serializer.ts +0 -32
@@ -2,12 +2,13 @@ import { Store, batch } from "@tanstack/store";
2
2
  import { createMemoryHistory, createBrowserHistory, parseHref } from "@tanstack/history";
3
3
  import invariant from "tiny-invariant";
4
4
  import { pick, createControlledPromise, deepEqual, replaceEqualDeep, last, functionalUpdate } from "./utils.js";
5
- import { trimPath, resolvePath, cleanPath, matchPathname, trimPathRight, interpolatePath, joinPaths, trimPathLeft, parsePathname } from "./path.js";
5
+ import { trimPath, resolvePath, cleanPath, matchPathname, trimPathRight, interpolatePath, joinPaths, trimPathLeft, parsePathname, SEGMENT_TYPE_PARAM, SEGMENT_TYPE_OPTIONAL_PARAM, SEGMENT_TYPE_WILDCARD, SEGMENT_TYPE_PATHNAME } from "./path.js";
6
6
  import { isNotFound } from "./not-found.js";
7
7
  import { setupScrollRestoration } from "./scroll-restoration.js";
8
8
  import { defaultParseSearch, defaultStringifySearch } from "./searchParams.js";
9
9
  import { rootRouteId } from "./root.js";
10
- import { isRedirect } from "./redirect.js";
10
+ import { redirect, isRedirect } from "./redirect.js";
11
+ import { createLRUCache } from "./lru-cache.js";
11
12
  function defaultSerializeError(err) {
12
13
  if (err instanceof Error) {
13
14
  const obj = {
@@ -26,9 +27,9 @@ function defaultSerializeError(err) {
26
27
  function getLocationChangeInfo(routerState) {
27
28
  const fromLocation = routerState.resolvedLocation;
28
29
  const toLocation = routerState.location;
29
- const pathChanged = (fromLocation == null ? void 0 : fromLocation.pathname) !== toLocation.pathname;
30
- const hrefChanged = (fromLocation == null ? void 0 : fromLocation.href) !== toLocation.href;
31
- const hashChanged = (fromLocation == null ? void 0 : fromLocation.hash) !== toLocation.hash;
30
+ const pathChanged = fromLocation?.pathname !== toLocation.pathname;
31
+ const hrefChanged = fromLocation?.href !== toLocation.href;
32
+ const hashChanged = fromLocation?.hash !== toLocation.hash;
32
33
  return { fromLocation, toLocation, pathChanged, hrefChanged, hashChanged };
33
34
  }
34
35
  class RouterCore {
@@ -46,9 +47,7 @@ class RouterCore {
46
47
  this.isScrollRestoring = false;
47
48
  this.isScrollRestorationSetup = false;
48
49
  this.startTransition = (fn) => fn();
49
- this.isShell = false;
50
50
  this.update = (newOptions) => {
51
- var _a;
52
51
  if (newOptions.notFoundRoute) {
53
52
  console.warn(
54
53
  "The notFoundRoute API is deprecated and will be removed in the next major version. See https://tanstack.com/router/v1/docs/framework/react/guide/not-found-errors#migrating-from-notfoundroute for more info."
@@ -96,22 +95,18 @@ class RouterCore {
96
95
  });
97
96
  setupScrollRestoration(this);
98
97
  }
99
- if (typeof window !== "undefined" && "CSS" in window && typeof ((_a = window.CSS) == null ? void 0 : _a.supports) === "function") {
98
+ if (typeof window !== "undefined" && "CSS" in window && typeof window.CSS?.supports === "function") {
100
99
  this.isViewTransitionTypesSupported = window.CSS.supports(
101
100
  "selector(:active-view-transition-type(a)"
102
101
  );
103
102
  }
104
- if (this.latestLocation.search.__TSS_SHELL) {
105
- this.isShell = true;
106
- }
107
103
  };
108
104
  this.buildRouteTree = () => {
109
105
  const { routesById, routesByPath, flatRoutes } = processRouteTree({
110
106
  routeTree: this.routeTree,
111
107
  initRoute: (route, i) => {
112
108
  route.init({
113
- originalIndex: i,
114
- defaultSsr: this.options.defaultSsr
109
+ originalIndex: i
115
110
  });
116
111
  }
117
112
  });
@@ -121,8 +116,7 @@ class RouterCore {
121
116
  const notFoundRoute = this.options.notFoundRoute;
122
117
  if (notFoundRoute) {
123
118
  notFoundRoute.init({
124
- originalIndex: 99999999999,
125
- defaultSsr: this.options.defaultSsr
119
+ originalIndex: 99999999999
126
120
  });
127
121
  this.routesById[notFoundRoute.id] = notFoundRoute;
128
122
  }
@@ -156,10 +150,10 @@ class RouterCore {
156
150
  return {
157
151
  pathname,
158
152
  searchStr,
159
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
153
+ search: replaceEqualDeep(previousLocation?.search, parsedSearch),
160
154
  hash: hash.split("#").reverse()[0] ?? "",
161
155
  href: `${pathname}${searchStr}${hash}`,
162
- state: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.state, state)
156
+ state: replaceEqualDeep(previousLocation?.state, state)
163
157
  };
164
158
  };
165
159
  const location = parse(locationToParse ?? this.history.location);
@@ -167,6 +161,7 @@ class RouterCore {
167
161
  if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
168
162
  const parsedTempLocation = parse(__tempLocation);
169
163
  parsedTempLocation.state.key = location.state.key;
164
+ parsedTempLocation.state.__TSR_key = location.state.__TSR_key;
170
165
  delete parsedTempLocation.state.__tempLocation;
171
166
  return {
172
167
  ...parsedTempLocation,
@@ -181,7 +176,8 @@ class RouterCore {
181
176
  base: from,
182
177
  to: cleanPath(path),
183
178
  trailingSlash: this.options.trailingSlash,
184
- caseSensitive: this.options.caseSensitive
179
+ caseSensitive: this.options.caseSensitive,
180
+ parseCache: this.parsePathnameCache
185
181
  });
186
182
  return resolvedPath;
187
183
  };
@@ -197,6 +193,7 @@ class RouterCore {
197
193
  }
198
194
  return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
199
195
  };
196
+ this.parsePathnameCache = createLRUCache(1e3);
200
197
  this.getMatchedRoutes = (pathname, routePathname) => {
201
198
  return getMatchedRoutes({
202
199
  pathname,
@@ -205,50 +202,71 @@ class RouterCore {
205
202
  caseSensitive: this.options.caseSensitive,
206
203
  routesByPath: this.routesByPath,
207
204
  routesById: this.routesById,
208
- flatRoutes: this.flatRoutes
205
+ flatRoutes: this.flatRoutes,
206
+ parseCache: this.parsePathnameCache
209
207
  });
210
208
  };
211
209
  this.cancelMatch = (id) => {
212
210
  const match = this.getMatch(id);
213
211
  if (!match) return;
214
212
  match.abortController.abort();
215
- clearTimeout(match.pendingTimeout);
213
+ this.updateMatch(id, (prev) => {
214
+ clearTimeout(prev.pendingTimeout);
215
+ return {
216
+ ...prev,
217
+ pendingTimeout: void 0
218
+ };
219
+ });
216
220
  };
217
221
  this.cancelMatches = () => {
218
- var _a;
219
- (_a = this.state.pendingMatches) == null ? void 0 : _a.forEach((match) => {
222
+ this.state.pendingMatches?.forEach((match) => {
220
223
  this.cancelMatch(match.id);
221
224
  });
222
225
  };
223
226
  this.buildLocation = (opts) => {
224
227
  const build = (dest = {}) => {
225
- var _a;
226
228
  const currentLocation = dest._fromLocation || this.latestLocation;
227
- const allFromMatches = this.matchRoutes(currentLocation, {
229
+ const allCurrentLocationMatches = this.matchRoutes(currentLocation, {
228
230
  _buildLocation: true
229
231
  });
230
- const lastMatch = last(allFromMatches);
232
+ const lastMatch = last(allCurrentLocationMatches);
231
233
  let fromPath = lastMatch.fullPath;
234
+ const toPath = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
235
+ const routeIsChanging = !!dest.to && !comparePaths(dest.to.toString(), fromPath) && !comparePaths(toPath, fromPath);
232
236
  if (dest.unsafeRelative === "path") {
233
237
  fromPath = currentLocation.pathname;
234
- } else if (dest.to && dest.from) {
238
+ } else if (routeIsChanging && dest.from) {
235
239
  fromPath = dest.from;
236
- const existingFrom = [...allFromMatches].reverse().find((d) => {
237
- return d.fullPath === fromPath || d.fullPath === joinPaths([fromPath, "/"]);
238
- });
239
- if (!existingFrom) {
240
- console.warn(`Could not find match for from: ${dest.from}`);
240
+ if (process.env.NODE_ENV !== "production" && dest._isNavigate) {
241
+ const allFromMatches = this.getMatchedRoutes(
242
+ dest.from,
243
+ void 0
244
+ ).matchedRoutes;
245
+ const matchedFrom = [...allCurrentLocationMatches].reverse().find((d) => {
246
+ return comparePaths(d.fullPath, fromPath);
247
+ });
248
+ const matchedCurrent = [...allFromMatches].reverse().find((d) => {
249
+ return comparePaths(d.fullPath, currentLocation.pathname);
250
+ });
251
+ if (!matchedFrom && !matchedCurrent) {
252
+ console.warn(`Could not find match for from: ${fromPath}`);
253
+ }
241
254
  }
242
255
  }
243
256
  const fromSearch = lastMatch.search;
244
257
  const fromParams = { ...lastMatch.params };
245
- const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : fromPath;
246
- let nextParams = (dest.params ?? true) === true ? fromParams : {
258
+ const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
259
+ let nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : {
247
260
  ...fromParams,
248
261
  ...functionalUpdate(dest.params, fromParams)
249
262
  };
263
+ const interpolatedNextTo = interpolatePath({
264
+ path: nextTo,
265
+ params: nextParams ?? {},
266
+ parseCache: this.parsePathnameCache
267
+ }).interpolatedPath;
250
268
  const destRoutes = this.matchRoutes(
251
- nextTo,
269
+ interpolatedNextTo,
252
270
  {},
253
271
  {
254
272
  _buildLocation: true
@@ -256,21 +274,23 @@ class RouterCore {
256
274
  ).map((d) => this.looseRoutesById[d.routeId]);
257
275
  if (Object.keys(nextParams).length > 0) {
258
276
  destRoutes.map((route) => {
259
- var _a2;
260
- return ((_a2 = route.options.params) == null ? void 0 : _a2.stringify) ?? route.options.stringifyParams;
277
+ return route.options.params?.stringify ?? route.options.stringifyParams;
261
278
  }).filter(Boolean).forEach((fn) => {
262
279
  nextParams = { ...nextParams, ...fn(nextParams) };
263
280
  });
264
281
  }
265
282
  const nextPathname = interpolatePath({
283
+ // Use the original template path for interpolation
284
+ // This preserves the original parameter syntax including optional parameters
266
285
  path: nextTo,
267
286
  params: nextParams ?? {},
268
287
  leaveWildcards: false,
269
288
  leaveParams: opts.leaveParams,
270
- decodeCharMap: this.pathParamsDecodeCharMap
289
+ decodeCharMap: this.pathParamsDecodeCharMap,
290
+ parseCache: this.parsePathnameCache
271
291
  }).interpolatedPath;
272
292
  let nextSearch = fromSearch;
273
- if (opts._includeValidateSearch && ((_a = this.options.search) == null ? void 0 : _a.strict)) {
293
+ if (opts._includeValidateSearch && this.options.search?.strict) {
274
294
  let validatedSearch = {};
275
295
  destRoutes.forEach((route) => {
276
296
  try {
@@ -311,17 +331,21 @@ class RouterCore {
311
331
  };
312
332
  };
313
333
  const buildWithMatches = (dest = {}, maskedDest) => {
314
- var _a;
315
334
  const next = build(dest);
316
335
  let maskedNext = maskedDest ? build(maskedDest) : void 0;
317
336
  if (!maskedNext) {
318
337
  let params = {};
319
- const foundMask = (_a = this.options.routeMasks) == null ? void 0 : _a.find((d) => {
320
- const match = matchPathname(this.basepath, next.pathname, {
321
- to: d.from,
322
- caseSensitive: false,
323
- fuzzy: false
324
- });
338
+ const foundMask = this.options.routeMasks?.find((d) => {
339
+ const match = matchPathname(
340
+ this.basepath,
341
+ next.pathname,
342
+ {
343
+ to: d.from,
344
+ caseSensitive: false,
345
+ fuzzy: false
346
+ },
347
+ this.parsePathnameCache
348
+ );
325
349
  if (match) {
326
350
  params = match;
327
351
  return true;
@@ -360,6 +384,8 @@ class RouterCore {
360
384
  const isSameState = () => {
361
385
  const ignoredProps = [
362
386
  "key",
387
+ // TODO: Remove in v2 - use __TSR_key instead
388
+ "__TSR_key",
363
389
  "__TSR_index",
364
390
  "__hashScrollIntoViewOptions"
365
391
  ];
@@ -375,7 +401,7 @@ class RouterCore {
375
401
  const isSameUrl = this.latestLocation.href === next.href;
376
402
  const previousCommitPromise = this.commitLocationPromise;
377
403
  this.commitLocationPromise = createControlledPromise(() => {
378
- previousCommitPromise == null ? void 0 : previousCommitPromise.resolve();
404
+ previousCommitPromise?.resolve();
379
405
  });
380
406
  if (isSameUrl && isSameState()) {
381
407
  this.load();
@@ -394,7 +420,9 @@ class RouterCore {
394
420
  ...nextHistory.state,
395
421
  __tempKey: void 0,
396
422
  __tempLocation: void 0,
423
+ __TSR_key: void 0,
397
424
  key: void 0
425
+ // TODO: Remove in v2 - use __TSR_key instead
398
426
  }
399
427
  }
400
428
  }
@@ -466,37 +494,58 @@ class RouterCore {
466
494
  } else {
467
495
  window.location.href = href;
468
496
  }
469
- return;
497
+ return Promise.resolve();
470
498
  }
471
499
  return this.buildAndCommitLocation({
472
500
  ...rest,
473
501
  href,
474
- to
502
+ to,
503
+ _isNavigate: true
475
504
  });
476
505
  };
477
506
  this.beforeLoad = () => {
478
507
  this.cancelMatches();
479
508
  this.latestLocation = this.parseLocation(this.latestLocation);
509
+ if (this.isServer) {
510
+ const nextLocation = this.buildLocation({
511
+ to: this.latestLocation.pathname,
512
+ search: true,
513
+ params: true,
514
+ hash: true,
515
+ state: true,
516
+ _includeValidateSearch: true
517
+ });
518
+ const normalizeUrl = (url) => {
519
+ try {
520
+ return encodeURI(decodeURI(url));
521
+ } catch {
522
+ return url;
523
+ }
524
+ };
525
+ if (trimPath(normalizeUrl(this.latestLocation.href)) !== trimPath(normalizeUrl(nextLocation.href))) {
526
+ throw redirect({ href: nextLocation.href });
527
+ }
528
+ }
480
529
  const pendingMatches = this.matchRoutes(this.latestLocation);
481
530
  this.__store.setState((s) => ({
482
531
  ...s,
483
532
  status: "pending",
533
+ statusCode: 200,
484
534
  isLoading: true,
485
535
  location: this.latestLocation,
486
536
  pendingMatches,
487
537
  // If a cached moved to pendingMatches, remove it from cachedMatches
488
- cachedMatches: s.cachedMatches.filter((d) => {
489
- return !pendingMatches.find((e) => e.id === d.id);
490
- })
538
+ cachedMatches: s.cachedMatches.filter(
539
+ (d) => !pendingMatches.some((e) => e.id === d.id)
540
+ )
491
541
  }));
492
542
  };
493
543
  this.load = async (opts) => {
494
- let redirect;
544
+ let redirect2;
495
545
  let notFound;
496
546
  let loadPromise;
497
547
  loadPromise = new Promise((resolve) => {
498
548
  this.startTransition(async () => {
499
- var _a;
500
549
  try {
501
550
  this.beforeLoad();
502
551
  const next = this.latestLocation;
@@ -518,7 +567,7 @@ class RouterCore {
518
567
  })
519
568
  });
520
569
  await this.loadMatches({
521
- sync: opts == null ? void 0 : opts.sync,
570
+ sync: opts?.sync,
522
571
  matches: this.state.pendingMatches,
523
572
  location: next,
524
573
  // eslint-disable-next-line @typescript-eslint/require-await
@@ -532,13 +581,13 @@ class RouterCore {
532
581
  const previousMatches = s.matches;
533
582
  const newMatches = s.pendingMatches || s.matches;
534
583
  exitingMatches = previousMatches.filter(
535
- (match) => !newMatches.find((d) => d.id === match.id)
584
+ (match) => !newMatches.some((d) => d.id === match.id)
536
585
  );
537
586
  enteringMatches = newMatches.filter(
538
- (match) => !previousMatches.find((d) => d.id === match.id)
587
+ (match) => !previousMatches.some((d) => d.id === match.id)
539
588
  );
540
589
  stayingMatches = previousMatches.filter(
541
- (match) => newMatches.find((d) => d.id === match.id)
590
+ (match) => newMatches.some((d) => d.id === match.id)
542
591
  );
543
592
  return {
544
593
  ...s,
@@ -560,8 +609,7 @@ class RouterCore {
560
609
  [stayingMatches, "onStay"]
561
610
  ].forEach(([matches, hook]) => {
562
611
  matches.forEach((match) => {
563
- var _a2, _b;
564
- (_b = (_a2 = this.looseRoutesById[match.routeId].options)[hook]) == null ? void 0 : _b.call(_a2, match);
612
+ this.looseRoutesById[match.routeId].options[hook]?.(match);
565
613
  });
566
614
  });
567
615
  });
@@ -569,10 +617,10 @@ class RouterCore {
569
617
  });
570
618
  } catch (err) {
571
619
  if (isRedirect(err)) {
572
- redirect = err;
620
+ redirect2 = err;
573
621
  if (!this.isServer) {
574
622
  this.navigate({
575
- ...redirect.options,
623
+ ...redirect2.options,
576
624
  replace: true,
577
625
  ignoreBlocker: true
578
626
  });
@@ -582,12 +630,12 @@ class RouterCore {
582
630
  }
583
631
  this.__store.setState((s) => ({
584
632
  ...s,
585
- statusCode: redirect ? redirect.status : notFound ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200,
586
- redirect
633
+ statusCode: redirect2 ? redirect2.status : notFound ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200,
634
+ redirect: redirect2
587
635
  }));
588
636
  }
589
637
  if (this.latestLoadPromise === loadPromise) {
590
- (_a = this.commitLocationPromise) == null ? void 0 : _a.resolve();
638
+ this.commitLocationPromise?.resolve();
591
639
  this.latestLoadPromise = void 0;
592
640
  this.commitLocationPromise = void 0;
593
641
  }
@@ -633,31 +681,17 @@ class RouterCore {
633
681
  }
634
682
  };
635
683
  this.updateMatch = (id, updater) => {
636
- var _a;
637
- let updated;
638
- const isPending = (_a = this.state.pendingMatches) == null ? void 0 : _a.find((d) => d.id === id);
639
- const isMatched = this.state.matches.find((d) => d.id === id);
640
- const isCached = this.state.cachedMatches.find((d) => d.id === id);
641
- const matchesKey = isPending ? "pendingMatches" : isMatched ? "matches" : isCached ? "cachedMatches" : "";
684
+ const matchesKey = this.state.pendingMatches?.some((d) => d.id === id) ? "pendingMatches" : this.state.matches.some((d) => d.id === id) ? "matches" : this.state.cachedMatches.some((d) => d.id === id) ? "cachedMatches" : "";
642
685
  if (matchesKey) {
643
- this.__store.setState((s) => {
644
- var _a2;
645
- return {
646
- ...s,
647
- [matchesKey]: (_a2 = s[matchesKey]) == null ? void 0 : _a2.map(
648
- (d) => d.id === id ? updated = updater(d) : d
649
- )
650
- };
651
- });
686
+ this.__store.setState((s) => ({
687
+ ...s,
688
+ [matchesKey]: s[matchesKey]?.map((d) => d.id === id ? updater(d) : d)
689
+ }));
652
690
  }
653
- return updated;
654
691
  };
655
692
  this.getMatch = (matchId) => {
656
- return [
657
- ...this.state.cachedMatches,
658
- ...this.state.pendingMatches ?? [],
659
- ...this.state.matches
660
- ].find((d) => d.id === matchId);
693
+ const findFn = (d) => d.id === matchId;
694
+ return this.state.cachedMatches.find(findFn) ?? this.state.pendingMatches?.find(findFn) ?? this.state.matches.find(findFn);
661
695
  };
662
696
  this.loadMatches = async ({
663
697
  location,
@@ -672,14 +706,16 @@ class RouterCore {
672
706
  const triggerOnReady = async () => {
673
707
  if (!rendered) {
674
708
  rendered = true;
675
- await (onReady == null ? void 0 : onReady());
709
+ await onReady?.();
676
710
  }
677
711
  };
678
712
  const resolvePreload = (matchId) => {
679
- return !!(allPreload && !this.state.matches.find((d) => d.id === matchId));
713
+ return !!(allPreload && !this.state.matches.some((d) => d.id === matchId));
680
714
  };
715
+ if (!this.isServer && this.state.matches.some((d) => d._forcePending)) {
716
+ triggerOnReady();
717
+ }
681
718
  const handleRedirectAndNotFound = (match, err) => {
682
- var _a, _b, _c, _d;
683
719
  if (isRedirect(err) || isNotFound(err)) {
684
720
  if (isRedirect(err)) {
685
721
  if (err.redirectHandled) {
@@ -688,6 +724,8 @@ class RouterCore {
688
724
  }
689
725
  }
690
726
  }
727
+ match.beforeLoadPromise?.resolve();
728
+ match.loaderPromise?.resolve();
691
729
  updateMatch(match.id, (prev) => ({
692
730
  ...prev,
693
731
  status: isRedirect(err) ? "redirected" : isNotFound(err) ? "notFound" : "error",
@@ -699,9 +737,7 @@ class RouterCore {
699
737
  if (!err.routeId) {
700
738
  err.routeId = match.routeId;
701
739
  }
702
- (_a = match.beforeLoadPromise) == null ? void 0 : _a.resolve();
703
- (_b = match.loaderPromise) == null ? void 0 : _b.resolve();
704
- (_c = match.loadPromise) == null ? void 0 : _c.resolve();
740
+ match.loadPromise?.resolve();
705
741
  if (isRedirect(err)) {
706
742
  rendered = true;
707
743
  err.options._fromLocation = location;
@@ -712,22 +748,28 @@ class RouterCore {
712
748
  this._handleNotFound(matches, err, {
713
749
  updateMatch
714
750
  });
715
- (_d = this.serverSsr) == null ? void 0 : _d.onMatchSettled({
716
- router: this,
717
- match: this.getMatch(match.id)
718
- });
719
751
  throw err;
720
752
  }
721
753
  }
722
754
  };
755
+ const shouldSkipLoader = (matchId) => {
756
+ const match = this.getMatch(matchId);
757
+ if (!this.isServer && match._dehydrated) {
758
+ return true;
759
+ }
760
+ if (this.isServer) {
761
+ if (match.ssr === false) {
762
+ return true;
763
+ }
764
+ }
765
+ return false;
766
+ };
723
767
  try {
724
768
  await new Promise((resolveAll, rejectAll) => {
725
769
  ;
726
770
  (async () => {
727
- var _a, _b, _c, _d;
728
771
  try {
729
772
  const handleSerialError = (index, err, routerCode) => {
730
- var _a2, _b2;
731
773
  const { id: matchId, routeId } = matches[index];
732
774
  const route = this.looseRoutesById[routeId];
733
775
  if (err instanceof Promise) {
@@ -737,15 +779,14 @@ class RouterCore {
737
779
  firstBadMatchIndex = firstBadMatchIndex ?? index;
738
780
  handleRedirectAndNotFound(this.getMatch(matchId), err);
739
781
  try {
740
- (_b2 = (_a2 = route.options).onError) == null ? void 0 : _b2.call(_a2, err);
782
+ route.options.onError?.(err);
741
783
  } catch (errorHandlerErr) {
742
784
  err = errorHandlerErr;
743
785
  handleRedirectAndNotFound(this.getMatch(matchId), err);
744
786
  }
745
787
  updateMatch(matchId, (prev) => {
746
- var _a3, _b3;
747
- (_a3 = prev.beforeLoadPromise) == null ? void 0 : _a3.resolve();
748
- (_b3 = prev.loadPromise) == null ? void 0 : _b3.resolve();
788
+ prev.beforeLoadPromise?.resolve();
789
+ prev.loadPromise?.resolve();
749
790
  return {
750
791
  ...prev,
751
792
  error: err,
@@ -759,26 +800,94 @@ class RouterCore {
759
800
  };
760
801
  for (const [index, { id: matchId, routeId }] of matches.entries()) {
761
802
  const existingMatch = this.getMatch(matchId);
762
- const parentMatchId = (_a = matches[index - 1]) == null ? void 0 : _a.id;
803
+ const parentMatchId = matches[index - 1]?.id;
804
+ const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
763
805
  const route = this.looseRoutesById[routeId];
764
806
  const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
765
- const shouldPending = !!(onReady && !this.isServer && !resolvePreload(matchId) && (route.options.loader || route.options.beforeLoad || routeNeedsPreload(route)) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? ((_b = this.options) == null ? void 0 : _b.defaultPendingComponent)));
807
+ if (this.isServer) {
808
+ let ssr;
809
+ if (this.isShell()) {
810
+ ssr = matchId === rootRouteId;
811
+ } else {
812
+ const defaultSsr = this.options.defaultSsr ?? true;
813
+ if (parentMatch?.ssr === false) {
814
+ ssr = false;
815
+ } else {
816
+ let tempSsr;
817
+ if (route.options.ssr === void 0) {
818
+ tempSsr = defaultSsr;
819
+ } else if (typeof route.options.ssr === "function") {
820
+ let makeMaybe = function(value, error) {
821
+ if (error) {
822
+ return { status: "error", error };
823
+ }
824
+ return { status: "success", value };
825
+ };
826
+ const { search, params } = this.getMatch(matchId);
827
+ const ssrFnContext = {
828
+ search: makeMaybe(search, existingMatch.searchError),
829
+ params: makeMaybe(params, existingMatch.paramsError),
830
+ location,
831
+ matches: matches.map((match) => ({
832
+ index: match.index,
833
+ pathname: match.pathname,
834
+ fullPath: match.fullPath,
835
+ staticData: match.staticData,
836
+ id: match.id,
837
+ routeId: match.routeId,
838
+ search: makeMaybe(match.search, match.searchError),
839
+ params: makeMaybe(match.params, match.paramsError),
840
+ ssr: match.ssr
841
+ }))
842
+ };
843
+ tempSsr = await route.options.ssr(ssrFnContext) ?? defaultSsr;
844
+ } else {
845
+ tempSsr = route.options.ssr;
846
+ }
847
+ if (tempSsr === true && parentMatch?.ssr === "data-only") {
848
+ ssr = "data-only";
849
+ } else {
850
+ ssr = tempSsr;
851
+ }
852
+ }
853
+ }
854
+ updateMatch(matchId, (prev) => ({
855
+ ...prev,
856
+ ssr
857
+ }));
858
+ }
859
+ if (shouldSkipLoader(matchId)) {
860
+ continue;
861
+ }
862
+ const shouldPending = !!(onReady && !this.isServer && !resolvePreload(matchId) && (route.options.loader || route.options.beforeLoad || routeNeedsPreload(route)) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? this.options?.defaultPendingComponent));
766
863
  let executeBeforeLoad = true;
767
- if (
768
- // If we are in the middle of a load, either of these will be present
769
- // (not to be confused with `loadPromise`, which is always defined)
770
- existingMatch.beforeLoadPromise || existingMatch.loaderPromise
771
- ) {
772
- if (shouldPending) {
773
- setTimeout(() => {
864
+ const setupPendingTimeout = () => {
865
+ if (shouldPending && this.getMatch(matchId).pendingTimeout === void 0) {
866
+ const pendingTimeout = setTimeout(() => {
774
867
  try {
775
868
  triggerOnReady();
776
869
  } catch {
777
870
  }
778
871
  }, pendingMs);
872
+ updateMatch(matchId, (prev) => ({
873
+ ...prev,
874
+ pendingTimeout
875
+ }));
779
876
  }
877
+ };
878
+ if (
879
+ // If we are in the middle of a load, either of these will be present
880
+ // (not to be confused with `loadPromise`, which is always defined)
881
+ existingMatch.beforeLoadPromise || existingMatch.loaderPromise
882
+ ) {
883
+ setupPendingTimeout();
780
884
  await existingMatch.beforeLoadPromise;
781
- executeBeforeLoad = this.getMatch(matchId).status !== "success";
885
+ const match = this.getMatch(matchId);
886
+ if (match.status === "error") {
887
+ executeBeforeLoad = true;
888
+ } else if (match.preload && (match.status === "redirected" || match.status === "notFound")) {
889
+ handleRedirectAndNotFound(match, match.error);
890
+ }
782
891
  }
783
892
  if (executeBeforeLoad) {
784
893
  try {
@@ -787,21 +896,11 @@ class RouterCore {
787
896
  return {
788
897
  ...prev,
789
898
  loadPromise: createControlledPromise(() => {
790
- prevLoadPromise == null ? void 0 : prevLoadPromise.resolve();
899
+ prevLoadPromise?.resolve();
791
900
  }),
792
901
  beforeLoadPromise: createControlledPromise()
793
902
  };
794
903
  });
795
- const abortController = new AbortController();
796
- let pendingTimeout;
797
- if (shouldPending) {
798
- pendingTimeout = setTimeout(() => {
799
- try {
800
- triggerOnReady();
801
- } catch {
802
- }
803
- }, pendingMs);
804
- }
805
904
  const { paramsError, searchError } = this.getMatch(matchId);
806
905
  if (paramsError) {
807
906
  handleSerialError(index, paramsError, "PARSE_PARAMS");
@@ -809,15 +908,16 @@ class RouterCore {
809
908
  if (searchError) {
810
909
  handleSerialError(index, searchError, "VALIDATE_SEARCH");
811
910
  }
812
- const getParentMatchContext = () => parentMatchId ? this.getMatch(parentMatchId).context : this.options.context ?? {};
911
+ setupPendingTimeout();
912
+ const abortController = new AbortController();
913
+ const parentMatchContext = parentMatch?.context ?? this.options.context ?? {};
813
914
  updateMatch(matchId, (prev) => ({
814
915
  ...prev,
815
916
  isFetching: "beforeLoad",
816
917
  fetchCount: prev.fetchCount + 1,
817
918
  abortController,
818
- pendingTimeout,
819
919
  context: {
820
- ...getParentMatchContext(),
920
+ ...parentMatchContext,
821
921
  ...prev.__routeContext
822
922
  }
823
923
  }));
@@ -835,7 +935,7 @@ class RouterCore {
835
935
  cause: preload ? "preload" : cause,
836
936
  matches
837
937
  };
838
- const beforeLoadContext = await ((_d = (_c = route.options).beforeLoad) == null ? void 0 : _d.call(_c, beforeLoadFnContext)) ?? {};
938
+ const beforeLoadContext = await route.options.beforeLoad?.(beforeLoadFnContext);
839
939
  if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
840
940
  handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
841
941
  }
@@ -844,7 +944,7 @@ class RouterCore {
844
944
  ...prev,
845
945
  __beforeLoadContext: beforeLoadContext,
846
946
  context: {
847
- ...getParentMatchContext(),
947
+ ...parentMatchContext,
848
948
  ...prev.__routeContext,
849
949
  ...beforeLoadContext
850
950
  },
@@ -855,8 +955,7 @@ class RouterCore {
855
955
  handleSerialError(index, err, "BEFORE_LOAD");
856
956
  }
857
957
  updateMatch(matchId, (prev) => {
858
- var _a2;
859
- (_a2 = prev.beforeLoadPromise) == null ? void 0 : _a2.resolve();
958
+ prev.beforeLoadPromise?.resolve();
860
959
  return {
861
960
  ...prev,
862
961
  beforeLoadPromise: void 0,
@@ -870,18 +969,63 @@ class RouterCore {
870
969
  validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
871
970
  matchPromises.push(
872
971
  (async () => {
873
- const { loaderPromise: prevLoaderPromise } = this.getMatch(matchId);
874
972
  let loaderShouldRunAsync = false;
875
973
  let loaderIsRunningAsync = false;
876
- if (prevLoaderPromise) {
877
- await prevLoaderPromise;
974
+ const route = this.looseRoutesById[routeId];
975
+ const executeHead = async () => {
976
+ const match = this.getMatch(matchId);
977
+ if (!match) {
978
+ return;
979
+ }
980
+ const assetContext = {
981
+ matches,
982
+ match,
983
+ params: match.params,
984
+ loaderData: match.loaderData
985
+ };
986
+ const headFnContent = await route.options.head?.(assetContext);
987
+ const meta = headFnContent?.meta;
988
+ const links = headFnContent?.links;
989
+ const headScripts = headFnContent?.scripts;
990
+ const styles = headFnContent?.styles;
991
+ const scripts = await route.options.scripts?.(assetContext);
992
+ const headers = await route.options.headers?.(assetContext);
993
+ return {
994
+ meta,
995
+ links,
996
+ headScripts,
997
+ headers,
998
+ scripts,
999
+ styles
1000
+ };
1001
+ };
1002
+ const potentialPendingMinPromise = async () => {
1003
+ const latestMatch = this.getMatch(matchId);
1004
+ if (latestMatch.minPendingPromise) {
1005
+ await latestMatch.minPendingPromise;
1006
+ }
1007
+ };
1008
+ const prevMatch = this.getMatch(matchId);
1009
+ if (shouldSkipLoader(matchId)) {
1010
+ if (this.isServer) {
1011
+ const head = await executeHead();
1012
+ updateMatch(matchId, (prev) => ({
1013
+ ...prev,
1014
+ ...head
1015
+ }));
1016
+ return this.getMatch(matchId);
1017
+ }
1018
+ } else if (prevMatch.loaderPromise) {
1019
+ if (prevMatch.status === "success" && !sync && !prevMatch.preload) {
1020
+ return this.getMatch(matchId);
1021
+ }
1022
+ await prevMatch.loaderPromise;
878
1023
  const match = this.getMatch(matchId);
879
1024
  if (match.error) {
880
1025
  handleRedirectAndNotFound(match, match.error);
881
1026
  }
882
1027
  } else {
883
1028
  const parentMatchPromise = matchPromises[index - 1];
884
- const route = this.looseRoutesById[routeId];
885
1029
  const getLoaderContext = () => {
886
1030
  const {
887
1031
  params,
@@ -912,49 +1056,29 @@ class RouterCore {
912
1056
  updateMatch(matchId, (prev) => ({
913
1057
  ...prev,
914
1058
  loaderPromise: createControlledPromise(),
915
- preload: !!preload && !this.state.matches.find((d) => d.id === matchId)
1059
+ preload: !!preload && !this.state.matches.some((d) => d.id === matchId)
916
1060
  }));
917
- const executeHead = async () => {
918
- var _a2, _b2, _c2, _d2, _e, _f;
919
- const match = this.getMatch(matchId);
920
- if (!match) {
921
- return;
922
- }
923
- const assetContext = {
924
- matches,
925
- match,
926
- params: match.params,
927
- loaderData: match.loaderData
928
- };
929
- const headFnContent = await ((_b2 = (_a2 = route.options).head) == null ? void 0 : _b2.call(_a2, assetContext));
930
- const meta = headFnContent == null ? void 0 : headFnContent.meta;
931
- const links = headFnContent == null ? void 0 : headFnContent.links;
932
- const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
933
- const scripts = await ((_d2 = (_c2 = route.options).scripts) == null ? void 0 : _d2.call(_c2, assetContext));
934
- const headers = await ((_f = (_e = route.options).headers) == null ? void 0 : _f.call(_e, assetContext));
935
- return { meta, links, headScripts, headers, scripts };
936
- };
937
1061
  const runLoader = async () => {
938
- var _a2, _b2, _c2, _d2, _e;
939
1062
  try {
940
- const potentialPendingMinPromise = async () => {
941
- const latestMatch = this.getMatch(matchId);
942
- if (latestMatch.minPendingPromise) {
943
- await latestMatch.minPendingPromise;
944
- }
945
- };
946
1063
  try {
947
- this.loadRouteChunk(route);
1064
+ if (!this.isServer || this.isServer && this.getMatch(matchId).ssr === true) {
1065
+ this.loadRouteChunk(route);
1066
+ }
948
1067
  updateMatch(matchId, (prev) => ({
949
1068
  ...prev,
950
1069
  isFetching: "loader"
951
1070
  }));
952
- const loaderData = await ((_b2 = (_a2 = route.options).loader) == null ? void 0 : _b2.call(_a2, getLoaderContext()));
1071
+ const loaderData = await route.options.loader?.(getLoaderContext());
953
1072
  handleRedirectAndNotFound(
954
1073
  this.getMatch(matchId),
955
1074
  loaderData
956
1075
  );
1076
+ updateMatch(matchId, (prev) => ({
1077
+ ...prev,
1078
+ loaderData
1079
+ }));
957
1080
  await route._lazyPromise;
1081
+ const head = await executeHead();
958
1082
  await potentialPendingMinPromise();
959
1083
  await route._componentsPromise;
960
1084
  updateMatch(matchId, (prev) => ({
@@ -963,11 +1087,6 @@ class RouterCore {
963
1087
  status: "success",
964
1088
  isFetching: false,
965
1089
  updatedAt: Date.now(),
966
- loaderData
967
- }));
968
- const head = await executeHead();
969
- updateMatch(matchId, (prev) => ({
970
- ...prev,
971
1090
  ...head
972
1091
  }));
973
1092
  } catch (e) {
@@ -975,7 +1094,7 @@ class RouterCore {
975
1094
  await potentialPendingMinPromise();
976
1095
  handleRedirectAndNotFound(this.getMatch(matchId), e);
977
1096
  try {
978
- (_d2 = (_c2 = route.options).onError) == null ? void 0 : _d2.call(_c2, e);
1097
+ route.options.onError?.(e);
979
1098
  } catch (onErrorError) {
980
1099
  error = onErrorError;
981
1100
  handleRedirectAndNotFound(
@@ -992,10 +1111,6 @@ class RouterCore {
992
1111
  ...head
993
1112
  }));
994
1113
  }
995
- (_e = this.serverSsr) == null ? void 0 : _e.onMatchSettled({
996
- router: this,
997
- match: this.getMatch(matchId)
998
- });
999
1114
  } catch (err) {
1000
1115
  const head = await executeHead();
1001
1116
  updateMatch(matchId, (prev) => ({
@@ -1015,8 +1130,8 @@ class RouterCore {
1015
1130
  try {
1016
1131
  await runLoader();
1017
1132
  const { loaderPromise, loadPromise } = this.getMatch(matchId);
1018
- loaderPromise == null ? void 0 : loaderPromise.resolve();
1019
- loadPromise == null ? void 0 : loadPromise.resolve();
1133
+ loaderPromise?.resolve();
1134
+ loadPromise?.resolve();
1020
1135
  updateMatch(matchId, (prev) => ({
1021
1136
  ...prev,
1022
1137
  loaderPromise: void 0
@@ -1039,15 +1154,20 @@ class RouterCore {
1039
1154
  }
1040
1155
  if (!loaderIsRunningAsync) {
1041
1156
  const { loaderPromise, loadPromise } = this.getMatch(matchId);
1042
- loaderPromise == null ? void 0 : loaderPromise.resolve();
1043
- loadPromise == null ? void 0 : loadPromise.resolve();
1157
+ loaderPromise?.resolve();
1158
+ loadPromise?.resolve();
1044
1159
  }
1045
- updateMatch(matchId, (prev) => ({
1046
- ...prev,
1047
- isFetching: loaderIsRunningAsync ? prev.isFetching : false,
1048
- loaderPromise: loaderIsRunningAsync ? prev.loaderPromise : void 0,
1049
- invalid: false
1050
- }));
1160
+ updateMatch(matchId, (prev) => {
1161
+ clearTimeout(prev.pendingTimeout);
1162
+ return {
1163
+ ...prev,
1164
+ isFetching: loaderIsRunningAsync ? prev.isFetching : false,
1165
+ loaderPromise: loaderIsRunningAsync ? prev.loaderPromise : void 0,
1166
+ invalid: false,
1167
+ pendingTimeout: void 0,
1168
+ _dehydrated: void 0
1169
+ };
1170
+ });
1051
1171
  return this.getMatch(matchId);
1052
1172
  })()
1053
1173
  );
@@ -1072,39 +1192,36 @@ class RouterCore {
1072
1192
  };
1073
1193
  this.invalidate = (opts) => {
1074
1194
  const invalidate = (d) => {
1075
- var _a;
1076
- if (((_a = opts == null ? void 0 : opts.filter) == null ? void 0 : _a.call(opts, d)) ?? true) {
1195
+ if (opts?.filter?.(d) ?? true) {
1077
1196
  return {
1078
1197
  ...d,
1079
1198
  invalid: true,
1080
- ...d.status === "error" ? { status: "pending", error: void 0 } : {}
1199
+ ...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : {}
1081
1200
  };
1082
1201
  }
1083
1202
  return d;
1084
1203
  };
1085
- this.__store.setState((s) => {
1086
- var _a;
1087
- return {
1088
- ...s,
1089
- matches: s.matches.map(invalidate),
1090
- cachedMatches: s.cachedMatches.map(invalidate),
1091
- pendingMatches: (_a = s.pendingMatches) == null ? void 0 : _a.map(invalidate)
1092
- };
1093
- });
1094
- return this.load({ sync: opts == null ? void 0 : opts.sync });
1204
+ this.__store.setState((s) => ({
1205
+ ...s,
1206
+ matches: s.matches.map(invalidate),
1207
+ cachedMatches: s.cachedMatches.map(invalidate),
1208
+ pendingMatches: s.pendingMatches?.map(invalidate)
1209
+ }));
1210
+ this.shouldViewTransition = false;
1211
+ return this.load({ sync: opts?.sync });
1095
1212
  };
1096
- this.resolveRedirect = (redirect) => {
1097
- if (!redirect.options.href) {
1098
- redirect.options.href = this.buildLocation(redirect.options).href;
1099
- redirect.headers.set("Location", redirect.options.href);
1213
+ this.resolveRedirect = (redirect2) => {
1214
+ if (!redirect2.options.href) {
1215
+ redirect2.options.href = this.buildLocation(redirect2.options).href;
1216
+ redirect2.headers.set("Location", redirect2.options.href);
1100
1217
  }
1101
- if (!redirect.headers.get("Location")) {
1102
- redirect.headers.set("Location", redirect.options.href);
1218
+ if (!redirect2.headers.get("Location")) {
1219
+ redirect2.headers.set("Location", redirect2.options.href);
1103
1220
  }
1104
- return redirect;
1221
+ return redirect2;
1105
1222
  };
1106
1223
  this.clearCache = (opts) => {
1107
- const filter = opts == null ? void 0 : opts.filter;
1224
+ const filter = opts?.filter;
1108
1225
  if (filter !== void 0) {
1109
1226
  this.__store.setState((s) => {
1110
1227
  return {
@@ -1130,7 +1247,10 @@ class RouterCore {
1130
1247
  return true;
1131
1248
  }
1132
1249
  const gcTime = (d.preload ? route.options.preloadGcTime ?? this.options.defaultPreloadGcTime : route.options.gcTime ?? this.options.defaultGcTime) ?? 5 * 60 * 1e3;
1133
- return !(d.status !== "error" && Date.now() - d.updatedAt < gcTime);
1250
+ const isError = d.status === "error";
1251
+ if (isError) return true;
1252
+ const gcEligible = Date.now() - d.updatedAt >= gcTime;
1253
+ return gcEligible;
1134
1254
  };
1135
1255
  this.clearCache({ filter });
1136
1256
  };
@@ -1150,7 +1270,7 @@ class RouterCore {
1150
1270
  () => Promise.all(
1151
1271
  componentTypes.map(async (type) => {
1152
1272
  const component = route.options[type];
1153
- if (component == null ? void 0 : component.preload) {
1273
+ if (component?.preload) {
1154
1274
  await component.preload();
1155
1275
  }
1156
1276
  })
@@ -1226,15 +1346,20 @@ class RouterCore {
1226
1346
  leaveParams: true
1227
1347
  };
1228
1348
  const next = this.buildLocation(matchLocation);
1229
- if ((opts == null ? void 0 : opts.pending) && this.state.status !== "pending") {
1349
+ if (opts?.pending && this.state.status !== "pending") {
1230
1350
  return false;
1231
1351
  }
1232
- const pending = (opts == null ? void 0 : opts.pending) === void 0 ? !this.state.isLoading : opts.pending;
1352
+ const pending = opts?.pending === void 0 ? !this.state.isLoading : opts.pending;
1233
1353
  const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
1234
- const match = matchPathname(this.basepath, baseLocation.pathname, {
1235
- ...opts,
1236
- to: next.pathname
1237
- });
1354
+ const match = matchPathname(
1355
+ this.basepath,
1356
+ baseLocation.pathname,
1357
+ {
1358
+ ...opts,
1359
+ to: next.pathname
1360
+ },
1361
+ this.parsePathnameCache
1362
+ );
1238
1363
  if (!match) {
1239
1364
  return false;
1240
1365
  }
@@ -1243,7 +1368,7 @@ class RouterCore {
1243
1368
  return false;
1244
1369
  }
1245
1370
  }
1246
- if (match && ((opts == null ? void 0 : opts.includeSearch) ?? true)) {
1371
+ if (match && (opts?.includeSearch ?? true)) {
1247
1372
  return deepEqual(baseLocation.search, next.search, { partial: true }) ? match : false;
1248
1373
  }
1249
1374
  return match;
@@ -1251,13 +1376,12 @@ class RouterCore {
1251
1376
  this._handleNotFound = (matches, err, {
1252
1377
  updateMatch = this.updateMatch
1253
1378
  } = {}) => {
1254
- var _a;
1255
1379
  const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
1256
1380
  const matchesByRouteId = {};
1257
1381
  for (const match of matches) {
1258
1382
  matchesByRouteId[match.routeId] = match;
1259
1383
  }
1260
- if (!routeCursor.options.notFoundComponent && ((_a = this.options) == null ? void 0 : _a.defaultNotFoundComponent)) {
1384
+ if (!routeCursor.options.notFoundComponent && this.options?.defaultNotFoundComponent) {
1261
1385
  routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
1262
1386
  }
1263
1387
  invariant(
@@ -1299,9 +1423,15 @@ class RouterCore {
1299
1423
  parseSearch: options.parseSearch ?? defaultParseSearch
1300
1424
  });
1301
1425
  if (typeof document !== "undefined") {
1302
- window.__TSR_ROUTER__ = this;
1426
+ self.__TSR_ROUTER__ = this;
1303
1427
  }
1304
1428
  }
1429
+ isShell() {
1430
+ return !!this.options.isShell;
1431
+ }
1432
+ isPrerendering() {
1433
+ return !!this.options.isPrerendering;
1434
+ }
1305
1435
  get state() {
1306
1436
  return this.__store.state;
1307
1437
  }
@@ -1309,10 +1439,9 @@ class RouterCore {
1309
1439
  return this.routesById;
1310
1440
  }
1311
1441
  matchRoutesInternal(next, opts) {
1312
- var _a;
1313
1442
  const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
1314
1443
  next.pathname,
1315
- (_a = opts == null ? void 0 : opts.dest) == null ? void 0 : _a.to
1444
+ opts?.dest?.to
1316
1445
  );
1317
1446
  let isGlobalNotFound = false;
1318
1447
  if (
@@ -1343,9 +1472,8 @@ class RouterCore {
1343
1472
  return rootRouteId;
1344
1473
  })();
1345
1474
  const parseErrors = matchedRoutes.map((route) => {
1346
- var _a2;
1347
1475
  let parsedParamsError;
1348
- const parseParams = ((_a2 = route.options.params) == null ? void 0 : _a2.parse) ?? route.options.parseParams;
1476
+ const parseParams = route.options.params?.parse ?? route.options.parseParams;
1349
1477
  if (parseParams) {
1350
1478
  try {
1351
1479
  const parsedParams = parseParams(routeParams);
@@ -1354,7 +1482,7 @@ class RouterCore {
1354
1482
  parsedParamsError = new PathParamError(err.message, {
1355
1483
  cause: err
1356
1484
  });
1357
- if (opts == null ? void 0 : opts.throwOnError) {
1485
+ if (opts?.throwOnError) {
1358
1486
  throw parsedParamsError;
1359
1487
  }
1360
1488
  return parsedParamsError;
@@ -1364,16 +1492,15 @@ class RouterCore {
1364
1492
  });
1365
1493
  const matches = [];
1366
1494
  const getParentContext = (parentMatch) => {
1367
- const parentMatchId = parentMatch == null ? void 0 : parentMatch.id;
1495
+ const parentMatchId = parentMatch?.id;
1368
1496
  const parentContext = !parentMatchId ? this.options.context ?? {} : parentMatch.context ?? this.options.context ?? {};
1369
1497
  return parentContext;
1370
1498
  };
1371
1499
  matchedRoutes.forEach((route, index) => {
1372
- var _a2, _b;
1373
1500
  const parentMatch = matches[index - 1];
1374
1501
  const [preMatchSearch, strictMatchSearch, searchError] = (() => {
1375
- const parentSearch = (parentMatch == null ? void 0 : parentMatch.search) ?? next.search;
1376
- const parentStrictSearch = (parentMatch == null ? void 0 : parentMatch._strictSearch) ?? {};
1502
+ const parentSearch = parentMatch?.search ?? next.search;
1503
+ const parentStrictSearch = parentMatch?._strictSearch ?? {};
1377
1504
  try {
1378
1505
  const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? {};
1379
1506
  return [
@@ -1391,15 +1518,15 @@ class RouterCore {
1391
1518
  cause: err
1392
1519
  });
1393
1520
  }
1394
- if (opts == null ? void 0 : opts.throwOnError) {
1521
+ if (opts?.throwOnError) {
1395
1522
  throw searchParamError;
1396
1523
  }
1397
1524
  return [parentSearch, {}, searchParamError];
1398
1525
  }
1399
1526
  })();
1400
- const loaderDeps = ((_b = (_a2 = route.options).loaderDeps) == null ? void 0 : _b.call(_a2, {
1527
+ const loaderDeps = route.options.loaderDeps?.({
1401
1528
  search: preMatchSearch
1402
- })) ?? "";
1529
+ }) ?? "";
1403
1530
  const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
1404
1531
  const { usedParams, interpolatedPath } = interpolatePath({
1405
1532
  path: route.fullPath,
@@ -1410,7 +1537,8 @@ class RouterCore {
1410
1537
  path: route.id,
1411
1538
  params: routeParams,
1412
1539
  leaveWildcards: true,
1413
- decodeCharMap: this.pathParamsDecodeCharMap
1540
+ decodeCharMap: this.pathParamsDecodeCharMap,
1541
+ parseCache: this.parsePathnameCache
1414
1542
  }).interpolatedPath + loaderDepsHash;
1415
1543
  const existingMatch = this.getMatch(matchId);
1416
1544
  const previousMatch = this.state.matches.find(
@@ -1445,7 +1573,7 @@ class RouterCore {
1445
1573
  error: void 0,
1446
1574
  paramsError: parseErrors[index],
1447
1575
  __routeContext: {},
1448
- __beforeLoadContext: {},
1576
+ __beforeLoadContext: void 0,
1449
1577
  context: {},
1450
1578
  abortController: new AbortController(),
1451
1579
  fetchCount: 0,
@@ -1462,7 +1590,7 @@ class RouterCore {
1462
1590
  fullPath: route.fullPath
1463
1591
  };
1464
1592
  }
1465
- if (!(opts == null ? void 0 : opts.preload)) {
1593
+ if (!opts?.preload) {
1466
1594
  match.globalNotFound = globalNotFoundRouteId === route.id;
1467
1595
  }
1468
1596
  match.searchError = searchError;
@@ -1475,10 +1603,9 @@ class RouterCore {
1475
1603
  matches.push(match);
1476
1604
  });
1477
1605
  matches.forEach((match, index) => {
1478
- var _a2, _b;
1479
1606
  const route = this.looseRoutesById[match.routeId];
1480
1607
  const existingMatch = this.getMatch(match.id);
1481
- if (!existingMatch && (opts == null ? void 0 : opts._buildLocation) !== true) {
1608
+ if (!existingMatch && opts?._buildLocation !== true) {
1482
1609
  const parentMatch = matches[index - 1];
1483
1610
  const parentContext = getParentContext(parentMatch);
1484
1611
  const contextFnContext = {
@@ -1493,7 +1620,7 @@ class RouterCore {
1493
1620
  preload: !!match.preload,
1494
1621
  matches
1495
1622
  };
1496
- match.__routeContext = ((_b = (_a2 = route.options).context) == null ? void 0 : _b.call(_a2, contextFnContext)) ?? {};
1623
+ match.__routeContext = route.options.context?.(contextFnContext) ?? {};
1497
1624
  match.context = {
1498
1625
  ...parentContext,
1499
1626
  ...match.__routeContext,
@@ -1508,6 +1635,10 @@ class SearchParamError extends Error {
1508
1635
  }
1509
1636
  class PathParamError extends Error {
1510
1637
  }
1638
+ const normalize = (str) => str.endsWith("/") && str.length > 1 ? str.slice(0, -1) : str;
1639
+ function comparePaths(a, b) {
1640
+ return normalize(a) === normalize(b);
1641
+ }
1511
1642
  function lazyFn(fn, key) {
1512
1643
  return async (...args) => {
1513
1644
  const imported = await fn();
@@ -1555,14 +1686,33 @@ const componentTypes = [
1555
1686
  "notFoundComponent"
1556
1687
  ];
1557
1688
  function routeNeedsPreload(route) {
1558
- var _a;
1559
1689
  for (const componentType of componentTypes) {
1560
- if ((_a = route.options[componentType]) == null ? void 0 : _a.preload) {
1690
+ if (route.options[componentType]?.preload) {
1561
1691
  return true;
1562
1692
  }
1563
1693
  }
1564
1694
  return false;
1565
1695
  }
1696
+ const REQUIRED_PARAM_BASE_SCORE = 0.5;
1697
+ const OPTIONAL_PARAM_BASE_SCORE = 0.4;
1698
+ const WILDCARD_PARAM_BASE_SCORE = 0.25;
1699
+ const BOTH_PRESENCE_BASE_SCORE = 0.05;
1700
+ const PREFIX_PRESENCE_BASE_SCORE = 0.02;
1701
+ const SUFFIX_PRESENCE_BASE_SCORE = 0.01;
1702
+ const PREFIX_LENGTH_SCORE_MULTIPLIER = 2e-4;
1703
+ const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1e-4;
1704
+ function handleParam(segment, baseScore) {
1705
+ if (segment.prefixSegment && segment.suffixSegment) {
1706
+ return baseScore + BOTH_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
1707
+ }
1708
+ if (segment.prefixSegment) {
1709
+ return baseScore + PREFIX_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length;
1710
+ }
1711
+ if (segment.suffixSegment) {
1712
+ return baseScore + SUFFIX_PRESENCE_BASE_SCORE + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
1713
+ }
1714
+ return baseScore;
1715
+ }
1566
1716
  function processRouteTree({
1567
1717
  routeTree,
1568
1718
  initRoute
@@ -1571,7 +1721,7 @@ function processRouteTree({
1571
1721
  const routesByPath = {};
1572
1722
  const recurseRoutes = (childRoutes) => {
1573
1723
  childRoutes.forEach((childRoute, i) => {
1574
- initRoute == null ? void 0 : initRoute(childRoute, i);
1724
+ initRoute?.(childRoute, i);
1575
1725
  const existingRoute = routesById[childRoute.id];
1576
1726
  invariant(
1577
1727
  !existingRoute,
@@ -1585,7 +1735,7 @@ function processRouteTree({
1585
1735
  }
1586
1736
  }
1587
1737
  const children = childRoute.children;
1588
- if (children == null ? void 0 : children.length) {
1738
+ if (children?.length) {
1589
1739
  recurseRoutes(children);
1590
1740
  }
1591
1741
  });
@@ -1594,46 +1744,52 @@ function processRouteTree({
1594
1744
  const scoredRoutes = [];
1595
1745
  const routes = Object.values(routesById);
1596
1746
  routes.forEach((d, i) => {
1597
- var _a;
1598
1747
  if (d.isRoot || !d.path) {
1599
1748
  return;
1600
1749
  }
1601
1750
  const trimmed = trimPathLeft(d.fullPath);
1602
- const parsed = parsePathname(trimmed);
1603
- while (parsed.length > 1 && ((_a = parsed[0]) == null ? void 0 : _a.value) === "/") {
1604
- parsed.shift();
1751
+ let parsed = parsePathname(trimmed);
1752
+ let skip = 0;
1753
+ while (parsed.length > skip + 1 && parsed[skip]?.value === "/") {
1754
+ skip++;
1605
1755
  }
1606
- const scores = parsed.map((segment) => {
1756
+ if (skip > 0) parsed = parsed.slice(skip);
1757
+ let optionalParamCount = 0;
1758
+ let hasStaticAfter = false;
1759
+ const scores = parsed.map((segment, index) => {
1607
1760
  if (segment.value === "/") {
1608
1761
  return 0.75;
1609
1762
  }
1610
- if (segment.type === "param" && segment.prefixSegment && segment.suffixSegment) {
1611
- return 0.55;
1612
- }
1613
- if (segment.type === "param" && segment.prefixSegment) {
1614
- return 0.52;
1763
+ let baseScore = void 0;
1764
+ if (segment.type === SEGMENT_TYPE_PARAM) {
1765
+ baseScore = REQUIRED_PARAM_BASE_SCORE;
1766
+ } else if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {
1767
+ baseScore = OPTIONAL_PARAM_BASE_SCORE;
1768
+ optionalParamCount++;
1769
+ } else if (segment.type === SEGMENT_TYPE_WILDCARD) {
1770
+ baseScore = WILDCARD_PARAM_BASE_SCORE;
1615
1771
  }
1616
- if (segment.type === "param" && segment.suffixSegment) {
1617
- return 0.51;
1618
- }
1619
- if (segment.type === "param") {
1620
- return 0.5;
1621
- }
1622
- if (segment.type === "wildcard" && segment.prefixSegment && segment.suffixSegment) {
1623
- return 0.3;
1624
- }
1625
- if (segment.type === "wildcard" && segment.prefixSegment) {
1626
- return 0.27;
1627
- }
1628
- if (segment.type === "wildcard" && segment.suffixSegment) {
1629
- return 0.26;
1630
- }
1631
- if (segment.type === "wildcard") {
1632
- return 0.25;
1772
+ if (baseScore) {
1773
+ for (let i2 = index + 1; i2 < parsed.length; i2++) {
1774
+ const nextSegment = parsed[i2];
1775
+ if (nextSegment.type === SEGMENT_TYPE_PATHNAME && nextSegment.value !== "/") {
1776
+ hasStaticAfter = true;
1777
+ return handleParam(segment, baseScore + 0.2);
1778
+ }
1779
+ }
1780
+ return handleParam(segment, baseScore);
1633
1781
  }
1634
1782
  return 1;
1635
1783
  });
1636
- scoredRoutes.push({ child: d, trimmed, parsed, index: i, scores });
1784
+ scoredRoutes.push({
1785
+ child: d,
1786
+ trimmed,
1787
+ parsed,
1788
+ index: i,
1789
+ scores,
1790
+ optionalParamCount,
1791
+ hasStaticAfter
1792
+ });
1637
1793
  });
1638
1794
  const flatRoutes = scoredRoutes.sort((a, b) => {
1639
1795
  const minLength = Math.min(a.scores.length, b.scores.length);
@@ -1643,6 +1799,15 @@ function processRouteTree({
1643
1799
  }
1644
1800
  }
1645
1801
  if (a.scores.length !== b.scores.length) {
1802
+ if (a.optionalParamCount !== b.optionalParamCount) {
1803
+ if (a.hasStaticAfter === b.hasStaticAfter) {
1804
+ return a.optionalParamCount - b.optionalParamCount;
1805
+ } else if (a.hasStaticAfter && !b.hasStaticAfter) {
1806
+ return -1;
1807
+ } else if (!a.hasStaticAfter && b.hasStaticAfter) {
1808
+ return 1;
1809
+ }
1810
+ }
1646
1811
  return b.scores.length - a.scores.length;
1647
1812
  }
1648
1813
  for (let i = 0; i < minLength; i++) {
@@ -1664,38 +1829,56 @@ function getMatchedRoutes({
1664
1829
  caseSensitive,
1665
1830
  routesByPath,
1666
1831
  routesById,
1667
- flatRoutes
1832
+ flatRoutes,
1833
+ parseCache
1668
1834
  }) {
1669
1835
  let routeParams = {};
1670
1836
  const trimmedPath = trimPathRight(pathname);
1671
1837
  const getMatchedParams = (route) => {
1672
- var _a;
1673
- const result = matchPathname(basepath, trimmedPath, {
1674
- to: route.fullPath,
1675
- caseSensitive: ((_a = route.options) == null ? void 0 : _a.caseSensitive) ?? caseSensitive,
1676
- fuzzy: true
1677
- });
1838
+ const result = matchPathname(
1839
+ basepath,
1840
+ trimmedPath,
1841
+ {
1842
+ to: route.fullPath,
1843
+ caseSensitive: route.options?.caseSensitive ?? caseSensitive,
1844
+ // we need fuzzy matching for `notFoundMode: 'fuzzy'`
1845
+ fuzzy: true
1846
+ },
1847
+ parseCache
1848
+ );
1678
1849
  return result;
1679
1850
  };
1680
1851
  let foundRoute = routePathname !== void 0 ? routesByPath[routePathname] : void 0;
1681
1852
  if (foundRoute) {
1682
1853
  routeParams = getMatchedParams(foundRoute);
1683
1854
  } else {
1684
- foundRoute = flatRoutes.find((route) => {
1855
+ let fuzzyMatch = void 0;
1856
+ for (const route of flatRoutes) {
1685
1857
  const matchedParams = getMatchedParams(route);
1686
1858
  if (matchedParams) {
1687
- routeParams = matchedParams;
1688
- return true;
1859
+ if (route.path !== "/" && matchedParams["**"]) {
1860
+ if (!fuzzyMatch) {
1861
+ fuzzyMatch = { foundRoute: route, routeParams: matchedParams };
1862
+ }
1863
+ } else {
1864
+ foundRoute = route;
1865
+ routeParams = matchedParams;
1866
+ break;
1867
+ }
1689
1868
  }
1690
- return false;
1691
- });
1869
+ }
1870
+ if (!foundRoute && fuzzyMatch) {
1871
+ foundRoute = fuzzyMatch.foundRoute;
1872
+ routeParams = fuzzyMatch.routeParams;
1873
+ }
1692
1874
  }
1693
1875
  let routeCursor = foundRoute || routesById[rootRouteId];
1694
1876
  const matchedRoutes = [routeCursor];
1695
1877
  while (routeCursor.parentRoute) {
1696
1878
  routeCursor = routeCursor.parentRoute;
1697
- matchedRoutes.unshift(routeCursor);
1879
+ matchedRoutes.push(routeCursor);
1698
1880
  }
1881
+ matchedRoutes.reverse();
1699
1882
  return { matchedRoutes, routeParams, foundRoute };
1700
1883
  }
1701
1884
  function applySearchMiddleware({
@@ -1706,10 +1889,9 @@ function applySearchMiddleware({
1706
1889
  }) {
1707
1890
  const allMiddlewares = destRoutes.reduce(
1708
1891
  (acc, route) => {
1709
- var _a;
1710
1892
  const middlewares = [];
1711
1893
  if ("search" in route.options) {
1712
- if ((_a = route.options.search) == null ? void 0 : _a.middlewares) {
1894
+ if (route.options.search?.middlewares) {
1713
1895
  middlewares.push(...route.options.search.middlewares);
1714
1896
  }
1715
1897
  } else if (route.options.preSearchFilters || route.options.postSearchFilters) {