@tanstack/router-core 1.132.0-alpha.2 → 1.132.0-alpha.4

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 (102) hide show
  1. package/dist/cjs/index.cjs +8 -2
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.d.cts +6 -2
  4. package/dist/cjs/load-matches.cjs +636 -0
  5. package/dist/cjs/load-matches.cjs.map +1 -0
  6. package/dist/cjs/load-matches.d.cts +16 -0
  7. package/dist/cjs/qss.cjs +19 -19
  8. package/dist/cjs/qss.cjs.map +1 -1
  9. package/dist/cjs/qss.d.cts +6 -4
  10. package/dist/cjs/redirect.cjs +3 -3
  11. package/dist/cjs/redirect.cjs.map +1 -1
  12. package/dist/cjs/router.cjs +33 -702
  13. package/dist/cjs/router.cjs.map +1 -1
  14. package/dist/cjs/router.d.cts +18 -39
  15. package/dist/cjs/scroll-restoration.cjs +32 -29
  16. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  17. package/dist/cjs/scroll-restoration.d.cts +1 -1
  18. package/dist/cjs/searchParams.cjs +7 -15
  19. package/dist/cjs/searchParams.cjs.map +1 -1
  20. package/dist/cjs/ssr/constants.cjs +5 -0
  21. package/dist/cjs/ssr/constants.cjs.map +1 -0
  22. package/dist/cjs/ssr/constants.d.cts +1 -0
  23. package/dist/cjs/ssr/{seroval-plugins.cjs → serializer/ShallowErrorPlugin.cjs} +2 -2
  24. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -0
  25. package/dist/cjs/ssr/{seroval-plugins.d.cts → serializer/ShallowErrorPlugin.d.cts} +1 -2
  26. package/dist/cjs/ssr/serializer/seroval-plugins.cjs +11 -0
  27. package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -0
  28. package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -0
  29. package/dist/cjs/ssr/serializer/transformer.cjs +50 -0
  30. package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -0
  31. package/dist/cjs/ssr/serializer/transformer.d.cts +18 -0
  32. package/dist/cjs/ssr/ssr-client.cjs +15 -1
  33. package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
  34. package/dist/cjs/ssr/ssr-client.d.cts +5 -1
  35. package/dist/cjs/ssr/ssr-server.cjs +12 -10
  36. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  37. package/dist/cjs/ssr/ssr-server.d.cts +0 -1
  38. package/dist/cjs/ssr/tsrScript.cjs +1 -1
  39. package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
  40. package/dist/cjs/utils.cjs +8 -7
  41. package/dist/cjs/utils.cjs.map +1 -1
  42. package/dist/cjs/utils.d.cts +1 -1
  43. package/dist/esm/index.d.ts +6 -2
  44. package/dist/esm/index.js +9 -3
  45. package/dist/esm/index.js.map +1 -1
  46. package/dist/esm/load-matches.d.ts +16 -0
  47. package/dist/esm/load-matches.js +636 -0
  48. package/dist/esm/load-matches.js.map +1 -0
  49. package/dist/esm/qss.d.ts +6 -4
  50. package/dist/esm/qss.js +19 -19
  51. package/dist/esm/qss.js.map +1 -1
  52. package/dist/esm/redirect.js +3 -3
  53. package/dist/esm/redirect.js.map +1 -1
  54. package/dist/esm/router.d.ts +18 -39
  55. package/dist/esm/router.js +33 -702
  56. package/dist/esm/router.js.map +1 -1
  57. package/dist/esm/scroll-restoration.d.ts +1 -1
  58. package/dist/esm/scroll-restoration.js +32 -29
  59. package/dist/esm/scroll-restoration.js.map +1 -1
  60. package/dist/esm/searchParams.js +7 -15
  61. package/dist/esm/searchParams.js.map +1 -1
  62. package/dist/esm/ssr/constants.d.ts +1 -0
  63. package/dist/esm/ssr/constants.js +5 -0
  64. package/dist/esm/ssr/constants.js.map +1 -0
  65. package/dist/esm/ssr/{seroval-plugins.d.ts → serializer/ShallowErrorPlugin.d.ts} +1 -2
  66. package/dist/esm/ssr/{seroval-plugins.js → serializer/ShallowErrorPlugin.js} +2 -2
  67. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -0
  68. package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -0
  69. package/dist/esm/ssr/serializer/seroval-plugins.js +11 -0
  70. package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -0
  71. package/dist/esm/ssr/serializer/transformer.d.ts +18 -0
  72. package/dist/esm/ssr/serializer/transformer.js +50 -0
  73. package/dist/esm/ssr/serializer/transformer.js.map +1 -0
  74. package/dist/esm/ssr/ssr-client.d.ts +5 -1
  75. package/dist/esm/ssr/ssr-client.js +15 -1
  76. package/dist/esm/ssr/ssr-client.js.map +1 -1
  77. package/dist/esm/ssr/ssr-server.d.ts +0 -1
  78. package/dist/esm/ssr/ssr-server.js +12 -10
  79. package/dist/esm/ssr/ssr-server.js.map +1 -1
  80. package/dist/esm/ssr/tsrScript.js +1 -1
  81. package/dist/esm/ssr/tsrScript.js.map +1 -1
  82. package/dist/esm/utils.d.ts +1 -1
  83. package/dist/esm/utils.js +8 -7
  84. package/dist/esm/utils.js.map +1 -1
  85. package/package.json +1 -1
  86. package/src/index.ts +12 -2
  87. package/src/load-matches.ts +955 -0
  88. package/src/qss.ts +27 -24
  89. package/src/redirect.ts +3 -3
  90. package/src/router.ts +66 -1050
  91. package/src/scroll-restoration.ts +42 -37
  92. package/src/searchParams.ts +8 -19
  93. package/src/ssr/constants.ts +1 -0
  94. package/src/ssr/{seroval-plugins.ts → serializer/ShallowErrorPlugin.ts} +2 -2
  95. package/src/ssr/serializer/seroval-plugins.ts +9 -0
  96. package/src/ssr/serializer/transformer.ts +78 -0
  97. package/src/ssr/ssr-client.ts +30 -3
  98. package/src/ssr/ssr-server.ts +18 -10
  99. package/src/ssr/tsrScript.ts +5 -1
  100. package/src/utils.ts +11 -10
  101. package/dist/cjs/ssr/seroval-plugins.cjs.map +0 -1
  102. package/dist/esm/ssr/seroval-plugins.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { Store, batch } from "@tanstack/store";
2
2
  import { createMemoryHistory, createBrowserHistory, parseHref } from "@tanstack/history";
3
3
  import invariant from "tiny-invariant";
4
- import { pick, createControlledPromise, isPromise, deepEqual, replaceEqualDeep, last, functionalUpdate } from "./utils.js";
4
+ import { createControlledPromise, deepEqual, replaceEqualDeep, last, findLast, functionalUpdate } from "./utils.js";
5
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";
6
6
  import { isNotFound } from "./not-found.js";
7
7
  import { setupScrollRestoration } from "./scroll-restoration.js";
@@ -9,6 +9,7 @@ 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";
12
13
  function defaultSerializeError(err) {
13
14
  if (err instanceof Error) {
14
15
  const obj = {
@@ -237,10 +238,10 @@ class RouterCore {
237
238
  dest.from,
238
239
  void 0
239
240
  ).matchedRoutes;
240
- const matchedFrom = [...allCurrentLocationMatches].reverse().find((d) => {
241
+ const matchedFrom = findLast(allCurrentLocationMatches, (d) => {
241
242
  return comparePaths(d.fullPath, fromPath);
242
243
  });
243
- const matchedCurrent = [...allFromMatches].reverse().find((d) => {
244
+ const matchedCurrent = findLast(allFromMatches, (d) => {
244
245
  return comparePaths(d.fullPath, currentLocation.pathname);
245
246
  });
246
247
  if (!matchedFrom && !matchedCurrent) {
@@ -252,30 +253,31 @@ class RouterCore {
252
253
  const fromSearch = lastMatch.search;
253
254
  const fromParams = { ...lastMatch.params };
254
255
  const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
255
- let nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : {
256
- ...fromParams,
257
- ...functionalUpdate(dest.params, fromParams)
258
- };
256
+ const nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : Object.assign(
257
+ fromParams,
258
+ functionalUpdate(dest.params, fromParams)
259
+ );
259
260
  const interpolatedNextTo = interpolatePath({
260
261
  path: nextTo,
261
- params: nextParams ?? {},
262
+ params: nextParams,
262
263
  parseCache: this.parsePathnameCache
263
264
  }).interpolatedPath;
264
265
  const destRoutes = this.matchRoutes(interpolatedNextTo, void 0, {
265
266
  _buildLocation: true
266
267
  }).map((d) => this.looseRoutesById[d.routeId]);
267
268
  if (Object.keys(nextParams).length > 0) {
268
- destRoutes.map((route) => {
269
- return route.options.params?.stringify ?? route.options.stringifyParams;
270
- }).filter(Boolean).forEach((fn) => {
271
- nextParams = { ...nextParams, ...fn(nextParams) };
272
- });
269
+ for (const route of destRoutes) {
270
+ const fn = route.options.params?.stringify ?? route.options.stringifyParams;
271
+ if (fn) {
272
+ Object.assign(nextParams, fn(nextParams));
273
+ }
274
+ }
273
275
  }
274
276
  const nextPathname = interpolatePath({
275
277
  // Use the original template path for interpolation
276
278
  // This preserves the original parameter syntax including optional parameters
277
279
  path: nextTo,
278
- params: nextParams ?? {},
280
+ params: nextParams,
279
281
  leaveWildcards: false,
280
282
  leaveParams: opts.leaveParams,
281
283
  decodeCharMap: this.pathParamsDecodeCharMap,
@@ -283,19 +285,19 @@ class RouterCore {
283
285
  }).interpolatedPath;
284
286
  let nextSearch = fromSearch;
285
287
  if (opts._includeValidateSearch && this.options.search?.strict) {
286
- let validatedSearch = {};
288
+ const validatedSearch = {};
287
289
  destRoutes.forEach((route) => {
288
- try {
289
- if (route.options.validateSearch) {
290
- validatedSearch = {
291
- ...validatedSearch,
292
- ...validateSearch(route.options.validateSearch, {
290
+ if (route.options.validateSearch) {
291
+ try {
292
+ Object.assign(
293
+ validatedSearch,
294
+ validateSearch(route.options.validateSearch, {
293
295
  ...validatedSearch,
294
296
  ...nextSearch
295
- }) ?? {}
296
- };
297
+ })
298
+ );
299
+ } catch {
297
300
  }
298
- } catch {
299
301
  }
300
302
  });
301
303
  nextSearch = validatedSearch;
@@ -347,7 +349,7 @@ class RouterCore {
347
349
  if (foundMask) {
348
350
  const { from: _from, ...maskProps } = foundMask;
349
351
  maskedDest = {
350
- ...pick(opts, ["from"]),
352
+ from: opts.from,
351
353
  ...maskProps,
352
354
  params
353
355
  };
@@ -362,7 +364,7 @@ class RouterCore {
362
364
  };
363
365
  if (opts.mask) {
364
366
  return buildWithMatches(opts, {
365
- ...pick(opts, ["from"]),
367
+ from: opts.from,
366
368
  ...opts.mask
367
369
  });
368
370
  }
@@ -558,10 +560,12 @@ class RouterCore {
558
560
  location: next
559
561
  })
560
562
  });
561
- await this.loadMatches({
563
+ await loadMatches({
564
+ router: this,
562
565
  sync: opts?.sync,
563
566
  matches: this.state.pendingMatches,
564
567
  location: next,
568
+ updateMatch: this.updateMatch,
565
569
  // eslint-disable-next-line @typescript-eslint/require-await
566
570
  onReady: async () => {
567
571
  this.startViewTransition(async () => {
@@ -685,598 +689,6 @@ class RouterCore {
685
689
  const findFn = (d) => d.id === matchId;
686
690
  return this.state.cachedMatches.find(findFn) ?? this.state.pendingMatches?.find(findFn) ?? this.state.matches.find(findFn);
687
691
  };
688
- this.triggerOnReady = (innerLoadContext) => {
689
- if (!innerLoadContext.rendered) {
690
- innerLoadContext.rendered = true;
691
- return innerLoadContext.onReady?.();
692
- }
693
- };
694
- this.resolvePreload = (innerLoadContext, matchId) => {
695
- return !!(innerLoadContext.preload && !this.state.matches.some((d) => d.id === matchId));
696
- };
697
- this.handleRedirectAndNotFound = (innerLoadContext, match, err) => {
698
- if (!isRedirect(err) && !isNotFound(err)) return;
699
- if (isRedirect(err) && err.redirectHandled && !err.options.reloadDocument) {
700
- throw err;
701
- }
702
- if (match) {
703
- match._nonReactive.beforeLoadPromise?.resolve();
704
- match._nonReactive.loaderPromise?.resolve();
705
- match._nonReactive.beforeLoadPromise = void 0;
706
- match._nonReactive.loaderPromise = void 0;
707
- const status = isRedirect(err) ? "redirected" : "notFound";
708
- innerLoadContext.updateMatch(match.id, (prev) => ({
709
- ...prev,
710
- status,
711
- isFetching: false,
712
- error: err
713
- }));
714
- if (isNotFound(err) && !err.routeId) {
715
- err.routeId = match.routeId;
716
- }
717
- match._nonReactive.loadPromise?.resolve();
718
- }
719
- if (isRedirect(err)) {
720
- innerLoadContext.rendered = true;
721
- err.options._fromLocation = innerLoadContext.location;
722
- err.redirectHandled = true;
723
- err = this.resolveRedirect(err);
724
- throw err;
725
- } else {
726
- this._handleNotFound(innerLoadContext, err);
727
- throw err;
728
- }
729
- };
730
- this.shouldSkipLoader = (matchId) => {
731
- const match = this.getMatch(matchId);
732
- if (!this.isServer && match._nonReactive.dehydrated) {
733
- return true;
734
- }
735
- if (this.isServer) {
736
- if (match.ssr === false) {
737
- return true;
738
- }
739
- }
740
- return false;
741
- };
742
- this.handleSerialError = (innerLoadContext, index, err, routerCode) => {
743
- const { id: matchId, routeId } = innerLoadContext.matches[index];
744
- const route = this.looseRoutesById[routeId];
745
- if (err instanceof Promise) {
746
- throw err;
747
- }
748
- err.routerCode = routerCode;
749
- innerLoadContext.firstBadMatchIndex ??= index;
750
- this.handleRedirectAndNotFound(
751
- innerLoadContext,
752
- this.getMatch(matchId),
753
- err
754
- );
755
- try {
756
- route.options.onError?.(err);
757
- } catch (errorHandlerErr) {
758
- err = errorHandlerErr;
759
- this.handleRedirectAndNotFound(
760
- innerLoadContext,
761
- this.getMatch(matchId),
762
- err
763
- );
764
- }
765
- innerLoadContext.updateMatch(matchId, (prev) => {
766
- prev._nonReactive.beforeLoadPromise?.resolve();
767
- prev._nonReactive.beforeLoadPromise = void 0;
768
- prev._nonReactive.loadPromise?.resolve();
769
- return {
770
- ...prev,
771
- error: err,
772
- status: "error",
773
- isFetching: false,
774
- updatedAt: Date.now(),
775
- abortController: new AbortController()
776
- };
777
- });
778
- };
779
- this.isBeforeLoadSsr = (innerLoadContext, matchId, index, route) => {
780
- const existingMatch = this.getMatch(matchId);
781
- const parentMatchId = innerLoadContext.matches[index - 1]?.id;
782
- const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
783
- if (this.isShell()) {
784
- existingMatch.ssr = matchId === rootRouteId;
785
- return;
786
- }
787
- if (parentMatch?.ssr === false) {
788
- existingMatch.ssr = false;
789
- return;
790
- }
791
- const parentOverride = (tempSsr2) => {
792
- if (tempSsr2 === true && parentMatch?.ssr === "data-only") {
793
- return "data-only";
794
- }
795
- return tempSsr2;
796
- };
797
- const defaultSsr = this.options.defaultSsr ?? true;
798
- if (route.options.ssr === void 0) {
799
- existingMatch.ssr = parentOverride(defaultSsr);
800
- return;
801
- }
802
- if (typeof route.options.ssr !== "function") {
803
- existingMatch.ssr = parentOverride(route.options.ssr);
804
- return;
805
- }
806
- const { search, params } = this.getMatch(matchId);
807
- const ssrFnContext = {
808
- search: makeMaybe(search, existingMatch.searchError),
809
- params: makeMaybe(params, existingMatch.paramsError),
810
- location: innerLoadContext.location,
811
- matches: innerLoadContext.matches.map((match) => ({
812
- index: match.index,
813
- pathname: match.pathname,
814
- fullPath: match.fullPath,
815
- staticData: match.staticData,
816
- id: match.id,
817
- routeId: match.routeId,
818
- search: makeMaybe(match.search, match.searchError),
819
- params: makeMaybe(match.params, match.paramsError),
820
- ssr: match.ssr
821
- }))
822
- };
823
- const tempSsr = route.options.ssr(ssrFnContext);
824
- if (isPromise(tempSsr)) {
825
- return tempSsr.then((ssr) => {
826
- existingMatch.ssr = parentOverride(ssr ?? defaultSsr);
827
- });
828
- }
829
- existingMatch.ssr = parentOverride(tempSsr ?? defaultSsr);
830
- return;
831
- };
832
- this.setupPendingTimeout = (innerLoadContext, matchId, route) => {
833
- const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
834
- const shouldPending = !!(innerLoadContext.onReady && !this.isServer && !this.resolvePreload(innerLoadContext, matchId) && (route.options.loader || route.options.beforeLoad || routeNeedsPreload(route)) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? this.options?.defaultPendingComponent));
835
- const match = this.getMatch(matchId);
836
- if (shouldPending && match._nonReactive.pendingTimeout === void 0) {
837
- const pendingTimeout = setTimeout(() => {
838
- this.triggerOnReady(innerLoadContext);
839
- }, pendingMs);
840
- match._nonReactive.pendingTimeout = pendingTimeout;
841
- }
842
- };
843
- this.shouldExecuteBeforeLoad = (innerLoadContext, matchId, route) => {
844
- const existingMatch = this.getMatch(matchId);
845
- if (!existingMatch._nonReactive.beforeLoadPromise && !existingMatch._nonReactive.loaderPromise)
846
- return true;
847
- this.setupPendingTimeout(innerLoadContext, matchId, route);
848
- const then = () => {
849
- let shouldExecuteBeforeLoad = true;
850
- const match = this.getMatch(matchId);
851
- if (match.status === "error") {
852
- shouldExecuteBeforeLoad = true;
853
- } else if (match.preload && (match.status === "redirected" || match.status === "notFound")) {
854
- this.handleRedirectAndNotFound(innerLoadContext, match, match.error);
855
- }
856
- return shouldExecuteBeforeLoad;
857
- };
858
- return existingMatch._nonReactive.beforeLoadPromise ? existingMatch._nonReactive.beforeLoadPromise.then(then) : then();
859
- };
860
- this.executeBeforeLoad = (innerLoadContext, matchId, index, route) => {
861
- const match = this.getMatch(matchId);
862
- match._nonReactive.beforeLoadPromise = createControlledPromise();
863
- const prevLoadPromise = match._nonReactive.loadPromise;
864
- match._nonReactive.loadPromise = createControlledPromise(() => {
865
- prevLoadPromise?.resolve();
866
- });
867
- const { paramsError, searchError } = match;
868
- if (paramsError) {
869
- this.handleSerialError(
870
- innerLoadContext,
871
- index,
872
- paramsError,
873
- "PARSE_PARAMS"
874
- );
875
- }
876
- if (searchError) {
877
- this.handleSerialError(
878
- innerLoadContext,
879
- index,
880
- searchError,
881
- "VALIDATE_SEARCH"
882
- );
883
- }
884
- this.setupPendingTimeout(innerLoadContext, matchId, route);
885
- const abortController = new AbortController();
886
- const parentMatchId = innerLoadContext.matches[index - 1]?.id;
887
- const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
888
- const parentMatchContext = parentMatch?.context ?? this.options.context ?? void 0;
889
- const context = { ...parentMatchContext, ...match.__routeContext };
890
- let isPending = false;
891
- const pending = () => {
892
- if (isPending) return;
893
- isPending = true;
894
- innerLoadContext.updateMatch(matchId, (prev) => ({
895
- ...prev,
896
- isFetching: "beforeLoad",
897
- fetchCount: prev.fetchCount + 1,
898
- abortController,
899
- context
900
- }));
901
- };
902
- const resolve = () => {
903
- match._nonReactive.beforeLoadPromise?.resolve();
904
- match._nonReactive.beforeLoadPromise = void 0;
905
- innerLoadContext.updateMatch(matchId, (prev) => ({
906
- ...prev,
907
- isFetching: false
908
- }));
909
- };
910
- if (!route.options.beforeLoad) {
911
- batch(() => {
912
- pending();
913
- resolve();
914
- });
915
- return;
916
- }
917
- const { search, params, cause } = match;
918
- const preload = this.resolvePreload(innerLoadContext, matchId);
919
- const beforeLoadFnContext = {
920
- search,
921
- abortController,
922
- params,
923
- preload,
924
- context,
925
- location: innerLoadContext.location,
926
- navigate: (opts) => this.navigate({ ...opts, _fromLocation: innerLoadContext.location }),
927
- buildLocation: this.buildLocation,
928
- cause: preload ? "preload" : cause,
929
- matches: innerLoadContext.matches
930
- };
931
- const updateContext = (beforeLoadContext2) => {
932
- if (beforeLoadContext2 === void 0) {
933
- batch(() => {
934
- pending();
935
- resolve();
936
- });
937
- return;
938
- }
939
- if (isRedirect(beforeLoadContext2) || isNotFound(beforeLoadContext2)) {
940
- pending();
941
- this.handleSerialError(
942
- innerLoadContext,
943
- index,
944
- beforeLoadContext2,
945
- "BEFORE_LOAD"
946
- );
947
- }
948
- batch(() => {
949
- pending();
950
- innerLoadContext.updateMatch(matchId, (prev) => ({
951
- ...prev,
952
- __beforeLoadContext: beforeLoadContext2,
953
- context: {
954
- ...prev.context,
955
- ...beforeLoadContext2
956
- }
957
- }));
958
- resolve();
959
- });
960
- };
961
- let beforeLoadContext;
962
- try {
963
- beforeLoadContext = route.options.beforeLoad(beforeLoadFnContext);
964
- if (isPromise(beforeLoadContext)) {
965
- pending();
966
- return beforeLoadContext.catch((err) => {
967
- this.handleSerialError(innerLoadContext, index, err, "BEFORE_LOAD");
968
- }).then(updateContext);
969
- }
970
- } catch (err) {
971
- pending();
972
- this.handleSerialError(innerLoadContext, index, err, "BEFORE_LOAD");
973
- }
974
- updateContext(beforeLoadContext);
975
- return;
976
- };
977
- this.handleBeforeLoad = (innerLoadContext, index) => {
978
- const { id: matchId, routeId } = innerLoadContext.matches[index];
979
- const route = this.looseRoutesById[routeId];
980
- const serverSsr = () => {
981
- if (this.isServer) {
982
- const maybePromise = this.isBeforeLoadSsr(
983
- innerLoadContext,
984
- matchId,
985
- index,
986
- route
987
- );
988
- if (isPromise(maybePromise)) return maybePromise.then(queueExecution);
989
- }
990
- return queueExecution();
991
- };
992
- const queueExecution = () => {
993
- if (this.shouldSkipLoader(matchId)) return;
994
- const shouldExecuteBeforeLoadResult = this.shouldExecuteBeforeLoad(
995
- innerLoadContext,
996
- matchId,
997
- route
998
- );
999
- return isPromise(shouldExecuteBeforeLoadResult) ? shouldExecuteBeforeLoadResult.then(execute) : execute(shouldExecuteBeforeLoadResult);
1000
- };
1001
- const execute = (shouldExecuteBeforeLoad) => {
1002
- if (shouldExecuteBeforeLoad) {
1003
- return this.executeBeforeLoad(innerLoadContext, matchId, index, route);
1004
- }
1005
- return;
1006
- };
1007
- return serverSsr();
1008
- };
1009
- this.executeHead = (innerLoadContext, matchId, route) => {
1010
- const match = this.getMatch(matchId);
1011
- if (!match) {
1012
- return;
1013
- }
1014
- if (!route.options.head && !route.options.scripts && !route.options.headers) {
1015
- return;
1016
- }
1017
- const assetContext = {
1018
- matches: innerLoadContext.matches,
1019
- match,
1020
- params: match.params,
1021
- loaderData: match.loaderData
1022
- };
1023
- return Promise.all([
1024
- route.options.head?.(assetContext),
1025
- route.options.scripts?.(assetContext),
1026
- route.options.headers?.(assetContext)
1027
- ]).then(([headFnContent, scripts, headers]) => {
1028
- const meta = headFnContent?.meta;
1029
- const links = headFnContent?.links;
1030
- const headScripts = headFnContent?.scripts;
1031
- const styles = headFnContent?.styles;
1032
- return {
1033
- meta,
1034
- links,
1035
- headScripts,
1036
- headers,
1037
- scripts,
1038
- styles
1039
- };
1040
- });
1041
- };
1042
- this.potentialPendingMinPromise = (matchId) => {
1043
- const latestMatch = this.getMatch(matchId);
1044
- return latestMatch._nonReactive.minPendingPromise;
1045
- };
1046
- this.getLoaderContext = (innerLoadContext, matchId, index, route) => {
1047
- const parentMatchPromise = innerLoadContext.matchPromises[index - 1];
1048
- const { params, loaderDeps, abortController, context, cause } = this.getMatch(matchId);
1049
- const preload = this.resolvePreload(innerLoadContext, matchId);
1050
- return {
1051
- params,
1052
- deps: loaderDeps,
1053
- preload: !!preload,
1054
- parentMatchPromise,
1055
- abortController,
1056
- context,
1057
- location: innerLoadContext.location,
1058
- navigate: (opts) => this.navigate({ ...opts, _fromLocation: innerLoadContext.location }),
1059
- cause: preload ? "preload" : cause,
1060
- route
1061
- };
1062
- };
1063
- this.runLoader = async (innerLoadContext, matchId, index, route) => {
1064
- try {
1065
- try {
1066
- if (!this.isServer || this.getMatch(matchId).ssr === true) {
1067
- this.loadRouteChunk(route);
1068
- }
1069
- const loaderResult = route.options.loader?.(
1070
- this.getLoaderContext(innerLoadContext, matchId, index, route)
1071
- );
1072
- const loaderResultIsPromise = route.options.loader && isPromise(loaderResult);
1073
- const willLoadSomething = !!(loaderResultIsPromise || route._lazyPromise || route._componentsPromise || route.options.head || route.options.scripts || route.options.headers || this.getMatch(matchId)._nonReactive.minPendingPromise);
1074
- if (willLoadSomething) {
1075
- innerLoadContext.updateMatch(matchId, (prev) => ({
1076
- ...prev,
1077
- isFetching: "loader"
1078
- }));
1079
- }
1080
- if (route.options.loader) {
1081
- const loaderData = loaderResultIsPromise ? await loaderResult : loaderResult;
1082
- this.handleRedirectAndNotFound(
1083
- innerLoadContext,
1084
- this.getMatch(matchId),
1085
- loaderData
1086
- );
1087
- if (loaderData !== void 0) {
1088
- innerLoadContext.updateMatch(matchId, (prev) => ({
1089
- ...prev,
1090
- loaderData
1091
- }));
1092
- }
1093
- }
1094
- if (route._lazyPromise) await route._lazyPromise;
1095
- const headResult = this.executeHead(innerLoadContext, matchId, route);
1096
- const head = headResult ? await headResult : void 0;
1097
- const pendingPromise = this.potentialPendingMinPromise(matchId);
1098
- if (pendingPromise) await pendingPromise;
1099
- if (route._componentsPromise) await route._componentsPromise;
1100
- innerLoadContext.updateMatch(matchId, (prev) => ({
1101
- ...prev,
1102
- error: void 0,
1103
- status: "success",
1104
- isFetching: false,
1105
- updatedAt: Date.now(),
1106
- ...head
1107
- }));
1108
- } catch (e) {
1109
- let error = e;
1110
- const pendingPromise = this.potentialPendingMinPromise(matchId);
1111
- if (pendingPromise) await pendingPromise;
1112
- this.handleRedirectAndNotFound(
1113
- innerLoadContext,
1114
- this.getMatch(matchId),
1115
- e
1116
- );
1117
- try {
1118
- route.options.onError?.(e);
1119
- } catch (onErrorError) {
1120
- error = onErrorError;
1121
- this.handleRedirectAndNotFound(
1122
- innerLoadContext,
1123
- this.getMatch(matchId),
1124
- onErrorError
1125
- );
1126
- }
1127
- const headResult = this.executeHead(innerLoadContext, matchId, route);
1128
- const head = headResult ? await headResult : void 0;
1129
- innerLoadContext.updateMatch(matchId, (prev) => ({
1130
- ...prev,
1131
- error,
1132
- status: "error",
1133
- isFetching: false,
1134
- ...head
1135
- }));
1136
- }
1137
- } catch (err) {
1138
- const match = this.getMatch(matchId);
1139
- if (match) {
1140
- const headResult = this.executeHead(innerLoadContext, matchId, route);
1141
- if (headResult) {
1142
- const head = await headResult;
1143
- innerLoadContext.updateMatch(matchId, (prev) => ({
1144
- ...prev,
1145
- ...head
1146
- }));
1147
- }
1148
- match._nonReactive.loaderPromise = void 0;
1149
- }
1150
- this.handleRedirectAndNotFound(innerLoadContext, match, err);
1151
- }
1152
- };
1153
- this.loadRouteMatch = async (innerLoadContext, index) => {
1154
- const { id: matchId, routeId } = innerLoadContext.matches[index];
1155
- let loaderShouldRunAsync = false;
1156
- let loaderIsRunningAsync = false;
1157
- const route = this.looseRoutesById[routeId];
1158
- const prevMatch = this.getMatch(matchId);
1159
- if (this.shouldSkipLoader(matchId)) {
1160
- if (this.isServer) {
1161
- const headResult = this.executeHead(innerLoadContext, matchId, route);
1162
- if (headResult) {
1163
- const head = await headResult;
1164
- innerLoadContext.updateMatch(matchId, (prev) => ({
1165
- ...prev,
1166
- ...head
1167
- }));
1168
- }
1169
- return this.getMatch(matchId);
1170
- }
1171
- } else if (prevMatch._nonReactive.loaderPromise) {
1172
- if (prevMatch.status === "success" && !innerLoadContext.sync && !prevMatch.preload) {
1173
- return this.getMatch(matchId);
1174
- }
1175
- await prevMatch._nonReactive.loaderPromise;
1176
- const match2 = this.getMatch(matchId);
1177
- if (match2.error) {
1178
- this.handleRedirectAndNotFound(innerLoadContext, match2, match2.error);
1179
- }
1180
- } else {
1181
- const age = Date.now() - this.getMatch(matchId).updatedAt;
1182
- const preload = this.resolvePreload(innerLoadContext, matchId);
1183
- const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
1184
- const shouldReloadOption = route.options.shouldReload;
1185
- const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(
1186
- this.getLoaderContext(innerLoadContext, matchId, index, route)
1187
- ) : shouldReloadOption;
1188
- const nextPreload = !!preload && !this.state.matches.some((d) => d.id === matchId);
1189
- const match2 = this.getMatch(matchId);
1190
- match2._nonReactive.loaderPromise = createControlledPromise();
1191
- if (nextPreload !== match2.preload) {
1192
- innerLoadContext.updateMatch(matchId, (prev) => ({
1193
- ...prev,
1194
- preload: nextPreload
1195
- }));
1196
- }
1197
- const { status, invalid } = this.getMatch(matchId);
1198
- loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? age > staleAge));
1199
- if (preload && route.options.preload === false) ;
1200
- else if (loaderShouldRunAsync && !innerLoadContext.sync) {
1201
- loaderIsRunningAsync = true;
1202
- (async () => {
1203
- try {
1204
- await this.runLoader(innerLoadContext, matchId, index, route);
1205
- const match3 = this.getMatch(matchId);
1206
- match3._nonReactive.loaderPromise?.resolve();
1207
- match3._nonReactive.loadPromise?.resolve();
1208
- match3._nonReactive.loaderPromise = void 0;
1209
- } catch (err) {
1210
- if (isRedirect(err)) {
1211
- await this.navigate(err.options);
1212
- }
1213
- }
1214
- })();
1215
- } else if (status !== "success" || loaderShouldRunAsync && innerLoadContext.sync) {
1216
- await this.runLoader(innerLoadContext, matchId, index, route);
1217
- } else {
1218
- const headResult = this.executeHead(innerLoadContext, matchId, route);
1219
- if (headResult) {
1220
- const head = await headResult;
1221
- innerLoadContext.updateMatch(matchId, (prev) => ({
1222
- ...prev,
1223
- ...head
1224
- }));
1225
- }
1226
- }
1227
- }
1228
- const match = this.getMatch(matchId);
1229
- if (!loaderIsRunningAsync) {
1230
- match._nonReactive.loaderPromise?.resolve();
1231
- match._nonReactive.loadPromise?.resolve();
1232
- }
1233
- clearTimeout(match._nonReactive.pendingTimeout);
1234
- match._nonReactive.pendingTimeout = void 0;
1235
- if (!loaderIsRunningAsync) match._nonReactive.loaderPromise = void 0;
1236
- match._nonReactive.dehydrated = void 0;
1237
- const nextIsFetching = loaderIsRunningAsync ? match.isFetching : false;
1238
- if (nextIsFetching !== match.isFetching || match.invalid !== false) {
1239
- innerLoadContext.updateMatch(matchId, (prev) => ({
1240
- ...prev,
1241
- isFetching: nextIsFetching,
1242
- invalid: false
1243
- }));
1244
- }
1245
- return this.getMatch(matchId);
1246
- };
1247
- this.loadMatches = async (baseContext) => {
1248
- const innerLoadContext = baseContext;
1249
- innerLoadContext.updateMatch ??= this.updateMatch;
1250
- innerLoadContext.matchPromises = [];
1251
- if (!this.isServer && this.state.matches.some((d) => d._forcePending)) {
1252
- this.triggerOnReady(innerLoadContext);
1253
- }
1254
- try {
1255
- for (let i = 0; i < innerLoadContext.matches.length; i++) {
1256
- const beforeLoad = this.handleBeforeLoad(innerLoadContext, i);
1257
- if (isPromise(beforeLoad)) await beforeLoad;
1258
- }
1259
- const max = innerLoadContext.firstBadMatchIndex ?? innerLoadContext.matches.length;
1260
- for (let i = 0; i < max; i++) {
1261
- innerLoadContext.matchPromises.push(
1262
- this.loadRouteMatch(innerLoadContext, i)
1263
- );
1264
- }
1265
- await Promise.all(innerLoadContext.matchPromises);
1266
- const readyPromise = this.triggerOnReady(innerLoadContext);
1267
- if (isPromise(readyPromise)) await readyPromise;
1268
- } catch (err) {
1269
- if (isNotFound(err) && !innerLoadContext.preload) {
1270
- const readyPromise = this.triggerOnReady(innerLoadContext);
1271
- if (isPromise(readyPromise)) await readyPromise;
1272
- throw err;
1273
- }
1274
- if (isRedirect(err)) {
1275
- throw err;
1276
- }
1277
- }
1278
- return innerLoadContext.matches;
1279
- };
1280
692
  this.invalidate = (opts) => {
1281
693
  const invalidate = (d) => {
1282
694
  if (opts?.filter?.(d) ?? true) {
@@ -1341,39 +753,7 @@ class RouterCore {
1341
753
  };
1342
754
  this.clearCache({ filter });
1343
755
  };
1344
- this.loadRouteChunk = (route) => {
1345
- if (!route._lazyLoaded && route._lazyPromise === void 0) {
1346
- if (route.lazyFn) {
1347
- route._lazyPromise = route.lazyFn().then((lazyRoute) => {
1348
- const { id: _id, ...options2 } = lazyRoute.options;
1349
- Object.assign(route.options, options2);
1350
- route._lazyLoaded = true;
1351
- route._lazyPromise = void 0;
1352
- });
1353
- } else {
1354
- route._lazyLoaded = true;
1355
- }
1356
- }
1357
- if (!route._componentsLoaded && route._componentsPromise === void 0) {
1358
- const loadComponents = () => {
1359
- const preloads = [];
1360
- for (const type of componentTypes) {
1361
- const preload = route.options[type]?.preload;
1362
- if (preload) preloads.push(preload());
1363
- }
1364
- if (preloads.length)
1365
- return Promise.all(preloads).then(() => {
1366
- route._componentsLoaded = true;
1367
- route._componentsPromise = void 0;
1368
- });
1369
- route._componentsLoaded = true;
1370
- route._componentsPromise = void 0;
1371
- return;
1372
- };
1373
- route._componentsPromise = route._lazyPromise ? route._lazyPromise.then(loadComponents) : loadComponents();
1374
- }
1375
- return route._componentsPromise;
1376
- };
756
+ this.loadRouteChunk = loadRouteChunk;
1377
757
  this.preloadRoute = async (opts) => {
1378
758
  const next = this.buildLocation(opts);
1379
759
  let matches = this.matchRoutes(next, {
@@ -1401,7 +781,8 @@ class RouterCore {
1401
781
  });
1402
782
  });
1403
783
  try {
1404
- matches = await this.loadMatches({
784
+ matches = await loadMatches({
785
+ router: this,
1405
786
  matches,
1406
787
  location: next,
1407
788
  preload: true,
@@ -1468,35 +849,6 @@ class RouterCore {
1468
849
  }
1469
850
  return match;
1470
851
  };
1471
- this._handleNotFound = (innerLoadContext, err) => {
1472
- const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
1473
- const matchesByRouteId = {};
1474
- for (const match of innerLoadContext.matches) {
1475
- matchesByRouteId[match.routeId] = match;
1476
- }
1477
- if (!routeCursor.options.notFoundComponent && this.options?.defaultNotFoundComponent) {
1478
- routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
1479
- }
1480
- invariant(
1481
- routeCursor.options.notFoundComponent,
1482
- "No notFoundComponent found. Please set a notFoundComponent on your route or provide a defaultNotFoundComponent to the router."
1483
- );
1484
- const matchForRoute = matchesByRouteId[routeCursor.id];
1485
- invariant(
1486
- matchForRoute,
1487
- "Could not find match for route: " + routeCursor.id
1488
- );
1489
- innerLoadContext.updateMatch(matchForRoute.id, (prev) => ({
1490
- ...prev,
1491
- status: "notFound",
1492
- error: err,
1493
- isFetching: false
1494
- }));
1495
- if (err.routerCode === "BEFORE_LOAD" && routeCursor.parentRoute) {
1496
- err.routeId = routeCursor.parentRoute.id;
1497
- this._handleNotFound(innerLoadContext, err);
1498
- }
1499
- };
1500
852
  this.hasNotFoundMatch = () => {
1501
853
  return this.__store.state.matches.some(
1502
854
  (d) => d.status === "notFound" || d.globalNotFound
@@ -1730,12 +1082,6 @@ class SearchParamError extends Error {
1730
1082
  }
1731
1083
  class PathParamError extends Error {
1732
1084
  }
1733
- function makeMaybe(value, error) {
1734
- if (error) {
1735
- return { status: "error", error };
1736
- }
1737
- return { status: "success", value };
1738
- }
1739
1085
  const normalize = (str) => str.endsWith("/") && str.length > 1 ? str.slice(0, -1) : str;
1740
1086
  function comparePaths(a, b) {
1741
1087
  return normalize(a) === normalize(b);
@@ -1780,20 +1126,6 @@ function validateSearch(validateSearch2, input) {
1780
1126
  }
1781
1127
  return {};
1782
1128
  }
1783
- const componentTypes = [
1784
- "component",
1785
- "errorComponent",
1786
- "pendingComponent",
1787
- "notFoundComponent"
1788
- ];
1789
- function routeNeedsPreload(route) {
1790
- for (const componentType of componentTypes) {
1791
- if (route.options[componentType]?.preload) {
1792
- return true;
1793
- }
1794
- }
1795
- return false;
1796
- }
1797
1129
  const REQUIRED_PARAM_BASE_SCORE = 0.5;
1798
1130
  const OPTIONAL_PARAM_BASE_SCORE = 0.4;
1799
1131
  const WILDCARD_PARAM_BASE_SCORE = 0.25;
@@ -2063,7 +1395,6 @@ export {
2063
1395
  PathParamError,
2064
1396
  RouterCore,
2065
1397
  SearchParamError,
2066
- componentTypes,
2067
1398
  defaultSerializeError,
2068
1399
  getInitialRouterState,
2069
1400
  getLocationChangeInfo,