@tanstack/router-core 1.131.14 → 1.131.17

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