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

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