@tanstack/router-core 1.120.4 → 1.121.0-alpha.1

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 (51) hide show
  1. package/dist/cjs/fileRoute.d.cts +6 -2
  2. package/dist/cjs/index.cjs +3 -0
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs/index.d.cts +6 -6
  5. package/dist/cjs/link.cjs.map +1 -1
  6. package/dist/cjs/link.d.cts +18 -1
  7. package/dist/cjs/path.cjs +130 -16
  8. package/dist/cjs/path.cjs.map +1 -1
  9. package/dist/cjs/path.d.cts +17 -0
  10. package/dist/cjs/redirect.cjs +17 -14
  11. package/dist/cjs/redirect.cjs.map +1 -1
  12. package/dist/cjs/redirect.d.cts +13 -7
  13. package/dist/cjs/route.cjs +12 -1
  14. package/dist/cjs/route.cjs.map +1 -1
  15. package/dist/cjs/route.d.cts +17 -18
  16. package/dist/cjs/router.cjs +290 -211
  17. package/dist/cjs/router.cjs.map +1 -1
  18. package/dist/cjs/router.d.cts +46 -3
  19. package/dist/cjs/typePrimitives.d.cts +2 -2
  20. package/dist/cjs/utils.cjs.map +1 -1
  21. package/dist/cjs/utils.d.cts +2 -0
  22. package/dist/esm/fileRoute.d.ts +6 -2
  23. package/dist/esm/index.d.ts +6 -6
  24. package/dist/esm/index.js +5 -2
  25. package/dist/esm/link.d.ts +18 -1
  26. package/dist/esm/link.js.map +1 -1
  27. package/dist/esm/path.d.ts +17 -0
  28. package/dist/esm/path.js +130 -16
  29. package/dist/esm/path.js.map +1 -1
  30. package/dist/esm/redirect.d.ts +13 -7
  31. package/dist/esm/redirect.js +17 -14
  32. package/dist/esm/redirect.js.map +1 -1
  33. package/dist/esm/route.d.ts +17 -18
  34. package/dist/esm/route.js +12 -1
  35. package/dist/esm/route.js.map +1 -1
  36. package/dist/esm/router.d.ts +46 -3
  37. package/dist/esm/router.js +293 -214
  38. package/dist/esm/router.js.map +1 -1
  39. package/dist/esm/typePrimitives.d.ts +2 -2
  40. package/dist/esm/utils.d.ts +2 -0
  41. package/dist/esm/utils.js.map +1 -1
  42. package/package.json +2 -2
  43. package/src/fileRoute.ts +90 -1
  44. package/src/index.ts +14 -6
  45. package/src/link.ts +97 -11
  46. package/src/path.ts +181 -16
  47. package/src/redirect.ts +37 -22
  48. package/src/route.ts +119 -39
  49. package/src/router.ts +393 -269
  50. package/src/typePrimitives.ts +2 -2
  51. package/src/utils.ts +14 -0
@@ -2,12 +2,12 @@ import { Store, batch } from "@tanstack/store";
2
2
  import { createMemoryHistory, createBrowserHistory, parseHref } from "@tanstack/history";
3
3
  import invariant from "tiny-invariant";
4
4
  import { pick, createControlledPromise, deepEqual, replaceEqualDeep, last, functionalUpdate } from "./utils.js";
5
- import { trimPath, trimPathLeft, parsePathname, resolvePath, cleanPath, trimPathRight, matchPathname, interpolatePath, joinPaths } from "./path.js";
5
+ import { trimPath, resolvePath, cleanPath, matchPathname, trimPathRight, interpolatePath, joinPaths, trimPathLeft, parsePathname } from "./path.js";
6
6
  import { isNotFound } from "./not-found.js";
7
7
  import { setupScrollRestoration } from "./scroll-restoration.js";
8
8
  import { defaultParseSearch, defaultStringifySearch } from "./searchParams.js";
9
9
  import { rootRouteId } from "./root.js";
10
- import { isResolvedRedirect, isRedirect } from "./redirect.js";
10
+ import { isRedirect } from "./redirect.js";
11
11
  function defaultSerializeError(err) {
12
12
  if (err instanceof Error) {
13
13
  const obj = {
@@ -46,6 +46,7 @@ class RouterCore {
46
46
  this.isScrollRestoring = false;
47
47
  this.isScrollRestorationSetup = false;
48
48
  this.startTransition = (fn) => fn();
49
+ this.isShell = false;
49
50
  this.update = (newOptions) => {
50
51
  var _a;
51
52
  if (newOptions.notFoundRoute) {
@@ -72,10 +73,7 @@ class RouterCore {
72
73
  this.basepath = `/${trimPath(newOptions.basepath)}`;
73
74
  }
74
75
  }
75
- if (
76
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
77
- !this.history || this.options.history && this.options.history !== this.history
78
- ) {
76
+ if (!this.history || this.options.history && this.options.history !== this.history) {
79
77
  this.history = this.options.history ?? (this.isServer ? createMemoryHistory({
80
78
  initialEntries: [this.basepath || "/"]
81
79
  }) : createBrowserHistory());
@@ -98,16 +96,28 @@ class RouterCore {
98
96
  });
99
97
  setupScrollRestoration(this);
100
98
  }
101
- if (typeof window !== "undefined" && "CSS" in window && // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
102
- typeof ((_a = window.CSS) == null ? void 0 : _a.supports) === "function") {
99
+ if (typeof window !== "undefined" && "CSS" in window && typeof ((_a = window.CSS) == null ? void 0 : _a.supports) === "function") {
103
100
  this.isViewTransitionTypesSupported = window.CSS.supports(
104
101
  "selector(:active-view-transition-type(a)"
105
102
  );
106
103
  }
104
+ if (this.latestLocation.search.__TSS_SHELL) {
105
+ this.isShell = true;
106
+ }
107
107
  };
108
108
  this.buildRouteTree = () => {
109
- this.routesById = {};
110
- this.routesByPath = {};
109
+ const { routesById, routesByPath, flatRoutes } = processRouteTree({
110
+ routeTree: this.routeTree,
111
+ initRoute: (route, i) => {
112
+ route.init({
113
+ originalIndex: i,
114
+ defaultSsr: this.options.defaultSsr
115
+ });
116
+ }
117
+ });
118
+ this.routesById = routesById;
119
+ this.routesByPath = routesByPath;
120
+ this.flatRoutes = flatRoutes;
111
121
  const notFoundRoute = this.options.notFoundRoute;
112
122
  if (notFoundRoute) {
113
123
  notFoundRoute.init({
@@ -116,77 +126,6 @@ class RouterCore {
116
126
  });
117
127
  this.routesById[notFoundRoute.id] = notFoundRoute;
118
128
  }
119
- const recurseRoutes = (childRoutes) => {
120
- childRoutes.forEach((childRoute, i) => {
121
- childRoute.init({
122
- originalIndex: i,
123
- defaultSsr: this.options.defaultSsr
124
- });
125
- const existingRoute = this.routesById[childRoute.id];
126
- invariant(
127
- !existingRoute,
128
- `Duplicate routes found with id: ${String(childRoute.id)}`
129
- );
130
- this.routesById[childRoute.id] = childRoute;
131
- if (!childRoute.isRoot && childRoute.path) {
132
- const trimmedFullPath = trimPathRight(childRoute.fullPath);
133
- if (!this.routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith("/")) {
134
- this.routesByPath[trimmedFullPath] = childRoute;
135
- }
136
- }
137
- const children = childRoute.children;
138
- if (children == null ? void 0 : children.length) {
139
- recurseRoutes(children);
140
- }
141
- });
142
- };
143
- recurseRoutes([this.routeTree]);
144
- const scoredRoutes = [];
145
- const routes = Object.values(this.routesById);
146
- routes.forEach((d, i) => {
147
- var _a;
148
- if (d.isRoot || !d.path) {
149
- return;
150
- }
151
- const trimmed = trimPathLeft(d.fullPath);
152
- const parsed = parsePathname(trimmed);
153
- while (parsed.length > 1 && ((_a = parsed[0]) == null ? void 0 : _a.value) === "/") {
154
- parsed.shift();
155
- }
156
- const scores = parsed.map((segment) => {
157
- if (segment.value === "/") {
158
- return 0.75;
159
- }
160
- if (segment.type === "param") {
161
- return 0.5;
162
- }
163
- if (segment.type === "wildcard") {
164
- return 0.25;
165
- }
166
- return 1;
167
- });
168
- scoredRoutes.push({ child: d, trimmed, parsed, index: i, scores });
169
- });
170
- this.flatRoutes = scoredRoutes.sort((a, b) => {
171
- const minLength = Math.min(a.scores.length, b.scores.length);
172
- for (let i = 0; i < minLength; i++) {
173
- if (a.scores[i] !== b.scores[i]) {
174
- return b.scores[i] - a.scores[i];
175
- }
176
- }
177
- if (a.scores.length !== b.scores.length) {
178
- return b.scores.length - a.scores.length;
179
- }
180
- for (let i = 0; i < minLength; i++) {
181
- if (a.parsed[i].value !== b.parsed[i].value) {
182
- return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
183
- }
184
- }
185
- return a.index - b.index;
186
- }).map((d, i) => {
187
- d.child.rank = i;
188
- return d.child;
189
- });
190
129
  };
191
130
  this.subscribe = (eventType, fn) => {
192
131
  const listener = {
@@ -259,37 +198,16 @@ class RouterCore {
259
198
  return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
260
199
  }
261
200
  };
262
- this.getMatchedRoutes = (next, dest) => {
263
- let routeParams = {};
264
- const trimmedPath = trimPathRight(next.pathname);
265
- const getMatchedParams = (route) => {
266
- const result = matchPathname(this.basepath, trimmedPath, {
267
- to: route.fullPath,
268
- caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
269
- fuzzy: true
270
- });
271
- return result;
272
- };
273
- let foundRoute = (dest == null ? void 0 : dest.to) !== void 0 ? this.routesByPath[dest.to] : void 0;
274
- if (foundRoute) {
275
- routeParams = getMatchedParams(foundRoute);
276
- } else {
277
- foundRoute = this.flatRoutes.find((route) => {
278
- const matchedParams = getMatchedParams(route);
279
- if (matchedParams) {
280
- routeParams = matchedParams;
281
- return true;
282
- }
283
- return false;
284
- });
285
- }
286
- let routeCursor = foundRoute || this.routesById[rootRouteId];
287
- const matchedRoutes = [routeCursor];
288
- while (routeCursor.parentRoute) {
289
- routeCursor = routeCursor.parentRoute;
290
- matchedRoutes.unshift(routeCursor);
291
- }
292
- return { matchedRoutes, routeParams, foundRoute };
201
+ this.getMatchedRoutes = (pathname, routePathname) => {
202
+ return getMatchedRoutes({
203
+ pathname,
204
+ routePathname,
205
+ basepath: this.basepath,
206
+ caseSensitive: this.options.caseSensitive,
207
+ routesByPath: this.routesByPath,
208
+ routesById: this.routesById,
209
+ flatRoutes: this.flatRoutes
210
+ });
293
211
  };
294
212
  this.cancelMatch = (id) => {
295
213
  const match = this.getMatch(id);
@@ -502,10 +420,16 @@ class RouterCore {
502
420
  maskedNext = build(maskedDest);
503
421
  }
504
422
  }
505
- const nextMatches = this.getMatchedRoutes(next, dest);
423
+ const nextMatches = this.getMatchedRoutes(
424
+ next.pathname,
425
+ dest.to
426
+ );
506
427
  const final = build(dest, nextMatches);
507
428
  if (maskedNext) {
508
- const maskedMatches = this.getMatchedRoutes(maskedNext, maskedDest);
429
+ const maskedMatches = this.getMatchedRoutes(
430
+ maskedNext.pathname,
431
+ maskedDest == null ? void 0 : maskedDest.to
432
+ );
509
433
  const maskedFinal = build(maskedDest, maskedMatches);
510
434
  final.maskedLocation = maskedFinal;
511
435
  }
@@ -616,6 +540,13 @@ class RouterCore {
616
540
  });
617
541
  };
618
542
  this.navigate = ({ to, reloadDocument, href, ...rest }) => {
543
+ if (!reloadDocument && href) {
544
+ try {
545
+ new URL(`${href}`);
546
+ reloadDocument = true;
547
+ } catch {
548
+ }
549
+ }
619
550
  if (reloadDocument) {
620
551
  if (!href) {
621
552
  const location = this.buildLocation({ to, ...rest });
@@ -634,8 +565,23 @@ class RouterCore {
634
565
  to
635
566
  });
636
567
  };
637
- this.load = async (opts) => {
568
+ this.beforeLoad = () => {
569
+ this.cancelMatches();
638
570
  this.latestLocation = this.parseLocation(this.latestLocation);
571
+ const pendingMatches = this.matchRoutes(this.latestLocation);
572
+ this.__store.setState((s) => ({
573
+ ...s,
574
+ status: "pending",
575
+ isLoading: true,
576
+ location: this.latestLocation,
577
+ pendingMatches,
578
+ // If a cached moved to pendingMatches, remove it from cachedMatches
579
+ cachedMatches: s.cachedMatches.filter((d) => {
580
+ return !pendingMatches.find((e) => e.id === d.id);
581
+ })
582
+ }));
583
+ };
584
+ this.load = async (opts) => {
639
585
  let redirect;
640
586
  let notFound;
641
587
  let loadPromise;
@@ -643,24 +589,9 @@ class RouterCore {
643
589
  this.startTransition(async () => {
644
590
  var _a;
645
591
  try {
592
+ this.beforeLoad();
646
593
  const next = this.latestLocation;
647
594
  const prevLocation = this.state.resolvedLocation;
648
- this.cancelMatches();
649
- let pendingMatches;
650
- batch(() => {
651
- pendingMatches = this.matchRoutes(next);
652
- this.__store.setState((s) => ({
653
- ...s,
654
- status: "pending",
655
- isLoading: true,
656
- location: next,
657
- pendingMatches,
658
- // If a cached moved to pendingMatches, remove it from cachedMatches
659
- cachedMatches: s.cachedMatches.filter((d) => {
660
- return !pendingMatches.find((e) => e.id === d.id);
661
- })
662
- }));
663
- });
664
595
  if (!this.state.redirect) {
665
596
  this.emit({
666
597
  type: "onBeforeNavigate",
@@ -679,7 +610,7 @@ class RouterCore {
679
610
  });
680
611
  await this.loadMatches({
681
612
  sync: opts == null ? void 0 : opts.sync,
682
- matches: pendingMatches,
613
+ matches: this.state.pendingMatches,
683
614
  location: next,
684
615
  // eslint-disable-next-line @typescript-eslint/require-await
685
616
  onReady: async () => {
@@ -728,11 +659,11 @@ class RouterCore {
728
659
  }
729
660
  });
730
661
  } catch (err) {
731
- if (isResolvedRedirect(err)) {
662
+ if (isRedirect(err)) {
732
663
  redirect = err;
733
664
  if (!this.isServer) {
734
665
  this.navigate({
735
- ...redirect,
666
+ ...redirect.options,
736
667
  replace: true,
737
668
  ignoreBlocker: true
738
669
  });
@@ -742,7 +673,7 @@ class RouterCore {
742
673
  }
743
674
  this.__store.setState((s) => ({
744
675
  ...s,
745
- statusCode: redirect ? redirect.statusCode : notFound ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200,
676
+ statusCode: redirect ? redirect.status : notFound ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200,
746
677
  redirect
747
678
  }));
748
679
  }
@@ -840,12 +771,14 @@ class RouterCore {
840
771
  };
841
772
  const handleRedirectAndNotFound = (match, err) => {
842
773
  var _a, _b, _c, _d;
843
- if (isResolvedRedirect(err)) {
844
- if (!err.reloadDocument) {
845
- throw err;
846
- }
847
- }
848
774
  if (isRedirect(err) || isNotFound(err)) {
775
+ if (isRedirect(err)) {
776
+ if (err.redirectHandled) {
777
+ if (!err.options.reloadDocument) {
778
+ throw err;
779
+ }
780
+ }
781
+ }
849
782
  updateMatch(match.id, (prev) => ({
850
783
  ...prev,
851
784
  status: isRedirect(err) ? "redirected" : isNotFound(err) ? "notFound" : "error",
@@ -862,7 +795,9 @@ class RouterCore {
862
795
  (_c = match.loadPromise) == null ? void 0 : _c.resolve();
863
796
  if (isRedirect(err)) {
864
797
  rendered = true;
865
- err = this.resolveRedirect({ ...err, _fromLocation: location });
798
+ err.options._fromLocation = location;
799
+ err.redirectHandled = true;
800
+ err = this.resolveRedirect(err);
866
801
  throw err;
867
802
  } else if (isNotFound(err)) {
868
803
  this._handleNotFound(matches, err, {
@@ -1070,8 +1005,35 @@ class RouterCore {
1070
1005
  loaderPromise: createControlledPromise(),
1071
1006
  preload: !!preload && !this.state.matches.find((d) => d.id === matchId)
1072
1007
  }));
1008
+ const executeHead = () => {
1009
+ var _a2, _b2, _c2, _d2, _e, _f;
1010
+ const match = this.getMatch(matchId);
1011
+ if (!match) {
1012
+ return;
1013
+ }
1014
+ const assetContext = {
1015
+ matches,
1016
+ match,
1017
+ params: match.params,
1018
+ loaderData: match.loaderData
1019
+ };
1020
+ const headFnContent = (_b2 = (_a2 = route.options).head) == null ? void 0 : _b2.call(_a2, assetContext);
1021
+ const meta = headFnContent == null ? void 0 : headFnContent.meta;
1022
+ const links = headFnContent == null ? void 0 : headFnContent.links;
1023
+ const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
1024
+ const scripts = (_d2 = (_c2 = route.options).scripts) == null ? void 0 : _d2.call(_c2, assetContext);
1025
+ const headers = (_f = (_e = route.options).headers) == null ? void 0 : _f.call(_e, assetContext);
1026
+ updateMatch(matchId, (prev) => ({
1027
+ ...prev,
1028
+ meta,
1029
+ links,
1030
+ headScripts,
1031
+ headers,
1032
+ scripts
1033
+ }));
1034
+ };
1073
1035
  const runLoader = async () => {
1074
- var _a2, _b2, _c2, _d2, _e, _f, _g, _h, _i, _j, _k;
1036
+ var _a2, _b2, _c2, _d2, _e;
1075
1037
  try {
1076
1038
  const potentialPendingMinPromise = async () => {
1077
1039
  const latestMatch = this.getMatch(matchId);
@@ -1092,40 +1054,24 @@ class RouterCore {
1092
1054
  );
1093
1055
  await route._lazyPromise;
1094
1056
  await potentialPendingMinPromise();
1095
- const assetContext = {
1096
- matches,
1097
- match: this.getMatch(matchId),
1098
- params: this.getMatch(matchId).params,
1099
- loaderData
1100
- };
1101
- const headFnContent = (_d2 = (_c2 = route.options).head) == null ? void 0 : _d2.call(_c2, assetContext);
1102
- const meta = headFnContent == null ? void 0 : headFnContent.meta;
1103
- const links = headFnContent == null ? void 0 : headFnContent.links;
1104
- const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
1105
- const scripts = (_f = (_e = route.options).scripts) == null ? void 0 : _f.call(_e, assetContext);
1106
- const headers = (_h = (_g = route.options).headers) == null ? void 0 : _h.call(_g, {
1107
- loaderData
1108
- });
1109
1057
  await route._componentsPromise;
1110
- updateMatch(matchId, (prev) => ({
1111
- ...prev,
1112
- error: void 0,
1113
- status: "success",
1114
- isFetching: false,
1115
- updatedAt: Date.now(),
1116
- loaderData,
1117
- meta,
1118
- links,
1119
- headScripts,
1120
- headers,
1121
- scripts
1122
- }));
1058
+ batch(() => {
1059
+ updateMatch(matchId, (prev) => ({
1060
+ ...prev,
1061
+ error: void 0,
1062
+ status: "success",
1063
+ isFetching: false,
1064
+ updatedAt: Date.now(),
1065
+ loaderData
1066
+ }));
1067
+ executeHead();
1068
+ });
1123
1069
  } catch (e) {
1124
1070
  let error = e;
1125
1071
  await potentialPendingMinPromise();
1126
1072
  handleRedirectAndNotFound(this.getMatch(matchId), e);
1127
1073
  try {
1128
- (_j = (_i = route.options).onError) == null ? void 0 : _j.call(_i, e);
1074
+ (_d2 = (_c2 = route.options).onError) == null ? void 0 : _d2.call(_c2, e);
1129
1075
  } catch (onErrorError) {
1130
1076
  error = onErrorError;
1131
1077
  handleRedirectAndNotFound(
@@ -1133,22 +1079,28 @@ class RouterCore {
1133
1079
  onErrorError
1134
1080
  );
1135
1081
  }
1136
- updateMatch(matchId, (prev) => ({
1137
- ...prev,
1138
- error,
1139
- status: "error",
1140
- isFetching: false
1141
- }));
1082
+ batch(() => {
1083
+ updateMatch(matchId, (prev) => ({
1084
+ ...prev,
1085
+ error,
1086
+ status: "error",
1087
+ isFetching: false
1088
+ }));
1089
+ executeHead();
1090
+ });
1142
1091
  }
1143
- (_k = this.serverSsr) == null ? void 0 : _k.onMatchSettled({
1092
+ (_e = this.serverSsr) == null ? void 0 : _e.onMatchSettled({
1144
1093
  router: this,
1145
1094
  match: this.getMatch(matchId)
1146
1095
  });
1147
1096
  } catch (err) {
1148
- updateMatch(matchId, (prev) => ({
1149
- ...prev,
1150
- loaderPromise: void 0
1151
- }));
1097
+ batch(() => {
1098
+ updateMatch(matchId, (prev) => ({
1099
+ ...prev,
1100
+ loaderPromise: void 0
1101
+ }));
1102
+ executeHead();
1103
+ });
1152
1104
  handleRedirectAndNotFound(this.getMatch(matchId), err);
1153
1105
  }
1154
1106
  };
@@ -1168,13 +1120,15 @@ class RouterCore {
1168
1120
  loaderPromise: void 0
1169
1121
  }));
1170
1122
  } catch (err) {
1171
- if (isResolvedRedirect(err)) {
1172
- await this.navigate(err);
1123
+ if (isRedirect(err)) {
1124
+ await this.navigate(err.options);
1173
1125
  }
1174
1126
  }
1175
1127
  })();
1176
1128
  } else if (status !== "success" || loaderShouldRunAsync && sync) {
1177
1129
  await runLoader();
1130
+ } else {
1131
+ executeHead();
1178
1132
  }
1179
1133
  }
1180
1134
  if (!loaderIsRunningAsync) {
@@ -1233,10 +1187,13 @@ class RouterCore {
1233
1187
  });
1234
1188
  return this.load({ sync: opts == null ? void 0 : opts.sync });
1235
1189
  };
1236
- this.resolveRedirect = (err) => {
1237
- const redirect = err;
1238
- if (!redirect.href) {
1239
- redirect.href = this.buildLocation(redirect).href;
1190
+ this.resolveRedirect = (redirect) => {
1191
+ if (!redirect.options.href) {
1192
+ redirect.options.href = this.buildLocation(redirect.options).href;
1193
+ redirect.headers.set("Location", redirect.options.href);
1194
+ }
1195
+ if (!redirect.headers.get("Location")) {
1196
+ redirect.headers.set("Location", redirect.options.href);
1240
1197
  }
1241
1198
  return redirect;
1242
1199
  };
@@ -1338,11 +1295,11 @@ class RouterCore {
1338
1295
  return matches;
1339
1296
  } catch (err) {
1340
1297
  if (isRedirect(err)) {
1341
- if (err.reloadDocument) {
1298
+ if (err.options.reloadDocument) {
1342
1299
  return void 0;
1343
1300
  }
1344
1301
  return await this.preloadRoute({
1345
- ...err,
1302
+ ...err.options,
1346
1303
  _fromLocation: next
1347
1304
  });
1348
1305
  }
@@ -1446,9 +1403,10 @@ class RouterCore {
1446
1403
  return this.routesById;
1447
1404
  }
1448
1405
  matchRoutesInternal(next, opts) {
1406
+ var _a;
1449
1407
  const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
1450
- next,
1451
- opts == null ? void 0 : opts.dest
1408
+ next.pathname,
1409
+ (_a = opts == null ? void 0 : opts.dest) == null ? void 0 : _a.to
1452
1410
  );
1453
1411
  let isGlobalNotFound = false;
1454
1412
  if (
@@ -1479,9 +1437,9 @@ class RouterCore {
1479
1437
  return rootRouteId;
1480
1438
  })();
1481
1439
  const parseErrors = matchedRoutes.map((route) => {
1482
- var _a;
1440
+ var _a2;
1483
1441
  let parsedParamsError;
1484
- const parseParams = ((_a = route.options.params) == null ? void 0 : _a.parse) ?? route.options.parseParams;
1442
+ const parseParams = ((_a2 = route.options.params) == null ? void 0 : _a2.parse) ?? route.options.parseParams;
1485
1443
  if (parseParams) {
1486
1444
  try {
1487
1445
  const parsedParams = parseParams(routeParams);
@@ -1505,7 +1463,7 @@ class RouterCore {
1505
1463
  return parentContext;
1506
1464
  };
1507
1465
  matchedRoutes.forEach((route, index) => {
1508
- var _a, _b;
1466
+ var _a2, _b;
1509
1467
  const parentMatch = matches[index - 1];
1510
1468
  const [preMatchSearch, strictMatchSearch, searchError] = (() => {
1511
1469
  const parentSearch = (parentMatch == null ? void 0 : parentMatch.search) ?? next.search;
@@ -1533,7 +1491,7 @@ class RouterCore {
1533
1491
  return [parentSearch, {}, searchParamError];
1534
1492
  }
1535
1493
  })();
1536
- const loaderDeps = ((_b = (_a = route.options).loaderDeps) == null ? void 0 : _b.call(_a, {
1494
+ const loaderDeps = ((_b = (_a2 = route.options).loaderDeps) == null ? void 0 : _b.call(_a2, {
1537
1495
  search: preMatchSearch
1538
1496
  })) ?? "";
1539
1497
  const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
@@ -1611,7 +1569,7 @@ class RouterCore {
1611
1569
  matches.push(match);
1612
1570
  });
1613
1571
  matches.forEach((match, index) => {
1614
- var _a, _b, _c, _d, _e, _f, _g, _h;
1572
+ var _a2, _b;
1615
1573
  const route = this.looseRoutesById[match.routeId];
1616
1574
  const existingMatch = this.getMatch(match.id);
1617
1575
  if (!existingMatch && (opts == null ? void 0 : opts._buildLocation) !== true) {
@@ -1629,29 +1587,13 @@ class RouterCore {
1629
1587
  preload: !!match.preload,
1630
1588
  matches
1631
1589
  };
1632
- match.__routeContext = ((_b = (_a = route.options).context) == null ? void 0 : _b.call(_a, contextFnContext)) ?? {};
1590
+ match.__routeContext = ((_b = (_a2 = route.options).context) == null ? void 0 : _b.call(_a2, contextFnContext)) ?? {};
1633
1591
  match.context = {
1634
1592
  ...parentContext,
1635
1593
  ...match.__routeContext,
1636
1594
  ...match.__beforeLoadContext
1637
1595
  };
1638
1596
  }
1639
- if (match.status === "success") {
1640
- match.headers = (_d = (_c = route.options).headers) == null ? void 0 : _d.call(_c, {
1641
- loaderData: match.loaderData
1642
- });
1643
- const assetContext = {
1644
- matches,
1645
- match,
1646
- params: match.params,
1647
- loaderData: match.loaderData
1648
- };
1649
- const headFnContent = (_f = (_e = route.options).head) == null ? void 0 : _f.call(_e, assetContext);
1650
- match.links = headFnContent == null ? void 0 : headFnContent.links;
1651
- match.headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
1652
- match.meta = headFnContent == null ? void 0 : headFnContent.meta;
1653
- match.scripts = (_h = (_g = route.options).scripts) == null ? void 0 : _h.call(_g, assetContext);
1654
- }
1655
1597
  });
1656
1598
  return matches;
1657
1599
  }
@@ -1715,6 +1657,141 @@ function routeNeedsPreload(route) {
1715
1657
  }
1716
1658
  return false;
1717
1659
  }
1660
+ function processRouteTree({
1661
+ routeTree,
1662
+ initRoute
1663
+ }) {
1664
+ const routesById = {};
1665
+ const routesByPath = {};
1666
+ const recurseRoutes = (childRoutes) => {
1667
+ childRoutes.forEach((childRoute, i) => {
1668
+ initRoute == null ? void 0 : initRoute(childRoute, i);
1669
+ const existingRoute = routesById[childRoute.id];
1670
+ invariant(
1671
+ !existingRoute,
1672
+ `Duplicate routes found with id: ${String(childRoute.id)}`
1673
+ );
1674
+ routesById[childRoute.id] = childRoute;
1675
+ if (!childRoute.isRoot && childRoute.path) {
1676
+ const trimmedFullPath = trimPathRight(childRoute.fullPath);
1677
+ if (!routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith("/")) {
1678
+ routesByPath[trimmedFullPath] = childRoute;
1679
+ }
1680
+ }
1681
+ const children = childRoute.children;
1682
+ if (children == null ? void 0 : children.length) {
1683
+ recurseRoutes(children);
1684
+ }
1685
+ });
1686
+ };
1687
+ recurseRoutes([routeTree]);
1688
+ const scoredRoutes = [];
1689
+ const routes = Object.values(routesById);
1690
+ routes.forEach((d, i) => {
1691
+ var _a;
1692
+ if (d.isRoot || !d.path) {
1693
+ return;
1694
+ }
1695
+ const trimmed = trimPathLeft(d.fullPath);
1696
+ const parsed = parsePathname(trimmed);
1697
+ while (parsed.length > 1 && ((_a = parsed[0]) == null ? void 0 : _a.value) === "/") {
1698
+ parsed.shift();
1699
+ }
1700
+ const scores = parsed.map((segment) => {
1701
+ if (segment.value === "/") {
1702
+ return 0.75;
1703
+ }
1704
+ if (segment.type === "param" && segment.prefixSegment && segment.suffixSegment) {
1705
+ return 0.55;
1706
+ }
1707
+ if (segment.type === "param" && segment.prefixSegment) {
1708
+ return 0.52;
1709
+ }
1710
+ if (segment.type === "param" && segment.suffixSegment) {
1711
+ return 0.51;
1712
+ }
1713
+ if (segment.type === "param") {
1714
+ return 0.5;
1715
+ }
1716
+ if (segment.type === "wildcard" && segment.prefixSegment && segment.suffixSegment) {
1717
+ return 0.3;
1718
+ }
1719
+ if (segment.type === "wildcard" && segment.prefixSegment) {
1720
+ return 0.27;
1721
+ }
1722
+ if (segment.type === "wildcard" && segment.suffixSegment) {
1723
+ return 0.26;
1724
+ }
1725
+ if (segment.type === "wildcard") {
1726
+ return 0.25;
1727
+ }
1728
+ return 1;
1729
+ });
1730
+ scoredRoutes.push({ child: d, trimmed, parsed, index: i, scores });
1731
+ });
1732
+ const flatRoutes = scoredRoutes.sort((a, b) => {
1733
+ const minLength = Math.min(a.scores.length, b.scores.length);
1734
+ for (let i = 0; i < minLength; i++) {
1735
+ if (a.scores[i] !== b.scores[i]) {
1736
+ return b.scores[i] - a.scores[i];
1737
+ }
1738
+ }
1739
+ if (a.scores.length !== b.scores.length) {
1740
+ return b.scores.length - a.scores.length;
1741
+ }
1742
+ for (let i = 0; i < minLength; i++) {
1743
+ if (a.parsed[i].value !== b.parsed[i].value) {
1744
+ return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
1745
+ }
1746
+ }
1747
+ return a.index - b.index;
1748
+ }).map((d, i) => {
1749
+ d.child.rank = i;
1750
+ return d.child;
1751
+ });
1752
+ return { routesById, routesByPath, flatRoutes };
1753
+ }
1754
+ function getMatchedRoutes({
1755
+ pathname,
1756
+ routePathname,
1757
+ basepath,
1758
+ caseSensitive,
1759
+ routesByPath,
1760
+ routesById,
1761
+ flatRoutes
1762
+ }) {
1763
+ let routeParams = {};
1764
+ const trimmedPath = trimPathRight(pathname);
1765
+ const getMatchedParams = (route) => {
1766
+ var _a;
1767
+ const result = matchPathname(basepath, trimmedPath, {
1768
+ to: route.fullPath,
1769
+ caseSensitive: ((_a = route.options) == null ? void 0 : _a.caseSensitive) ?? caseSensitive,
1770
+ fuzzy: true
1771
+ });
1772
+ return result;
1773
+ };
1774
+ let foundRoute = routePathname !== void 0 ? routesByPath[routePathname] : void 0;
1775
+ if (foundRoute) {
1776
+ routeParams = getMatchedParams(foundRoute);
1777
+ } else {
1778
+ foundRoute = flatRoutes.find((route) => {
1779
+ const matchedParams = getMatchedParams(route);
1780
+ if (matchedParams) {
1781
+ routeParams = matchedParams;
1782
+ return true;
1783
+ }
1784
+ return false;
1785
+ });
1786
+ }
1787
+ let routeCursor = foundRoute || routesById[rootRouteId];
1788
+ const matchedRoutes = [routeCursor];
1789
+ while (routeCursor.parentRoute) {
1790
+ routeCursor = routeCursor.parentRoute;
1791
+ matchedRoutes.unshift(routeCursor);
1792
+ }
1793
+ return { matchedRoutes, routeParams, foundRoute };
1794
+ }
1718
1795
  export {
1719
1796
  PathParamError,
1720
1797
  RouterCore,
@@ -1723,6 +1800,8 @@ export {
1723
1800
  defaultSerializeError,
1724
1801
  getInitialRouterState,
1725
1802
  getLocationChangeInfo,
1726
- lazyFn
1803
+ getMatchedRoutes,
1804
+ lazyFn,
1805
+ processRouteTree
1727
1806
  };
1728
1807
  //# sourceMappingURL=router.js.map