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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +31 -1
  3. package/dist/cjs/RouterProvider.d.cts +2 -1
  4. package/dist/cjs/defer.cjs +1 -1
  5. package/dist/cjs/defer.cjs.map +1 -1
  6. package/dist/cjs/global.d.cts +7 -0
  7. package/dist/cjs/index.cjs +1 -2
  8. package/dist/cjs/index.cjs.map +1 -1
  9. package/dist/cjs/index.d.cts +6 -6
  10. package/dist/cjs/link.cjs.map +1 -1
  11. package/dist/cjs/link.d.cts +12 -0
  12. package/dist/cjs/lru-cache.cjs +62 -0
  13. package/dist/cjs/lru-cache.cjs.map +1 -0
  14. package/dist/cjs/lru-cache.d.cts +5 -0
  15. package/dist/cjs/not-found.cjs +1 -1
  16. package/dist/cjs/not-found.cjs.map +1 -1
  17. package/dist/cjs/path.cjs +316 -148
  18. package/dist/cjs/path.cjs.map +1 -1
  19. package/dist/cjs/path.d.cts +18 -24
  20. package/dist/cjs/qss.cjs.map +1 -1
  21. package/dist/cjs/redirect.cjs +3 -0
  22. package/dist/cjs/redirect.cjs.map +1 -1
  23. package/dist/cjs/route.cjs +6 -12
  24. package/dist/cjs/route.cjs.map +1 -1
  25. package/dist/cjs/route.d.cts +29 -9
  26. package/dist/cjs/router.cjs +453 -272
  27. package/dist/cjs/router.cjs.map +1 -1
  28. package/dist/cjs/router.d.cts +55 -85
  29. package/dist/cjs/scroll-restoration.cjs +20 -13
  30. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  31. package/dist/cjs/scroll-restoration.d.cts +9 -1
  32. package/dist/cjs/searchMiddleware.cjs.map +1 -1
  33. package/dist/cjs/searchParams.cjs.map +1 -1
  34. package/dist/cjs/ssr/client.cjs +10 -0
  35. package/dist/cjs/ssr/client.cjs.map +1 -0
  36. package/dist/cjs/ssr/client.d.cts +5 -0
  37. package/dist/cjs/ssr/createRequestHandler.cjs +50 -0
  38. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -0
  39. package/dist/cjs/ssr/createRequestHandler.d.cts +9 -0
  40. package/dist/cjs/ssr/handlerCallback.cjs +7 -0
  41. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -0
  42. package/dist/cjs/ssr/handlerCallback.d.cts +9 -0
  43. package/dist/cjs/ssr/headers.cjs +39 -0
  44. package/dist/cjs/ssr/headers.cjs.map +1 -0
  45. package/dist/cjs/ssr/headers.d.cts +5 -0
  46. package/dist/cjs/ssr/json.cjs +14 -0
  47. package/dist/cjs/ssr/json.cjs.map +1 -0
  48. package/dist/cjs/ssr/json.d.cts +4 -0
  49. package/dist/cjs/ssr/seroval-plugins.cjs +34 -0
  50. package/dist/cjs/ssr/seroval-plugins.cjs.map +1 -0
  51. package/dist/cjs/ssr/seroval-plugins.d.cts +10 -0
  52. package/dist/cjs/ssr/server.cjs +13 -0
  53. package/dist/cjs/ssr/server.cjs.map +1 -0
  54. package/dist/cjs/ssr/server.d.cts +6 -0
  55. package/dist/cjs/ssr/ssr-client.cjs +159 -0
  56. package/dist/cjs/ssr/ssr-client.cjs.map +1 -0
  57. package/dist/cjs/ssr/ssr-client.d.cts +29 -0
  58. package/dist/cjs/ssr/ssr-server.cjs +107 -0
  59. package/dist/cjs/ssr/ssr-server.cjs.map +1 -0
  60. package/dist/cjs/ssr/ssr-server.d.cts +18 -0
  61. package/dist/cjs/ssr/transformStreamWithRouter.cjs +183 -0
  62. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -0
  63. package/dist/cjs/ssr/transformStreamWithRouter.d.cts +6 -0
  64. package/dist/cjs/ssr/tsrScript.cjs +4 -0
  65. package/dist/cjs/ssr/tsrScript.cjs.map +1 -0
  66. package/dist/cjs/ssr/tsrScript.d.cts +0 -0
  67. package/dist/cjs/utils.cjs +7 -25
  68. package/dist/cjs/utils.cjs.map +1 -1
  69. package/dist/cjs/utils.d.cts +1 -6
  70. package/dist/esm/Matches.d.ts +31 -1
  71. package/dist/esm/Matches.js.map +1 -1
  72. package/dist/esm/RouterProvider.d.ts +2 -1
  73. package/dist/esm/defer.js +1 -1
  74. package/dist/esm/defer.js.map +1 -1
  75. package/dist/esm/global.d.ts +7 -0
  76. package/dist/esm/index.d.ts +6 -6
  77. package/dist/esm/index.js +2 -3
  78. package/dist/esm/link.d.ts +12 -0
  79. package/dist/esm/link.js.map +1 -1
  80. package/dist/esm/lru-cache.d.ts +5 -0
  81. package/dist/esm/lru-cache.js +62 -0
  82. package/dist/esm/lru-cache.js.map +1 -0
  83. package/dist/esm/not-found.js +1 -1
  84. package/dist/esm/not-found.js.map +1 -1
  85. package/dist/esm/path.d.ts +18 -24
  86. package/dist/esm/path.js +316 -148
  87. package/dist/esm/path.js.map +1 -1
  88. package/dist/esm/qss.js.map +1 -1
  89. package/dist/esm/redirect.js +3 -0
  90. package/dist/esm/redirect.js.map +1 -1
  91. package/dist/esm/route.d.ts +29 -9
  92. package/dist/esm/route.js +6 -12
  93. package/dist/esm/route.js.map +1 -1
  94. package/dist/esm/router.d.ts +55 -85
  95. package/dist/esm/router.js +462 -281
  96. package/dist/esm/router.js.map +1 -1
  97. package/dist/esm/scroll-restoration.d.ts +9 -1
  98. package/dist/esm/scroll-restoration.js +20 -13
  99. package/dist/esm/scroll-restoration.js.map +1 -1
  100. package/dist/esm/searchMiddleware.js.map +1 -1
  101. package/dist/esm/searchParams.js.map +1 -1
  102. package/dist/esm/ssr/client.d.ts +5 -0
  103. package/dist/esm/ssr/client.js +10 -0
  104. package/dist/esm/ssr/client.js.map +1 -0
  105. package/dist/esm/ssr/createRequestHandler.d.ts +9 -0
  106. package/dist/esm/ssr/createRequestHandler.js +50 -0
  107. package/dist/esm/ssr/createRequestHandler.js.map +1 -0
  108. package/dist/esm/ssr/handlerCallback.d.ts +9 -0
  109. package/dist/esm/ssr/handlerCallback.js +7 -0
  110. package/dist/esm/ssr/handlerCallback.js.map +1 -0
  111. package/dist/esm/ssr/headers.d.ts +5 -0
  112. package/dist/esm/ssr/headers.js +39 -0
  113. package/dist/esm/ssr/headers.js.map +1 -0
  114. package/dist/esm/ssr/json.d.ts +4 -0
  115. package/dist/esm/ssr/json.js +14 -0
  116. package/dist/esm/ssr/json.js.map +1 -0
  117. package/dist/esm/ssr/seroval-plugins.d.ts +10 -0
  118. package/dist/esm/ssr/seroval-plugins.js +34 -0
  119. package/dist/esm/ssr/seroval-plugins.js.map +1 -0
  120. package/dist/esm/ssr/server.d.ts +6 -0
  121. package/dist/esm/ssr/server.js +13 -0
  122. package/dist/esm/ssr/server.js.map +1 -0
  123. package/dist/esm/ssr/ssr-client.d.ts +29 -0
  124. package/dist/esm/ssr/ssr-client.js +159 -0
  125. package/dist/esm/ssr/ssr-client.js.map +1 -0
  126. package/dist/esm/ssr/ssr-server.d.ts +18 -0
  127. package/dist/esm/ssr/ssr-server.js +107 -0
  128. package/dist/esm/ssr/ssr-server.js.map +1 -0
  129. package/dist/esm/ssr/transformStreamWithRouter.d.ts +6 -0
  130. package/dist/esm/ssr/transformStreamWithRouter.js +183 -0
  131. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -0
  132. package/dist/esm/ssr/tsrScript.d.ts +0 -0
  133. package/dist/esm/ssr/tsrScript.js +5 -0
  134. package/dist/esm/ssr/tsrScript.js.map +1 -0
  135. package/dist/esm/utils.d.ts +1 -6
  136. package/dist/esm/utils.js +8 -26
  137. package/dist/esm/utils.js.map +1 -1
  138. package/package.json +29 -2
  139. package/src/Matches.ts +40 -1
  140. package/src/RouterProvider.ts +2 -1
  141. package/src/global.ts +9 -0
  142. package/src/index.ts +12 -20
  143. package/src/link.ts +12 -0
  144. package/src/lru-cache.ts +68 -0
  145. package/src/path.ts +424 -174
  146. package/src/redirect.ts +3 -0
  147. package/src/route.ts +44 -13
  148. package/src/router.ts +580 -312
  149. package/src/scroll-restoration.ts +30 -18
  150. package/src/ssr/client.ts +5 -0
  151. package/src/ssr/createRequestHandler.ts +74 -0
  152. package/src/ssr/handlerCallback.ts +15 -0
  153. package/src/ssr/headers.ts +51 -0
  154. package/src/ssr/json.ts +18 -0
  155. package/src/ssr/seroval-plugins.ts +43 -0
  156. package/src/ssr/server.ts +10 -0
  157. package/src/ssr/ssr-client.ts +242 -0
  158. package/src/ssr/ssr-server.ts +132 -0
  159. package/src/ssr/transformStreamWithRouter.ts +259 -0
  160. package/src/ssr/tsrScript.ts +7 -0
  161. package/src/utils.ts +10 -39
  162. package/src/vite-env.d.ts +4 -0
  163. package/dist/cjs/serializer.d.cts +0 -22
  164. package/dist/esm/serializer.d.ts +0 -22
  165. package/src/serializer.ts +0 -32
@@ -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,27 +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
- });
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
+ }));
1096
1212
  this.shouldViewTransition = false;
1097
- return this.load({ sync: opts == null ? void 0 : opts.sync });
1213
+ return this.load({ sync: opts?.sync });
1098
1214
  };
1099
1215
  this.resolveRedirect = (redirect2) => {
1100
1216
  if (!redirect2.options.href) {
@@ -1107,7 +1223,7 @@ class RouterCore {
1107
1223
  return redirect2;
1108
1224
  };
1109
1225
  this.clearCache = (opts) => {
1110
- const filter = opts == null ? void 0 : opts.filter;
1226
+ const filter = opts?.filter;
1111
1227
  if (filter !== void 0) {
1112
1228
  this.__store.setState((s) => {
1113
1229
  return {
@@ -1133,7 +1249,10 @@ class RouterCore {
1133
1249
  return true;
1134
1250
  }
1135
1251
  const gcTime = (d.preload ? route.options.preloadGcTime ?? this.options.defaultPreloadGcTime : route.options.gcTime ?? this.options.defaultGcTime) ?? 5 * 60 * 1e3;
1136
- 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;
1137
1256
  };
1138
1257
  this.clearCache({ filter });
1139
1258
  };
@@ -1153,7 +1272,7 @@ class RouterCore {
1153
1272
  () => Promise.all(
1154
1273
  componentTypes.map(async (type) => {
1155
1274
  const component = route.options[type];
1156
- if (component == null ? void 0 : component.preload) {
1275
+ if (component?.preload) {
1157
1276
  await component.preload();
1158
1277
  }
1159
1278
  })
@@ -1229,15 +1348,20 @@ class RouterCore {
1229
1348
  leaveParams: true
1230
1349
  };
1231
1350
  const next = this.buildLocation(matchLocation);
1232
- if ((opts == null ? void 0 : opts.pending) && this.state.status !== "pending") {
1351
+ if (opts?.pending && this.state.status !== "pending") {
1233
1352
  return false;
1234
1353
  }
1235
- 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;
1236
1355
  const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
1237
- const match = path.matchPathname(this.basepath, baseLocation.pathname, {
1238
- ...opts,
1239
- to: next.pathname
1240
- });
1356
+ const match = path.matchPathname(
1357
+ this.basepath,
1358
+ baseLocation.pathname,
1359
+ {
1360
+ ...opts,
1361
+ to: next.pathname
1362
+ },
1363
+ this.parsePathnameCache
1364
+ );
1241
1365
  if (!match) {
1242
1366
  return false;
1243
1367
  }
@@ -1246,7 +1370,7 @@ class RouterCore {
1246
1370
  return false;
1247
1371
  }
1248
1372
  }
1249
- if (match && ((opts == null ? void 0 : opts.includeSearch) ?? true)) {
1373
+ if (match && (opts?.includeSearch ?? true)) {
1250
1374
  return utils.deepEqual(baseLocation.search, next.search, { partial: true }) ? match : false;
1251
1375
  }
1252
1376
  return match;
@@ -1254,13 +1378,12 @@ class RouterCore {
1254
1378
  this._handleNotFound = (matches, err, {
1255
1379
  updateMatch = this.updateMatch
1256
1380
  } = {}) => {
1257
- var _a;
1258
1381
  const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
1259
1382
  const matchesByRouteId = {};
1260
1383
  for (const match of matches) {
1261
1384
  matchesByRouteId[match.routeId] = match;
1262
1385
  }
1263
- if (!routeCursor.options.notFoundComponent && ((_a = this.options) == null ? void 0 : _a.defaultNotFoundComponent)) {
1386
+ if (!routeCursor.options.notFoundComponent && this.options?.defaultNotFoundComponent) {
1264
1387
  routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
1265
1388
  }
1266
1389
  invariant(
@@ -1302,9 +1425,15 @@ class RouterCore {
1302
1425
  parseSearch: options.parseSearch ?? searchParams.defaultParseSearch
1303
1426
  });
1304
1427
  if (typeof document !== "undefined") {
1305
- window.__TSR_ROUTER__ = this;
1428
+ self.__TSR_ROUTER__ = this;
1306
1429
  }
1307
1430
  }
1431
+ isShell() {
1432
+ return !!this.options.isShell;
1433
+ }
1434
+ isPrerendering() {
1435
+ return !!this.options.isPrerendering;
1436
+ }
1308
1437
  get state() {
1309
1438
  return this.__store.state;
1310
1439
  }
@@ -1312,10 +1441,9 @@ class RouterCore {
1312
1441
  return this.routesById;
1313
1442
  }
1314
1443
  matchRoutesInternal(next, opts) {
1315
- var _a;
1316
1444
  const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
1317
1445
  next.pathname,
1318
- (_a = opts == null ? void 0 : opts.dest) == null ? void 0 : _a.to
1446
+ opts?.dest?.to
1319
1447
  );
1320
1448
  let isGlobalNotFound = false;
1321
1449
  if (
@@ -1346,9 +1474,8 @@ class RouterCore {
1346
1474
  return root.rootRouteId;
1347
1475
  })();
1348
1476
  const parseErrors = matchedRoutes.map((route) => {
1349
- var _a2;
1350
1477
  let parsedParamsError;
1351
- const parseParams = ((_a2 = route.options.params) == null ? void 0 : _a2.parse) ?? route.options.parseParams;
1478
+ const parseParams = route.options.params?.parse ?? route.options.parseParams;
1352
1479
  if (parseParams) {
1353
1480
  try {
1354
1481
  const parsedParams = parseParams(routeParams);
@@ -1357,7 +1484,7 @@ class RouterCore {
1357
1484
  parsedParamsError = new PathParamError(err.message, {
1358
1485
  cause: err
1359
1486
  });
1360
- if (opts == null ? void 0 : opts.throwOnError) {
1487
+ if (opts?.throwOnError) {
1361
1488
  throw parsedParamsError;
1362
1489
  }
1363
1490
  return parsedParamsError;
@@ -1367,16 +1494,15 @@ class RouterCore {
1367
1494
  });
1368
1495
  const matches = [];
1369
1496
  const getParentContext = (parentMatch) => {
1370
- const parentMatchId = parentMatch == null ? void 0 : parentMatch.id;
1497
+ const parentMatchId = parentMatch?.id;
1371
1498
  const parentContext = !parentMatchId ? this.options.context ?? {} : parentMatch.context ?? this.options.context ?? {};
1372
1499
  return parentContext;
1373
1500
  };
1374
1501
  matchedRoutes.forEach((route, index) => {
1375
- var _a2, _b;
1376
1502
  const parentMatch = matches[index - 1];
1377
1503
  const [preMatchSearch, strictMatchSearch, searchError] = (() => {
1378
- const parentSearch = (parentMatch == null ? void 0 : parentMatch.search) ?? next.search;
1379
- const parentStrictSearch = (parentMatch == null ? void 0 : parentMatch._strictSearch) ?? {};
1504
+ const parentSearch = parentMatch?.search ?? next.search;
1505
+ const parentStrictSearch = parentMatch?._strictSearch ?? {};
1380
1506
  try {
1381
1507
  const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? {};
1382
1508
  return [
@@ -1394,15 +1520,15 @@ class RouterCore {
1394
1520
  cause: err
1395
1521
  });
1396
1522
  }
1397
- if (opts == null ? void 0 : opts.throwOnError) {
1523
+ if (opts?.throwOnError) {
1398
1524
  throw searchParamError;
1399
1525
  }
1400
1526
  return [parentSearch, {}, searchParamError];
1401
1527
  }
1402
1528
  })();
1403
- const loaderDeps = ((_b = (_a2 = route.options).loaderDeps) == null ? void 0 : _b.call(_a2, {
1529
+ const loaderDeps = route.options.loaderDeps?.({
1404
1530
  search: preMatchSearch
1405
- })) ?? "";
1531
+ }) ?? "";
1406
1532
  const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
1407
1533
  const { usedParams, interpolatedPath } = path.interpolatePath({
1408
1534
  path: route.fullPath,
@@ -1413,7 +1539,8 @@ class RouterCore {
1413
1539
  path: route.id,
1414
1540
  params: routeParams,
1415
1541
  leaveWildcards: true,
1416
- decodeCharMap: this.pathParamsDecodeCharMap
1542
+ decodeCharMap: this.pathParamsDecodeCharMap,
1543
+ parseCache: this.parsePathnameCache
1417
1544
  }).interpolatedPath + loaderDepsHash;
1418
1545
  const existingMatch = this.getMatch(matchId);
1419
1546
  const previousMatch = this.state.matches.find(
@@ -1448,7 +1575,7 @@ class RouterCore {
1448
1575
  error: void 0,
1449
1576
  paramsError: parseErrors[index],
1450
1577
  __routeContext: {},
1451
- __beforeLoadContext: {},
1578
+ __beforeLoadContext: void 0,
1452
1579
  context: {},
1453
1580
  abortController: new AbortController(),
1454
1581
  fetchCount: 0,
@@ -1465,7 +1592,7 @@ class RouterCore {
1465
1592
  fullPath: route.fullPath
1466
1593
  };
1467
1594
  }
1468
- if (!(opts == null ? void 0 : opts.preload)) {
1595
+ if (!opts?.preload) {
1469
1596
  match.globalNotFound = globalNotFoundRouteId === route.id;
1470
1597
  }
1471
1598
  match.searchError = searchError;
@@ -1478,10 +1605,9 @@ class RouterCore {
1478
1605
  matches.push(match);
1479
1606
  });
1480
1607
  matches.forEach((match, index) => {
1481
- var _a2, _b;
1482
1608
  const route = this.looseRoutesById[match.routeId];
1483
1609
  const existingMatch = this.getMatch(match.id);
1484
- if (!existingMatch && (opts == null ? void 0 : opts._buildLocation) !== true) {
1610
+ if (!existingMatch && opts?._buildLocation !== true) {
1485
1611
  const parentMatch = matches[index - 1];
1486
1612
  const parentContext = getParentContext(parentMatch);
1487
1613
  const contextFnContext = {
@@ -1496,7 +1622,7 @@ class RouterCore {
1496
1622
  preload: !!match.preload,
1497
1623
  matches
1498
1624
  };
1499
- match.__routeContext = ((_b = (_a2 = route.options).context) == null ? void 0 : _b.call(_a2, contextFnContext)) ?? {};
1625
+ match.__routeContext = route.options.context?.(contextFnContext) ?? {};
1500
1626
  match.context = {
1501
1627
  ...parentContext,
1502
1628
  ...match.__routeContext,
@@ -1511,6 +1637,10 @@ class SearchParamError extends Error {
1511
1637
  }
1512
1638
  class PathParamError extends Error {
1513
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
+ }
1514
1644
  function lazyFn(fn, key) {
1515
1645
  return async (...args) => {
1516
1646
  const imported = await fn();
@@ -1558,14 +1688,33 @@ const componentTypes = [
1558
1688
  "notFoundComponent"
1559
1689
  ];
1560
1690
  function routeNeedsPreload(route) {
1561
- var _a;
1562
1691
  for (const componentType of componentTypes) {
1563
- if ((_a = route.options[componentType]) == null ? void 0 : _a.preload) {
1692
+ if (route.options[componentType]?.preload) {
1564
1693
  return true;
1565
1694
  }
1566
1695
  }
1567
1696
  return false;
1568
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
+ }
1569
1718
  function processRouteTree({
1570
1719
  routeTree,
1571
1720
  initRoute
@@ -1574,7 +1723,7 @@ function processRouteTree({
1574
1723
  const routesByPath = {};
1575
1724
  const recurseRoutes = (childRoutes) => {
1576
1725
  childRoutes.forEach((childRoute, i) => {
1577
- initRoute == null ? void 0 : initRoute(childRoute, i);
1726
+ initRoute?.(childRoute, i);
1578
1727
  const existingRoute = routesById[childRoute.id];
1579
1728
  invariant(
1580
1729
  !existingRoute,
@@ -1588,7 +1737,7 @@ function processRouteTree({
1588
1737
  }
1589
1738
  }
1590
1739
  const children = childRoute.children;
1591
- if (children == null ? void 0 : children.length) {
1740
+ if (children?.length) {
1592
1741
  recurseRoutes(children);
1593
1742
  }
1594
1743
  });
@@ -1597,46 +1746,52 @@ function processRouteTree({
1597
1746
  const scoredRoutes = [];
1598
1747
  const routes = Object.values(routesById);
1599
1748
  routes.forEach((d, i) => {
1600
- var _a;
1601
1749
  if (d.isRoot || !d.path) {
1602
1750
  return;
1603
1751
  }
1604
1752
  const trimmed = path.trimPathLeft(d.fullPath);
1605
- const parsed = path.parsePathname(trimmed);
1606
- while (parsed.length > 1 && ((_a = parsed[0]) == null ? void 0 : _a.value) === "/") {
1607
- parsed.shift();
1753
+ let parsed = path.parsePathname(trimmed);
1754
+ let skip = 0;
1755
+ while (parsed.length > skip + 1 && parsed[skip]?.value === "/") {
1756
+ skip++;
1608
1757
  }
1609
- 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) => {
1610
1762
  if (segment.value === "/") {
1611
1763
  return 0.75;
1612
1764
  }
1613
- if (segment.type === "param" && segment.prefixSegment && segment.suffixSegment) {
1614
- return 0.55;
1615
- }
1616
- if (segment.type === "param" && segment.prefixSegment) {
1617
- 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;
1618
1773
  }
1619
- if (segment.type === "param" && segment.suffixSegment) {
1620
- return 0.51;
1621
- }
1622
- if (segment.type === "param") {
1623
- return 0.5;
1624
- }
1625
- if (segment.type === "wildcard" && segment.prefixSegment && segment.suffixSegment) {
1626
- return 0.3;
1627
- }
1628
- if (segment.type === "wildcard" && segment.prefixSegment) {
1629
- return 0.27;
1630
- }
1631
- if (segment.type === "wildcard" && segment.suffixSegment) {
1632
- return 0.26;
1633
- }
1634
- if (segment.type === "wildcard") {
1635
- 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);
1636
1783
  }
1637
1784
  return 1;
1638
1785
  });
1639
- 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
+ });
1640
1795
  });
1641
1796
  const flatRoutes = scoredRoutes.sort((a, b) => {
1642
1797
  const minLength = Math.min(a.scores.length, b.scores.length);
@@ -1646,6 +1801,15 @@ function processRouteTree({
1646
1801
  }
1647
1802
  }
1648
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
+ }
1649
1813
  return b.scores.length - a.scores.length;
1650
1814
  }
1651
1815
  for (let i = 0; i < minLength; i++) {
@@ -1667,38 +1831,56 @@ function getMatchedRoutes({
1667
1831
  caseSensitive,
1668
1832
  routesByPath,
1669
1833
  routesById,
1670
- flatRoutes
1834
+ flatRoutes,
1835
+ parseCache
1671
1836
  }) {
1672
1837
  let routeParams = {};
1673
1838
  const trimmedPath = path.trimPathRight(pathname);
1674
1839
  const getMatchedParams = (route) => {
1675
- var _a;
1676
- const result = path.matchPathname(basepath, trimmedPath, {
1677
- to: route.fullPath,
1678
- caseSensitive: ((_a = route.options) == null ? void 0 : _a.caseSensitive) ?? caseSensitive,
1679
- fuzzy: true
1680
- });
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
+ );
1681
1851
  return result;
1682
1852
  };
1683
1853
  let foundRoute = routePathname !== void 0 ? routesByPath[routePathname] : void 0;
1684
1854
  if (foundRoute) {
1685
1855
  routeParams = getMatchedParams(foundRoute);
1686
1856
  } else {
1687
- foundRoute = flatRoutes.find((route) => {
1857
+ let fuzzyMatch = void 0;
1858
+ for (const route of flatRoutes) {
1688
1859
  const matchedParams = getMatchedParams(route);
1689
1860
  if (matchedParams) {
1690
- routeParams = matchedParams;
1691
- 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
+ }
1692
1870
  }
1693
- return false;
1694
- });
1871
+ }
1872
+ if (!foundRoute && fuzzyMatch) {
1873
+ foundRoute = fuzzyMatch.foundRoute;
1874
+ routeParams = fuzzyMatch.routeParams;
1875
+ }
1695
1876
  }
1696
1877
  let routeCursor = foundRoute || routesById[root.rootRouteId];
1697
1878
  const matchedRoutes = [routeCursor];
1698
1879
  while (routeCursor.parentRoute) {
1699
1880
  routeCursor = routeCursor.parentRoute;
1700
- matchedRoutes.unshift(routeCursor);
1881
+ matchedRoutes.push(routeCursor);
1701
1882
  }
1883
+ matchedRoutes.reverse();
1702
1884
  return { matchedRoutes, routeParams, foundRoute };
1703
1885
  }
1704
1886
  function applySearchMiddleware({
@@ -1709,10 +1891,9 @@ function applySearchMiddleware({
1709
1891
  }) {
1710
1892
  const allMiddlewares = destRoutes.reduce(
1711
1893
  (acc, route) => {
1712
- var _a;
1713
1894
  const middlewares = [];
1714
1895
  if ("search" in route.options) {
1715
- if ((_a = route.options.search) == null ? void 0 : _a.middlewares) {
1896
+ if (route.options.search?.middlewares) {
1716
1897
  middlewares.push(...route.options.search.middlewares);
1717
1898
  }
1718
1899
  } else if (route.options.preSearchFilters || route.options.postSearchFilters) {