@tanstack/router-core 1.131.13 → 1.131.16

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.
@@ -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, deepEqual, replaceEqualDeep, last, functionalUpdate } from "./utils.js";
4
+ import { pick, createControlledPromise, isPromise, deepEqual, replaceEqualDeep, last, 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";
@@ -703,518 +703,598 @@ class RouterCore {
703
703
  const findFn = (d) => d.id === matchId;
704
704
  return this.state.cachedMatches.find(findFn) ?? ((_a = this.state.pendingMatches) == null ? void 0 : _a.find(findFn)) ?? this.state.matches.find(findFn);
705
705
  };
706
- this.loadMatches = async ({
707
- location,
708
- matches,
709
- preload: allPreload,
710
- onReady,
711
- updateMatch = this.updateMatch,
712
- sync
713
- }) => {
714
- let firstBadMatchIndex;
715
- let rendered = false;
716
- const triggerOnReady = async () => {
717
- if (!rendered) {
718
- rendered = true;
719
- await (onReady == null ? void 0 : onReady());
706
+ this.triggerOnReady = (innerLoadContext) => {
707
+ var _a;
708
+ if (!innerLoadContext.rendered) {
709
+ innerLoadContext.rendered = true;
710
+ return (_a = innerLoadContext.onReady) == null ? void 0 : _a.call(innerLoadContext);
711
+ }
712
+ };
713
+ this.resolvePreload = (innerLoadContext, matchId) => {
714
+ return !!(innerLoadContext.preload && !this.state.matches.some((d) => d.id === matchId));
715
+ };
716
+ this.handleRedirectAndNotFound = (innerLoadContext, match, err) => {
717
+ var _a, _b, _c;
718
+ if (!isRedirect(err) && !isNotFound(err)) return;
719
+ if (isRedirect(err) && err.redirectHandled && !err.options.reloadDocument) {
720
+ throw err;
721
+ }
722
+ if (match) {
723
+ (_a = match._nonReactive.beforeLoadPromise) == null ? void 0 : _a.resolve();
724
+ (_b = match._nonReactive.loaderPromise) == null ? void 0 : _b.resolve();
725
+ match._nonReactive.beforeLoadPromise = void 0;
726
+ match._nonReactive.loaderPromise = void 0;
727
+ const status = isRedirect(err) ? "redirected" : "notFound";
728
+ innerLoadContext.updateMatch(match.id, (prev) => ({
729
+ ...prev,
730
+ status,
731
+ isFetching: false,
732
+ error: err
733
+ }));
734
+ if (isNotFound(err) && !err.routeId) {
735
+ err.routeId = match.routeId;
736
+ }
737
+ (_c = match._nonReactive.loadPromise) == null ? void 0 : _c.resolve();
738
+ }
739
+ if (isRedirect(err)) {
740
+ innerLoadContext.rendered = true;
741
+ err.options._fromLocation = innerLoadContext.location;
742
+ err.redirectHandled = true;
743
+ err = this.resolveRedirect(err);
744
+ throw err;
745
+ } else {
746
+ this._handleNotFound(innerLoadContext, err);
747
+ throw err;
748
+ }
749
+ };
750
+ this.shouldSkipLoader = (matchId) => {
751
+ const match = this.getMatch(matchId);
752
+ if (!this.isServer && match._nonReactive.dehydrated) {
753
+ return true;
754
+ }
755
+ if (this.isServer) {
756
+ if (match.ssr === false) {
757
+ return true;
758
+ }
759
+ }
760
+ return false;
761
+ };
762
+ this.handleSerialError = (innerLoadContext, index, err, routerCode) => {
763
+ var _a, _b;
764
+ const { id: matchId, routeId } = innerLoadContext.matches[index];
765
+ const route = this.looseRoutesById[routeId];
766
+ if (err instanceof Promise) {
767
+ throw err;
768
+ }
769
+ err.routerCode = routerCode;
770
+ innerLoadContext.firstBadMatchIndex ?? (innerLoadContext.firstBadMatchIndex = index);
771
+ this.handleRedirectAndNotFound(
772
+ innerLoadContext,
773
+ this.getMatch(matchId),
774
+ err
775
+ );
776
+ try {
777
+ (_b = (_a = route.options).onError) == null ? void 0 : _b.call(_a, err);
778
+ } catch (errorHandlerErr) {
779
+ err = errorHandlerErr;
780
+ this.handleRedirectAndNotFound(
781
+ innerLoadContext,
782
+ this.getMatch(matchId),
783
+ err
784
+ );
785
+ }
786
+ innerLoadContext.updateMatch(matchId, (prev) => {
787
+ var _a2, _b2;
788
+ (_a2 = prev._nonReactive.beforeLoadPromise) == null ? void 0 : _a2.resolve();
789
+ prev._nonReactive.beforeLoadPromise = void 0;
790
+ (_b2 = prev._nonReactive.loadPromise) == null ? void 0 : _b2.resolve();
791
+ return {
792
+ ...prev,
793
+ error: err,
794
+ status: "error",
795
+ isFetching: false,
796
+ updatedAt: Date.now(),
797
+ abortController: new AbortController()
798
+ };
799
+ });
800
+ };
801
+ this.isBeforeLoadSsr = (innerLoadContext, matchId, index, route) => {
802
+ var _a;
803
+ const existingMatch = this.getMatch(matchId);
804
+ const parentMatchId = (_a = innerLoadContext.matches[index - 1]) == null ? void 0 : _a.id;
805
+ const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
806
+ if (this.isShell()) {
807
+ existingMatch.ssr = matchId === rootRouteId;
808
+ return;
809
+ }
810
+ if ((parentMatch == null ? void 0 : parentMatch.ssr) === false) {
811
+ existingMatch.ssr = false;
812
+ return;
813
+ }
814
+ const parentOverride = (tempSsr2) => {
815
+ if (tempSsr2 === true && (parentMatch == null ? void 0 : parentMatch.ssr) === "data-only") {
816
+ return "data-only";
720
817
  }
818
+ return tempSsr2;
721
819
  };
722
- const resolvePreload = (matchId) => {
723
- return !!(allPreload && !this.state.matches.some((d) => d.id === matchId));
820
+ const defaultSsr = this.options.defaultSsr ?? true;
821
+ if (route.options.ssr === void 0) {
822
+ existingMatch.ssr = parentOverride(defaultSsr);
823
+ return;
824
+ }
825
+ if (typeof route.options.ssr !== "function") {
826
+ existingMatch.ssr = parentOverride(route.options.ssr);
827
+ return;
828
+ }
829
+ const { search, params } = this.getMatch(matchId);
830
+ const ssrFnContext = {
831
+ search: makeMaybe(search, existingMatch.searchError),
832
+ params: makeMaybe(params, existingMatch.paramsError),
833
+ location: innerLoadContext.location,
834
+ matches: innerLoadContext.matches.map((match) => ({
835
+ index: match.index,
836
+ pathname: match.pathname,
837
+ fullPath: match.fullPath,
838
+ staticData: match.staticData,
839
+ id: match.id,
840
+ routeId: match.routeId,
841
+ search: makeMaybe(match.search, match.searchError),
842
+ params: makeMaybe(match.params, match.paramsError),
843
+ ssr: match.ssr
844
+ }))
724
845
  };
725
- if (!this.isServer && this.state.matches.some((d) => d._forcePending)) {
726
- triggerOnReady();
846
+ const tempSsr = route.options.ssr(ssrFnContext);
847
+ if (isPromise(tempSsr)) {
848
+ return tempSsr.then((ssr) => {
849
+ existingMatch.ssr = parentOverride(ssr ?? defaultSsr);
850
+ });
727
851
  }
728
- const handleRedirectAndNotFound = (match, err) => {
729
- var _a, _b, _c;
730
- if (!isRedirect(err) && !isNotFound(err)) return;
731
- if (isRedirect(err) && err.redirectHandled && !err.options.reloadDocument) {
732
- throw err;
852
+ existingMatch.ssr = parentOverride(tempSsr ?? defaultSsr);
853
+ return;
854
+ };
855
+ this.setupPendingTimeout = (innerLoadContext, matchId, route) => {
856
+ var _a;
857
+ const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
858
+ 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 ?? ((_a = this.options) == null ? void 0 : _a.defaultPendingComponent)));
859
+ const match = this.getMatch(matchId);
860
+ if (shouldPending && match._nonReactive.pendingTimeout === void 0) {
861
+ const pendingTimeout = setTimeout(() => {
862
+ try {
863
+ this.triggerOnReady(innerLoadContext);
864
+ } catch {
865
+ }
866
+ }, pendingMs);
867
+ match._nonReactive.pendingTimeout = pendingTimeout;
868
+ }
869
+ };
870
+ this.shouldExecuteBeforeLoad = (innerLoadContext, matchId, route) => {
871
+ const existingMatch = this.getMatch(matchId);
872
+ if (!existingMatch._nonReactive.beforeLoadPromise && !existingMatch._nonReactive.loaderPromise)
873
+ return true;
874
+ this.setupPendingTimeout(innerLoadContext, matchId, route);
875
+ const then = () => {
876
+ let shouldExecuteBeforeLoad = true;
877
+ const match = this.getMatch(matchId);
878
+ if (match.status === "error") {
879
+ shouldExecuteBeforeLoad = true;
880
+ } else if (match.preload && (match.status === "redirected" || match.status === "notFound")) {
881
+ this.handleRedirectAndNotFound(innerLoadContext, match, match.error);
733
882
  }
734
- if (match) {
735
- (_a = match._nonReactive.beforeLoadPromise) == null ? void 0 : _a.resolve();
736
- (_b = match._nonReactive.loaderPromise) == null ? void 0 : _b.resolve();
737
- match._nonReactive.beforeLoadPromise = void 0;
738
- match._nonReactive.loaderPromise = void 0;
739
- const status = isRedirect(err) ? "redirected" : "notFound";
740
- updateMatch(match.id, (prev) => ({
883
+ return shouldExecuteBeforeLoad;
884
+ };
885
+ return existingMatch._nonReactive.beforeLoadPromise ? existingMatch._nonReactive.beforeLoadPromise.then(then) : then();
886
+ };
887
+ this.executeBeforeLoad = (innerLoadContext, matchId, index, route) => {
888
+ var _a, _b, _c;
889
+ const resolve = () => {
890
+ innerLoadContext.updateMatch(matchId, (prev) => {
891
+ var _a2;
892
+ (_a2 = prev._nonReactive.beforeLoadPromise) == null ? void 0 : _a2.resolve();
893
+ prev._nonReactive.beforeLoadPromise = void 0;
894
+ return {
741
895
  ...prev,
742
- status,
743
- isFetching: false,
744
- error: err
745
- }));
746
- if (isNotFound(err) && !err.routeId) {
747
- err.routeId = match.routeId;
748
- }
749
- (_c = match._nonReactive.loadPromise) == null ? void 0 : _c.resolve();
896
+ isFetching: false
897
+ };
898
+ });
899
+ };
900
+ try {
901
+ const match = this.getMatch(matchId);
902
+ match._nonReactive.beforeLoadPromise = createControlledPromise();
903
+ const prevLoadPromise = match._nonReactive.loadPromise;
904
+ match._nonReactive.loadPromise = createControlledPromise(() => {
905
+ prevLoadPromise == null ? void 0 : prevLoadPromise.resolve();
906
+ });
907
+ const { paramsError, searchError } = this.getMatch(matchId);
908
+ if (paramsError) {
909
+ this.handleSerialError(
910
+ innerLoadContext,
911
+ index,
912
+ paramsError,
913
+ "PARSE_PARAMS"
914
+ );
750
915
  }
751
- if (isRedirect(err)) {
752
- rendered = true;
753
- err.options._fromLocation = location;
754
- err.redirectHandled = true;
755
- err = this.resolveRedirect(err);
756
- throw err;
916
+ if (searchError) {
917
+ this.handleSerialError(
918
+ innerLoadContext,
919
+ index,
920
+ searchError,
921
+ "VALIDATE_SEARCH"
922
+ );
923
+ }
924
+ this.setupPendingTimeout(innerLoadContext, matchId, route);
925
+ const abortController = new AbortController();
926
+ const parentMatchId = (_a = innerLoadContext.matches[index - 1]) == null ? void 0 : _a.id;
927
+ const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
928
+ const parentMatchContext = (parentMatch == null ? void 0 : parentMatch.context) ?? this.options.context ?? void 0;
929
+ innerLoadContext.updateMatch(matchId, (prev) => ({
930
+ ...prev,
931
+ isFetching: "beforeLoad",
932
+ fetchCount: prev.fetchCount + 1,
933
+ abortController,
934
+ context: {
935
+ ...parentMatchContext,
936
+ ...prev.__routeContext
937
+ }
938
+ }));
939
+ const { search, params, context, cause } = this.getMatch(matchId);
940
+ const preload = this.resolvePreload(innerLoadContext, matchId);
941
+ const beforeLoadFnContext = {
942
+ search,
943
+ abortController,
944
+ params,
945
+ preload,
946
+ context,
947
+ location: innerLoadContext.location,
948
+ navigate: (opts) => this.navigate({ ...opts, _fromLocation: innerLoadContext.location }),
949
+ buildLocation: this.buildLocation,
950
+ cause: preload ? "preload" : cause,
951
+ matches: innerLoadContext.matches
952
+ };
953
+ const updateContext = (beforeLoadContext2) => {
954
+ if (isRedirect(beforeLoadContext2) || isNotFound(beforeLoadContext2)) {
955
+ this.handleSerialError(
956
+ innerLoadContext,
957
+ index,
958
+ beforeLoadContext2,
959
+ "BEFORE_LOAD"
960
+ );
961
+ }
962
+ innerLoadContext.updateMatch(matchId, (prev) => ({
963
+ ...prev,
964
+ __beforeLoadContext: beforeLoadContext2,
965
+ context: {
966
+ ...parentMatchContext,
967
+ ...prev.__routeContext,
968
+ ...beforeLoadContext2
969
+ },
970
+ abortController
971
+ }));
972
+ };
973
+ const beforeLoadContext = (_c = (_b = route.options).beforeLoad) == null ? void 0 : _c.call(_b, beforeLoadFnContext);
974
+ if (isPromise(beforeLoadContext)) {
975
+ return beforeLoadContext.then(updateContext).catch((err) => {
976
+ this.handleSerialError(innerLoadContext, index, err, "BEFORE_LOAD");
977
+ }).then(resolve);
757
978
  } else {
758
- this._handleNotFound(matches, err, updateMatch);
759
- throw err;
979
+ updateContext(beforeLoadContext);
980
+ }
981
+ } catch (err) {
982
+ this.handleSerialError(innerLoadContext, index, err, "BEFORE_LOAD");
983
+ }
984
+ resolve();
985
+ return;
986
+ };
987
+ this.handleBeforeLoad = (innerLoadContext, index) => {
988
+ const { id: matchId, routeId } = innerLoadContext.matches[index];
989
+ const route = this.looseRoutesById[routeId];
990
+ const serverSsr = () => {
991
+ if (this.isServer) {
992
+ const maybePromise = this.isBeforeLoadSsr(
993
+ innerLoadContext,
994
+ matchId,
995
+ index,
996
+ route
997
+ );
998
+ if (isPromise(maybePromise)) return maybePromise.then(queueExecution);
760
999
  }
1000
+ return queueExecution();
1001
+ };
1002
+ const queueExecution = () => {
1003
+ if (this.shouldSkipLoader(matchId)) return;
1004
+ const shouldExecuteBeforeLoadResult = this.shouldExecuteBeforeLoad(
1005
+ innerLoadContext,
1006
+ matchId,
1007
+ route
1008
+ );
1009
+ return isPromise(shouldExecuteBeforeLoadResult) ? shouldExecuteBeforeLoadResult.then(execute) : execute(shouldExecuteBeforeLoadResult);
1010
+ };
1011
+ const execute = (shouldExecuteBeforeLoad) => {
1012
+ if (shouldExecuteBeforeLoad) {
1013
+ return this.executeBeforeLoad(innerLoadContext, matchId, index, route);
1014
+ }
1015
+ return;
1016
+ };
1017
+ return serverSsr();
1018
+ };
1019
+ this.executeHead = (innerLoadContext, matchId, route) => {
1020
+ var _a, _b, _c, _d, _e, _f;
1021
+ const match = this.getMatch(matchId);
1022
+ if (!match) {
1023
+ return;
1024
+ }
1025
+ if (!route.options.head && !route.options.scripts && !route.options.headers) {
1026
+ return;
1027
+ }
1028
+ const assetContext = {
1029
+ matches: innerLoadContext.matches,
1030
+ match,
1031
+ params: match.params,
1032
+ loaderData: match.loaderData
1033
+ };
1034
+ return Promise.all([
1035
+ (_b = (_a = route.options).head) == null ? void 0 : _b.call(_a, assetContext),
1036
+ (_d = (_c = route.options).scripts) == null ? void 0 : _d.call(_c, assetContext),
1037
+ (_f = (_e = route.options).headers) == null ? void 0 : _f.call(_e, assetContext)
1038
+ ]).then(([headFnContent, scripts, headers]) => {
1039
+ const meta = headFnContent == null ? void 0 : headFnContent.meta;
1040
+ const links = headFnContent == null ? void 0 : headFnContent.links;
1041
+ const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
1042
+ const styles = headFnContent == null ? void 0 : headFnContent.styles;
1043
+ return {
1044
+ meta,
1045
+ links,
1046
+ headScripts,
1047
+ headers,
1048
+ scripts,
1049
+ styles
1050
+ };
1051
+ });
1052
+ };
1053
+ this.potentialPendingMinPromise = (matchId) => {
1054
+ const latestMatch = this.getMatch(matchId);
1055
+ return latestMatch._nonReactive.minPendingPromise;
1056
+ };
1057
+ this.getLoaderContext = (innerLoadContext, matchId, index, route) => {
1058
+ const parentMatchPromise = innerLoadContext.matchPromises[index - 1];
1059
+ const { params, loaderDeps, abortController, context, cause } = this.getMatch(matchId);
1060
+ const preload = this.resolvePreload(innerLoadContext, matchId);
1061
+ return {
1062
+ params,
1063
+ deps: loaderDeps,
1064
+ preload: !!preload,
1065
+ parentMatchPromise,
1066
+ abortController,
1067
+ context,
1068
+ location: innerLoadContext.location,
1069
+ navigate: (opts) => this.navigate({ ...opts, _fromLocation: innerLoadContext.location }),
1070
+ cause: preload ? "preload" : cause,
1071
+ route
761
1072
  };
762
- const shouldSkipLoader = (matchId) => {
1073
+ };
1074
+ this.runLoader = async (innerLoadContext, matchId, index, route) => {
1075
+ var _a, _b, _c, _d;
1076
+ try {
1077
+ try {
1078
+ if (!this.isServer || this.getMatch(matchId).ssr === true) {
1079
+ this.loadRouteChunk(route);
1080
+ }
1081
+ const loaderResult = (_b = (_a = route.options).loader) == null ? void 0 : _b.call(
1082
+ _a,
1083
+ this.getLoaderContext(innerLoadContext, matchId, index, route)
1084
+ );
1085
+ const loaderResultIsPromise = route.options.loader && isPromise(loaderResult);
1086
+ const willLoadSomething = !!(loaderResultIsPromise || route._lazyPromise || route._componentsPromise || route.options.head || route.options.scripts || route.options.headers || this.getMatch(matchId)._nonReactive.minPendingPromise);
1087
+ if (willLoadSomething) {
1088
+ innerLoadContext.updateMatch(matchId, (prev) => ({
1089
+ ...prev,
1090
+ isFetching: "loader"
1091
+ }));
1092
+ }
1093
+ if (route.options.loader) {
1094
+ const loaderData = loaderResultIsPromise ? await loaderResult : loaderResult;
1095
+ this.handleRedirectAndNotFound(
1096
+ innerLoadContext,
1097
+ this.getMatch(matchId),
1098
+ loaderData
1099
+ );
1100
+ innerLoadContext.updateMatch(matchId, (prev) => ({
1101
+ ...prev,
1102
+ loaderData
1103
+ }));
1104
+ }
1105
+ if (route._lazyPromise) await route._lazyPromise;
1106
+ const headResult = this.executeHead(innerLoadContext, matchId, route);
1107
+ const head = headResult ? await headResult : void 0;
1108
+ const pendingPromise = this.potentialPendingMinPromise(matchId);
1109
+ if (pendingPromise) await pendingPromise;
1110
+ if (route._componentsPromise) await route._componentsPromise;
1111
+ innerLoadContext.updateMatch(matchId, (prev) => ({
1112
+ ...prev,
1113
+ error: void 0,
1114
+ status: "success",
1115
+ isFetching: false,
1116
+ updatedAt: Date.now(),
1117
+ ...head
1118
+ }));
1119
+ } catch (e) {
1120
+ let error = e;
1121
+ await this.potentialPendingMinPromise(matchId);
1122
+ this.handleRedirectAndNotFound(
1123
+ innerLoadContext,
1124
+ this.getMatch(matchId),
1125
+ e
1126
+ );
1127
+ try {
1128
+ (_d = (_c = route.options).onError) == null ? void 0 : _d.call(_c, e);
1129
+ } catch (onErrorError) {
1130
+ error = onErrorError;
1131
+ this.handleRedirectAndNotFound(
1132
+ innerLoadContext,
1133
+ this.getMatch(matchId),
1134
+ onErrorError
1135
+ );
1136
+ }
1137
+ const headResult = this.executeHead(innerLoadContext, matchId, route);
1138
+ const head = headResult ? await headResult : void 0;
1139
+ innerLoadContext.updateMatch(matchId, (prev) => ({
1140
+ ...prev,
1141
+ error,
1142
+ status: "error",
1143
+ isFetching: false,
1144
+ ...head
1145
+ }));
1146
+ }
1147
+ } catch (err) {
763
1148
  const match = this.getMatch(matchId);
764
- if (!this.isServer && match._nonReactive.dehydrated) {
765
- return true;
1149
+ if (match) {
1150
+ const headResult = this.executeHead(innerLoadContext, matchId, route);
1151
+ if (headResult) {
1152
+ const head = await headResult;
1153
+ innerLoadContext.updateMatch(matchId, (prev) => ({
1154
+ ...prev,
1155
+ ...head
1156
+ }));
1157
+ }
1158
+ match._nonReactive.loaderPromise = void 0;
766
1159
  }
1160
+ this.handleRedirectAndNotFound(innerLoadContext, match, err);
1161
+ }
1162
+ };
1163
+ this.loadRouteMatch = async (innerLoadContext, index) => {
1164
+ var _a, _b;
1165
+ const { id: matchId, routeId } = innerLoadContext.matches[index];
1166
+ let loaderShouldRunAsync = false;
1167
+ let loaderIsRunningAsync = false;
1168
+ const route = this.looseRoutesById[routeId];
1169
+ const prevMatch = this.getMatch(matchId);
1170
+ if (this.shouldSkipLoader(matchId)) {
767
1171
  if (this.isServer) {
768
- if (match.ssr === false) {
769
- return true;
1172
+ const headResult = this.executeHead(innerLoadContext, matchId, route);
1173
+ if (headResult) {
1174
+ const head = await headResult;
1175
+ innerLoadContext.updateMatch(matchId, (prev) => ({
1176
+ ...prev,
1177
+ ...head
1178
+ }));
770
1179
  }
1180
+ return this.getMatch(matchId);
771
1181
  }
772
- return false;
773
- };
1182
+ } else if (prevMatch._nonReactive.loaderPromise) {
1183
+ if (prevMatch.status === "success" && !innerLoadContext.sync && !prevMatch.preload) {
1184
+ return this.getMatch(matchId);
1185
+ }
1186
+ await prevMatch._nonReactive.loaderPromise;
1187
+ const match = this.getMatch(matchId);
1188
+ if (match.error) {
1189
+ this.handleRedirectAndNotFound(innerLoadContext, match, match.error);
1190
+ }
1191
+ } else {
1192
+ const age = Date.now() - this.getMatch(matchId).updatedAt;
1193
+ const preload = this.resolvePreload(innerLoadContext, matchId);
1194
+ const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
1195
+ const shouldReloadOption = route.options.shouldReload;
1196
+ const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(
1197
+ this.getLoaderContext(innerLoadContext, matchId, index, route)
1198
+ ) : shouldReloadOption;
1199
+ innerLoadContext.updateMatch(matchId, (prev) => {
1200
+ prev._nonReactive.loaderPromise = createControlledPromise();
1201
+ return {
1202
+ ...prev,
1203
+ preload: !!preload && !this.state.matches.some((d) => d.id === matchId)
1204
+ };
1205
+ });
1206
+ const { status, invalid } = this.getMatch(matchId);
1207
+ loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? age > staleAge));
1208
+ if (preload && route.options.preload === false) ;
1209
+ else if (loaderShouldRunAsync && !innerLoadContext.sync) {
1210
+ loaderIsRunningAsync = true;
1211
+ (async () => {
1212
+ var _a2, _b2;
1213
+ try {
1214
+ await this.runLoader(innerLoadContext, matchId, index, route);
1215
+ const match = this.getMatch(matchId);
1216
+ (_a2 = match._nonReactive.loaderPromise) == null ? void 0 : _a2.resolve();
1217
+ (_b2 = match._nonReactive.loadPromise) == null ? void 0 : _b2.resolve();
1218
+ match._nonReactive.loaderPromise = void 0;
1219
+ } catch (err) {
1220
+ if (isRedirect(err)) {
1221
+ await this.navigate(err.options);
1222
+ }
1223
+ }
1224
+ })();
1225
+ } else if (status !== "success" || loaderShouldRunAsync && innerLoadContext.sync) {
1226
+ await this.runLoader(innerLoadContext, matchId, index, route);
1227
+ } else {
1228
+ const headResult = this.executeHead(innerLoadContext, matchId, route);
1229
+ if (headResult) {
1230
+ const head = await headResult;
1231
+ innerLoadContext.updateMatch(matchId, (prev) => ({
1232
+ ...prev,
1233
+ ...head
1234
+ }));
1235
+ }
1236
+ }
1237
+ }
1238
+ if (!loaderIsRunningAsync) {
1239
+ const match = this.getMatch(matchId);
1240
+ (_a = match._nonReactive.loaderPromise) == null ? void 0 : _a.resolve();
1241
+ (_b = match._nonReactive.loadPromise) == null ? void 0 : _b.resolve();
1242
+ }
1243
+ innerLoadContext.updateMatch(matchId, (prev) => {
1244
+ clearTimeout(prev._nonReactive.pendingTimeout);
1245
+ prev._nonReactive.pendingTimeout = void 0;
1246
+ if (!loaderIsRunningAsync) prev._nonReactive.loaderPromise = void 0;
1247
+ prev._nonReactive.dehydrated = void 0;
1248
+ return {
1249
+ ...prev,
1250
+ isFetching: loaderIsRunningAsync ? prev.isFetching : false,
1251
+ invalid: false
1252
+ };
1253
+ });
1254
+ return this.getMatch(matchId);
1255
+ };
1256
+ this.loadMatches = async (baseContext) => {
1257
+ const innerLoadContext = baseContext;
1258
+ innerLoadContext.updateMatch ?? (innerLoadContext.updateMatch = this.updateMatch);
1259
+ innerLoadContext.matchPromises = [];
1260
+ if (!this.isServer && this.state.matches.some((d) => d._forcePending)) {
1261
+ this.triggerOnReady(innerLoadContext);
1262
+ }
774
1263
  try {
775
1264
  await new Promise((resolveAll, rejectAll) => {
776
1265
  ;
777
1266
  (async () => {
778
- var _a, _b, _c, _d;
779
1267
  try {
780
- const handleSerialError = (index, err, routerCode) => {
781
- var _a2, _b2;
782
- const { id: matchId, routeId } = matches[index];
783
- const route = this.looseRoutesById[routeId];
784
- if (err instanceof Promise) {
785
- throw err;
786
- }
787
- err.routerCode = routerCode;
788
- firstBadMatchIndex = firstBadMatchIndex ?? index;
789
- handleRedirectAndNotFound(this.getMatch(matchId), err);
790
- try {
791
- (_b2 = (_a2 = route.options).onError) == null ? void 0 : _b2.call(_a2, err);
792
- } catch (errorHandlerErr) {
793
- err = errorHandlerErr;
794
- handleRedirectAndNotFound(this.getMatch(matchId), err);
795
- }
796
- updateMatch(matchId, (prev) => {
797
- var _a3, _b3;
798
- (_a3 = prev._nonReactive.beforeLoadPromise) == null ? void 0 : _a3.resolve();
799
- prev._nonReactive.beforeLoadPromise = void 0;
800
- (_b3 = prev._nonReactive.loadPromise) == null ? void 0 : _b3.resolve();
801
- return {
802
- ...prev,
803
- error: err,
804
- status: "error",
805
- isFetching: false,
806
- updatedAt: Date.now(),
807
- abortController: new AbortController()
808
- };
809
- });
810
- };
811
- for (const [index, { id: matchId, routeId }] of matches.entries()) {
812
- const existingMatch = this.getMatch(matchId);
813
- const parentMatchId = (_a = matches[index - 1]) == null ? void 0 : _a.id;
814
- const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
815
- const route = this.looseRoutesById[routeId];
816
- const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
817
- if (this.isServer) {
818
- let ssr;
819
- if (this.isShell()) {
820
- ssr = matchId === rootRouteId;
821
- } else {
822
- const defaultSsr = this.options.defaultSsr ?? true;
823
- if ((parentMatch == null ? void 0 : parentMatch.ssr) === false) {
824
- ssr = false;
825
- } else {
826
- let tempSsr;
827
- if (route.options.ssr === void 0) {
828
- tempSsr = defaultSsr;
829
- } else if (typeof route.options.ssr === "function") {
830
- let makeMaybe = function(value, error) {
831
- if (error) {
832
- return { status: "error", error };
833
- }
834
- return { status: "success", value };
835
- };
836
- const { search, params } = this.getMatch(matchId);
837
- const ssrFnContext = {
838
- search: makeMaybe(search, existingMatch.searchError),
839
- params: makeMaybe(params, existingMatch.paramsError),
840
- location,
841
- matches: matches.map((match) => ({
842
- index: match.index,
843
- pathname: match.pathname,
844
- fullPath: match.fullPath,
845
- staticData: match.staticData,
846
- id: match.id,
847
- routeId: match.routeId,
848
- search: makeMaybe(match.search, match.searchError),
849
- params: makeMaybe(match.params, match.paramsError),
850
- ssr: match.ssr
851
- }))
852
- };
853
- tempSsr = await route.options.ssr(ssrFnContext) ?? defaultSsr;
854
- } else {
855
- tempSsr = route.options.ssr;
856
- }
857
- if (tempSsr === true && (parentMatch == null ? void 0 : parentMatch.ssr) === "data-only") {
858
- ssr = "data-only";
859
- } else {
860
- ssr = tempSsr;
861
- }
862
- }
863
- }
864
- existingMatch.ssr = ssr;
865
- }
866
- if (shouldSkipLoader(matchId)) {
867
- continue;
868
- }
869
- const shouldPending = !!(onReady && !this.isServer && !resolvePreload(matchId) && (route.options.loader || route.options.beforeLoad || routeNeedsPreload(route)) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? ((_b = this.options) == null ? void 0 : _b.defaultPendingComponent)));
870
- let executeBeforeLoad = true;
871
- const setupPendingTimeout = () => {
872
- const match = this.getMatch(matchId);
873
- if (shouldPending && match._nonReactive.pendingTimeout === void 0) {
874
- const pendingTimeout = setTimeout(() => {
875
- try {
876
- triggerOnReady();
877
- } catch {
878
- }
879
- }, pendingMs);
880
- match._nonReactive.pendingTimeout = pendingTimeout;
881
- }
882
- };
883
- if (
884
- // If we are in the middle of a load, either of these will be present
885
- // (not to be confused with `loadPromise`, which is always defined)
886
- existingMatch._nonReactive.beforeLoadPromise || existingMatch._nonReactive.loaderPromise
887
- ) {
888
- setupPendingTimeout();
889
- await existingMatch._nonReactive.beforeLoadPromise;
890
- const match = this.getMatch(matchId);
891
- if (match.status === "error") {
892
- executeBeforeLoad = true;
893
- } else if (match.preload && (match.status === "redirected" || match.status === "notFound")) {
894
- handleRedirectAndNotFound(match, match.error);
895
- }
896
- }
897
- if (executeBeforeLoad) {
898
- try {
899
- const match = this.getMatch(matchId);
900
- match._nonReactive.beforeLoadPromise = createControlledPromise();
901
- const prevLoadPromise = match._nonReactive.loadPromise;
902
- match._nonReactive.loadPromise = createControlledPromise(() => {
903
- prevLoadPromise == null ? void 0 : prevLoadPromise.resolve();
904
- });
905
- const { paramsError, searchError } = this.getMatch(matchId);
906
- if (paramsError) {
907
- handleSerialError(index, paramsError, "PARSE_PARAMS");
908
- }
909
- if (searchError) {
910
- handleSerialError(index, searchError, "VALIDATE_SEARCH");
911
- }
912
- setupPendingTimeout();
913
- const abortController = new AbortController();
914
- const parentMatchContext = (parentMatch == null ? void 0 : parentMatch.context) ?? this.options.context ?? void 0;
915
- updateMatch(matchId, (prev) => ({
916
- ...prev,
917
- isFetching: "beforeLoad",
918
- fetchCount: prev.fetchCount + 1,
919
- abortController,
920
- context: {
921
- ...parentMatchContext,
922
- ...prev.__routeContext
923
- }
924
- }));
925
- const { search, params, context, cause } = this.getMatch(matchId);
926
- const preload = resolvePreload(matchId);
927
- const beforeLoadFnContext = {
928
- search,
929
- abortController,
930
- params,
931
- preload,
932
- context,
933
- location,
934
- navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
935
- buildLocation: this.buildLocation,
936
- cause: preload ? "preload" : cause,
937
- matches
938
- };
939
- const beforeLoadContext = await ((_d = (_c = route.options).beforeLoad) == null ? void 0 : _d.call(_c, beforeLoadFnContext));
940
- if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
941
- handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
942
- }
943
- updateMatch(matchId, (prev) => {
944
- return {
945
- ...prev,
946
- __beforeLoadContext: beforeLoadContext,
947
- context: {
948
- ...parentMatchContext,
949
- ...prev.__routeContext,
950
- ...beforeLoadContext
951
- },
952
- abortController
953
- };
954
- });
955
- } catch (err) {
956
- handleSerialError(index, err, "BEFORE_LOAD");
957
- }
958
- updateMatch(matchId, (prev) => {
959
- var _a2;
960
- (_a2 = prev._nonReactive.beforeLoadPromise) == null ? void 0 : _a2.resolve();
961
- prev._nonReactive.beforeLoadPromise = void 0;
962
- return {
963
- ...prev,
964
- isFetching: false
965
- };
966
- });
967
- }
1268
+ for (let i = 0; i < innerLoadContext.matches.length; i++) {
1269
+ const beforeLoad = this.handleBeforeLoad(innerLoadContext, i);
1270
+ if (isPromise(beforeLoad)) await beforeLoad;
968
1271
  }
969
- const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
970
- const matchPromises = [];
971
- validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
972
- matchPromises.push(
973
- (async () => {
974
- var _a2, _b2;
975
- let loaderShouldRunAsync = false;
976
- let loaderIsRunningAsync = false;
977
- const route = this.looseRoutesById[routeId];
978
- const executeHead = () => {
979
- var _a3, _b3, _c2, _d2, _e, _f;
980
- const match = this.getMatch(matchId);
981
- if (!match) {
982
- return;
983
- }
984
- if (!route.options.head && !route.options.scripts && !route.options.headers) {
985
- return;
986
- }
987
- const assetContext = {
988
- matches,
989
- match,
990
- params: match.params,
991
- loaderData: match.loaderData
992
- };
993
- return Promise.all([
994
- (_b3 = (_a3 = route.options).head) == null ? void 0 : _b3.call(_a3, assetContext),
995
- (_d2 = (_c2 = route.options).scripts) == null ? void 0 : _d2.call(_c2, assetContext),
996
- (_f = (_e = route.options).headers) == null ? void 0 : _f.call(_e, assetContext)
997
- ]).then(([headFnContent, scripts, headers]) => {
998
- const meta = headFnContent == null ? void 0 : headFnContent.meta;
999
- const links = headFnContent == null ? void 0 : headFnContent.links;
1000
- const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
1001
- const styles = headFnContent == null ? void 0 : headFnContent.styles;
1002
- return {
1003
- meta,
1004
- links,
1005
- headScripts,
1006
- headers,
1007
- scripts,
1008
- styles
1009
- };
1010
- });
1011
- };
1012
- const potentialPendingMinPromise = async () => {
1013
- const latestMatch = this.getMatch(matchId);
1014
- if (latestMatch._nonReactive.minPendingPromise) {
1015
- await latestMatch._nonReactive.minPendingPromise;
1016
- }
1017
- };
1018
- const prevMatch = this.getMatch(matchId);
1019
- if (shouldSkipLoader(matchId)) {
1020
- if (this.isServer) {
1021
- const headResult = executeHead();
1022
- if (headResult) {
1023
- const head = await headResult;
1024
- updateMatch(matchId, (prev) => ({
1025
- ...prev,
1026
- ...head
1027
- }));
1028
- }
1029
- return this.getMatch(matchId);
1030
- }
1031
- } else if (prevMatch._nonReactive.loaderPromise) {
1032
- if (prevMatch.status === "success" && !sync && !prevMatch.preload) {
1033
- return this.getMatch(matchId);
1034
- }
1035
- await prevMatch._nonReactive.loaderPromise;
1036
- const match = this.getMatch(matchId);
1037
- if (match.error) {
1038
- handleRedirectAndNotFound(match, match.error);
1039
- }
1040
- } else {
1041
- const parentMatchPromise = matchPromises[index - 1];
1042
- const getLoaderContext = () => {
1043
- const {
1044
- params,
1045
- loaderDeps,
1046
- abortController,
1047
- context,
1048
- cause
1049
- } = this.getMatch(matchId);
1050
- const preload2 = resolvePreload(matchId);
1051
- return {
1052
- params,
1053
- deps: loaderDeps,
1054
- preload: !!preload2,
1055
- parentMatchPromise,
1056
- abortController,
1057
- context,
1058
- location,
1059
- navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
1060
- cause: preload2 ? "preload" : cause,
1061
- route
1062
- };
1063
- };
1064
- const age = Date.now() - this.getMatch(matchId).updatedAt;
1065
- const preload = resolvePreload(matchId);
1066
- const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
1067
- const shouldReloadOption = route.options.shouldReload;
1068
- const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext()) : shouldReloadOption;
1069
- updateMatch(matchId, (prev) => {
1070
- prev._nonReactive.loaderPromise = createControlledPromise();
1071
- return {
1072
- ...prev,
1073
- preload: !!preload && !this.state.matches.some((d) => d.id === matchId)
1074
- };
1075
- });
1076
- const runLoader = async () => {
1077
- var _a3, _b3, _c2, _d2;
1078
- try {
1079
- try {
1080
- if (!this.isServer || this.isServer && this.getMatch(matchId).ssr === true) {
1081
- this.loadRouteChunk(route);
1082
- }
1083
- updateMatch(matchId, (prev) => ({
1084
- ...prev,
1085
- isFetching: "loader"
1086
- }));
1087
- const loaderData = await ((_b3 = (_a3 = route.options).loader) == null ? void 0 : _b3.call(_a3, getLoaderContext()));
1088
- handleRedirectAndNotFound(
1089
- this.getMatch(matchId),
1090
- loaderData
1091
- );
1092
- updateMatch(matchId, (prev) => ({
1093
- ...prev,
1094
- loaderData
1095
- }));
1096
- await route._lazyPromise;
1097
- const headResult = executeHead();
1098
- const head = headResult ? await headResult : void 0;
1099
- await potentialPendingMinPromise();
1100
- await route._componentsPromise;
1101
- updateMatch(matchId, (prev) => ({
1102
- ...prev,
1103
- error: void 0,
1104
- status: "success",
1105
- isFetching: false,
1106
- updatedAt: Date.now(),
1107
- ...head
1108
- }));
1109
- } catch (e) {
1110
- let error = e;
1111
- await potentialPendingMinPromise();
1112
- handleRedirectAndNotFound(this.getMatch(matchId), e);
1113
- try {
1114
- (_d2 = (_c2 = route.options).onError) == null ? void 0 : _d2.call(_c2, e);
1115
- } catch (onErrorError) {
1116
- error = onErrorError;
1117
- handleRedirectAndNotFound(
1118
- this.getMatch(matchId),
1119
- onErrorError
1120
- );
1121
- }
1122
- const headResult = executeHead();
1123
- const head = headResult ? await headResult : void 0;
1124
- updateMatch(matchId, (prev) => ({
1125
- ...prev,
1126
- error,
1127
- status: "error",
1128
- isFetching: false,
1129
- ...head
1130
- }));
1131
- }
1132
- } catch (err) {
1133
- const match = this.getMatch(matchId);
1134
- if (match) {
1135
- const headResult = executeHead();
1136
- if (headResult) {
1137
- const head = await headResult;
1138
- updateMatch(matchId, (prev) => ({
1139
- ...prev,
1140
- ...head
1141
- }));
1142
- }
1143
- match._nonReactive.loaderPromise = void 0;
1144
- }
1145
- handleRedirectAndNotFound(match, err);
1146
- }
1147
- };
1148
- const { status, invalid } = this.getMatch(matchId);
1149
- loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? age > staleAge));
1150
- if (preload && route.options.preload === false) {
1151
- } else if (loaderShouldRunAsync && !sync) {
1152
- loaderIsRunningAsync = true;
1153
- (async () => {
1154
- var _a3, _b3;
1155
- try {
1156
- await runLoader();
1157
- const match = this.getMatch(matchId);
1158
- (_a3 = match._nonReactive.loaderPromise) == null ? void 0 : _a3.resolve();
1159
- (_b3 = match._nonReactive.loadPromise) == null ? void 0 : _b3.resolve();
1160
- match._nonReactive.loaderPromise = void 0;
1161
- } catch (err) {
1162
- if (isRedirect(err)) {
1163
- await this.navigate(err.options);
1164
- }
1165
- }
1166
- })();
1167
- } else if (status !== "success" || loaderShouldRunAsync && sync) {
1168
- await runLoader();
1169
- } else {
1170
- const headResult = executeHead();
1171
- if (headResult) {
1172
- const head = await headResult;
1173
- updateMatch(matchId, (prev) => ({
1174
- ...prev,
1175
- ...head
1176
- }));
1177
- }
1178
- }
1179
- }
1180
- if (!loaderIsRunningAsync) {
1181
- const match = this.getMatch(matchId);
1182
- (_a2 = match._nonReactive.loaderPromise) == null ? void 0 : _a2.resolve();
1183
- (_b2 = match._nonReactive.loadPromise) == null ? void 0 : _b2.resolve();
1184
- }
1185
- updateMatch(matchId, (prev) => {
1186
- clearTimeout(prev._nonReactive.pendingTimeout);
1187
- prev._nonReactive.pendingTimeout = void 0;
1188
- if (!loaderIsRunningAsync)
1189
- prev._nonReactive.loaderPromise = void 0;
1190
- prev._nonReactive.dehydrated = void 0;
1191
- return {
1192
- ...prev,
1193
- isFetching: loaderIsRunningAsync ? prev.isFetching : false,
1194
- invalid: false
1195
- };
1196
- });
1197
- return this.getMatch(matchId);
1198
- })()
1272
+ const max = innerLoadContext.firstBadMatchIndex ?? innerLoadContext.matches.length;
1273
+ for (let i = 0; i < max; i++) {
1274
+ innerLoadContext.matchPromises.push(
1275
+ this.loadRouteMatch(innerLoadContext, i)
1199
1276
  );
1200
- });
1201
- await Promise.all(matchPromises);
1277
+ }
1278
+ await Promise.all(innerLoadContext.matchPromises);
1202
1279
  resolveAll();
1203
1280
  } catch (err) {
1204
1281
  rejectAll(err);
1205
1282
  }
1206
1283
  })();
1207
1284
  });
1208
- await triggerOnReady();
1285
+ const readyPromise = this.triggerOnReady(innerLoadContext);
1286
+ if (isPromise(readyPromise)) await readyPromise;
1209
1287
  } catch (err) {
1210
- if (isRedirect(err) || isNotFound(err)) {
1211
- if (isNotFound(err) && !allPreload) {
1212
- await triggerOnReady();
1213
- }
1288
+ if (isNotFound(err) && !innerLoadContext.preload) {
1289
+ const readyPromise = this.triggerOnReady(innerLoadContext);
1290
+ if (isPromise(readyPromise)) await readyPromise;
1291
+ throw err;
1292
+ }
1293
+ if (isRedirect(err)) {
1214
1294
  throw err;
1215
1295
  }
1216
1296
  }
1217
- return matches;
1297
+ return innerLoadContext.matches;
1218
1298
  };
1219
1299
  this.invalidate = (opts) => {
1220
1300
  const invalidate = (d) => {
@@ -1285,27 +1365,36 @@ class RouterCore {
1285
1365
  this.clearCache({ filter });
1286
1366
  };
1287
1367
  this.loadRouteChunk = (route) => {
1288
- if (route._lazyPromise === void 0) {
1368
+ if (!route._lazyLoaded && route._lazyPromise === void 0) {
1289
1369
  if (route.lazyFn) {
1290
1370
  route._lazyPromise = route.lazyFn().then((lazyRoute) => {
1291
1371
  const { id: _id, ...options2 } = lazyRoute.options;
1292
1372
  Object.assign(route.options, options2);
1373
+ route._lazyLoaded = true;
1374
+ route._lazyPromise = void 0;
1293
1375
  });
1294
1376
  } else {
1295
- route._lazyPromise = Promise.resolve();
1377
+ route._lazyLoaded = true;
1296
1378
  }
1297
1379
  }
1298
- if (route._componentsPromise === void 0) {
1299
- route._componentsPromise = route._lazyPromise.then(
1300
- () => Promise.all(
1301
- componentTypes.map(async (type) => {
1302
- const component = route.options[type];
1303
- if (component == null ? void 0 : component.preload) {
1304
- await component.preload();
1305
- }
1306
- })
1307
- )
1308
- );
1380
+ if (!route._componentsLoaded && route._componentsPromise === void 0) {
1381
+ const loadComponents = () => {
1382
+ var _a;
1383
+ const preloads = [];
1384
+ for (const type of componentTypes) {
1385
+ const preload = (_a = route.options[type]) == null ? void 0 : _a.preload;
1386
+ if (preload) preloads.push(preload());
1387
+ }
1388
+ if (preloads.length)
1389
+ return Promise.all(preloads).then(() => {
1390
+ route._componentsLoaded = true;
1391
+ route._componentsPromise = void 0;
1392
+ });
1393
+ route._componentsLoaded = true;
1394
+ route._componentsPromise = void 0;
1395
+ return;
1396
+ };
1397
+ route._componentsPromise = route._lazyPromise ? route._lazyPromise.then(loadComponents) : loadComponents();
1309
1398
  }
1310
1399
  return route._componentsPromise;
1311
1400
  };
@@ -1403,11 +1492,11 @@ class RouterCore {
1403
1492
  }
1404
1493
  return match;
1405
1494
  };
1406
- this._handleNotFound = (matches, err, updateMatch = this.updateMatch) => {
1495
+ this._handleNotFound = (innerLoadContext, err) => {
1407
1496
  var _a;
1408
1497
  const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
1409
1498
  const matchesByRouteId = {};
1410
- for (const match of matches) {
1499
+ for (const match of innerLoadContext.matches) {
1411
1500
  matchesByRouteId[match.routeId] = match;
1412
1501
  }
1413
1502
  if (!routeCursor.options.notFoundComponent && ((_a = this.options) == null ? void 0 : _a.defaultNotFoundComponent)) {
@@ -1422,7 +1511,7 @@ class RouterCore {
1422
1511
  matchForRoute,
1423
1512
  "Could not find match for route: " + routeCursor.id
1424
1513
  );
1425
- updateMatch(matchForRoute.id, (prev) => ({
1514
+ innerLoadContext.updateMatch(matchForRoute.id, (prev) => ({
1426
1515
  ...prev,
1427
1516
  status: "notFound",
1428
1517
  error: err,
@@ -1430,7 +1519,7 @@ class RouterCore {
1430
1519
  }));
1431
1520
  if (err.routerCode === "BEFORE_LOAD" && routeCursor.parentRoute) {
1432
1521
  err.routeId = routeCursor.parentRoute.id;
1433
- this._handleNotFound(matches, err, updateMatch);
1522
+ this._handleNotFound(innerLoadContext, err);
1434
1523
  }
1435
1524
  };
1436
1525
  this.hasNotFoundMatch = () => {
@@ -1669,6 +1758,12 @@ class SearchParamError extends Error {
1669
1758
  }
1670
1759
  class PathParamError extends Error {
1671
1760
  }
1761
+ function makeMaybe(value, error) {
1762
+ if (error) {
1763
+ return { status: "error", error };
1764
+ }
1765
+ return { status: "success", value };
1766
+ }
1672
1767
  const normalize = (str) => str.endsWith("/") && str.length > 1 ? str.slice(0, -1) : str;
1673
1768
  function comparePaths(a, b) {
1674
1769
  return normalize(a) === normalize(b);