@tanstack/router-core 1.132.0-alpha.1 → 1.132.0-alpha.15

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 (145) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +9 -11
  3. package/dist/cjs/config.cjs +10 -0
  4. package/dist/cjs/config.cjs.map +1 -0
  5. package/dist/cjs/config.d.cts +17 -0
  6. package/dist/cjs/fileRoute.d.cts +3 -2
  7. package/dist/cjs/index.cjs +15 -3
  8. package/dist/cjs/index.cjs.map +1 -1
  9. package/dist/cjs/index.d.cts +11 -4
  10. package/dist/cjs/load-matches.cjs +636 -0
  11. package/dist/cjs/load-matches.cjs.map +1 -0
  12. package/dist/cjs/load-matches.d.cts +16 -0
  13. package/dist/cjs/location.d.cts +38 -0
  14. package/dist/cjs/path.cjs +6 -49
  15. package/dist/cjs/path.cjs.map +1 -1
  16. package/dist/cjs/path.d.cts +3 -6
  17. package/dist/cjs/qss.cjs +19 -19
  18. package/dist/cjs/qss.cjs.map +1 -1
  19. package/dist/cjs/qss.d.cts +6 -4
  20. package/dist/cjs/redirect.cjs +3 -3
  21. package/dist/cjs/redirect.cjs.map +1 -1
  22. package/dist/cjs/rewrite.cjs +63 -0
  23. package/dist/cjs/rewrite.cjs.map +1 -0
  24. package/dist/cjs/rewrite.d.cts +22 -0
  25. package/dist/cjs/route.cjs.map +1 -1
  26. package/dist/cjs/route.d.cts +42 -41
  27. package/dist/cjs/router.cjs +134 -681
  28. package/dist/cjs/router.cjs.map +1 -1
  29. package/dist/cjs/router.d.cts +68 -25
  30. package/dist/cjs/scroll-restoration.cjs +32 -29
  31. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  32. package/dist/cjs/scroll-restoration.d.cts +1 -10
  33. package/dist/cjs/searchParams.cjs +7 -15
  34. package/dist/cjs/searchParams.cjs.map +1 -1
  35. package/dist/cjs/ssr/constants.cjs +5 -0
  36. package/dist/cjs/ssr/constants.cjs.map +1 -0
  37. package/dist/cjs/ssr/constants.d.cts +1 -0
  38. package/dist/cjs/ssr/{seroval-plugins.cjs → serializer/ShallowErrorPlugin.cjs} +2 -2
  39. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -0
  40. package/dist/cjs/ssr/{seroval-plugins.d.cts → serializer/ShallowErrorPlugin.d.cts} +1 -2
  41. package/dist/cjs/ssr/serializer/seroval-plugins.cjs +11 -0
  42. package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -0
  43. package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -0
  44. package/dist/cjs/ssr/serializer/transformer.cjs +52 -0
  45. package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -0
  46. package/dist/cjs/ssr/serializer/transformer.d.cts +56 -0
  47. package/dist/cjs/ssr/server.d.cts +5 -0
  48. package/dist/cjs/ssr/ssr-client.cjs +53 -40
  49. package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
  50. package/dist/cjs/ssr/ssr-client.d.cts +5 -1
  51. package/dist/cjs/ssr/ssr-server.cjs +12 -10
  52. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  53. package/dist/cjs/ssr/ssr-server.d.cts +0 -1
  54. package/dist/cjs/ssr/tsrScript.cjs +1 -1
  55. package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
  56. package/dist/cjs/typePrimitives.d.cts +6 -6
  57. package/dist/cjs/utils.cjs +14 -7
  58. package/dist/cjs/utils.cjs.map +1 -1
  59. package/dist/cjs/utils.d.cts +2 -1
  60. package/dist/esm/Matches.d.ts +9 -11
  61. package/dist/esm/Matches.js.map +1 -1
  62. package/dist/esm/config.d.ts +17 -0
  63. package/dist/esm/config.js +10 -0
  64. package/dist/esm/config.js.map +1 -0
  65. package/dist/esm/fileRoute.d.ts +3 -2
  66. package/dist/esm/index.d.ts +11 -4
  67. package/dist/esm/index.js +17 -5
  68. package/dist/esm/index.js.map +1 -1
  69. package/dist/esm/load-matches.d.ts +16 -0
  70. package/dist/esm/load-matches.js +636 -0
  71. package/dist/esm/load-matches.js.map +1 -0
  72. package/dist/esm/location.d.ts +38 -0
  73. package/dist/esm/path.d.ts +3 -6
  74. package/dist/esm/path.js +6 -49
  75. package/dist/esm/path.js.map +1 -1
  76. package/dist/esm/qss.d.ts +6 -4
  77. package/dist/esm/qss.js +19 -19
  78. package/dist/esm/qss.js.map +1 -1
  79. package/dist/esm/redirect.js +3 -3
  80. package/dist/esm/redirect.js.map +1 -1
  81. package/dist/esm/rewrite.d.ts +22 -0
  82. package/dist/esm/rewrite.js +63 -0
  83. package/dist/esm/rewrite.js.map +1 -0
  84. package/dist/esm/route.d.ts +42 -41
  85. package/dist/esm/route.js.map +1 -1
  86. package/dist/esm/router.d.ts +68 -25
  87. package/dist/esm/router.js +136 -683
  88. package/dist/esm/router.js.map +1 -1
  89. package/dist/esm/scroll-restoration.d.ts +1 -10
  90. package/dist/esm/scroll-restoration.js +32 -29
  91. package/dist/esm/scroll-restoration.js.map +1 -1
  92. package/dist/esm/searchParams.js +7 -15
  93. package/dist/esm/searchParams.js.map +1 -1
  94. package/dist/esm/ssr/constants.d.ts +1 -0
  95. package/dist/esm/ssr/constants.js +5 -0
  96. package/dist/esm/ssr/constants.js.map +1 -0
  97. package/dist/esm/ssr/{seroval-plugins.d.ts → serializer/ShallowErrorPlugin.d.ts} +1 -2
  98. package/dist/esm/ssr/{seroval-plugins.js → serializer/ShallowErrorPlugin.js} +2 -2
  99. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -0
  100. package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -0
  101. package/dist/esm/ssr/serializer/seroval-plugins.js +11 -0
  102. package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -0
  103. package/dist/esm/ssr/serializer/transformer.d.ts +56 -0
  104. package/dist/esm/ssr/serializer/transformer.js +52 -0
  105. package/dist/esm/ssr/serializer/transformer.js.map +1 -0
  106. package/dist/esm/ssr/server.d.ts +5 -0
  107. package/dist/esm/ssr/ssr-client.d.ts +5 -1
  108. package/dist/esm/ssr/ssr-client.js +53 -40
  109. package/dist/esm/ssr/ssr-client.js.map +1 -1
  110. package/dist/esm/ssr/ssr-server.d.ts +0 -1
  111. package/dist/esm/ssr/ssr-server.js +12 -10
  112. package/dist/esm/ssr/ssr-server.js.map +1 -1
  113. package/dist/esm/ssr/tsrScript.js +1 -1
  114. package/dist/esm/ssr/tsrScript.js.map +1 -1
  115. package/dist/esm/typePrimitives.d.ts +6 -6
  116. package/dist/esm/utils.d.ts +2 -1
  117. package/dist/esm/utils.js +14 -7
  118. package/dist/esm/utils.js.map +1 -1
  119. package/package.json +1 -1
  120. package/src/Matches.ts +18 -10
  121. package/src/config.ts +42 -0
  122. package/src/fileRoute.ts +15 -3
  123. package/src/index.ts +32 -3
  124. package/src/load-matches.ts +955 -0
  125. package/src/location.ts +38 -0
  126. package/src/path.ts +5 -66
  127. package/src/qss.ts +27 -24
  128. package/src/redirect.ts +3 -3
  129. package/src/rewrite.ts +70 -0
  130. package/src/route.ts +146 -35
  131. package/src/router.ts +263 -972
  132. package/src/scroll-restoration.ts +42 -37
  133. package/src/searchParams.ts +8 -19
  134. package/src/ssr/constants.ts +1 -0
  135. package/src/ssr/{seroval-plugins.ts → serializer/ShallowErrorPlugin.ts} +2 -2
  136. package/src/ssr/serializer/seroval-plugins.ts +9 -0
  137. package/src/ssr/serializer/transformer.ts +215 -0
  138. package/src/ssr/server.ts +6 -0
  139. package/src/ssr/ssr-client.ts +72 -44
  140. package/src/ssr/ssr-server.ts +18 -10
  141. package/src/ssr/tsrScript.ts +5 -1
  142. package/src/typePrimitives.ts +6 -6
  143. package/src/utils.ts +21 -10
  144. package/dist/cjs/ssr/seroval-plugins.cjs.map +0 -1
  145. package/dist/esm/ssr/seroval-plugins.js.map +0 -1
@@ -11,6 +11,8 @@ const searchParams = require("./searchParams.cjs");
11
11
  const root = require("./root.cjs");
12
12
  const redirect = require("./redirect.cjs");
13
13
  const lruCache = require("./lru-cache.cjs");
14
+ const loadMatches = require("./load-matches.cjs");
15
+ const rewrite = require("./rewrite.cjs");
14
16
  function defaultSerializeError(err) {
15
17
  if (err instanceof Error) {
16
18
  const obj = {
@@ -55,7 +57,6 @@ class RouterCore {
55
57
  "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."
56
58
  );
57
59
  }
58
- const previousOptions = this.options;
59
60
  this.options = {
60
61
  ...this.options,
61
62
  ...newOptions
@@ -67,24 +68,43 @@ class RouterCore {
67
68
  char
68
69
  ])
69
70
  ) : void 0;
70
- if (!this.basepath || newOptions.basepath && newOptions.basepath !== previousOptions.basepath) {
71
- if (newOptions.basepath === void 0 || newOptions.basepath === "" || newOptions.basepath === "/") {
72
- this.basepath = "/";
71
+ if (!this.history || this.options.history && this.options.history !== this.history) {
72
+ if (!this.options.history) {
73
+ if (!this.isServer) {
74
+ this.history = history.createBrowserHistory();
75
+ }
73
76
  } else {
74
- this.basepath = `/${path.trimPath(newOptions.basepath)}`;
77
+ this.history = this.options.history;
75
78
  }
76
79
  }
77
- if (!this.history || this.options.history && this.options.history !== this.history) {
78
- this.history = this.options.history ?? (this.isServer ? history.createMemoryHistory({
79
- initialEntries: [this.basepath || "/"]
80
- }) : history.createBrowserHistory());
81
- this.latestLocation = this.parseLocation();
80
+ if (this.options.basepath) {
81
+ const basepathRewrite = rewrite.rewriteBasepath({
82
+ basepath: this.options.basepath
83
+ });
84
+ if (this.options.rewrite) {
85
+ this.rewrite = rewrite.composeRewrites([basepathRewrite, this.options.rewrite]);
86
+ } else {
87
+ this.rewrite = basepathRewrite;
88
+ }
89
+ } else {
90
+ this.rewrite = this.options.rewrite;
91
+ }
92
+ this.origin = this.options.origin;
93
+ if (!this.origin) {
94
+ if (!this.isServer) {
95
+ this.origin = window.origin;
96
+ } else {
97
+ this.origin = "http://localhost";
98
+ }
99
+ }
100
+ if (this.history) {
101
+ this.updateLatestLocation();
82
102
  }
83
103
  if (this.options.routeTree !== this.routeTree) {
84
104
  this.routeTree = this.options.routeTree;
85
105
  this.buildRouteTree();
86
106
  }
87
- if (!this.__store) {
107
+ if (!this.__store && this.latestLocation) {
88
108
  this.__store = new store.Store(getInitialRouterState(this.latestLocation), {
89
109
  onUpdate: () => {
90
110
  this.__store.state = {
@@ -103,6 +123,12 @@ class RouterCore {
103
123
  );
104
124
  }
105
125
  };
126
+ this.updateLatestLocation = () => {
127
+ this.latestLocation = this.parseLocation(
128
+ this.history.location,
129
+ this.latestLocation
130
+ );
131
+ };
106
132
  this.buildRouteTree = () => {
107
133
  const { routesById, routesByPath, flatRoutes } = processRouteTree({
108
134
  routeTree: this.routeTree,
@@ -140,25 +166,30 @@ class RouterCore {
140
166
  }
141
167
  });
142
168
  };
143
- this.parseLocation = (previousLocation, locationToParse) => {
169
+ this.parseLocation = (locationToParse, previousLocation) => {
144
170
  const parse = ({
145
- pathname,
146
- search,
147
- hash,
171
+ href,
148
172
  state
149
173
  }) => {
150
- const parsedSearch = this.options.parseSearch(search);
174
+ const fullUrl = new URL(href, this.origin);
175
+ const url = rewrite.executeRewriteInput(this.rewrite, fullUrl);
176
+ const parsedSearch = this.options.parseSearch(url.search);
151
177
  const searchStr = this.options.stringifySearch(parsedSearch);
178
+ url.search = searchStr;
179
+ const fullPath = url.href.replace(url.origin, "");
180
+ const { pathname, hash } = url;
152
181
  return {
182
+ href: fullPath,
183
+ publicHref: href,
184
+ url: url.href,
153
185
  pathname,
154
186
  searchStr,
155
187
  search: utils.replaceEqualDeep(previousLocation?.search, parsedSearch),
156
188
  hash: hash.split("#").reverse()[0] ?? "",
157
- href: `${pathname}${searchStr}${hash}`,
158
189
  state: utils.replaceEqualDeep(previousLocation?.state, state)
159
190
  };
160
191
  };
161
- const location = parse(locationToParse ?? this.history.location);
192
+ const location = parse(locationToParse);
162
193
  const { __tempLocation, __tempKey } = location.state;
163
194
  if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
164
195
  const parsedTempLocation = parse(__tempLocation);
@@ -174,11 +205,9 @@ class RouterCore {
174
205
  };
175
206
  this.resolvePathWithBase = (from, path$1) => {
176
207
  const resolvedPath = path.resolvePath({
177
- basepath: this.basepath,
178
208
  base: from,
179
209
  to: path.cleanPath(path$1),
180
210
  trailingSlash: this.options.trailingSlash,
181
- caseSensitive: this.options.caseSensitive,
182
211
  parseCache: this.parsePathnameCache
183
212
  });
184
213
  return resolvedPath;
@@ -200,7 +229,6 @@ class RouterCore {
200
229
  return getMatchedRoutes({
201
230
  pathname,
202
231
  routePathname,
203
- basepath: this.basepath,
204
232
  caseSensitive: this.options.caseSensitive,
205
233
  routesByPath: this.routesByPath,
206
234
  routesById: this.routesById,
@@ -212,13 +240,8 @@ class RouterCore {
212
240
  const match = this.getMatch(id);
213
241
  if (!match) return;
214
242
  match.abortController.abort();
215
- this.updateMatch(id, (prev) => {
216
- clearTimeout(prev.pendingTimeout);
217
- return {
218
- ...prev,
219
- pendingTimeout: void 0
220
- };
221
- });
243
+ clearTimeout(match._nonReactive.pendingTimeout);
244
+ match._nonReactive.pendingTimeout = void 0;
222
245
  };
223
246
  this.cancelMatches = () => {
224
247
  this.state.pendingMatches?.forEach((match) => {
@@ -232,60 +255,51 @@ class RouterCore {
232
255
  _buildLocation: true
233
256
  });
234
257
  const lastMatch = utils.last(allCurrentLocationMatches);
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);
238
- if (dest.unsafeRelative === "path") {
239
- fromPath = currentLocation.pathname;
240
- } else if (routeIsChanging && dest.from) {
241
- fromPath = 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
- }
258
+ if (dest.from && process.env.NODE_ENV !== "production" && dest._isNavigate) {
259
+ const allFromMatches = this.getMatchedRoutes(
260
+ dest.from,
261
+ void 0
262
+ ).matchedRoutes;
263
+ const matchedFrom = utils.findLast(allCurrentLocationMatches, (d) => {
264
+ return comparePaths(d.fullPath, dest.from);
265
+ });
266
+ const matchedCurrent = utils.findLast(allFromMatches, (d) => {
267
+ return comparePaths(d.fullPath, lastMatch.fullPath);
268
+ });
269
+ if (!matchedFrom && !matchedCurrent) {
270
+ console.warn(`Could not find match for from: ${dest.from}`);
256
271
  }
257
272
  }
273
+ const defaultedFromPath = dest.unsafeRelative === "path" ? currentLocation.pathname : dest.from ?? lastMatch.fullPath;
274
+ const fromPath = this.resolvePathWithBase(defaultedFromPath, ".");
258
275
  const fromSearch = lastMatch.search;
259
276
  const fromParams = { ...lastMatch.params };
260
277
  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 : {
262
- ...fromParams,
263
- ...utils.functionalUpdate(dest.params, fromParams)
264
- };
278
+ const nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : Object.assign(
279
+ fromParams,
280
+ utils.functionalUpdate(dest.params, fromParams)
281
+ );
265
282
  const interpolatedNextTo = path.interpolatePath({
266
283
  path: nextTo,
267
- params: nextParams ?? {},
284
+ params: nextParams,
268
285
  parseCache: this.parsePathnameCache
269
286
  }).interpolatedPath;
270
- const destRoutes = this.matchRoutes(
271
- interpolatedNextTo,
272
- {},
273
- {
274
- _buildLocation: true
275
- }
276
- ).map((d) => this.looseRoutesById[d.routeId]);
287
+ const destRoutes = this.matchRoutes(interpolatedNextTo, void 0, {
288
+ _buildLocation: true
289
+ }).map((d) => this.looseRoutesById[d.routeId]);
277
290
  if (Object.keys(nextParams).length > 0) {
278
- destRoutes.map((route) => {
279
- return route.options.params?.stringify ?? route.options.stringifyParams;
280
- }).filter(Boolean).forEach((fn) => {
281
- nextParams = { ...nextParams, ...fn(nextParams) };
282
- });
291
+ for (const route of destRoutes) {
292
+ const fn = route.options.params?.stringify ?? route.options.stringifyParams;
293
+ if (fn) {
294
+ Object.assign(nextParams, fn(nextParams));
295
+ }
296
+ }
283
297
  }
284
298
  const nextPathname = path.interpolatePath({
285
299
  // Use the original template path for interpolation
286
300
  // This preserves the original parameter syntax including optional parameters
287
301
  path: nextTo,
288
- params: nextParams ?? {},
302
+ params: nextParams,
289
303
  leaveWildcards: false,
290
304
  leaveParams: opts.leaveParams,
291
305
  decodeCharMap: this.pathParamsDecodeCharMap,
@@ -293,19 +307,19 @@ class RouterCore {
293
307
  }).interpolatedPath;
294
308
  let nextSearch = fromSearch;
295
309
  if (opts._includeValidateSearch && this.options.search?.strict) {
296
- let validatedSearch = {};
310
+ const validatedSearch = {};
297
311
  destRoutes.forEach((route) => {
298
- try {
299
- if (route.options.validateSearch) {
300
- validatedSearch = {
301
- ...validatedSearch,
302
- ...validateSearch(route.options.validateSearch, {
312
+ if (route.options.validateSearch) {
313
+ try {
314
+ Object.assign(
315
+ validatedSearch,
316
+ validateSearch(route.options.validateSearch, {
303
317
  ...validatedSearch,
304
318
  ...nextSearch
305
- }) ?? {}
306
- };
319
+ })
320
+ );
321
+ } catch {
307
322
  }
308
- } catch {
309
323
  }
310
324
  });
311
325
  nextSearch = validatedSearch;
@@ -322,13 +336,18 @@ class RouterCore {
322
336
  const hashStr = hash ? `#${hash}` : "";
323
337
  let nextState = dest.state === true ? currentLocation.state : dest.state ? utils.functionalUpdate(dest.state, currentLocation.state) : {};
324
338
  nextState = utils.replaceEqualDeep(currentLocation.state, nextState);
339
+ const fullPath = `${nextPathname}${searchStr}${hashStr}`;
340
+ const url = new URL(fullPath, this.origin);
341
+ const rewrittenUrl = rewrite.executeRewriteOutput(this.rewrite, url);
325
342
  return {
343
+ publicHref: rewrittenUrl.pathname + rewrittenUrl.search + rewrittenUrl.hash,
344
+ href: fullPath,
345
+ url: rewrittenUrl.href,
326
346
  pathname: nextPathname,
327
347
  search: nextSearch,
328
348
  searchStr,
329
349
  state: nextState,
330
350
  hash: hash ?? "",
331
- href: `${nextPathname}${searchStr}${hashStr}`,
332
351
  unmaskOnReload: dest.unmaskOnReload
333
352
  };
334
353
  };
@@ -339,7 +358,6 @@ class RouterCore {
339
358
  let params = {};
340
359
  const foundMask = this.options.routeMasks?.find((d) => {
341
360
  const match = path.matchPathname(
342
- this.basepath,
343
361
  next.pathname,
344
362
  {
345
363
  to: d.from,
@@ -357,7 +375,7 @@ class RouterCore {
357
375
  if (foundMask) {
358
376
  const { from: _from, ...maskProps } = foundMask;
359
377
  maskedDest = {
360
- ...utils.pick(opts, ["from"]),
378
+ from: opts.from,
361
379
  ...maskProps,
362
380
  params
363
381
  };
@@ -372,7 +390,7 @@ class RouterCore {
372
390
  };
373
391
  if (opts.mask) {
374
392
  return buildWithMatches(opts, {
375
- ...utils.pick(opts, ["from"]),
393
+ from: opts.from,
376
394
  ...opts.mask
377
395
  });
378
396
  }
@@ -400,7 +418,7 @@ class RouterCore {
400
418
  });
401
419
  return isEqual;
402
420
  };
403
- const isSameUrl = this.latestLocation.href === next.href;
421
+ const isSameUrl = path.trimPathRight(this.latestLocation.href) === path.trimPathRight(next.href);
404
422
  const previousCommitPromise = this.commitLocationPromise;
405
423
  this.commitLocationPromise = utils.createControlledPromise(() => {
406
424
  previousCommitPromise?.resolve();
@@ -436,7 +454,7 @@ class RouterCore {
436
454
  nextHistory.state.__hashScrollIntoViewOptions = hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true;
437
455
  this.shouldViewTransition = viewTransition;
438
456
  this.history[next.replace ? "replace" : "push"](
439
- nextHistory.href,
457
+ nextHistory.publicHref,
440
458
  nextHistory.state,
441
459
  { ignoreBlocker }
442
460
  );
@@ -489,7 +507,7 @@ class RouterCore {
489
507
  if (reloadDocument) {
490
508
  if (!href) {
491
509
  const location = this.buildLocation({ to, ...rest });
492
- href = this.history.createHref(location.href);
510
+ href = location.href;
493
511
  }
494
512
  if (rest.replace) {
495
513
  window.location.replace(href);
@@ -507,7 +525,7 @@ class RouterCore {
507
525
  };
508
526
  this.beforeLoad = () => {
509
527
  this.cancelMatches();
510
- this.latestLocation = this.parseLocation(this.latestLocation);
528
+ this.updateLatestLocation();
511
529
  if (this.isServer) {
512
530
  const nextLocation = this.buildLocation({
513
531
  to: this.latestLocation.pathname,
@@ -568,10 +586,12 @@ class RouterCore {
568
586
  location: next
569
587
  })
570
588
  });
571
- await this.loadMatches({
589
+ await loadMatches.loadMatches({
590
+ router: this,
572
591
  sync: opts?.sync,
573
592
  matches: this.state.pendingMatches,
574
593
  location: next,
594
+ updateMatch: this.updateMatch,
575
595
  // eslint-disable-next-line @typescript-eslint/require-await
576
596
  onReady: async () => {
577
597
  this.startViewTransition(async () => {
@@ -695,510 +715,13 @@ class RouterCore {
695
715
  const findFn = (d) => d.id === matchId;
696
716
  return this.state.cachedMatches.find(findFn) ?? this.state.pendingMatches?.find(findFn) ?? this.state.matches.find(findFn);
697
717
  };
698
- this.loadMatches = async ({
699
- location,
700
- matches,
701
- preload: allPreload,
702
- onReady,
703
- updateMatch = this.updateMatch,
704
- sync
705
- }) => {
706
- let firstBadMatchIndex;
707
- let rendered = false;
708
- const triggerOnReady = async () => {
709
- if (!rendered) {
710
- rendered = true;
711
- await onReady?.();
712
- }
713
- };
714
- const resolvePreload = (matchId) => {
715
- return !!(allPreload && !this.state.matches.some((d) => d.id === matchId));
716
- };
717
- if (!this.isServer && this.state.matches.some((d) => d._forcePending)) {
718
- triggerOnReady();
719
- }
720
- const handleRedirectAndNotFound = (match, err) => {
721
- if (redirect.isRedirect(err) || notFound.isNotFound(err)) {
722
- if (redirect.isRedirect(err)) {
723
- if (err.redirectHandled) {
724
- if (!err.options.reloadDocument) {
725
- throw err;
726
- }
727
- }
728
- }
729
- match.beforeLoadPromise?.resolve();
730
- match.loaderPromise?.resolve();
731
- updateMatch(match.id, (prev) => ({
732
- ...prev,
733
- status: redirect.isRedirect(err) ? "redirected" : notFound.isNotFound(err) ? "notFound" : "error",
734
- isFetching: false,
735
- error: err,
736
- beforeLoadPromise: void 0,
737
- loaderPromise: void 0
738
- }));
739
- if (!err.routeId) {
740
- err.routeId = match.routeId;
741
- }
742
- match.loadPromise?.resolve();
743
- if (redirect.isRedirect(err)) {
744
- rendered = true;
745
- err.options._fromLocation = location;
746
- err.redirectHandled = true;
747
- err = this.resolveRedirect(err);
748
- throw err;
749
- } else if (notFound.isNotFound(err)) {
750
- this._handleNotFound(matches, err, {
751
- updateMatch
752
- });
753
- throw err;
754
- }
755
- }
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
- };
769
- try {
770
- await new Promise((resolveAll, rejectAll) => {
771
- ;
772
- (async () => {
773
- try {
774
- const handleSerialError = (index, err, routerCode) => {
775
- const { id: matchId, routeId } = matches[index];
776
- const route = this.looseRoutesById[routeId];
777
- if (err instanceof Promise) {
778
- throw err;
779
- }
780
- err.routerCode = routerCode;
781
- firstBadMatchIndex = firstBadMatchIndex ?? index;
782
- handleRedirectAndNotFound(this.getMatch(matchId), err);
783
- try {
784
- route.options.onError?.(err);
785
- } catch (errorHandlerErr) {
786
- err = errorHandlerErr;
787
- handleRedirectAndNotFound(this.getMatch(matchId), err);
788
- }
789
- updateMatch(matchId, (prev) => {
790
- prev.beforeLoadPromise?.resolve();
791
- prev.loadPromise?.resolve();
792
- return {
793
- ...prev,
794
- error: err,
795
- status: "error",
796
- isFetching: false,
797
- updatedAt: Date.now(),
798
- abortController: new AbortController(),
799
- beforeLoadPromise: void 0
800
- };
801
- });
802
- };
803
- for (const [index, { id: matchId, routeId }] of matches.entries()) {
804
- const existingMatch = this.getMatch(matchId);
805
- const parentMatchId = matches[index - 1]?.id;
806
- const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
807
- const route = this.looseRoutesById[routeId];
808
- const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
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));
865
- let executeBeforeLoad = true;
866
- const setupPendingTimeout = () => {
867
- if (shouldPending && this.getMatch(matchId).pendingTimeout === void 0) {
868
- const pendingTimeout = setTimeout(() => {
869
- try {
870
- triggerOnReady();
871
- } catch {
872
- }
873
- }, pendingMs);
874
- updateMatch(matchId, (prev) => ({
875
- ...prev,
876
- pendingTimeout
877
- }));
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();
886
- await existingMatch.beforeLoadPromise;
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
- }
893
- }
894
- if (executeBeforeLoad) {
895
- try {
896
- updateMatch(matchId, (prev) => {
897
- const prevLoadPromise = prev.loadPromise;
898
- return {
899
- ...prev,
900
- loadPromise: utils.createControlledPromise(() => {
901
- prevLoadPromise?.resolve();
902
- }),
903
- beforeLoadPromise: utils.createControlledPromise()
904
- };
905
- });
906
- const { paramsError, searchError } = this.getMatch(matchId);
907
- if (paramsError) {
908
- handleSerialError(index, paramsError, "PARSE_PARAMS");
909
- }
910
- if (searchError) {
911
- handleSerialError(index, searchError, "VALIDATE_SEARCH");
912
- }
913
- setupPendingTimeout();
914
- const abortController = new AbortController();
915
- const parentMatchContext = parentMatch?.context ?? this.options.context ?? {};
916
- updateMatch(matchId, (prev) => ({
917
- ...prev,
918
- isFetching: "beforeLoad",
919
- fetchCount: prev.fetchCount + 1,
920
- abortController,
921
- context: {
922
- ...parentMatchContext,
923
- ...prev.__routeContext
924
- }
925
- }));
926
- const { search, params, context, cause } = this.getMatch(matchId);
927
- const preload = resolvePreload(matchId);
928
- const beforeLoadFnContext = {
929
- search,
930
- abortController,
931
- params,
932
- preload,
933
- context,
934
- location,
935
- navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
936
- buildLocation: this.buildLocation,
937
- cause: preload ? "preload" : cause,
938
- matches
939
- };
940
- const beforeLoadContext = await route.options.beforeLoad?.(beforeLoadFnContext);
941
- if (redirect.isRedirect(beforeLoadContext) || notFound.isNotFound(beforeLoadContext)) {
942
- handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
943
- }
944
- updateMatch(matchId, (prev) => {
945
- return {
946
- ...prev,
947
- __beforeLoadContext: beforeLoadContext,
948
- context: {
949
- ...parentMatchContext,
950
- ...prev.__routeContext,
951
- ...beforeLoadContext
952
- },
953
- abortController
954
- };
955
- });
956
- } catch (err) {
957
- handleSerialError(index, err, "BEFORE_LOAD");
958
- }
959
- updateMatch(matchId, (prev) => {
960
- prev.beforeLoadPromise?.resolve();
961
- return {
962
- ...prev,
963
- beforeLoadPromise: void 0,
964
- isFetching: false
965
- };
966
- });
967
- }
968
- }
969
- const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
970
- const matchPromises = [];
971
- validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
972
- matchPromises.push(
973
- (async () => {
974
- let loaderShouldRunAsync = false;
975
- let loaderIsRunningAsync = false;
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;
1025
- const match = this.getMatch(matchId);
1026
- if (match.error) {
1027
- handleRedirectAndNotFound(match, match.error);
1028
- }
1029
- } else {
1030
- const parentMatchPromise = matchPromises[index - 1];
1031
- const getLoaderContext = () => {
1032
- const {
1033
- params,
1034
- loaderDeps,
1035
- abortController,
1036
- context,
1037
- cause
1038
- } = this.getMatch(matchId);
1039
- const preload2 = resolvePreload(matchId);
1040
- return {
1041
- params,
1042
- deps: loaderDeps,
1043
- preload: !!preload2,
1044
- parentMatchPromise,
1045
- abortController,
1046
- context,
1047
- location,
1048
- navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
1049
- cause: preload2 ? "preload" : cause,
1050
- route
1051
- };
1052
- };
1053
- const age = Date.now() - this.getMatch(matchId).updatedAt;
1054
- const preload = resolvePreload(matchId);
1055
- const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
1056
- const shouldReloadOption = route.options.shouldReload;
1057
- const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext()) : shouldReloadOption;
1058
- updateMatch(matchId, (prev) => ({
1059
- ...prev,
1060
- loaderPromise: utils.createControlledPromise(),
1061
- preload: !!preload && !this.state.matches.some((d) => d.id === matchId)
1062
- }));
1063
- const runLoader = async () => {
1064
- try {
1065
- try {
1066
- if (!this.isServer || this.isServer && this.getMatch(matchId).ssr === true) {
1067
- this.loadRouteChunk(route);
1068
- }
1069
- updateMatch(matchId, (prev) => ({
1070
- ...prev,
1071
- isFetching: "loader"
1072
- }));
1073
- const loaderData = await route.options.loader?.(getLoaderContext());
1074
- handleRedirectAndNotFound(
1075
- this.getMatch(matchId),
1076
- loaderData
1077
- );
1078
- updateMatch(matchId, (prev) => ({
1079
- ...prev,
1080
- loaderData
1081
- }));
1082
- await route._lazyPromise;
1083
- const head = await executeHead();
1084
- await potentialPendingMinPromise();
1085
- await route._componentsPromise;
1086
- updateMatch(matchId, (prev) => ({
1087
- ...prev,
1088
- error: void 0,
1089
- status: "success",
1090
- isFetching: false,
1091
- updatedAt: Date.now(),
1092
- ...head
1093
- }));
1094
- } catch (e) {
1095
- let error = e;
1096
- await potentialPendingMinPromise();
1097
- handleRedirectAndNotFound(this.getMatch(matchId), e);
1098
- try {
1099
- route.options.onError?.(e);
1100
- } catch (onErrorError) {
1101
- error = onErrorError;
1102
- handleRedirectAndNotFound(
1103
- this.getMatch(matchId),
1104
- onErrorError
1105
- );
1106
- }
1107
- const head = await executeHead();
1108
- updateMatch(matchId, (prev) => ({
1109
- ...prev,
1110
- error,
1111
- status: "error",
1112
- isFetching: false,
1113
- ...head
1114
- }));
1115
- }
1116
- } catch (err) {
1117
- const head = await executeHead();
1118
- updateMatch(matchId, (prev) => ({
1119
- ...prev,
1120
- loaderPromise: void 0,
1121
- ...head
1122
- }));
1123
- handleRedirectAndNotFound(this.getMatch(matchId), err);
1124
- }
1125
- };
1126
- const { status, invalid } = this.getMatch(matchId);
1127
- loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? age > staleAge));
1128
- if (preload && route.options.preload === false) {
1129
- } else if (loaderShouldRunAsync && !sync) {
1130
- loaderIsRunningAsync = true;
1131
- (async () => {
1132
- try {
1133
- await runLoader();
1134
- const { loaderPromise, loadPromise } = this.getMatch(matchId);
1135
- loaderPromise?.resolve();
1136
- loadPromise?.resolve();
1137
- updateMatch(matchId, (prev) => ({
1138
- ...prev,
1139
- loaderPromise: void 0
1140
- }));
1141
- } catch (err) {
1142
- if (redirect.isRedirect(err)) {
1143
- await this.navigate(err.options);
1144
- }
1145
- }
1146
- })();
1147
- } else if (status !== "success" || loaderShouldRunAsync && sync) {
1148
- await runLoader();
1149
- } else {
1150
- const head = await executeHead();
1151
- updateMatch(matchId, (prev) => ({
1152
- ...prev,
1153
- ...head
1154
- }));
1155
- }
1156
- }
1157
- if (!loaderIsRunningAsync) {
1158
- const { loaderPromise, loadPromise } = this.getMatch(matchId);
1159
- loaderPromise?.resolve();
1160
- loadPromise?.resolve();
1161
- }
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
- });
1173
- return this.getMatch(matchId);
1174
- })()
1175
- );
1176
- });
1177
- await Promise.all(matchPromises);
1178
- resolveAll();
1179
- } catch (err) {
1180
- rejectAll(err);
1181
- }
1182
- })();
1183
- });
1184
- await triggerOnReady();
1185
- } catch (err) {
1186
- if (redirect.isRedirect(err) || notFound.isNotFound(err)) {
1187
- if (notFound.isNotFound(err) && !allPreload) {
1188
- await triggerOnReady();
1189
- }
1190
- throw err;
1191
- }
1192
- }
1193
- return matches;
1194
- };
1195
718
  this.invalidate = (opts) => {
1196
719
  const invalidate = (d) => {
1197
720
  if (opts?.filter?.(d) ?? true) {
1198
721
  return {
1199
722
  ...d,
1200
723
  invalid: true,
1201
- ...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : {}
724
+ ...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : void 0
1202
725
  };
1203
726
  }
1204
727
  return d;
@@ -1256,31 +779,7 @@ class RouterCore {
1256
779
  };
1257
780
  this.clearCache({ filter });
1258
781
  };
1259
- this.loadRouteChunk = (route) => {
1260
- if (route._lazyPromise === void 0) {
1261
- if (route.lazyFn) {
1262
- route._lazyPromise = route.lazyFn().then((lazyRoute) => {
1263
- const { id: _id, ...options2 } = lazyRoute.options;
1264
- Object.assign(route.options, options2);
1265
- });
1266
- } else {
1267
- route._lazyPromise = Promise.resolve();
1268
- }
1269
- }
1270
- if (route._componentsPromise === void 0) {
1271
- route._componentsPromise = route._lazyPromise.then(
1272
- () => Promise.all(
1273
- componentTypes.map(async (type) => {
1274
- const component = route.options[type];
1275
- if (component?.preload) {
1276
- await component.preload();
1277
- }
1278
- })
1279
- )
1280
- );
1281
- }
1282
- return route._componentsPromise;
1283
- };
782
+ this.loadRouteChunk = loadMatches.loadRouteChunk;
1284
783
  this.preloadRoute = async (opts) => {
1285
784
  const next = this.buildLocation(opts);
1286
785
  let matches = this.matchRoutes(next, {
@@ -1308,7 +807,8 @@ class RouterCore {
1308
807
  });
1309
808
  });
1310
809
  try {
1311
- matches = await this.loadMatches({
810
+ matches = await loadMatches.loadMatches({
811
+ router: this,
1312
812
  matches,
1313
813
  location: next,
1314
814
  preload: true,
@@ -1354,7 +854,6 @@ class RouterCore {
1354
854
  const pending = opts?.pending === void 0 ? !this.state.isLoading : opts.pending;
1355
855
  const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
1356
856
  const match = path.matchPathname(
1357
- this.basepath,
1358
857
  baseLocation.pathname,
1359
858
  {
1360
859
  ...opts,
@@ -1375,39 +874,6 @@ class RouterCore {
1375
874
  }
1376
875
  return match;
1377
876
  };
1378
- this._handleNotFound = (matches, err, {
1379
- updateMatch = this.updateMatch
1380
- } = {}) => {
1381
- const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
1382
- const matchesByRouteId = {};
1383
- for (const match of matches) {
1384
- matchesByRouteId[match.routeId] = match;
1385
- }
1386
- if (!routeCursor.options.notFoundComponent && this.options?.defaultNotFoundComponent) {
1387
- routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
1388
- }
1389
- invariant(
1390
- routeCursor.options.notFoundComponent,
1391
- "No notFoundComponent found. Please set a notFoundComponent on your route or provide a defaultNotFoundComponent to the router."
1392
- );
1393
- const matchForRoute = matchesByRouteId[routeCursor.id];
1394
- invariant(
1395
- matchForRoute,
1396
- "Could not find match for route: " + routeCursor.id
1397
- );
1398
- updateMatch(matchForRoute.id, (prev) => ({
1399
- ...prev,
1400
- status: "notFound",
1401
- error: err,
1402
- isFetching: false
1403
- }));
1404
- if (err.routerCode === "BEFORE_LOAD" && routeCursor.parentRoute) {
1405
- err.routeId = routeCursor.parentRoute.id;
1406
- this._handleNotFound(matches, err, {
1407
- updateMatch
1408
- });
1409
- }
1410
- };
1411
877
  this.hasNotFoundMatch = () => {
1412
878
  return this.__store.state.matches.some(
1413
879
  (d) => d.status === "notFound" || d.globalNotFound
@@ -1495,16 +961,16 @@ class RouterCore {
1495
961
  const matches = [];
1496
962
  const getParentContext = (parentMatch) => {
1497
963
  const parentMatchId = parentMatch?.id;
1498
- const parentContext = !parentMatchId ? this.options.context ?? {} : parentMatch.context ?? this.options.context ?? {};
964
+ const parentContext = !parentMatchId ? this.options.context ?? void 0 : parentMatch.context ?? this.options.context ?? void 0;
1499
965
  return parentContext;
1500
966
  };
1501
967
  matchedRoutes.forEach((route, index) => {
1502
968
  const parentMatch = matches[index - 1];
1503
969
  const [preMatchSearch, strictMatchSearch, searchError] = (() => {
1504
970
  const parentSearch = parentMatch?.search ?? next.search;
1505
- const parentStrictSearch = parentMatch?._strictSearch ?? {};
971
+ const parentStrictSearch = parentMatch?._strictSearch ?? void 0;
1506
972
  try {
1507
- const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? {};
973
+ const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? void 0;
1508
974
  return [
1509
975
  {
1510
976
  ...parentSearch,
@@ -1558,14 +1024,14 @@ class RouterCore {
1558
1024
  _strictSearch: strictMatchSearch
1559
1025
  };
1560
1026
  } else {
1561
- const status = route.options.loader || route.options.beforeLoad || route.lazyFn || routeNeedsPreload(route) ? "pending" : "success";
1027
+ const status = route.options.loader || route.options.beforeLoad || route.lazyFn || loadMatches.routeNeedsPreload(route) ? "pending" : "success";
1562
1028
  match = {
1563
1029
  id: matchId,
1564
1030
  index,
1565
1031
  routeId: route.id,
1566
1032
  params: previousMatch ? utils.replaceEqualDeep(previousMatch.params, routeParams) : routeParams,
1567
1033
  _strictParams: usedParams,
1568
- pathname: path.joinPaths([this.basepath, interpolatedPath]),
1034
+ pathname: interpolatedPath,
1569
1035
  updatedAt: Date.now(),
1570
1036
  search: previousMatch ? utils.replaceEqualDeep(previousMatch.search, preMatchSearch) : preMatchSearch,
1571
1037
  _strictSearch: strictMatchSearch,
@@ -1574,7 +1040,10 @@ class RouterCore {
1574
1040
  isFetching: false,
1575
1041
  error: void 0,
1576
1042
  paramsError: parseErrors[index],
1577
- __routeContext: {},
1043
+ __routeContext: void 0,
1044
+ _nonReactive: {
1045
+ loadPromise: utils.createControlledPromise()
1046
+ },
1578
1047
  __beforeLoadContext: void 0,
1579
1048
  context: {},
1580
1049
  abortController: new AbortController(),
@@ -1588,7 +1057,6 @@ class RouterCore {
1588
1057
  headScripts: void 0,
1589
1058
  meta: void 0,
1590
1059
  staticData: route.options.staticData || {},
1591
- loadPromise: utils.createControlledPromise(),
1592
1060
  fullPath: route.fullPath
1593
1061
  };
1594
1062
  }
@@ -1610,19 +1078,21 @@ class RouterCore {
1610
1078
  if (!existingMatch && opts?._buildLocation !== true) {
1611
1079
  const parentMatch = matches[index - 1];
1612
1080
  const parentContext = getParentContext(parentMatch);
1613
- const contextFnContext = {
1614
- deps: match.loaderDeps,
1615
- params: match.params,
1616
- context: parentContext,
1617
- location: next,
1618
- navigate: (opts2) => this.navigate({ ...opts2, _fromLocation: next }),
1619
- buildLocation: this.buildLocation,
1620
- cause: match.cause,
1621
- abortController: match.abortController,
1622
- preload: !!match.preload,
1623
- matches
1624
- };
1625
- match.__routeContext = route.options.context?.(contextFnContext) ?? {};
1081
+ if (route.options.context) {
1082
+ const contextFnContext = {
1083
+ deps: match.loaderDeps,
1084
+ params: match.params,
1085
+ context: parentContext ?? {},
1086
+ location: next,
1087
+ navigate: (opts2) => this.navigate({ ...opts2, _fromLocation: next }),
1088
+ buildLocation: this.buildLocation,
1089
+ cause: match.cause,
1090
+ abortController: match.abortController,
1091
+ preload: !!match.preload,
1092
+ matches
1093
+ };
1094
+ match.__routeContext = route.options.context(contextFnContext) ?? void 0;
1095
+ }
1626
1096
  match.context = {
1627
1097
  ...parentContext,
1628
1098
  ...match.__routeContext,
@@ -1681,20 +1151,6 @@ function validateSearch(validateSearch2, input) {
1681
1151
  }
1682
1152
  return {};
1683
1153
  }
1684
- const componentTypes = [
1685
- "component",
1686
- "errorComponent",
1687
- "pendingComponent",
1688
- "notFoundComponent"
1689
- ];
1690
- function routeNeedsPreload(route) {
1691
- for (const componentType of componentTypes) {
1692
- if (route.options[componentType]?.preload) {
1693
- return true;
1694
- }
1695
- }
1696
- return false;
1697
- }
1698
1154
  const REQUIRED_PARAM_BASE_SCORE = 0.5;
1699
1155
  const OPTIONAL_PARAM_BASE_SCORE = 0.4;
1700
1156
  const WILDCARD_PARAM_BASE_SCORE = 0.25;
@@ -1827,7 +1283,6 @@ function processRouteTree({
1827
1283
  function getMatchedRoutes({
1828
1284
  pathname,
1829
1285
  routePathname,
1830
- basepath,
1831
1286
  caseSensitive,
1832
1287
  routesByPath,
1833
1288
  routesById,
@@ -1838,7 +1293,6 @@ function getMatchedRoutes({
1838
1293
  const trimmedPath = path.trimPathRight(pathname);
1839
1294
  const getMatchedParams = (route) => {
1840
1295
  const result = path.matchPathname(
1841
- basepath,
1842
1296
  trimmedPath,
1843
1297
  {
1844
1298
  to: route.fullPath,
@@ -1925,7 +1379,7 @@ function applySearchMiddleware({
1925
1379
  try {
1926
1380
  const validatedSearch = {
1927
1381
  ...result,
1928
- ...validateSearch(route.options.validateSearch, result) ?? {}
1382
+ ...validateSearch(route.options.validateSearch, result) ?? void 0
1929
1383
  };
1930
1384
  return validatedSearch;
1931
1385
  } catch {
@@ -1963,7 +1417,6 @@ function applySearchMiddleware({
1963
1417
  exports.PathParamError = PathParamError;
1964
1418
  exports.RouterCore = RouterCore;
1965
1419
  exports.SearchParamError = SearchParamError;
1966
- exports.componentTypes = componentTypes;
1967
1420
  exports.defaultSerializeError = defaultSerializeError;
1968
1421
  exports.getInitialRouterState = getInitialRouterState;
1969
1422
  exports.getLocationChangeInfo = getLocationChangeInfo;