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