@tanstack/router-core 1.132.0-alpha.0 → 1.132.0-alpha.12

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 (128) 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 +10 -2
  8. package/dist/cjs/index.cjs.map +1 -1
  9. package/dist/cjs/index.d.cts +8 -3
  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/qss.cjs +19 -19
  14. package/dist/cjs/qss.cjs.map +1 -1
  15. package/dist/cjs/qss.d.cts +6 -4
  16. package/dist/cjs/redirect.cjs +3 -3
  17. package/dist/cjs/redirect.cjs.map +1 -1
  18. package/dist/cjs/route.cjs.map +1 -1
  19. package/dist/cjs/route.d.cts +42 -41
  20. package/dist/cjs/router.cjs +85 -654
  21. package/dist/cjs/router.cjs.map +1 -1
  22. package/dist/cjs/router.d.cts +19 -23
  23. package/dist/cjs/scroll-restoration.cjs +32 -29
  24. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  25. package/dist/cjs/scroll-restoration.d.cts +1 -10
  26. package/dist/cjs/searchParams.cjs +7 -15
  27. package/dist/cjs/searchParams.cjs.map +1 -1
  28. package/dist/cjs/ssr/constants.cjs +5 -0
  29. package/dist/cjs/ssr/constants.cjs.map +1 -0
  30. package/dist/cjs/ssr/constants.d.cts +1 -0
  31. package/dist/cjs/ssr/{seroval-plugins.cjs → serializer/ShallowErrorPlugin.cjs} +2 -2
  32. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -0
  33. package/dist/cjs/ssr/{seroval-plugins.d.cts → serializer/ShallowErrorPlugin.d.cts} +1 -2
  34. package/dist/cjs/ssr/serializer/seroval-plugins.cjs +11 -0
  35. package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -0
  36. package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -0
  37. package/dist/cjs/ssr/serializer/transformer.cjs +52 -0
  38. package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -0
  39. package/dist/cjs/ssr/serializer/transformer.d.cts +56 -0
  40. package/dist/cjs/ssr/server.d.cts +5 -0
  41. package/dist/cjs/ssr/ssr-client.cjs +53 -40
  42. package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
  43. package/dist/cjs/ssr/ssr-client.d.cts +5 -1
  44. package/dist/cjs/ssr/ssr-server.cjs +12 -10
  45. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  46. package/dist/cjs/ssr/ssr-server.d.cts +0 -1
  47. package/dist/cjs/ssr/tsrScript.cjs +1 -1
  48. package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
  49. package/dist/cjs/typePrimitives.d.cts +6 -6
  50. package/dist/cjs/utils.cjs +14 -7
  51. package/dist/cjs/utils.cjs.map +1 -1
  52. package/dist/cjs/utils.d.cts +2 -1
  53. package/dist/esm/Matches.d.ts +9 -11
  54. package/dist/esm/Matches.js.map +1 -1
  55. package/dist/esm/config.d.ts +17 -0
  56. package/dist/esm/config.js +10 -0
  57. package/dist/esm/config.js.map +1 -0
  58. package/dist/esm/fileRoute.d.ts +3 -2
  59. package/dist/esm/index.d.ts +8 -3
  60. package/dist/esm/index.js +11 -3
  61. package/dist/esm/index.js.map +1 -1
  62. package/dist/esm/load-matches.d.ts +16 -0
  63. package/dist/esm/load-matches.js +636 -0
  64. package/dist/esm/load-matches.js.map +1 -0
  65. package/dist/esm/qss.d.ts +6 -4
  66. package/dist/esm/qss.js +19 -19
  67. package/dist/esm/qss.js.map +1 -1
  68. package/dist/esm/redirect.js +3 -3
  69. package/dist/esm/redirect.js.map +1 -1
  70. package/dist/esm/route.d.ts +42 -41
  71. package/dist/esm/route.js.map +1 -1
  72. package/dist/esm/router.d.ts +19 -23
  73. package/dist/esm/router.js +85 -654
  74. package/dist/esm/router.js.map +1 -1
  75. package/dist/esm/scroll-restoration.d.ts +1 -10
  76. package/dist/esm/scroll-restoration.js +32 -29
  77. package/dist/esm/scroll-restoration.js.map +1 -1
  78. package/dist/esm/searchParams.js +7 -15
  79. package/dist/esm/searchParams.js.map +1 -1
  80. package/dist/esm/ssr/constants.d.ts +1 -0
  81. package/dist/esm/ssr/constants.js +5 -0
  82. package/dist/esm/ssr/constants.js.map +1 -0
  83. package/dist/esm/ssr/{seroval-plugins.d.ts → serializer/ShallowErrorPlugin.d.ts} +1 -2
  84. package/dist/esm/ssr/{seroval-plugins.js → serializer/ShallowErrorPlugin.js} +2 -2
  85. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -0
  86. package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -0
  87. package/dist/esm/ssr/serializer/seroval-plugins.js +11 -0
  88. package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -0
  89. package/dist/esm/ssr/serializer/transformer.d.ts +56 -0
  90. package/dist/esm/ssr/serializer/transformer.js +52 -0
  91. package/dist/esm/ssr/serializer/transformer.js.map +1 -0
  92. package/dist/esm/ssr/server.d.ts +5 -0
  93. package/dist/esm/ssr/ssr-client.d.ts +5 -1
  94. package/dist/esm/ssr/ssr-client.js +53 -40
  95. package/dist/esm/ssr/ssr-client.js.map +1 -1
  96. package/dist/esm/ssr/ssr-server.d.ts +0 -1
  97. package/dist/esm/ssr/ssr-server.js +12 -10
  98. package/dist/esm/ssr/ssr-server.js.map +1 -1
  99. package/dist/esm/ssr/tsrScript.js +1 -1
  100. package/dist/esm/ssr/tsrScript.js.map +1 -1
  101. package/dist/esm/typePrimitives.d.ts +6 -6
  102. package/dist/esm/utils.d.ts +2 -1
  103. package/dist/esm/utils.js +14 -7
  104. package/dist/esm/utils.js.map +1 -1
  105. package/package.json +2 -2
  106. package/src/Matches.ts +18 -10
  107. package/src/config.ts +42 -0
  108. package/src/fileRoute.ts +15 -3
  109. package/src/index.ts +24 -2
  110. package/src/load-matches.ts +955 -0
  111. package/src/qss.ts +27 -24
  112. package/src/redirect.ts +3 -3
  113. package/src/route.ts +146 -35
  114. package/src/router.ts +135 -925
  115. package/src/scroll-restoration.ts +42 -37
  116. package/src/searchParams.ts +8 -19
  117. package/src/ssr/constants.ts +1 -0
  118. package/src/ssr/{seroval-plugins.ts → serializer/ShallowErrorPlugin.ts} +2 -2
  119. package/src/ssr/serializer/seroval-plugins.ts +9 -0
  120. package/src/ssr/serializer/transformer.ts +215 -0
  121. package/src/ssr/server.ts +6 -0
  122. package/src/ssr/ssr-client.ts +72 -44
  123. package/src/ssr/ssr-server.ts +18 -10
  124. package/src/ssr/tsrScript.ts +5 -1
  125. package/src/typePrimitives.ts +6 -6
  126. package/src/utils.ts +21 -10
  127. package/dist/cjs/ssr/seroval-plugins.cjs.map +0 -1
  128. package/dist/esm/ssr/seroval-plugins.js.map +0 -1
@@ -11,6 +11,7 @@ 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");
14
15
  function defaultSerializeError(err) {
15
16
  if (err instanceof Error) {
16
17
  const obj = {
@@ -78,7 +79,7 @@ class RouterCore {
78
79
  this.history = this.options.history ?? (this.isServer ? history.createMemoryHistory({
79
80
  initialEntries: [this.basepath || "/"]
80
81
  }) : history.createBrowserHistory());
81
- this.latestLocation = this.parseLocation();
82
+ this.updateLatestLocation();
82
83
  }
83
84
  if (this.options.routeTree !== this.routeTree) {
84
85
  this.routeTree = this.options.routeTree;
@@ -103,6 +104,12 @@ class RouterCore {
103
104
  );
104
105
  }
105
106
  };
107
+ this.updateLatestLocation = () => {
108
+ this.latestLocation = this.parseLocation(
109
+ this.history.location,
110
+ this.latestLocation
111
+ );
112
+ };
106
113
  this.buildRouteTree = () => {
107
114
  const { routesById, routesByPath, flatRoutes } = processRouteTree({
108
115
  routeTree: this.routeTree,
@@ -140,7 +147,7 @@ class RouterCore {
140
147
  }
141
148
  });
142
149
  };
143
- this.parseLocation = (previousLocation, locationToParse) => {
150
+ this.parseLocation = (locationToParse, previousLocation) => {
144
151
  const parse = ({
145
152
  pathname,
146
153
  search,
@@ -158,7 +165,7 @@ class RouterCore {
158
165
  state: utils.replaceEqualDeep(previousLocation?.state, state)
159
166
  };
160
167
  };
161
- const location = parse(locationToParse ?? this.history.location);
168
+ const location = parse(locationToParse);
162
169
  const { __tempLocation, __tempKey } = location.state;
163
170
  if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
164
171
  const parsedTempLocation = parse(__tempLocation);
@@ -212,13 +219,8 @@ class RouterCore {
212
219
  const match = this.getMatch(id);
213
220
  if (!match) return;
214
221
  match.abortController.abort();
215
- this.updateMatch(id, (prev) => {
216
- clearTimeout(prev.pendingTimeout);
217
- return {
218
- ...prev,
219
- pendingTimeout: void 0
220
- };
221
- });
222
+ clearTimeout(match._nonReactive.pendingTimeout);
223
+ match._nonReactive.pendingTimeout = void 0;
222
224
  };
223
225
  this.cancelMatches = () => {
224
226
  this.state.pendingMatches?.forEach((match) => {
@@ -232,60 +234,51 @@ class RouterCore {
232
234
  _buildLocation: true
233
235
  });
234
236
  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
- }
237
+ if (dest.from && process.env.NODE_ENV !== "production" && dest._isNavigate) {
238
+ const allFromMatches = this.getMatchedRoutes(
239
+ dest.from,
240
+ void 0
241
+ ).matchedRoutes;
242
+ const matchedFrom = utils.findLast(allCurrentLocationMatches, (d) => {
243
+ return comparePaths(d.fullPath, dest.from);
244
+ });
245
+ const matchedCurrent = utils.findLast(allFromMatches, (d) => {
246
+ return comparePaths(d.fullPath, lastMatch.fullPath);
247
+ });
248
+ if (!matchedFrom && !matchedCurrent) {
249
+ console.warn(`Could not find match for from: ${dest.from}`);
256
250
  }
257
251
  }
252
+ const defaultedFromPath = dest.unsafeRelative === "path" ? currentLocation.pathname : dest.from ?? lastMatch.fullPath;
253
+ const fromPath = this.resolvePathWithBase(defaultedFromPath, ".");
258
254
  const fromSearch = lastMatch.search;
259
255
  const fromParams = { ...lastMatch.params };
260
256
  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
- };
257
+ const nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : Object.assign(
258
+ fromParams,
259
+ utils.functionalUpdate(dest.params, fromParams)
260
+ );
265
261
  const interpolatedNextTo = path.interpolatePath({
266
262
  path: nextTo,
267
- params: nextParams ?? {},
263
+ params: nextParams,
268
264
  parseCache: this.parsePathnameCache
269
265
  }).interpolatedPath;
270
- const destRoutes = this.matchRoutes(
271
- interpolatedNextTo,
272
- {},
273
- {
274
- _buildLocation: true
275
- }
276
- ).map((d) => this.looseRoutesById[d.routeId]);
266
+ const destRoutes = this.matchRoutes(interpolatedNextTo, void 0, {
267
+ _buildLocation: true
268
+ }).map((d) => this.looseRoutesById[d.routeId]);
277
269
  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
- });
270
+ for (const route of destRoutes) {
271
+ const fn = route.options.params?.stringify ?? route.options.stringifyParams;
272
+ if (fn) {
273
+ Object.assign(nextParams, fn(nextParams));
274
+ }
275
+ }
283
276
  }
284
277
  const nextPathname = path.interpolatePath({
285
278
  // Use the original template path for interpolation
286
279
  // This preserves the original parameter syntax including optional parameters
287
280
  path: nextTo,
288
- params: nextParams ?? {},
281
+ params: nextParams,
289
282
  leaveWildcards: false,
290
283
  leaveParams: opts.leaveParams,
291
284
  decodeCharMap: this.pathParamsDecodeCharMap,
@@ -293,19 +286,19 @@ class RouterCore {
293
286
  }).interpolatedPath;
294
287
  let nextSearch = fromSearch;
295
288
  if (opts._includeValidateSearch && this.options.search?.strict) {
296
- let validatedSearch = {};
289
+ const validatedSearch = {};
297
290
  destRoutes.forEach((route) => {
298
- try {
299
- if (route.options.validateSearch) {
300
- validatedSearch = {
301
- ...validatedSearch,
302
- ...validateSearch(route.options.validateSearch, {
291
+ if (route.options.validateSearch) {
292
+ try {
293
+ Object.assign(
294
+ validatedSearch,
295
+ validateSearch(route.options.validateSearch, {
303
296
  ...validatedSearch,
304
297
  ...nextSearch
305
- }) ?? {}
306
- };
298
+ })
299
+ );
300
+ } catch {
307
301
  }
308
- } catch {
309
302
  }
310
303
  });
311
304
  nextSearch = validatedSearch;
@@ -357,7 +350,7 @@ class RouterCore {
357
350
  if (foundMask) {
358
351
  const { from: _from, ...maskProps } = foundMask;
359
352
  maskedDest = {
360
- ...utils.pick(opts, ["from"]),
353
+ from: opts.from,
361
354
  ...maskProps,
362
355
  params
363
356
  };
@@ -372,7 +365,7 @@ class RouterCore {
372
365
  };
373
366
  if (opts.mask) {
374
367
  return buildWithMatches(opts, {
375
- ...utils.pick(opts, ["from"]),
368
+ from: opts.from,
376
369
  ...opts.mask
377
370
  });
378
371
  }
@@ -507,7 +500,7 @@ class RouterCore {
507
500
  };
508
501
  this.beforeLoad = () => {
509
502
  this.cancelMatches();
510
- this.latestLocation = this.parseLocation(this.latestLocation);
503
+ this.updateLatestLocation();
511
504
  if (this.isServer) {
512
505
  const nextLocation = this.buildLocation({
513
506
  to: this.latestLocation.pathname,
@@ -568,10 +561,12 @@ class RouterCore {
568
561
  location: next
569
562
  })
570
563
  });
571
- await this.loadMatches({
564
+ await loadMatches.loadMatches({
565
+ router: this,
572
566
  sync: opts?.sync,
573
567
  matches: this.state.pendingMatches,
574
568
  location: next,
569
+ updateMatch: this.updateMatch,
575
570
  // eslint-disable-next-line @typescript-eslint/require-await
576
571
  onReady: async () => {
577
572
  this.startViewTransition(async () => {
@@ -695,510 +690,13 @@ class RouterCore {
695
690
  const findFn = (d) => d.id === matchId;
696
691
  return this.state.cachedMatches.find(findFn) ?? this.state.pendingMatches?.find(findFn) ?? this.state.matches.find(findFn);
697
692
  };
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
693
  this.invalidate = (opts) => {
1196
694
  const invalidate = (d) => {
1197
695
  if (opts?.filter?.(d) ?? true) {
1198
696
  return {
1199
697
  ...d,
1200
698
  invalid: true,
1201
- ...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : {}
699
+ ...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : void 0
1202
700
  };
1203
701
  }
1204
702
  return d;
@@ -1256,31 +754,7 @@ class RouterCore {
1256
754
  };
1257
755
  this.clearCache({ filter });
1258
756
  };
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
- };
757
+ this.loadRouteChunk = loadMatches.loadRouteChunk;
1284
758
  this.preloadRoute = async (opts) => {
1285
759
  const next = this.buildLocation(opts);
1286
760
  let matches = this.matchRoutes(next, {
@@ -1308,7 +782,8 @@ class RouterCore {
1308
782
  });
1309
783
  });
1310
784
  try {
1311
- matches = await this.loadMatches({
785
+ matches = await loadMatches.loadMatches({
786
+ router: this,
1312
787
  matches,
1313
788
  location: next,
1314
789
  preload: true,
@@ -1375,39 +850,6 @@ class RouterCore {
1375
850
  }
1376
851
  return match;
1377
852
  };
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
853
  this.hasNotFoundMatch = () => {
1412
854
  return this.__store.state.matches.some(
1413
855
  (d) => d.status === "notFound" || d.globalNotFound
@@ -1495,16 +937,16 @@ class RouterCore {
1495
937
  const matches = [];
1496
938
  const getParentContext = (parentMatch) => {
1497
939
  const parentMatchId = parentMatch?.id;
1498
- const parentContext = !parentMatchId ? this.options.context ?? {} : parentMatch.context ?? this.options.context ?? {};
940
+ const parentContext = !parentMatchId ? this.options.context ?? void 0 : parentMatch.context ?? this.options.context ?? void 0;
1499
941
  return parentContext;
1500
942
  };
1501
943
  matchedRoutes.forEach((route, index) => {
1502
944
  const parentMatch = matches[index - 1];
1503
945
  const [preMatchSearch, strictMatchSearch, searchError] = (() => {
1504
946
  const parentSearch = parentMatch?.search ?? next.search;
1505
- const parentStrictSearch = parentMatch?._strictSearch ?? {};
947
+ const parentStrictSearch = parentMatch?._strictSearch ?? void 0;
1506
948
  try {
1507
- const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? {};
949
+ const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? void 0;
1508
950
  return [
1509
951
  {
1510
952
  ...parentSearch,
@@ -1558,7 +1000,7 @@ class RouterCore {
1558
1000
  _strictSearch: strictMatchSearch
1559
1001
  };
1560
1002
  } else {
1561
- const status = route.options.loader || route.options.beforeLoad || route.lazyFn || routeNeedsPreload(route) ? "pending" : "success";
1003
+ const status = route.options.loader || route.options.beforeLoad || route.lazyFn || loadMatches.routeNeedsPreload(route) ? "pending" : "success";
1562
1004
  match = {
1563
1005
  id: matchId,
1564
1006
  index,
@@ -1574,7 +1016,10 @@ class RouterCore {
1574
1016
  isFetching: false,
1575
1017
  error: void 0,
1576
1018
  paramsError: parseErrors[index],
1577
- __routeContext: {},
1019
+ __routeContext: void 0,
1020
+ _nonReactive: {
1021
+ loadPromise: utils.createControlledPromise()
1022
+ },
1578
1023
  __beforeLoadContext: void 0,
1579
1024
  context: {},
1580
1025
  abortController: new AbortController(),
@@ -1588,7 +1033,6 @@ class RouterCore {
1588
1033
  headScripts: void 0,
1589
1034
  meta: void 0,
1590
1035
  staticData: route.options.staticData || {},
1591
- loadPromise: utils.createControlledPromise(),
1592
1036
  fullPath: route.fullPath
1593
1037
  };
1594
1038
  }
@@ -1610,19 +1054,21 @@ class RouterCore {
1610
1054
  if (!existingMatch && opts?._buildLocation !== true) {
1611
1055
  const parentMatch = matches[index - 1];
1612
1056
  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) ?? {};
1057
+ if (route.options.context) {
1058
+ const contextFnContext = {
1059
+ deps: match.loaderDeps,
1060
+ params: match.params,
1061
+ context: parentContext ?? {},
1062
+ location: next,
1063
+ navigate: (opts2) => this.navigate({ ...opts2, _fromLocation: next }),
1064
+ buildLocation: this.buildLocation,
1065
+ cause: match.cause,
1066
+ abortController: match.abortController,
1067
+ preload: !!match.preload,
1068
+ matches
1069
+ };
1070
+ match.__routeContext = route.options.context(contextFnContext) ?? void 0;
1071
+ }
1626
1072
  match.context = {
1627
1073
  ...parentContext,
1628
1074
  ...match.__routeContext,
@@ -1681,20 +1127,6 @@ function validateSearch(validateSearch2, input) {
1681
1127
  }
1682
1128
  return {};
1683
1129
  }
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
1130
  const REQUIRED_PARAM_BASE_SCORE = 0.5;
1699
1131
  const OPTIONAL_PARAM_BASE_SCORE = 0.4;
1700
1132
  const WILDCARD_PARAM_BASE_SCORE = 0.25;
@@ -1925,7 +1357,7 @@ function applySearchMiddleware({
1925
1357
  try {
1926
1358
  const validatedSearch = {
1927
1359
  ...result,
1928
- ...validateSearch(route.options.validateSearch, result) ?? {}
1360
+ ...validateSearch(route.options.validateSearch, result) ?? void 0
1929
1361
  };
1930
1362
  return validatedSearch;
1931
1363
  } catch {
@@ -1963,7 +1395,6 @@ function applySearchMiddleware({
1963
1395
  exports.PathParamError = PathParamError;
1964
1396
  exports.RouterCore = RouterCore;
1965
1397
  exports.SearchParamError = SearchParamError;
1966
- exports.componentTypes = componentTypes;
1967
1398
  exports.defaultSerializeError = defaultSerializeError;
1968
1399
  exports.getInitialRouterState = getInitialRouterState;
1969
1400
  exports.getLocationChangeInfo = getLocationChangeInfo;