@tanstack/router-core 1.120.4-alpha.19 → 1.120.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/fileRoute.d.cts +2 -6
- package/dist/cjs/index.cjs +0 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +6 -6
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +1 -18
- package/dist/cjs/path.cjs +16 -130
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +0 -17
- package/dist/cjs/redirect.cjs +14 -17
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/redirect.d.cts +7 -13
- package/dist/cjs/route.cjs +1 -12
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +14 -15
- package/dist/cjs/router.cjs +155 -231
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -46
- package/dist/cjs/scroll-restoration.cjs +23 -12
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.d.cts +1 -1
- package/dist/cjs/typePrimitives.d.cts +2 -2
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +0 -2
- package/dist/esm/fileRoute.d.ts +2 -6
- package/dist/esm/index.d.ts +6 -6
- package/dist/esm/index.js +2 -5
- package/dist/esm/link.d.ts +1 -18
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/path.d.ts +0 -17
- package/dist/esm/path.js +16 -130
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/redirect.d.ts +7 -13
- package/dist/esm/redirect.js +14 -17
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/route.d.ts +14 -15
- package/dist/esm/route.js +1 -12
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +3 -46
- package/dist/esm/router.js +158 -234
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +1 -1
- package/dist/esm/scroll-restoration.js +23 -12
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/typePrimitives.d.ts +2 -2
- package/dist/esm/utils.d.ts +0 -2
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/fileRoute.ts +1 -90
- package/src/index.ts +6 -14
- package/src/link.ts +11 -97
- package/src/path.ts +16 -181
- package/src/redirect.ts +22 -37
- package/src/route.ts +35 -104
- package/src/router.ts +209 -332
- package/src/scroll-restoration.ts +44 -27
- package/src/typePrimitives.ts +2 -2
- package/src/utils.ts +0 -14
package/src/router.ts
CHANGED
|
@@ -28,7 +28,7 @@ import { isNotFound } from './not-found'
|
|
|
28
28
|
import { setupScrollRestoration } from './scroll-restoration'
|
|
29
29
|
import { defaultParseSearch, defaultStringifySearch } from './searchParams'
|
|
30
30
|
import { rootRouteId } from './root'
|
|
31
|
-
import { isRedirect } from './redirect'
|
|
31
|
+
import { isRedirect, isResolvedRedirect } from './redirect'
|
|
32
32
|
import type { SearchParser, SearchSerializer } from './searchParams'
|
|
33
33
|
import type { AnyRedirect, ResolvedRedirect } from './redirect'
|
|
34
34
|
import type {
|
|
@@ -165,14 +165,6 @@ export interface RouterOptions<
|
|
|
165
165
|
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/preloading#preload-delay)
|
|
166
166
|
*/
|
|
167
167
|
defaultPreloadDelay?: number
|
|
168
|
-
/**
|
|
169
|
-
* The default `preloadIntentProximity` a route should use if no preloadIntentProximity is provided.
|
|
170
|
-
*
|
|
171
|
-
* @default 0
|
|
172
|
-
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#defaultpreloadintentproximity-property)
|
|
173
|
-
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/preloading#preload-intent-proximity)
|
|
174
|
-
*/
|
|
175
|
-
defaultPreloadIntentProximity?: number
|
|
176
168
|
/**
|
|
177
169
|
* The default `pendingMs` a route should use if no pendingMs is provided.
|
|
178
170
|
*
|
|
@@ -415,7 +407,7 @@ export interface RouterState<
|
|
|
415
407
|
location: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
416
408
|
resolvedLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
417
409
|
statusCode: number
|
|
418
|
-
redirect?:
|
|
410
|
+
redirect?: ResolvedRedirect
|
|
419
411
|
}
|
|
420
412
|
|
|
421
413
|
export interface BuildNextOptions {
|
|
@@ -601,8 +593,8 @@ export type ParseLocationFn<TRouteTree extends AnyRoute> = (
|
|
|
601
593
|
) => ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
602
594
|
|
|
603
595
|
export type GetMatchRoutesFn = (
|
|
604
|
-
|
|
605
|
-
|
|
596
|
+
next: ParsedLocation,
|
|
597
|
+
dest?: BuildNextOptions,
|
|
606
598
|
) => {
|
|
607
599
|
matchedRoutes: Array<AnyRoute>
|
|
608
600
|
routeParams: Record<string, string>
|
|
@@ -844,8 +836,6 @@ export class RouterCore<
|
|
|
844
836
|
// router can be used in a non-react environment if necessary
|
|
845
837
|
startTransition: StartTransitionFn = (fn) => fn()
|
|
846
838
|
|
|
847
|
-
isShell = false
|
|
848
|
-
|
|
849
839
|
update: UpdateFn<
|
|
850
840
|
TRouteTree,
|
|
851
841
|
TTrailingSlashOption,
|
|
@@ -892,6 +882,7 @@ export class RouterCore<
|
|
|
892
882
|
}
|
|
893
883
|
|
|
894
884
|
if (
|
|
885
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
895
886
|
!this.history ||
|
|
896
887
|
(this.options.history && this.options.history !== this.history)
|
|
897
888
|
) {
|
|
@@ -910,6 +901,7 @@ export class RouterCore<
|
|
|
910
901
|
this.buildRouteTree()
|
|
911
902
|
}
|
|
912
903
|
|
|
904
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
913
905
|
if (!this.__store) {
|
|
914
906
|
this.__store = new Store(getInitialRouterState(this.latestLocation), {
|
|
915
907
|
onUpdate: () => {
|
|
@@ -928,16 +920,13 @@ export class RouterCore<
|
|
|
928
920
|
if (
|
|
929
921
|
typeof window !== 'undefined' &&
|
|
930
922
|
'CSS' in window &&
|
|
923
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
931
924
|
typeof window.CSS?.supports === 'function'
|
|
932
925
|
) {
|
|
933
926
|
this.isViewTransitionTypesSupported = window.CSS.supports(
|
|
934
927
|
'selector(:active-view-transition-type(a)',
|
|
935
928
|
)
|
|
936
929
|
}
|
|
937
|
-
|
|
938
|
-
if ((this.latestLocation.search as any).__TSS_SHELL) {
|
|
939
|
-
this.isShell = true
|
|
940
|
-
}
|
|
941
930
|
}
|
|
942
931
|
|
|
943
932
|
get state() {
|
|
@@ -945,29 +934,124 @@ export class RouterCore<
|
|
|
945
934
|
}
|
|
946
935
|
|
|
947
936
|
buildRouteTree = () => {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
initRoute: (route, i) => {
|
|
951
|
-
route.init({
|
|
952
|
-
originalIndex: i,
|
|
953
|
-
defaultSsr: this.options.defaultSsr,
|
|
954
|
-
})
|
|
955
|
-
},
|
|
956
|
-
})
|
|
957
|
-
|
|
958
|
-
this.routesById = routesById as RoutesById<TRouteTree>
|
|
959
|
-
this.routesByPath = routesByPath as RoutesByPath<TRouteTree>
|
|
960
|
-
this.flatRoutes = flatRoutes as Array<AnyRoute>
|
|
937
|
+
this.routesById = {} as RoutesById<TRouteTree>
|
|
938
|
+
this.routesByPath = {} as RoutesByPath<TRouteTree>
|
|
961
939
|
|
|
962
940
|
const notFoundRoute = this.options.notFoundRoute
|
|
963
|
-
|
|
964
941
|
if (notFoundRoute) {
|
|
965
942
|
notFoundRoute.init({
|
|
966
943
|
originalIndex: 99999999999,
|
|
967
944
|
defaultSsr: this.options.defaultSsr,
|
|
968
945
|
})
|
|
969
|
-
this.routesById[notFoundRoute.id] = notFoundRoute
|
|
946
|
+
;(this.routesById as any)[notFoundRoute.id] = notFoundRoute
|
|
970
947
|
}
|
|
948
|
+
|
|
949
|
+
const recurseRoutes = (childRoutes: Array<AnyRoute>) => {
|
|
950
|
+
childRoutes.forEach((childRoute, i) => {
|
|
951
|
+
childRoute.init({
|
|
952
|
+
originalIndex: i,
|
|
953
|
+
defaultSsr: this.options.defaultSsr,
|
|
954
|
+
})
|
|
955
|
+
|
|
956
|
+
const existingRoute = (this.routesById as any)[childRoute.id]
|
|
957
|
+
|
|
958
|
+
invariant(
|
|
959
|
+
!existingRoute,
|
|
960
|
+
`Duplicate routes found with id: ${String(childRoute.id)}`,
|
|
961
|
+
)
|
|
962
|
+
;(this.routesById as any)[childRoute.id] = childRoute
|
|
963
|
+
|
|
964
|
+
if (!childRoute.isRoot && childRoute.path) {
|
|
965
|
+
const trimmedFullPath = trimPathRight(childRoute.fullPath)
|
|
966
|
+
if (
|
|
967
|
+
!(this.routesByPath as any)[trimmedFullPath] ||
|
|
968
|
+
childRoute.fullPath.endsWith('/')
|
|
969
|
+
) {
|
|
970
|
+
;(this.routesByPath as any)[trimmedFullPath] = childRoute
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
const children = childRoute.children
|
|
975
|
+
|
|
976
|
+
if (children?.length) {
|
|
977
|
+
recurseRoutes(children)
|
|
978
|
+
}
|
|
979
|
+
})
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
recurseRoutes([this.routeTree])
|
|
983
|
+
|
|
984
|
+
const scoredRoutes: Array<{
|
|
985
|
+
child: AnyRoute
|
|
986
|
+
trimmed: string
|
|
987
|
+
parsed: ReturnType<typeof parsePathname>
|
|
988
|
+
index: number
|
|
989
|
+
scores: Array<number>
|
|
990
|
+
}> = []
|
|
991
|
+
|
|
992
|
+
const routes: Array<AnyRoute> = Object.values(this.routesById)
|
|
993
|
+
|
|
994
|
+
routes.forEach((d, i) => {
|
|
995
|
+
if (d.isRoot || !d.path) {
|
|
996
|
+
return
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
const trimmed = trimPathLeft(d.fullPath)
|
|
1000
|
+
const parsed = parsePathname(trimmed)
|
|
1001
|
+
|
|
1002
|
+
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
1003
|
+
parsed.shift()
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
const scores = parsed.map((segment) => {
|
|
1007
|
+
if (segment.value === '/') {
|
|
1008
|
+
return 0.75
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
if (segment.type === 'param') {
|
|
1012
|
+
return 0.5
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
if (segment.type === 'wildcard') {
|
|
1016
|
+
return 0.25
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
return 1
|
|
1020
|
+
})
|
|
1021
|
+
|
|
1022
|
+
scoredRoutes.push({ child: d, trimmed, parsed, index: i, scores })
|
|
1023
|
+
})
|
|
1024
|
+
|
|
1025
|
+
this.flatRoutes = scoredRoutes
|
|
1026
|
+
.sort((a, b) => {
|
|
1027
|
+
const minLength = Math.min(a.scores.length, b.scores.length)
|
|
1028
|
+
|
|
1029
|
+
// Sort by min available score
|
|
1030
|
+
for (let i = 0; i < minLength; i++) {
|
|
1031
|
+
if (a.scores[i] !== b.scores[i]) {
|
|
1032
|
+
return b.scores[i]! - a.scores[i]!
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// Sort by length of score
|
|
1037
|
+
if (a.scores.length !== b.scores.length) {
|
|
1038
|
+
return b.scores.length - a.scores.length
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
// Sort by min available parsed value
|
|
1042
|
+
for (let i = 0; i < minLength; i++) {
|
|
1043
|
+
if (a.parsed[i]!.value !== b.parsed[i]!.value) {
|
|
1044
|
+
return a.parsed[i]!.value > b.parsed[i]!.value ? 1 : -1
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
// Sort by original index
|
|
1049
|
+
return a.index - b.index
|
|
1050
|
+
})
|
|
1051
|
+
.map((d, i) => {
|
|
1052
|
+
d.child.rank = i
|
|
1053
|
+
return d.child
|
|
1054
|
+
})
|
|
971
1055
|
}
|
|
972
1056
|
|
|
973
1057
|
subscribe: SubscribeFn = (eventType, fn) => {
|
|
@@ -1081,8 +1165,8 @@ export class RouterCore<
|
|
|
1081
1165
|
opts?: MatchRoutesOpts,
|
|
1082
1166
|
): Array<AnyRouteMatch> {
|
|
1083
1167
|
const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
|
|
1084
|
-
next
|
|
1085
|
-
opts?.dest
|
|
1168
|
+
next,
|
|
1169
|
+
opts?.dest,
|
|
1086
1170
|
)
|
|
1087
1171
|
let isGlobalNotFound = false
|
|
1088
1172
|
|
|
@@ -1388,19 +1472,47 @@ export class RouterCore<
|
|
|
1388
1472
|
return matches
|
|
1389
1473
|
}
|
|
1390
1474
|
|
|
1391
|
-
getMatchedRoutes: GetMatchRoutesFn = (
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1475
|
+
getMatchedRoutes: GetMatchRoutesFn = (next, dest) => {
|
|
1476
|
+
let routeParams: Record<string, string> = {}
|
|
1477
|
+
const trimmedPath = trimPathRight(next.pathname)
|
|
1478
|
+
const getMatchedParams = (route: AnyRoute) => {
|
|
1479
|
+
const result = matchPathname(this.basepath, trimmedPath, {
|
|
1480
|
+
to: route.fullPath,
|
|
1481
|
+
caseSensitive:
|
|
1482
|
+
route.options.caseSensitive ?? this.options.caseSensitive,
|
|
1483
|
+
fuzzy: true,
|
|
1484
|
+
})
|
|
1485
|
+
return result
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
let foundRoute: AnyRoute | undefined =
|
|
1489
|
+
dest?.to !== undefined ? this.routesByPath[dest.to!] : undefined
|
|
1490
|
+
if (foundRoute) {
|
|
1491
|
+
routeParams = getMatchedParams(foundRoute)!
|
|
1492
|
+
} else {
|
|
1493
|
+
foundRoute = this.flatRoutes.find((route) => {
|
|
1494
|
+
const matchedParams = getMatchedParams(route)
|
|
1495
|
+
|
|
1496
|
+
if (matchedParams) {
|
|
1497
|
+
routeParams = matchedParams
|
|
1498
|
+
return true
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
return false
|
|
1502
|
+
})
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
let routeCursor: AnyRoute =
|
|
1506
|
+
foundRoute || (this.routesById as any)[rootRouteId]
|
|
1507
|
+
|
|
1508
|
+
const matchedRoutes: Array<AnyRoute> = [routeCursor]
|
|
1509
|
+
|
|
1510
|
+
while (routeCursor.parentRoute) {
|
|
1511
|
+
routeCursor = routeCursor.parentRoute
|
|
1512
|
+
matchedRoutes.unshift(routeCursor)
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
return { matchedRoutes, routeParams, foundRoute }
|
|
1404
1516
|
}
|
|
1405
1517
|
|
|
1406
1518
|
cancelMatch = (id: string) => {
|
|
@@ -1700,17 +1812,11 @@ export class RouterCore<
|
|
|
1700
1812
|
}
|
|
1701
1813
|
}
|
|
1702
1814
|
|
|
1703
|
-
const nextMatches = this.getMatchedRoutes(
|
|
1704
|
-
next.pathname,
|
|
1705
|
-
dest.to as string,
|
|
1706
|
-
)
|
|
1815
|
+
const nextMatches = this.getMatchedRoutes(next, dest)
|
|
1707
1816
|
const final = build(dest, nextMatches)
|
|
1708
1817
|
|
|
1709
1818
|
if (maskedNext) {
|
|
1710
|
-
const maskedMatches = this.getMatchedRoutes(
|
|
1711
|
-
maskedNext.pathname,
|
|
1712
|
-
maskedDest?.to as string,
|
|
1713
|
-
)
|
|
1819
|
+
const maskedMatches = this.getMatchedRoutes(maskedNext, maskedDest)
|
|
1714
1820
|
const maskedFinal = build(maskedDest, maskedMatches)
|
|
1715
1821
|
final.maskedLocation = maskedFinal
|
|
1716
1822
|
}
|
|
@@ -1852,13 +1958,6 @@ export class RouterCore<
|
|
|
1852
1958
|
}
|
|
1853
1959
|
|
|
1854
1960
|
navigate: NavigateFn = ({ to, reloadDocument, href, ...rest }) => {
|
|
1855
|
-
if (!reloadDocument && href) {
|
|
1856
|
-
try {
|
|
1857
|
-
new URL(`${href}`)
|
|
1858
|
-
reloadDocument = true
|
|
1859
|
-
} catch {}
|
|
1860
|
-
}
|
|
1861
|
-
|
|
1862
1961
|
if (reloadDocument) {
|
|
1863
1962
|
if (!href) {
|
|
1864
1963
|
const location = this.buildLocation({ to, ...rest } as any)
|
|
@@ -1881,30 +1980,10 @@ export class RouterCore<
|
|
|
1881
1980
|
|
|
1882
1981
|
latestLoadPromise: undefined | Promise<void>
|
|
1883
1982
|
|
|
1884
|
-
|
|
1885
|
-
// Cancel any pending matches
|
|
1886
|
-
this.cancelMatches()
|
|
1983
|
+
load: LoadFn = async (opts?: { sync?: boolean }): Promise<void> => {
|
|
1887
1984
|
this.latestLocation = this.parseLocation(this.latestLocation)
|
|
1888
1985
|
|
|
1889
|
-
|
|
1890
|
-
const pendingMatches = this.matchRoutes(this.latestLocation)
|
|
1891
|
-
|
|
1892
|
-
// Ingest the new matches
|
|
1893
|
-
this.__store.setState((s) => ({
|
|
1894
|
-
...s,
|
|
1895
|
-
status: 'pending',
|
|
1896
|
-
isLoading: true,
|
|
1897
|
-
location: this.latestLocation,
|
|
1898
|
-
pendingMatches,
|
|
1899
|
-
// If a cached moved to pendingMatches, remove it from cachedMatches
|
|
1900
|
-
cachedMatches: s.cachedMatches.filter((d) => {
|
|
1901
|
-
return !pendingMatches.find((e) => e.id === d.id)
|
|
1902
|
-
}),
|
|
1903
|
-
}))
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
|
-
load: LoadFn = async (opts?: { sync?: boolean }): Promise<void> => {
|
|
1907
|
-
let redirect: AnyRedirect | undefined
|
|
1986
|
+
let redirect: ResolvedRedirect | undefined
|
|
1908
1987
|
let notFound: NotFoundError | undefined
|
|
1909
1988
|
|
|
1910
1989
|
let loadPromise: Promise<void>
|
|
@@ -1913,10 +1992,36 @@ export class RouterCore<
|
|
|
1913
1992
|
loadPromise = new Promise<void>((resolve) => {
|
|
1914
1993
|
this.startTransition(async () => {
|
|
1915
1994
|
try {
|
|
1916
|
-
this.beforeLoad()
|
|
1917
1995
|
const next = this.latestLocation
|
|
1918
1996
|
const prevLocation = this.state.resolvedLocation
|
|
1919
1997
|
|
|
1998
|
+
// Cancel any pending matches
|
|
1999
|
+
this.cancelMatches()
|
|
2000
|
+
|
|
2001
|
+
let pendingMatches!: Array<AnyRouteMatch>
|
|
2002
|
+
|
|
2003
|
+
batch(() => {
|
|
2004
|
+
// this call breaks a route context of destination route after a redirect
|
|
2005
|
+
// we should be fine not eagerly calling this since we call it later
|
|
2006
|
+
// this.clearExpiredCache()
|
|
2007
|
+
|
|
2008
|
+
// Match the routes
|
|
2009
|
+
pendingMatches = this.matchRoutes(next)
|
|
2010
|
+
|
|
2011
|
+
// Ingest the new matches
|
|
2012
|
+
this.__store.setState((s) => ({
|
|
2013
|
+
...s,
|
|
2014
|
+
status: 'pending',
|
|
2015
|
+
isLoading: true,
|
|
2016
|
+
location: next,
|
|
2017
|
+
pendingMatches,
|
|
2018
|
+
// If a cached moved to pendingMatches, remove it from cachedMatches
|
|
2019
|
+
cachedMatches: s.cachedMatches.filter((d) => {
|
|
2020
|
+
return !pendingMatches.find((e) => e.id === d.id)
|
|
2021
|
+
}),
|
|
2022
|
+
}))
|
|
2023
|
+
})
|
|
2024
|
+
|
|
1920
2025
|
if (!this.state.redirect) {
|
|
1921
2026
|
this.emit({
|
|
1922
2027
|
type: 'onBeforeNavigate',
|
|
@@ -1937,7 +2042,7 @@ export class RouterCore<
|
|
|
1937
2042
|
|
|
1938
2043
|
await this.loadMatches({
|
|
1939
2044
|
sync: opts?.sync,
|
|
1940
|
-
matches:
|
|
2045
|
+
matches: pendingMatches,
|
|
1941
2046
|
location: next,
|
|
1942
2047
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
1943
2048
|
onReady: async () => {
|
|
@@ -1998,11 +2103,11 @@ export class RouterCore<
|
|
|
1998
2103
|
},
|
|
1999
2104
|
})
|
|
2000
2105
|
} catch (err) {
|
|
2001
|
-
if (
|
|
2106
|
+
if (isResolvedRedirect(err)) {
|
|
2002
2107
|
redirect = err
|
|
2003
2108
|
if (!this.isServer) {
|
|
2004
2109
|
this.navigate({
|
|
2005
|
-
...redirect
|
|
2110
|
+
...redirect,
|
|
2006
2111
|
replace: true,
|
|
2007
2112
|
ignoreBlocker: true,
|
|
2008
2113
|
})
|
|
@@ -2014,7 +2119,7 @@ export class RouterCore<
|
|
|
2014
2119
|
this.__store.setState((s) => ({
|
|
2015
2120
|
...s,
|
|
2016
2121
|
statusCode: redirect
|
|
2017
|
-
? redirect.
|
|
2122
|
+
? redirect.statusCode
|
|
2018
2123
|
: notFound
|
|
2019
2124
|
? 404
|
|
2020
2125
|
: s.matches.some((d) => d.status === 'error')
|
|
@@ -2170,15 +2275,13 @@ export class RouterCore<
|
|
|
2170
2275
|
}
|
|
2171
2276
|
|
|
2172
2277
|
const handleRedirectAndNotFound = (match: AnyRouteMatch, err: any) => {
|
|
2173
|
-
if (
|
|
2174
|
-
if (
|
|
2175
|
-
|
|
2176
|
-
if (!err.options.reloadDocument) {
|
|
2177
|
-
throw err
|
|
2178
|
-
}
|
|
2179
|
-
}
|
|
2278
|
+
if (isResolvedRedirect(err)) {
|
|
2279
|
+
if (!err.reloadDocument) {
|
|
2280
|
+
throw err
|
|
2180
2281
|
}
|
|
2282
|
+
}
|
|
2181
2283
|
|
|
2284
|
+
if (isRedirect(err) || isNotFound(err)) {
|
|
2182
2285
|
updateMatch(match.id, (prev) => ({
|
|
2183
2286
|
...prev,
|
|
2184
2287
|
status: isRedirect(err)
|
|
@@ -2202,9 +2305,7 @@ export class RouterCore<
|
|
|
2202
2305
|
|
|
2203
2306
|
if (isRedirect(err)) {
|
|
2204
2307
|
rendered = true
|
|
2205
|
-
err.
|
|
2206
|
-
err.redirectHandled = true
|
|
2207
|
-
err = this.resolveRedirect(err)
|
|
2308
|
+
err = this.resolveRedirect({ ...err, _fromLocation: location })
|
|
2208
2309
|
throw err
|
|
2209
2310
|
} else if (isNotFound(err)) {
|
|
2210
2311
|
this._handleNotFound(matches, err, {
|
|
@@ -2641,8 +2742,8 @@ export class RouterCore<
|
|
|
2641
2742
|
loaderPromise: undefined,
|
|
2642
2743
|
}))
|
|
2643
2744
|
} catch (err) {
|
|
2644
|
-
if (
|
|
2645
|
-
await this.navigate(err
|
|
2745
|
+
if (isResolvedRedirect(err)) {
|
|
2746
|
+
await this.navigate(err)
|
|
2646
2747
|
}
|
|
2647
2748
|
}
|
|
2648
2749
|
})()
|
|
@@ -2727,14 +2828,11 @@ export class RouterCore<
|
|
|
2727
2828
|
return this.load({ sync: opts?.sync })
|
|
2728
2829
|
}
|
|
2729
2830
|
|
|
2730
|
-
resolveRedirect = (
|
|
2731
|
-
|
|
2732
|
-
redirect.options.href = this.buildLocation(redirect.options).href
|
|
2733
|
-
redirect.headers.set('Location', redirect.options.href)
|
|
2734
|
-
}
|
|
2831
|
+
resolveRedirect = (err: AnyRedirect): ResolvedRedirect => {
|
|
2832
|
+
const redirect = err as ResolvedRedirect
|
|
2735
2833
|
|
|
2736
|
-
if (!redirect.
|
|
2737
|
-
redirect.
|
|
2834
|
+
if (!redirect.href) {
|
|
2835
|
+
redirect.href = this.buildLocation(redirect as any).href
|
|
2738
2836
|
}
|
|
2739
2837
|
|
|
2740
2838
|
return redirect
|
|
@@ -2869,11 +2967,11 @@ export class RouterCore<
|
|
|
2869
2967
|
return matches
|
|
2870
2968
|
} catch (err) {
|
|
2871
2969
|
if (isRedirect(err)) {
|
|
2872
|
-
if (err.
|
|
2970
|
+
if (err.reloadDocument) {
|
|
2873
2971
|
return undefined
|
|
2874
2972
|
}
|
|
2875
2973
|
return await this.preloadRoute({
|
|
2876
|
-
...err
|
|
2974
|
+
...(err as any),
|
|
2877
2975
|
_fromLocation: next,
|
|
2878
2976
|
})
|
|
2879
2977
|
}
|
|
@@ -3107,224 +3205,3 @@ function routeNeedsPreload(route: AnyRoute) {
|
|
|
3107
3205
|
}
|
|
3108
3206
|
return false
|
|
3109
3207
|
}
|
|
3110
|
-
|
|
3111
|
-
interface RouteLike {
|
|
3112
|
-
id: string
|
|
3113
|
-
isRoot?: boolean
|
|
3114
|
-
path?: string
|
|
3115
|
-
fullPath: string
|
|
3116
|
-
rank?: number
|
|
3117
|
-
parentRoute?: RouteLike
|
|
3118
|
-
children?: Array<RouteLike>
|
|
3119
|
-
options?: {
|
|
3120
|
-
caseSensitive?: boolean
|
|
3121
|
-
}
|
|
3122
|
-
}
|
|
3123
|
-
|
|
3124
|
-
export function processRouteTree<TRouteLike extends RouteLike>({
|
|
3125
|
-
routeTree,
|
|
3126
|
-
initRoute,
|
|
3127
|
-
}: {
|
|
3128
|
-
routeTree: TRouteLike
|
|
3129
|
-
initRoute?: (route: TRouteLike, index: number) => void
|
|
3130
|
-
}) {
|
|
3131
|
-
const routesById = {} as Record<string, TRouteLike>
|
|
3132
|
-
const routesByPath = {} as Record<string, TRouteLike>
|
|
3133
|
-
|
|
3134
|
-
const recurseRoutes = (childRoutes: Array<TRouteLike>) => {
|
|
3135
|
-
childRoutes.forEach((childRoute, i) => {
|
|
3136
|
-
initRoute?.(childRoute, i)
|
|
3137
|
-
|
|
3138
|
-
const existingRoute = routesById[childRoute.id]
|
|
3139
|
-
|
|
3140
|
-
invariant(
|
|
3141
|
-
!existingRoute,
|
|
3142
|
-
`Duplicate routes found with id: ${String(childRoute.id)}`,
|
|
3143
|
-
)
|
|
3144
|
-
|
|
3145
|
-
routesById[childRoute.id] = childRoute
|
|
3146
|
-
|
|
3147
|
-
if (!childRoute.isRoot && childRoute.path) {
|
|
3148
|
-
const trimmedFullPath = trimPathRight(childRoute.fullPath)
|
|
3149
|
-
if (
|
|
3150
|
-
!routesByPath[trimmedFullPath] ||
|
|
3151
|
-
childRoute.fullPath.endsWith('/')
|
|
3152
|
-
) {
|
|
3153
|
-
routesByPath[trimmedFullPath] = childRoute
|
|
3154
|
-
}
|
|
3155
|
-
}
|
|
3156
|
-
|
|
3157
|
-
const children = childRoute.children as Array<TRouteLike>
|
|
3158
|
-
|
|
3159
|
-
if (children?.length) {
|
|
3160
|
-
recurseRoutes(children)
|
|
3161
|
-
}
|
|
3162
|
-
})
|
|
3163
|
-
}
|
|
3164
|
-
|
|
3165
|
-
recurseRoutes([routeTree])
|
|
3166
|
-
|
|
3167
|
-
const scoredRoutes: Array<{
|
|
3168
|
-
child: TRouteLike
|
|
3169
|
-
trimmed: string
|
|
3170
|
-
parsed: ReturnType<typeof parsePathname>
|
|
3171
|
-
index: number
|
|
3172
|
-
scores: Array<number>
|
|
3173
|
-
}> = []
|
|
3174
|
-
|
|
3175
|
-
const routes: Array<TRouteLike> = Object.values(routesById)
|
|
3176
|
-
|
|
3177
|
-
routes.forEach((d, i) => {
|
|
3178
|
-
if (d.isRoot || !d.path) {
|
|
3179
|
-
return
|
|
3180
|
-
}
|
|
3181
|
-
|
|
3182
|
-
const trimmed = trimPathLeft(d.fullPath)
|
|
3183
|
-
const parsed = parsePathname(trimmed)
|
|
3184
|
-
|
|
3185
|
-
// Removes the leading slash if it is not the only remaining segment
|
|
3186
|
-
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
3187
|
-
parsed.shift()
|
|
3188
|
-
}
|
|
3189
|
-
|
|
3190
|
-
const scores = parsed.map((segment) => {
|
|
3191
|
-
if (segment.value === '/') {
|
|
3192
|
-
return 0.75
|
|
3193
|
-
}
|
|
3194
|
-
|
|
3195
|
-
if (
|
|
3196
|
-
segment.type === 'param' &&
|
|
3197
|
-
segment.prefixSegment &&
|
|
3198
|
-
segment.suffixSegment
|
|
3199
|
-
) {
|
|
3200
|
-
return 0.55
|
|
3201
|
-
}
|
|
3202
|
-
|
|
3203
|
-
if (segment.type === 'param' && segment.prefixSegment) {
|
|
3204
|
-
return 0.52
|
|
3205
|
-
}
|
|
3206
|
-
|
|
3207
|
-
if (segment.type === 'param' && segment.suffixSegment) {
|
|
3208
|
-
return 0.51
|
|
3209
|
-
}
|
|
3210
|
-
|
|
3211
|
-
if (segment.type === 'param') {
|
|
3212
|
-
return 0.5
|
|
3213
|
-
}
|
|
3214
|
-
|
|
3215
|
-
if (
|
|
3216
|
-
segment.type === 'wildcard' &&
|
|
3217
|
-
segment.prefixSegment &&
|
|
3218
|
-
segment.suffixSegment
|
|
3219
|
-
) {
|
|
3220
|
-
return 0.3
|
|
3221
|
-
}
|
|
3222
|
-
|
|
3223
|
-
if (segment.type === 'wildcard' && segment.prefixSegment) {
|
|
3224
|
-
return 0.27
|
|
3225
|
-
}
|
|
3226
|
-
|
|
3227
|
-
if (segment.type === 'wildcard' && segment.suffixSegment) {
|
|
3228
|
-
return 0.26
|
|
3229
|
-
}
|
|
3230
|
-
|
|
3231
|
-
if (segment.type === 'wildcard') {
|
|
3232
|
-
return 0.25
|
|
3233
|
-
}
|
|
3234
|
-
|
|
3235
|
-
return 1
|
|
3236
|
-
})
|
|
3237
|
-
|
|
3238
|
-
scoredRoutes.push({ child: d, trimmed, parsed, index: i, scores })
|
|
3239
|
-
})
|
|
3240
|
-
|
|
3241
|
-
const flatRoutes = scoredRoutes
|
|
3242
|
-
.sort((a, b) => {
|
|
3243
|
-
const minLength = Math.min(a.scores.length, b.scores.length)
|
|
3244
|
-
|
|
3245
|
-
// Sort by min available score
|
|
3246
|
-
for (let i = 0; i < minLength; i++) {
|
|
3247
|
-
if (a.scores[i] !== b.scores[i]) {
|
|
3248
|
-
return b.scores[i]! - a.scores[i]!
|
|
3249
|
-
}
|
|
3250
|
-
}
|
|
3251
|
-
|
|
3252
|
-
// Sort by length of score
|
|
3253
|
-
if (a.scores.length !== b.scores.length) {
|
|
3254
|
-
return b.scores.length - a.scores.length
|
|
3255
|
-
}
|
|
3256
|
-
|
|
3257
|
-
// Sort by min available parsed value
|
|
3258
|
-
for (let i = 0; i < minLength; i++) {
|
|
3259
|
-
if (a.parsed[i]!.value !== b.parsed[i]!.value) {
|
|
3260
|
-
return a.parsed[i]!.value > b.parsed[i]!.value ? 1 : -1
|
|
3261
|
-
}
|
|
3262
|
-
}
|
|
3263
|
-
|
|
3264
|
-
// Sort by original index
|
|
3265
|
-
return a.index - b.index
|
|
3266
|
-
})
|
|
3267
|
-
.map((d, i) => {
|
|
3268
|
-
d.child.rank = i
|
|
3269
|
-
return d.child
|
|
3270
|
-
})
|
|
3271
|
-
|
|
3272
|
-
return { routesById, routesByPath, flatRoutes }
|
|
3273
|
-
}
|
|
3274
|
-
|
|
3275
|
-
export function getMatchedRoutes<TRouteLike extends RouteLike>({
|
|
3276
|
-
pathname,
|
|
3277
|
-
routePathname,
|
|
3278
|
-
basepath,
|
|
3279
|
-
caseSensitive,
|
|
3280
|
-
routesByPath,
|
|
3281
|
-
routesById,
|
|
3282
|
-
flatRoutes,
|
|
3283
|
-
}: {
|
|
3284
|
-
pathname: string
|
|
3285
|
-
routePathname?: string
|
|
3286
|
-
basepath: string
|
|
3287
|
-
caseSensitive?: boolean
|
|
3288
|
-
routesByPath: Record<string, TRouteLike>
|
|
3289
|
-
routesById: Record<string, TRouteLike>
|
|
3290
|
-
flatRoutes: Array<TRouteLike>
|
|
3291
|
-
}) {
|
|
3292
|
-
let routeParams: Record<string, string> = {}
|
|
3293
|
-
const trimmedPath = trimPathRight(pathname)
|
|
3294
|
-
const getMatchedParams = (route: TRouteLike) => {
|
|
3295
|
-
const result = matchPathname(basepath, trimmedPath, {
|
|
3296
|
-
to: route.fullPath,
|
|
3297
|
-
caseSensitive: route.options?.caseSensitive ?? caseSensitive,
|
|
3298
|
-
fuzzy: true,
|
|
3299
|
-
})
|
|
3300
|
-
return result
|
|
3301
|
-
}
|
|
3302
|
-
|
|
3303
|
-
let foundRoute: TRouteLike | undefined =
|
|
3304
|
-
routePathname !== undefined ? routesByPath[routePathname] : undefined
|
|
3305
|
-
if (foundRoute) {
|
|
3306
|
-
routeParams = getMatchedParams(foundRoute)!
|
|
3307
|
-
} else {
|
|
3308
|
-
foundRoute = flatRoutes.find((route) => {
|
|
3309
|
-
const matchedParams = getMatchedParams(route)
|
|
3310
|
-
|
|
3311
|
-
if (matchedParams) {
|
|
3312
|
-
routeParams = matchedParams
|
|
3313
|
-
return true
|
|
3314
|
-
}
|
|
3315
|
-
|
|
3316
|
-
return false
|
|
3317
|
-
})
|
|
3318
|
-
}
|
|
3319
|
-
|
|
3320
|
-
let routeCursor: TRouteLike = foundRoute || routesById[rootRouteId]!
|
|
3321
|
-
|
|
3322
|
-
const matchedRoutes: Array<TRouteLike> = [routeCursor]
|
|
3323
|
-
|
|
3324
|
-
while (routeCursor.parentRoute) {
|
|
3325
|
-
routeCursor = routeCursor.parentRoute as TRouteLike
|
|
3326
|
-
matchedRoutes.unshift(routeCursor)
|
|
3327
|
-
}
|
|
3328
|
-
|
|
3329
|
-
return { matchedRoutes, routeParams, foundRoute }
|
|
3330
|
-
}
|