@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
@@ -1,14 +1,16 @@
1
1
  import { Store, batch } from "@tanstack/store";
2
- import { createMemoryHistory, createBrowserHistory, parseHref } from "@tanstack/history";
2
+ import { createBrowserHistory, parseHref } from "@tanstack/history";
3
3
  import invariant from "tiny-invariant";
4
- import { pick, createControlledPromise, deepEqual, replaceEqualDeep, last, functionalUpdate } from "./utils.js";
5
- import { trimPath, resolvePath, cleanPath, matchPathname, trimPathRight, interpolatePath, joinPaths, trimPathLeft, parsePathname, SEGMENT_TYPE_PARAM, SEGMENT_TYPE_OPTIONAL_PARAM, SEGMENT_TYPE_WILDCARD, SEGMENT_TYPE_PATHNAME } from "./path.js";
4
+ import { createControlledPromise, deepEqual, replaceEqualDeep, last, findLast, functionalUpdate } from "./utils.js";
5
+ import { resolvePath, cleanPath, trimPathRight, trimPath, matchPathname, interpolatePath, trimPathLeft, parsePathname, SEGMENT_TYPE_PARAM, SEGMENT_TYPE_OPTIONAL_PARAM, SEGMENT_TYPE_WILDCARD, SEGMENT_TYPE_PATHNAME } from "./path.js";
6
6
  import { isNotFound } from "./not-found.js";
7
7
  import { setupScrollRestoration } from "./scroll-restoration.js";
8
8
  import { defaultParseSearch, defaultStringifySearch } from "./searchParams.js";
9
9
  import { rootRouteId } from "./root.js";
10
10
  import { redirect, isRedirect } from "./redirect.js";
11
11
  import { createLRUCache } from "./lru-cache.js";
12
+ import { loadMatches, loadRouteChunk, routeNeedsPreload } from "./load-matches.js";
13
+ import { rewriteBasepath, composeRewrites, executeRewriteInput, executeRewriteOutput } from "./rewrite.js";
12
14
  function defaultSerializeError(err) {
13
15
  if (err instanceof Error) {
14
16
  const obj = {
@@ -53,7 +55,6 @@ class RouterCore {
53
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."
54
56
  );
55
57
  }
56
- const previousOptions = this.options;
57
58
  this.options = {
58
59
  ...this.options,
59
60
  ...newOptions
@@ -65,24 +66,43 @@ class RouterCore {
65
66
  char
66
67
  ])
67
68
  ) : void 0;
68
- if (!this.basepath || newOptions.basepath && newOptions.basepath !== previousOptions.basepath) {
69
- if (newOptions.basepath === void 0 || newOptions.basepath === "" || newOptions.basepath === "/") {
70
- this.basepath = "/";
69
+ if (!this.history || this.options.history && this.options.history !== this.history) {
70
+ if (!this.options.history) {
71
+ if (!this.isServer) {
72
+ this.history = createBrowserHistory();
73
+ }
71
74
  } else {
72
- this.basepath = `/${trimPath(newOptions.basepath)}`;
75
+ this.history = this.options.history;
73
76
  }
74
77
  }
75
- if (!this.history || this.options.history && this.options.history !== this.history) {
76
- this.history = this.options.history ?? (this.isServer ? createMemoryHistory({
77
- initialEntries: [this.basepath || "/"]
78
- }) : createBrowserHistory());
79
- this.latestLocation = this.parseLocation();
78
+ if (this.options.basepath) {
79
+ const basepathRewrite = rewriteBasepath({
80
+ basepath: this.options.basepath
81
+ });
82
+ if (this.options.rewrite) {
83
+ this.rewrite = composeRewrites([basepathRewrite, this.options.rewrite]);
84
+ } else {
85
+ this.rewrite = basepathRewrite;
86
+ }
87
+ } else {
88
+ this.rewrite = this.options.rewrite;
89
+ }
90
+ this.origin = this.options.origin;
91
+ if (!this.origin) {
92
+ if (!this.isServer) {
93
+ this.origin = window.origin;
94
+ } else {
95
+ this.origin = "http://localhost";
96
+ }
97
+ }
98
+ if (this.history) {
99
+ this.updateLatestLocation();
80
100
  }
81
101
  if (this.options.routeTree !== this.routeTree) {
82
102
  this.routeTree = this.options.routeTree;
83
103
  this.buildRouteTree();
84
104
  }
85
- if (!this.__store) {
105
+ if (!this.__store && this.latestLocation) {
86
106
  this.__store = new Store(getInitialRouterState(this.latestLocation), {
87
107
  onUpdate: () => {
88
108
  this.__store.state = {
@@ -101,6 +121,12 @@ class RouterCore {
101
121
  );
102
122
  }
103
123
  };
124
+ this.updateLatestLocation = () => {
125
+ this.latestLocation = this.parseLocation(
126
+ this.history.location,
127
+ this.latestLocation
128
+ );
129
+ };
104
130
  this.buildRouteTree = () => {
105
131
  const { routesById, routesByPath, flatRoutes } = processRouteTree({
106
132
  routeTree: this.routeTree,
@@ -138,25 +164,30 @@ class RouterCore {
138
164
  }
139
165
  });
140
166
  };
141
- this.parseLocation = (previousLocation, locationToParse) => {
167
+ this.parseLocation = (locationToParse, previousLocation) => {
142
168
  const parse = ({
143
- pathname,
144
- search,
145
- hash,
169
+ href,
146
170
  state
147
171
  }) => {
148
- const parsedSearch = this.options.parseSearch(search);
172
+ const fullUrl = new URL(href, this.origin);
173
+ const url = executeRewriteInput(this.rewrite, fullUrl);
174
+ const parsedSearch = this.options.parseSearch(url.search);
149
175
  const searchStr = this.options.stringifySearch(parsedSearch);
176
+ url.search = searchStr;
177
+ const fullPath = url.href.replace(url.origin, "");
178
+ const { pathname, hash } = url;
150
179
  return {
180
+ href: fullPath,
181
+ publicHref: href,
182
+ url: url.href,
151
183
  pathname,
152
184
  searchStr,
153
185
  search: replaceEqualDeep(previousLocation?.search, parsedSearch),
154
186
  hash: hash.split("#").reverse()[0] ?? "",
155
- href: `${pathname}${searchStr}${hash}`,
156
187
  state: replaceEqualDeep(previousLocation?.state, state)
157
188
  };
158
189
  };
159
- const location = parse(locationToParse ?? this.history.location);
190
+ const location = parse(locationToParse);
160
191
  const { __tempLocation, __tempKey } = location.state;
161
192
  if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
162
193
  const parsedTempLocation = parse(__tempLocation);
@@ -172,11 +203,9 @@ class RouterCore {
172
203
  };
173
204
  this.resolvePathWithBase = (from, path) => {
174
205
  const resolvedPath = resolvePath({
175
- basepath: this.basepath,
176
206
  base: from,
177
207
  to: cleanPath(path),
178
208
  trailingSlash: this.options.trailingSlash,
179
- caseSensitive: this.options.caseSensitive,
180
209
  parseCache: this.parsePathnameCache
181
210
  });
182
211
  return resolvedPath;
@@ -198,7 +227,6 @@ class RouterCore {
198
227
  return getMatchedRoutes({
199
228
  pathname,
200
229
  routePathname,
201
- basepath: this.basepath,
202
230
  caseSensitive: this.options.caseSensitive,
203
231
  routesByPath: this.routesByPath,
204
232
  routesById: this.routesById,
@@ -210,13 +238,8 @@ class RouterCore {
210
238
  const match = this.getMatch(id);
211
239
  if (!match) return;
212
240
  match.abortController.abort();
213
- this.updateMatch(id, (prev) => {
214
- clearTimeout(prev.pendingTimeout);
215
- return {
216
- ...prev,
217
- pendingTimeout: void 0
218
- };
219
- });
241
+ clearTimeout(match._nonReactive.pendingTimeout);
242
+ match._nonReactive.pendingTimeout = void 0;
220
243
  };
221
244
  this.cancelMatches = () => {
222
245
  this.state.pendingMatches?.forEach((match) => {
@@ -230,60 +253,51 @@ class RouterCore {
230
253
  _buildLocation: true
231
254
  });
232
255
  const lastMatch = last(allCurrentLocationMatches);
233
- let fromPath = lastMatch.fullPath;
234
- const toPath = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
235
- const routeIsChanging = !!dest.to && !comparePaths(dest.to.toString(), fromPath) && !comparePaths(toPath, fromPath);
236
- if (dest.unsafeRelative === "path") {
237
- fromPath = currentLocation.pathname;
238
- } else if (routeIsChanging && dest.from) {
239
- fromPath = dest.from;
240
- if (process.env.NODE_ENV !== "production" && dest._isNavigate) {
241
- const allFromMatches = this.getMatchedRoutes(
242
- dest.from,
243
- void 0
244
- ).matchedRoutes;
245
- const matchedFrom = [...allCurrentLocationMatches].reverse().find((d) => {
246
- return comparePaths(d.fullPath, fromPath);
247
- });
248
- const matchedCurrent = [...allFromMatches].reverse().find((d) => {
249
- return comparePaths(d.fullPath, currentLocation.pathname);
250
- });
251
- if (!matchedFrom && !matchedCurrent) {
252
- console.warn(`Could not find match for from: ${fromPath}`);
253
- }
256
+ if (dest.from && process.env.NODE_ENV !== "production" && dest._isNavigate) {
257
+ const allFromMatches = this.getMatchedRoutes(
258
+ dest.from,
259
+ void 0
260
+ ).matchedRoutes;
261
+ const matchedFrom = findLast(allCurrentLocationMatches, (d) => {
262
+ return comparePaths(d.fullPath, dest.from);
263
+ });
264
+ const matchedCurrent = findLast(allFromMatches, (d) => {
265
+ return comparePaths(d.fullPath, lastMatch.fullPath);
266
+ });
267
+ if (!matchedFrom && !matchedCurrent) {
268
+ console.warn(`Could not find match for from: ${dest.from}`);
254
269
  }
255
270
  }
271
+ const defaultedFromPath = dest.unsafeRelative === "path" ? currentLocation.pathname : dest.from ?? lastMatch.fullPath;
272
+ const fromPath = this.resolvePathWithBase(defaultedFromPath, ".");
256
273
  const fromSearch = lastMatch.search;
257
274
  const fromParams = { ...lastMatch.params };
258
275
  const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
259
- let nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : {
260
- ...fromParams,
261
- ...functionalUpdate(dest.params, fromParams)
262
- };
276
+ const nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : Object.assign(
277
+ fromParams,
278
+ functionalUpdate(dest.params, fromParams)
279
+ );
263
280
  const interpolatedNextTo = interpolatePath({
264
281
  path: nextTo,
265
- params: nextParams ?? {},
282
+ params: nextParams,
266
283
  parseCache: this.parsePathnameCache
267
284
  }).interpolatedPath;
268
- const destRoutes = this.matchRoutes(
269
- interpolatedNextTo,
270
- {},
271
- {
272
- _buildLocation: true
273
- }
274
- ).map((d) => this.looseRoutesById[d.routeId]);
285
+ const destRoutes = this.matchRoutes(interpolatedNextTo, void 0, {
286
+ _buildLocation: true
287
+ }).map((d) => this.looseRoutesById[d.routeId]);
275
288
  if (Object.keys(nextParams).length > 0) {
276
- destRoutes.map((route) => {
277
- return route.options.params?.stringify ?? route.options.stringifyParams;
278
- }).filter(Boolean).forEach((fn) => {
279
- nextParams = { ...nextParams, ...fn(nextParams) };
280
- });
289
+ for (const route of destRoutes) {
290
+ const fn = route.options.params?.stringify ?? route.options.stringifyParams;
291
+ if (fn) {
292
+ Object.assign(nextParams, fn(nextParams));
293
+ }
294
+ }
281
295
  }
282
296
  const nextPathname = interpolatePath({
283
297
  // Use the original template path for interpolation
284
298
  // This preserves the original parameter syntax including optional parameters
285
299
  path: nextTo,
286
- params: nextParams ?? {},
300
+ params: nextParams,
287
301
  leaveWildcards: false,
288
302
  leaveParams: opts.leaveParams,
289
303
  decodeCharMap: this.pathParamsDecodeCharMap,
@@ -291,19 +305,19 @@ class RouterCore {
291
305
  }).interpolatedPath;
292
306
  let nextSearch = fromSearch;
293
307
  if (opts._includeValidateSearch && this.options.search?.strict) {
294
- let validatedSearch = {};
308
+ const validatedSearch = {};
295
309
  destRoutes.forEach((route) => {
296
- try {
297
- if (route.options.validateSearch) {
298
- validatedSearch = {
299
- ...validatedSearch,
300
- ...validateSearch(route.options.validateSearch, {
310
+ if (route.options.validateSearch) {
311
+ try {
312
+ Object.assign(
313
+ validatedSearch,
314
+ validateSearch(route.options.validateSearch, {
301
315
  ...validatedSearch,
302
316
  ...nextSearch
303
- }) ?? {}
304
- };
317
+ })
318
+ );
319
+ } catch {
305
320
  }
306
- } catch {
307
321
  }
308
322
  });
309
323
  nextSearch = validatedSearch;
@@ -320,13 +334,18 @@ class RouterCore {
320
334
  const hashStr = hash ? `#${hash}` : "";
321
335
  let nextState = dest.state === true ? currentLocation.state : dest.state ? functionalUpdate(dest.state, currentLocation.state) : {};
322
336
  nextState = replaceEqualDeep(currentLocation.state, nextState);
337
+ const fullPath = `${nextPathname}${searchStr}${hashStr}`;
338
+ const url = new URL(fullPath, this.origin);
339
+ const rewrittenUrl = executeRewriteOutput(this.rewrite, url);
323
340
  return {
341
+ publicHref: rewrittenUrl.pathname + rewrittenUrl.search + rewrittenUrl.hash,
342
+ href: fullPath,
343
+ url: rewrittenUrl.href,
324
344
  pathname: nextPathname,
325
345
  search: nextSearch,
326
346
  searchStr,
327
347
  state: nextState,
328
348
  hash: hash ?? "",
329
- href: `${nextPathname}${searchStr}${hashStr}`,
330
349
  unmaskOnReload: dest.unmaskOnReload
331
350
  };
332
351
  };
@@ -337,7 +356,6 @@ class RouterCore {
337
356
  let params = {};
338
357
  const foundMask = this.options.routeMasks?.find((d) => {
339
358
  const match = matchPathname(
340
- this.basepath,
341
359
  next.pathname,
342
360
  {
343
361
  to: d.from,
@@ -355,7 +373,7 @@ class RouterCore {
355
373
  if (foundMask) {
356
374
  const { from: _from, ...maskProps } = foundMask;
357
375
  maskedDest = {
358
- ...pick(opts, ["from"]),
376
+ from: opts.from,
359
377
  ...maskProps,
360
378
  params
361
379
  };
@@ -370,7 +388,7 @@ class RouterCore {
370
388
  };
371
389
  if (opts.mask) {
372
390
  return buildWithMatches(opts, {
373
- ...pick(opts, ["from"]),
391
+ from: opts.from,
374
392
  ...opts.mask
375
393
  });
376
394
  }
@@ -398,7 +416,7 @@ class RouterCore {
398
416
  });
399
417
  return isEqual;
400
418
  };
401
- const isSameUrl = this.latestLocation.href === next.href;
419
+ const isSameUrl = trimPathRight(this.latestLocation.href) === trimPathRight(next.href);
402
420
  const previousCommitPromise = this.commitLocationPromise;
403
421
  this.commitLocationPromise = createControlledPromise(() => {
404
422
  previousCommitPromise?.resolve();
@@ -434,7 +452,7 @@ class RouterCore {
434
452
  nextHistory.state.__hashScrollIntoViewOptions = hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true;
435
453
  this.shouldViewTransition = viewTransition;
436
454
  this.history[next.replace ? "replace" : "push"](
437
- nextHistory.href,
455
+ nextHistory.publicHref,
438
456
  nextHistory.state,
439
457
  { ignoreBlocker }
440
458
  );
@@ -487,7 +505,7 @@ class RouterCore {
487
505
  if (reloadDocument) {
488
506
  if (!href) {
489
507
  const location = this.buildLocation({ to, ...rest });
490
- href = this.history.createHref(location.href);
508
+ href = location.href;
491
509
  }
492
510
  if (rest.replace) {
493
511
  window.location.replace(href);
@@ -505,7 +523,7 @@ class RouterCore {
505
523
  };
506
524
  this.beforeLoad = () => {
507
525
  this.cancelMatches();
508
- this.latestLocation = this.parseLocation(this.latestLocation);
526
+ this.updateLatestLocation();
509
527
  if (this.isServer) {
510
528
  const nextLocation = this.buildLocation({
511
529
  to: this.latestLocation.pathname,
@@ -566,10 +584,12 @@ class RouterCore {
566
584
  location: next
567
585
  })
568
586
  });
569
- await this.loadMatches({
587
+ await loadMatches({
588
+ router: this,
570
589
  sync: opts?.sync,
571
590
  matches: this.state.pendingMatches,
572
591
  location: next,
592
+ updateMatch: this.updateMatch,
573
593
  // eslint-disable-next-line @typescript-eslint/require-await
574
594
  onReady: async () => {
575
595
  this.startViewTransition(async () => {
@@ -693,510 +713,13 @@ class RouterCore {
693
713
  const findFn = (d) => d.id === matchId;
694
714
  return this.state.cachedMatches.find(findFn) ?? this.state.pendingMatches?.find(findFn) ?? this.state.matches.find(findFn);
695
715
  };
696
- this.loadMatches = async ({
697
- location,
698
- matches,
699
- preload: allPreload,
700
- onReady,
701
- updateMatch = this.updateMatch,
702
- sync
703
- }) => {
704
- let firstBadMatchIndex;
705
- let rendered = false;
706
- const triggerOnReady = async () => {
707
- if (!rendered) {
708
- rendered = true;
709
- await onReady?.();
710
- }
711
- };
712
- const resolvePreload = (matchId) => {
713
- return !!(allPreload && !this.state.matches.some((d) => d.id === matchId));
714
- };
715
- if (!this.isServer && this.state.matches.some((d) => d._forcePending)) {
716
- triggerOnReady();
717
- }
718
- const handleRedirectAndNotFound = (match, err) => {
719
- if (isRedirect(err) || isNotFound(err)) {
720
- if (isRedirect(err)) {
721
- if (err.redirectHandled) {
722
- if (!err.options.reloadDocument) {
723
- throw err;
724
- }
725
- }
726
- }
727
- match.beforeLoadPromise?.resolve();
728
- match.loaderPromise?.resolve();
729
- updateMatch(match.id, (prev) => ({
730
- ...prev,
731
- status: isRedirect(err) ? "redirected" : isNotFound(err) ? "notFound" : "error",
732
- isFetching: false,
733
- error: err,
734
- beforeLoadPromise: void 0,
735
- loaderPromise: void 0
736
- }));
737
- if (!err.routeId) {
738
- err.routeId = match.routeId;
739
- }
740
- match.loadPromise?.resolve();
741
- if (isRedirect(err)) {
742
- rendered = true;
743
- err.options._fromLocation = location;
744
- err.redirectHandled = true;
745
- err = this.resolveRedirect(err);
746
- throw err;
747
- } else if (isNotFound(err)) {
748
- this._handleNotFound(matches, err, {
749
- updateMatch
750
- });
751
- throw err;
752
- }
753
- }
754
- };
755
- const shouldSkipLoader = (matchId) => {
756
- const match = this.getMatch(matchId);
757
- if (!this.isServer && match._dehydrated) {
758
- return true;
759
- }
760
- if (this.isServer) {
761
- if (match.ssr === false) {
762
- return true;
763
- }
764
- }
765
- return false;
766
- };
767
- try {
768
- await new Promise((resolveAll, rejectAll) => {
769
- ;
770
- (async () => {
771
- try {
772
- const handleSerialError = (index, err, routerCode) => {
773
- const { id: matchId, routeId } = matches[index];
774
- const route = this.looseRoutesById[routeId];
775
- if (err instanceof Promise) {
776
- throw err;
777
- }
778
- err.routerCode = routerCode;
779
- firstBadMatchIndex = firstBadMatchIndex ?? index;
780
- handleRedirectAndNotFound(this.getMatch(matchId), err);
781
- try {
782
- route.options.onError?.(err);
783
- } catch (errorHandlerErr) {
784
- err = errorHandlerErr;
785
- handleRedirectAndNotFound(this.getMatch(matchId), err);
786
- }
787
- updateMatch(matchId, (prev) => {
788
- prev.beforeLoadPromise?.resolve();
789
- prev.loadPromise?.resolve();
790
- return {
791
- ...prev,
792
- error: err,
793
- status: "error",
794
- isFetching: false,
795
- updatedAt: Date.now(),
796
- abortController: new AbortController(),
797
- beforeLoadPromise: void 0
798
- };
799
- });
800
- };
801
- for (const [index, { id: matchId, routeId }] of matches.entries()) {
802
- const existingMatch = this.getMatch(matchId);
803
- const parentMatchId = matches[index - 1]?.id;
804
- const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
805
- const route = this.looseRoutesById[routeId];
806
- const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
807
- if (this.isServer) {
808
- let ssr;
809
- if (this.isShell()) {
810
- ssr = matchId === rootRouteId;
811
- } else {
812
- const defaultSsr = this.options.defaultSsr ?? true;
813
- if (parentMatch?.ssr === false) {
814
- ssr = false;
815
- } else {
816
- let tempSsr;
817
- if (route.options.ssr === void 0) {
818
- tempSsr = defaultSsr;
819
- } else if (typeof route.options.ssr === "function") {
820
- let makeMaybe = function(value, error) {
821
- if (error) {
822
- return { status: "error", error };
823
- }
824
- return { status: "success", value };
825
- };
826
- const { search, params } = this.getMatch(matchId);
827
- const ssrFnContext = {
828
- search: makeMaybe(search, existingMatch.searchError),
829
- params: makeMaybe(params, existingMatch.paramsError),
830
- location,
831
- matches: matches.map((match) => ({
832
- index: match.index,
833
- pathname: match.pathname,
834
- fullPath: match.fullPath,
835
- staticData: match.staticData,
836
- id: match.id,
837
- routeId: match.routeId,
838
- search: makeMaybe(match.search, match.searchError),
839
- params: makeMaybe(match.params, match.paramsError),
840
- ssr: match.ssr
841
- }))
842
- };
843
- tempSsr = await route.options.ssr(ssrFnContext) ?? defaultSsr;
844
- } else {
845
- tempSsr = route.options.ssr;
846
- }
847
- if (tempSsr === true && parentMatch?.ssr === "data-only") {
848
- ssr = "data-only";
849
- } else {
850
- ssr = tempSsr;
851
- }
852
- }
853
- }
854
- updateMatch(matchId, (prev) => ({
855
- ...prev,
856
- ssr
857
- }));
858
- }
859
- if (shouldSkipLoader(matchId)) {
860
- continue;
861
- }
862
- const shouldPending = !!(onReady && !this.isServer && !resolvePreload(matchId) && (route.options.loader || route.options.beforeLoad || routeNeedsPreload(route)) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? this.options?.defaultPendingComponent));
863
- let executeBeforeLoad = true;
864
- const setupPendingTimeout = () => {
865
- if (shouldPending && this.getMatch(matchId).pendingTimeout === void 0) {
866
- const pendingTimeout = setTimeout(() => {
867
- try {
868
- triggerOnReady();
869
- } catch {
870
- }
871
- }, pendingMs);
872
- updateMatch(matchId, (prev) => ({
873
- ...prev,
874
- pendingTimeout
875
- }));
876
- }
877
- };
878
- if (
879
- // If we are in the middle of a load, either of these will be present
880
- // (not to be confused with `loadPromise`, which is always defined)
881
- existingMatch.beforeLoadPromise || existingMatch.loaderPromise
882
- ) {
883
- setupPendingTimeout();
884
- await existingMatch.beforeLoadPromise;
885
- const match = this.getMatch(matchId);
886
- if (match.status === "error") {
887
- executeBeforeLoad = true;
888
- } else if (match.preload && (match.status === "redirected" || match.status === "notFound")) {
889
- handleRedirectAndNotFound(match, match.error);
890
- }
891
- }
892
- if (executeBeforeLoad) {
893
- try {
894
- updateMatch(matchId, (prev) => {
895
- const prevLoadPromise = prev.loadPromise;
896
- return {
897
- ...prev,
898
- loadPromise: createControlledPromise(() => {
899
- prevLoadPromise?.resolve();
900
- }),
901
- beforeLoadPromise: createControlledPromise()
902
- };
903
- });
904
- const { paramsError, searchError } = this.getMatch(matchId);
905
- if (paramsError) {
906
- handleSerialError(index, paramsError, "PARSE_PARAMS");
907
- }
908
- if (searchError) {
909
- handleSerialError(index, searchError, "VALIDATE_SEARCH");
910
- }
911
- setupPendingTimeout();
912
- const abortController = new AbortController();
913
- const parentMatchContext = parentMatch?.context ?? this.options.context ?? {};
914
- updateMatch(matchId, (prev) => ({
915
- ...prev,
916
- isFetching: "beforeLoad",
917
- fetchCount: prev.fetchCount + 1,
918
- abortController,
919
- context: {
920
- ...parentMatchContext,
921
- ...prev.__routeContext
922
- }
923
- }));
924
- const { search, params, context, cause } = this.getMatch(matchId);
925
- const preload = resolvePreload(matchId);
926
- const beforeLoadFnContext = {
927
- search,
928
- abortController,
929
- params,
930
- preload,
931
- context,
932
- location,
933
- navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
934
- buildLocation: this.buildLocation,
935
- cause: preload ? "preload" : cause,
936
- matches
937
- };
938
- const beforeLoadContext = await route.options.beforeLoad?.(beforeLoadFnContext);
939
- if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
940
- handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
941
- }
942
- updateMatch(matchId, (prev) => {
943
- return {
944
- ...prev,
945
- __beforeLoadContext: beforeLoadContext,
946
- context: {
947
- ...parentMatchContext,
948
- ...prev.__routeContext,
949
- ...beforeLoadContext
950
- },
951
- abortController
952
- };
953
- });
954
- } catch (err) {
955
- handleSerialError(index, err, "BEFORE_LOAD");
956
- }
957
- updateMatch(matchId, (prev) => {
958
- prev.beforeLoadPromise?.resolve();
959
- return {
960
- ...prev,
961
- beforeLoadPromise: void 0,
962
- isFetching: false
963
- };
964
- });
965
- }
966
- }
967
- const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
968
- const matchPromises = [];
969
- validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
970
- matchPromises.push(
971
- (async () => {
972
- let loaderShouldRunAsync = false;
973
- let loaderIsRunningAsync = false;
974
- const route = this.looseRoutesById[routeId];
975
- const executeHead = async () => {
976
- const match = this.getMatch(matchId);
977
- if (!match) {
978
- return;
979
- }
980
- const assetContext = {
981
- matches,
982
- match,
983
- params: match.params,
984
- loaderData: match.loaderData
985
- };
986
- const headFnContent = await route.options.head?.(assetContext);
987
- const meta = headFnContent?.meta;
988
- const links = headFnContent?.links;
989
- const headScripts = headFnContent?.scripts;
990
- const styles = headFnContent?.styles;
991
- const scripts = await route.options.scripts?.(assetContext);
992
- const headers = await route.options.headers?.(assetContext);
993
- return {
994
- meta,
995
- links,
996
- headScripts,
997
- headers,
998
- scripts,
999
- styles
1000
- };
1001
- };
1002
- const potentialPendingMinPromise = async () => {
1003
- const latestMatch = this.getMatch(matchId);
1004
- if (latestMatch.minPendingPromise) {
1005
- await latestMatch.minPendingPromise;
1006
- }
1007
- };
1008
- const prevMatch = this.getMatch(matchId);
1009
- if (shouldSkipLoader(matchId)) {
1010
- if (this.isServer) {
1011
- const head = await executeHead();
1012
- updateMatch(matchId, (prev) => ({
1013
- ...prev,
1014
- ...head
1015
- }));
1016
- return this.getMatch(matchId);
1017
- }
1018
- } else if (prevMatch.loaderPromise) {
1019
- if (prevMatch.status === "success" && !sync && !prevMatch.preload) {
1020
- return this.getMatch(matchId);
1021
- }
1022
- await prevMatch.loaderPromise;
1023
- const match = this.getMatch(matchId);
1024
- if (match.error) {
1025
- handleRedirectAndNotFound(match, match.error);
1026
- }
1027
- } else {
1028
- const parentMatchPromise = matchPromises[index - 1];
1029
- const getLoaderContext = () => {
1030
- const {
1031
- params,
1032
- loaderDeps,
1033
- abortController,
1034
- context,
1035
- cause
1036
- } = this.getMatch(matchId);
1037
- const preload2 = resolvePreload(matchId);
1038
- return {
1039
- params,
1040
- deps: loaderDeps,
1041
- preload: !!preload2,
1042
- parentMatchPromise,
1043
- abortController,
1044
- context,
1045
- location,
1046
- navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
1047
- cause: preload2 ? "preload" : cause,
1048
- route
1049
- };
1050
- };
1051
- const age = Date.now() - this.getMatch(matchId).updatedAt;
1052
- const preload = resolvePreload(matchId);
1053
- const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
1054
- const shouldReloadOption = route.options.shouldReload;
1055
- const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext()) : shouldReloadOption;
1056
- updateMatch(matchId, (prev) => ({
1057
- ...prev,
1058
- loaderPromise: createControlledPromise(),
1059
- preload: !!preload && !this.state.matches.some((d) => d.id === matchId)
1060
- }));
1061
- const runLoader = async () => {
1062
- try {
1063
- try {
1064
- if (!this.isServer || this.isServer && this.getMatch(matchId).ssr === true) {
1065
- this.loadRouteChunk(route);
1066
- }
1067
- updateMatch(matchId, (prev) => ({
1068
- ...prev,
1069
- isFetching: "loader"
1070
- }));
1071
- const loaderData = await route.options.loader?.(getLoaderContext());
1072
- handleRedirectAndNotFound(
1073
- this.getMatch(matchId),
1074
- loaderData
1075
- );
1076
- updateMatch(matchId, (prev) => ({
1077
- ...prev,
1078
- loaderData
1079
- }));
1080
- await route._lazyPromise;
1081
- const head = await executeHead();
1082
- await potentialPendingMinPromise();
1083
- await route._componentsPromise;
1084
- updateMatch(matchId, (prev) => ({
1085
- ...prev,
1086
- error: void 0,
1087
- status: "success",
1088
- isFetching: false,
1089
- updatedAt: Date.now(),
1090
- ...head
1091
- }));
1092
- } catch (e) {
1093
- let error = e;
1094
- await potentialPendingMinPromise();
1095
- handleRedirectAndNotFound(this.getMatch(matchId), e);
1096
- try {
1097
- route.options.onError?.(e);
1098
- } catch (onErrorError) {
1099
- error = onErrorError;
1100
- handleRedirectAndNotFound(
1101
- this.getMatch(matchId),
1102
- onErrorError
1103
- );
1104
- }
1105
- const head = await executeHead();
1106
- updateMatch(matchId, (prev) => ({
1107
- ...prev,
1108
- error,
1109
- status: "error",
1110
- isFetching: false,
1111
- ...head
1112
- }));
1113
- }
1114
- } catch (err) {
1115
- const head = await executeHead();
1116
- updateMatch(matchId, (prev) => ({
1117
- ...prev,
1118
- loaderPromise: void 0,
1119
- ...head
1120
- }));
1121
- handleRedirectAndNotFound(this.getMatch(matchId), err);
1122
- }
1123
- };
1124
- const { status, invalid } = this.getMatch(matchId);
1125
- loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? age > staleAge));
1126
- if (preload && route.options.preload === false) {
1127
- } else if (loaderShouldRunAsync && !sync) {
1128
- loaderIsRunningAsync = true;
1129
- (async () => {
1130
- try {
1131
- await runLoader();
1132
- const { loaderPromise, loadPromise } = this.getMatch(matchId);
1133
- loaderPromise?.resolve();
1134
- loadPromise?.resolve();
1135
- updateMatch(matchId, (prev) => ({
1136
- ...prev,
1137
- loaderPromise: void 0
1138
- }));
1139
- } catch (err) {
1140
- if (isRedirect(err)) {
1141
- await this.navigate(err.options);
1142
- }
1143
- }
1144
- })();
1145
- } else if (status !== "success" || loaderShouldRunAsync && sync) {
1146
- await runLoader();
1147
- } else {
1148
- const head = await executeHead();
1149
- updateMatch(matchId, (prev) => ({
1150
- ...prev,
1151
- ...head
1152
- }));
1153
- }
1154
- }
1155
- if (!loaderIsRunningAsync) {
1156
- const { loaderPromise, loadPromise } = this.getMatch(matchId);
1157
- loaderPromise?.resolve();
1158
- loadPromise?.resolve();
1159
- }
1160
- updateMatch(matchId, (prev) => {
1161
- clearTimeout(prev.pendingTimeout);
1162
- return {
1163
- ...prev,
1164
- isFetching: loaderIsRunningAsync ? prev.isFetching : false,
1165
- loaderPromise: loaderIsRunningAsync ? prev.loaderPromise : void 0,
1166
- invalid: false,
1167
- pendingTimeout: void 0,
1168
- _dehydrated: void 0
1169
- };
1170
- });
1171
- return this.getMatch(matchId);
1172
- })()
1173
- );
1174
- });
1175
- await Promise.all(matchPromises);
1176
- resolveAll();
1177
- } catch (err) {
1178
- rejectAll(err);
1179
- }
1180
- })();
1181
- });
1182
- await triggerOnReady();
1183
- } catch (err) {
1184
- if (isRedirect(err) || isNotFound(err)) {
1185
- if (isNotFound(err) && !allPreload) {
1186
- await triggerOnReady();
1187
- }
1188
- throw err;
1189
- }
1190
- }
1191
- return matches;
1192
- };
1193
716
  this.invalidate = (opts) => {
1194
717
  const invalidate = (d) => {
1195
718
  if (opts?.filter?.(d) ?? true) {
1196
719
  return {
1197
720
  ...d,
1198
721
  invalid: true,
1199
- ...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : {}
722
+ ...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : void 0
1200
723
  };
1201
724
  }
1202
725
  return d;
@@ -1254,31 +777,7 @@ class RouterCore {
1254
777
  };
1255
778
  this.clearCache({ filter });
1256
779
  };
1257
- this.loadRouteChunk = (route) => {
1258
- if (route._lazyPromise === void 0) {
1259
- if (route.lazyFn) {
1260
- route._lazyPromise = route.lazyFn().then((lazyRoute) => {
1261
- const { id: _id, ...options2 } = lazyRoute.options;
1262
- Object.assign(route.options, options2);
1263
- });
1264
- } else {
1265
- route._lazyPromise = Promise.resolve();
1266
- }
1267
- }
1268
- if (route._componentsPromise === void 0) {
1269
- route._componentsPromise = route._lazyPromise.then(
1270
- () => Promise.all(
1271
- componentTypes.map(async (type) => {
1272
- const component = route.options[type];
1273
- if (component?.preload) {
1274
- await component.preload();
1275
- }
1276
- })
1277
- )
1278
- );
1279
- }
1280
- return route._componentsPromise;
1281
- };
780
+ this.loadRouteChunk = loadRouteChunk;
1282
781
  this.preloadRoute = async (opts) => {
1283
782
  const next = this.buildLocation(opts);
1284
783
  let matches = this.matchRoutes(next, {
@@ -1306,7 +805,8 @@ class RouterCore {
1306
805
  });
1307
806
  });
1308
807
  try {
1309
- matches = await this.loadMatches({
808
+ matches = await loadMatches({
809
+ router: this,
1310
810
  matches,
1311
811
  location: next,
1312
812
  preload: true,
@@ -1352,7 +852,6 @@ class RouterCore {
1352
852
  const pending = opts?.pending === void 0 ? !this.state.isLoading : opts.pending;
1353
853
  const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
1354
854
  const match = matchPathname(
1355
- this.basepath,
1356
855
  baseLocation.pathname,
1357
856
  {
1358
857
  ...opts,
@@ -1373,39 +872,6 @@ class RouterCore {
1373
872
  }
1374
873
  return match;
1375
874
  };
1376
- this._handleNotFound = (matches, err, {
1377
- updateMatch = this.updateMatch
1378
- } = {}) => {
1379
- const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
1380
- const matchesByRouteId = {};
1381
- for (const match of matches) {
1382
- matchesByRouteId[match.routeId] = match;
1383
- }
1384
- if (!routeCursor.options.notFoundComponent && this.options?.defaultNotFoundComponent) {
1385
- routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
1386
- }
1387
- invariant(
1388
- routeCursor.options.notFoundComponent,
1389
- "No notFoundComponent found. Please set a notFoundComponent on your route or provide a defaultNotFoundComponent to the router."
1390
- );
1391
- const matchForRoute = matchesByRouteId[routeCursor.id];
1392
- invariant(
1393
- matchForRoute,
1394
- "Could not find match for route: " + routeCursor.id
1395
- );
1396
- updateMatch(matchForRoute.id, (prev) => ({
1397
- ...prev,
1398
- status: "notFound",
1399
- error: err,
1400
- isFetching: false
1401
- }));
1402
- if (err.routerCode === "BEFORE_LOAD" && routeCursor.parentRoute) {
1403
- err.routeId = routeCursor.parentRoute.id;
1404
- this._handleNotFound(matches, err, {
1405
- updateMatch
1406
- });
1407
- }
1408
- };
1409
875
  this.hasNotFoundMatch = () => {
1410
876
  return this.__store.state.matches.some(
1411
877
  (d) => d.status === "notFound" || d.globalNotFound
@@ -1493,16 +959,16 @@ class RouterCore {
1493
959
  const matches = [];
1494
960
  const getParentContext = (parentMatch) => {
1495
961
  const parentMatchId = parentMatch?.id;
1496
- const parentContext = !parentMatchId ? this.options.context ?? {} : parentMatch.context ?? this.options.context ?? {};
962
+ const parentContext = !parentMatchId ? this.options.context ?? void 0 : parentMatch.context ?? this.options.context ?? void 0;
1497
963
  return parentContext;
1498
964
  };
1499
965
  matchedRoutes.forEach((route, index) => {
1500
966
  const parentMatch = matches[index - 1];
1501
967
  const [preMatchSearch, strictMatchSearch, searchError] = (() => {
1502
968
  const parentSearch = parentMatch?.search ?? next.search;
1503
- const parentStrictSearch = parentMatch?._strictSearch ?? {};
969
+ const parentStrictSearch = parentMatch?._strictSearch ?? void 0;
1504
970
  try {
1505
- const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? {};
971
+ const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? void 0;
1506
972
  return [
1507
973
  {
1508
974
  ...parentSearch,
@@ -1563,7 +1029,7 @@ class RouterCore {
1563
1029
  routeId: route.id,
1564
1030
  params: previousMatch ? replaceEqualDeep(previousMatch.params, routeParams) : routeParams,
1565
1031
  _strictParams: usedParams,
1566
- pathname: joinPaths([this.basepath, interpolatedPath]),
1032
+ pathname: interpolatedPath,
1567
1033
  updatedAt: Date.now(),
1568
1034
  search: previousMatch ? replaceEqualDeep(previousMatch.search, preMatchSearch) : preMatchSearch,
1569
1035
  _strictSearch: strictMatchSearch,
@@ -1572,7 +1038,10 @@ class RouterCore {
1572
1038
  isFetching: false,
1573
1039
  error: void 0,
1574
1040
  paramsError: parseErrors[index],
1575
- __routeContext: {},
1041
+ __routeContext: void 0,
1042
+ _nonReactive: {
1043
+ loadPromise: createControlledPromise()
1044
+ },
1576
1045
  __beforeLoadContext: void 0,
1577
1046
  context: {},
1578
1047
  abortController: new AbortController(),
@@ -1586,7 +1055,6 @@ class RouterCore {
1586
1055
  headScripts: void 0,
1587
1056
  meta: void 0,
1588
1057
  staticData: route.options.staticData || {},
1589
- loadPromise: createControlledPromise(),
1590
1058
  fullPath: route.fullPath
1591
1059
  };
1592
1060
  }
@@ -1608,19 +1076,21 @@ class RouterCore {
1608
1076
  if (!existingMatch && opts?._buildLocation !== true) {
1609
1077
  const parentMatch = matches[index - 1];
1610
1078
  const parentContext = getParentContext(parentMatch);
1611
- const contextFnContext = {
1612
- deps: match.loaderDeps,
1613
- params: match.params,
1614
- context: parentContext,
1615
- location: next,
1616
- navigate: (opts2) => this.navigate({ ...opts2, _fromLocation: next }),
1617
- buildLocation: this.buildLocation,
1618
- cause: match.cause,
1619
- abortController: match.abortController,
1620
- preload: !!match.preload,
1621
- matches
1622
- };
1623
- match.__routeContext = route.options.context?.(contextFnContext) ?? {};
1079
+ if (route.options.context) {
1080
+ const contextFnContext = {
1081
+ deps: match.loaderDeps,
1082
+ params: match.params,
1083
+ context: parentContext ?? {},
1084
+ location: next,
1085
+ navigate: (opts2) => this.navigate({ ...opts2, _fromLocation: next }),
1086
+ buildLocation: this.buildLocation,
1087
+ cause: match.cause,
1088
+ abortController: match.abortController,
1089
+ preload: !!match.preload,
1090
+ matches
1091
+ };
1092
+ match.__routeContext = route.options.context(contextFnContext) ?? void 0;
1093
+ }
1624
1094
  match.context = {
1625
1095
  ...parentContext,
1626
1096
  ...match.__routeContext,
@@ -1679,20 +1149,6 @@ function validateSearch(validateSearch2, input) {
1679
1149
  }
1680
1150
  return {};
1681
1151
  }
1682
- const componentTypes = [
1683
- "component",
1684
- "errorComponent",
1685
- "pendingComponent",
1686
- "notFoundComponent"
1687
- ];
1688
- function routeNeedsPreload(route) {
1689
- for (const componentType of componentTypes) {
1690
- if (route.options[componentType]?.preload) {
1691
- return true;
1692
- }
1693
- }
1694
- return false;
1695
- }
1696
1152
  const REQUIRED_PARAM_BASE_SCORE = 0.5;
1697
1153
  const OPTIONAL_PARAM_BASE_SCORE = 0.4;
1698
1154
  const WILDCARD_PARAM_BASE_SCORE = 0.25;
@@ -1825,7 +1281,6 @@ function processRouteTree({
1825
1281
  function getMatchedRoutes({
1826
1282
  pathname,
1827
1283
  routePathname,
1828
- basepath,
1829
1284
  caseSensitive,
1830
1285
  routesByPath,
1831
1286
  routesById,
@@ -1836,7 +1291,6 @@ function getMatchedRoutes({
1836
1291
  const trimmedPath = trimPathRight(pathname);
1837
1292
  const getMatchedParams = (route) => {
1838
1293
  const result = matchPathname(
1839
- basepath,
1840
1294
  trimmedPath,
1841
1295
  {
1842
1296
  to: route.fullPath,
@@ -1923,7 +1377,7 @@ function applySearchMiddleware({
1923
1377
  try {
1924
1378
  const validatedSearch = {
1925
1379
  ...result,
1926
- ...validateSearch(route.options.validateSearch, result) ?? {}
1380
+ ...validateSearch(route.options.validateSearch, result) ?? void 0
1927
1381
  };
1928
1382
  return validatedSearch;
1929
1383
  } catch {
@@ -1962,7 +1416,6 @@ export {
1962
1416
  PathParamError,
1963
1417
  RouterCore,
1964
1418
  SearchParamError,
1965
- componentTypes,
1966
1419
  defaultSerializeError,
1967
1420
  getInitialRouterState,
1968
1421
  getLocationChangeInfo,