@tanstack/router-core 1.136.4 → 1.136.5
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/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +2 -0
- package/dist/cjs/index.cjs +0 -5
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -4
- package/dist/cjs/lru-cache.cjs +5 -0
- package/dist/cjs/lru-cache.cjs.map +1 -1
- package/dist/cjs/lru-cache.d.cts +1 -0
- package/dist/cjs/new-process-route-tree.cjs +655 -0
- package/dist/cjs/new-process-route-tree.cjs.map +1 -0
- package/dist/cjs/new-process-route-tree.d.cts +177 -0
- package/dist/cjs/path.cjs +133 -434
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +3 -39
- package/dist/cjs/router.cjs +47 -98
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +6 -11
- package/dist/esm/Matches.d.ts +2 -0
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/index.d.ts +1 -4
- package/dist/esm/index.js +1 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lru-cache.d.ts +1 -0
- package/dist/esm/lru-cache.js +5 -0
- package/dist/esm/lru-cache.js.map +1 -1
- package/dist/esm/new-process-route-tree.d.ts +177 -0
- package/dist/esm/new-process-route-tree.js +655 -0
- package/dist/esm/new-process-route-tree.js.map +1 -0
- package/dist/esm/path.d.ts +3 -39
- package/dist/esm/path.js +133 -434
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/router.d.ts +6 -11
- package/dist/esm/router.js +48 -99
- package/dist/esm/router.js.map +1 -1
- package/package.json +1 -1
- package/src/Matches.ts +2 -0
- package/src/index.ts +0 -6
- package/src/lru-cache.ts +6 -0
- package/src/new-process-route-tree.ts +1036 -0
- package/src/path.ts +168 -639
- package/src/router.ts +57 -126
- package/dist/cjs/process-route-tree.cjs +0 -144
- package/dist/cjs/process-route-tree.cjs.map +0 -1
- package/dist/cjs/process-route-tree.d.cts +0 -18
- package/dist/esm/process-route-tree.d.ts +0 -18
- package/dist/esm/process-route-tree.js +0 -144
- package/dist/esm/process-route-tree.js.map +0 -1
- package/src/process-route-tree.ts +0 -241
package/src/router.ts
CHANGED
|
@@ -9,21 +9,26 @@ import {
|
|
|
9
9
|
last,
|
|
10
10
|
replaceEqualDeep,
|
|
11
11
|
} from './utils'
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
findFlatMatch,
|
|
14
|
+
findRouteMatch,
|
|
15
|
+
findSingleMatch,
|
|
16
|
+
processRouteMasks,
|
|
17
|
+
processRouteTree,
|
|
18
|
+
} from './new-process-route-tree'
|
|
13
19
|
import {
|
|
14
20
|
cleanPath,
|
|
15
21
|
interpolatePath,
|
|
16
|
-
matchPathname,
|
|
17
22
|
resolvePath,
|
|
18
23
|
trimPath,
|
|
19
24
|
trimPathRight,
|
|
20
25
|
} from './path'
|
|
26
|
+
import { createLRUCache } from './lru-cache'
|
|
21
27
|
import { isNotFound } from './not-found'
|
|
22
28
|
import { setupScrollRestoration } from './scroll-restoration'
|
|
23
29
|
import { defaultParseSearch, defaultStringifySearch } from './searchParams'
|
|
24
30
|
import { rootRouteId } from './root'
|
|
25
31
|
import { isRedirect, redirect } from './redirect'
|
|
26
|
-
import { createLRUCache } from './lru-cache'
|
|
27
32
|
import { loadMatches, loadRouteChunk, routeNeedsPreload } from './load-matches'
|
|
28
33
|
import {
|
|
29
34
|
composeRewrites,
|
|
@@ -31,7 +36,7 @@ import {
|
|
|
31
36
|
executeRewriteOutput,
|
|
32
37
|
rewriteBasepath,
|
|
33
38
|
} from './rewrite'
|
|
34
|
-
import type {
|
|
39
|
+
import type { ProcessedTree } from './new-process-route-tree'
|
|
35
40
|
import type { SearchParser, SearchSerializer } from './searchParams'
|
|
36
41
|
import type { AnyRedirect, ResolvedRedirect } from './redirect'
|
|
37
42
|
import type {
|
|
@@ -691,10 +696,7 @@ export type ParseLocationFn<TRouteTree extends AnyRoute> = (
|
|
|
691
696
|
previousLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>,
|
|
692
697
|
) => ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
693
698
|
|
|
694
|
-
export type GetMatchRoutesFn = (
|
|
695
|
-
pathname: string,
|
|
696
|
-
routePathname: string | undefined,
|
|
697
|
-
) => {
|
|
699
|
+
export type GetMatchRoutesFn = (pathname: string) => {
|
|
698
700
|
matchedRoutes: Array<AnyRoute>
|
|
699
701
|
routeParams: Record<string, string>
|
|
700
702
|
foundRoute: AnyRoute | undefined
|
|
@@ -902,7 +904,7 @@ export class RouterCore<
|
|
|
902
904
|
routeTree!: TRouteTree
|
|
903
905
|
routesById!: RoutesById<TRouteTree>
|
|
904
906
|
routesByPath!: RoutesByPath<TRouteTree>
|
|
905
|
-
|
|
907
|
+
processedTree!: ProcessedTree<TRouteTree, any, any>
|
|
906
908
|
isServer!: boolean
|
|
907
909
|
pathParamsDecodeCharMap?: Map<string, string>
|
|
908
910
|
|
|
@@ -1094,18 +1096,22 @@ export class RouterCore<
|
|
|
1094
1096
|
}
|
|
1095
1097
|
|
|
1096
1098
|
buildRouteTree = () => {
|
|
1097
|
-
const { routesById, routesByPath,
|
|
1098
|
-
|
|
1099
|
-
|
|
1099
|
+
const { routesById, routesByPath, processedTree } = processRouteTree(
|
|
1100
|
+
this.routeTree,
|
|
1101
|
+
this.options.caseSensitive,
|
|
1102
|
+
(route, i) => {
|
|
1100
1103
|
route.init({
|
|
1101
1104
|
originalIndex: i,
|
|
1102
1105
|
})
|
|
1103
1106
|
},
|
|
1104
|
-
|
|
1107
|
+
)
|
|
1108
|
+
if (this.options.routeMasks) {
|
|
1109
|
+
processRouteMasks(this.options.routeMasks, processedTree)
|
|
1110
|
+
}
|
|
1105
1111
|
|
|
1106
1112
|
this.routesById = routesById as RoutesById<TRouteTree>
|
|
1107
1113
|
this.routesByPath = routesByPath as RoutesByPath<TRouteTree>
|
|
1108
|
-
this.
|
|
1114
|
+
this.processedTree = processedTree
|
|
1109
1115
|
|
|
1110
1116
|
const notFoundRoute = this.options.notFoundRoute
|
|
1111
1117
|
|
|
@@ -1203,13 +1209,15 @@ export class RouterCore<
|
|
|
1203
1209
|
return location
|
|
1204
1210
|
}
|
|
1205
1211
|
|
|
1212
|
+
resolvePathCache = createLRUCache<string, string>(1000)
|
|
1213
|
+
|
|
1206
1214
|
/** Resolve a path against the router basepath and trailing-slash policy. */
|
|
1207
1215
|
resolvePathWithBase = (from: string, path: string) => {
|
|
1208
1216
|
const resolvedPath = resolvePath({
|
|
1209
1217
|
base: from,
|
|
1210
1218
|
to: cleanPath(path),
|
|
1211
1219
|
trailingSlash: this.options.trailingSlash,
|
|
1212
|
-
|
|
1220
|
+
cache: this.resolvePathCache,
|
|
1213
1221
|
})
|
|
1214
1222
|
return resolvedPath
|
|
1215
1223
|
}
|
|
@@ -1242,7 +1250,6 @@ export class RouterCore<
|
|
|
1242
1250
|
): Array<AnyRouteMatch> {
|
|
1243
1251
|
const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
|
|
1244
1252
|
next.pathname,
|
|
1245
|
-
opts?.dest?.to as string,
|
|
1246
1253
|
)
|
|
1247
1254
|
let isGlobalNotFound = false
|
|
1248
1255
|
|
|
@@ -1535,21 +1542,11 @@ export class RouterCore<
|
|
|
1535
1542
|
return matches
|
|
1536
1543
|
}
|
|
1537
1544
|
|
|
1538
|
-
|
|
1539
|
-
private parsePathnameCache: ParsePathnameCache = createLRUCache(1000)
|
|
1540
|
-
|
|
1541
|
-
getMatchedRoutes: GetMatchRoutesFn = (
|
|
1542
|
-
pathname: string,
|
|
1543
|
-
routePathname: string | undefined,
|
|
1544
|
-
) => {
|
|
1545
|
+
getMatchedRoutes: GetMatchRoutesFn = (pathname) => {
|
|
1545
1546
|
return getMatchedRoutes({
|
|
1546
1547
|
pathname,
|
|
1547
|
-
routePathname,
|
|
1548
|
-
caseSensitive: this.options.caseSensitive,
|
|
1549
|
-
routesByPath: this.routesByPath,
|
|
1550
1548
|
routesById: this.routesById,
|
|
1551
|
-
|
|
1552
|
-
parseCache: this.parsePathnameCache,
|
|
1549
|
+
processedTree: this.processedTree,
|
|
1553
1550
|
})
|
|
1554
1551
|
}
|
|
1555
1552
|
|
|
@@ -1612,10 +1609,7 @@ export class RouterCore<
|
|
|
1612
1609
|
process.env.NODE_ENV !== 'production' &&
|
|
1613
1610
|
dest._isNavigate
|
|
1614
1611
|
) {
|
|
1615
|
-
const allFromMatches = this.getMatchedRoutes(
|
|
1616
|
-
dest.from,
|
|
1617
|
-
undefined,
|
|
1618
|
-
).matchedRoutes
|
|
1612
|
+
const allFromMatches = this.getMatchedRoutes(dest.from).matchedRoutes
|
|
1619
1613
|
|
|
1620
1614
|
const matchedFrom = findLast(allCurrentLocationMatches, (d) => {
|
|
1621
1615
|
return comparePaths(d.fullPath, dest.from!)
|
|
@@ -1666,7 +1660,6 @@ export class RouterCore<
|
|
|
1666
1660
|
const interpolatedNextTo = interpolatePath({
|
|
1667
1661
|
path: nextTo,
|
|
1668
1662
|
params: nextParams,
|
|
1669
|
-
parseCache: this.parsePathnameCache,
|
|
1670
1663
|
}).interpolatedPath
|
|
1671
1664
|
|
|
1672
1665
|
const destRoutes = this.matchRoutes(interpolatedNextTo, undefined, {
|
|
@@ -1693,7 +1686,6 @@ export class RouterCore<
|
|
|
1693
1686
|
path: nextTo,
|
|
1694
1687
|
params: nextParams,
|
|
1695
1688
|
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
1696
|
-
parseCache: this.parsePathnameCache,
|
|
1697
1689
|
}).interpolatedPath,
|
|
1698
1690
|
)
|
|
1699
1691
|
|
|
@@ -1786,35 +1778,23 @@ export class RouterCore<
|
|
|
1786
1778
|
let maskedNext = maskedDest ? build(maskedDest) : undefined
|
|
1787
1779
|
|
|
1788
1780
|
if (!maskedNext) {
|
|
1789
|
-
|
|
1781
|
+
const params = {}
|
|
1790
1782
|
|
|
1791
|
-
|
|
1792
|
-
const match =
|
|
1783
|
+
if (this.options.routeMasks) {
|
|
1784
|
+
const match = findFlatMatch<RouteMask<TRouteTree>>(
|
|
1793
1785
|
next.pathname,
|
|
1794
|
-
|
|
1795
|
-
to: d.from,
|
|
1796
|
-
caseSensitive: false,
|
|
1797
|
-
fuzzy: false,
|
|
1798
|
-
},
|
|
1799
|
-
this.parsePathnameCache,
|
|
1786
|
+
this.processedTree,
|
|
1800
1787
|
)
|
|
1801
|
-
|
|
1802
1788
|
if (match) {
|
|
1803
|
-
params
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
const { from: _from, ...maskProps } = foundMask
|
|
1812
|
-
maskedDest = {
|
|
1813
|
-
from: opts.from,
|
|
1814
|
-
...maskProps,
|
|
1815
|
-
params,
|
|
1789
|
+
Object.assign(params, match.params) // Copy params, because they're cached
|
|
1790
|
+
const { from: _from, ...maskProps } = match.route
|
|
1791
|
+
maskedDest = {
|
|
1792
|
+
from: opts.from,
|
|
1793
|
+
...maskProps,
|
|
1794
|
+
params,
|
|
1795
|
+
}
|
|
1796
|
+
maskedNext = build(maskedDest)
|
|
1816
1797
|
}
|
|
1817
|
-
maskedNext = build(maskedDest)
|
|
1818
1798
|
}
|
|
1819
1799
|
}
|
|
1820
1800
|
|
|
@@ -2525,31 +2505,31 @@ export class RouterCore<
|
|
|
2525
2505
|
? this.latestLocation
|
|
2526
2506
|
: this.state.resolvedLocation || this.state.location
|
|
2527
2507
|
|
|
2528
|
-
const match =
|
|
2508
|
+
const match = findSingleMatch(
|
|
2509
|
+
next.pathname,
|
|
2510
|
+
opts?.caseSensitive ?? false,
|
|
2511
|
+
opts?.fuzzy ?? false,
|
|
2529
2512
|
baseLocation.pathname,
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
to: next.pathname,
|
|
2533
|
-
},
|
|
2534
|
-
this.parsePathnameCache,
|
|
2535
|
-
) as any
|
|
2513
|
+
this.processedTree,
|
|
2514
|
+
)
|
|
2536
2515
|
|
|
2537
2516
|
if (!match) {
|
|
2538
2517
|
return false
|
|
2539
2518
|
}
|
|
2519
|
+
|
|
2540
2520
|
if (location.params) {
|
|
2541
|
-
if (!deepEqual(match, location.params, { partial: true })) {
|
|
2521
|
+
if (!deepEqual(match.params, location.params, { partial: true })) {
|
|
2542
2522
|
return false
|
|
2543
2523
|
}
|
|
2544
2524
|
}
|
|
2545
2525
|
|
|
2546
|
-
if (
|
|
2526
|
+
if (opts?.includeSearch ?? true) {
|
|
2547
2527
|
return deepEqual(baseLocation.search, next.search, { partial: true })
|
|
2548
|
-
? match
|
|
2528
|
+
? match.params
|
|
2549
2529
|
: false
|
|
2550
2530
|
}
|
|
2551
2531
|
|
|
2552
|
-
return match
|
|
2532
|
+
return match.params
|
|
2553
2533
|
}
|
|
2554
2534
|
|
|
2555
2535
|
ssr?: {
|
|
@@ -2645,70 +2625,21 @@ function validateSearch(validateSearch: AnyValidator, input: unknown): unknown {
|
|
|
2645
2625
|
*/
|
|
2646
2626
|
export function getMatchedRoutes<TRouteLike extends RouteLike>({
|
|
2647
2627
|
pathname,
|
|
2648
|
-
routePathname,
|
|
2649
|
-
caseSensitive,
|
|
2650
|
-
routesByPath,
|
|
2651
2628
|
routesById,
|
|
2652
|
-
|
|
2653
|
-
parseCache,
|
|
2629
|
+
processedTree,
|
|
2654
2630
|
}: {
|
|
2655
2631
|
pathname: string
|
|
2656
|
-
routePathname?: string
|
|
2657
|
-
caseSensitive?: boolean
|
|
2658
|
-
routesByPath: Record<string, TRouteLike>
|
|
2659
2632
|
routesById: Record<string, TRouteLike>
|
|
2660
|
-
|
|
2661
|
-
parseCache?: ParsePathnameCache
|
|
2633
|
+
processedTree: ProcessedTree<any, any, any>
|
|
2662
2634
|
}) {
|
|
2663
|
-
|
|
2635
|
+
const routeParams: Record<string, string> = {}
|
|
2664
2636
|
const trimmedPath = trimPathRight(pathname)
|
|
2665
|
-
const getMatchedParams = (route: TRouteLike) => {
|
|
2666
|
-
const result = matchPathname(
|
|
2667
|
-
trimmedPath,
|
|
2668
|
-
{
|
|
2669
|
-
to: route.fullPath,
|
|
2670
|
-
caseSensitive: route.options?.caseSensitive ?? caseSensitive,
|
|
2671
|
-
// we need fuzzy matching for `notFoundMode: 'fuzzy'`
|
|
2672
|
-
fuzzy: true,
|
|
2673
|
-
},
|
|
2674
|
-
parseCache,
|
|
2675
|
-
)
|
|
2676
|
-
return result
|
|
2677
|
-
}
|
|
2678
2637
|
|
|
2679
|
-
let foundRoute: TRouteLike | undefined =
|
|
2680
|
-
|
|
2681
|
-
if (
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
// iterate over flatRoutes to find the best match
|
|
2685
|
-
// if we find a fuzzy matching route, keep looking for a perfect fit
|
|
2686
|
-
let fuzzyMatch:
|
|
2687
|
-
| { foundRoute: TRouteLike; routeParams: Record<string, string> }
|
|
2688
|
-
| undefined = undefined
|
|
2689
|
-
for (const route of flatRoutes) {
|
|
2690
|
-
const matchedParams = getMatchedParams(route)
|
|
2691
|
-
|
|
2692
|
-
if (matchedParams) {
|
|
2693
|
-
if (
|
|
2694
|
-
route.path !== '/' &&
|
|
2695
|
-
(matchedParams as Record<string, string>)['**']
|
|
2696
|
-
) {
|
|
2697
|
-
if (!fuzzyMatch) {
|
|
2698
|
-
fuzzyMatch = { foundRoute: route, routeParams: matchedParams }
|
|
2699
|
-
}
|
|
2700
|
-
} else {
|
|
2701
|
-
foundRoute = route
|
|
2702
|
-
routeParams = matchedParams
|
|
2703
|
-
break
|
|
2704
|
-
}
|
|
2705
|
-
}
|
|
2706
|
-
}
|
|
2707
|
-
// did not find a perfect fit, so take the fuzzy matching route if it exists
|
|
2708
|
-
if (!foundRoute && fuzzyMatch) {
|
|
2709
|
-
foundRoute = fuzzyMatch.foundRoute
|
|
2710
|
-
routeParams = fuzzyMatch.routeParams
|
|
2711
|
-
}
|
|
2638
|
+
let foundRoute: TRouteLike | undefined = undefined
|
|
2639
|
+
const match = findRouteMatch<TRouteLike>(trimmedPath, processedTree, true)
|
|
2640
|
+
if (match) {
|
|
2641
|
+
foundRoute = match.route
|
|
2642
|
+
Object.assign(routeParams, match.params) // Copy params, because they're cached
|
|
2712
2643
|
}
|
|
2713
2644
|
|
|
2714
2645
|
let routeCursor: TRouteLike = foundRoute || routesById[rootRouteId]!
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const invariant = require("tiny-invariant");
|
|
4
|
-
const path = require("./path.cjs");
|
|
5
|
-
const SLASH_SCORE = 0.75;
|
|
6
|
-
const STATIC_SEGMENT_SCORE = 1;
|
|
7
|
-
const REQUIRED_PARAM_BASE_SCORE = 0.5;
|
|
8
|
-
const OPTIONAL_PARAM_BASE_SCORE = 0.4;
|
|
9
|
-
const WILDCARD_PARAM_BASE_SCORE = 0.25;
|
|
10
|
-
const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 0.2;
|
|
11
|
-
const BOTH_PRESENCE_BASE_SCORE = 0.05;
|
|
12
|
-
const PREFIX_PRESENCE_BASE_SCORE = 0.02;
|
|
13
|
-
const SUFFIX_PRESENCE_BASE_SCORE = 0.01;
|
|
14
|
-
const PREFIX_LENGTH_SCORE_MULTIPLIER = 2e-4;
|
|
15
|
-
const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1e-4;
|
|
16
|
-
function handleParam(segment, baseScore) {
|
|
17
|
-
if (segment.prefixSegment && segment.suffixSegment) {
|
|
18
|
-
return baseScore + BOTH_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
|
|
19
|
-
}
|
|
20
|
-
if (segment.prefixSegment) {
|
|
21
|
-
return baseScore + PREFIX_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length;
|
|
22
|
-
}
|
|
23
|
-
if (segment.suffixSegment) {
|
|
24
|
-
return baseScore + SUFFIX_PRESENCE_BASE_SCORE + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
|
|
25
|
-
}
|
|
26
|
-
return baseScore;
|
|
27
|
-
}
|
|
28
|
-
function sortRoutes(routes) {
|
|
29
|
-
const scoredRoutes = [];
|
|
30
|
-
routes.forEach((d, i) => {
|
|
31
|
-
if (d.isRoot || !d.path) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const trimmed = path.trimPathLeft(d.fullPath);
|
|
35
|
-
let parsed = path.parsePathname(trimmed);
|
|
36
|
-
let skip = 0;
|
|
37
|
-
while (parsed.length > skip + 1 && parsed[skip]?.value === "/") {
|
|
38
|
-
skip++;
|
|
39
|
-
}
|
|
40
|
-
if (skip > 0) parsed = parsed.slice(skip);
|
|
41
|
-
let optionalParamCount = 0;
|
|
42
|
-
let hasStaticAfter = false;
|
|
43
|
-
const scores = parsed.map((segment, index) => {
|
|
44
|
-
if (segment.value === "/") {
|
|
45
|
-
return SLASH_SCORE;
|
|
46
|
-
}
|
|
47
|
-
if (segment.type === path.SEGMENT_TYPE_PATHNAME) {
|
|
48
|
-
return STATIC_SEGMENT_SCORE;
|
|
49
|
-
}
|
|
50
|
-
let baseScore = void 0;
|
|
51
|
-
if (segment.type === path.SEGMENT_TYPE_PARAM) {
|
|
52
|
-
baseScore = REQUIRED_PARAM_BASE_SCORE;
|
|
53
|
-
} else if (segment.type === path.SEGMENT_TYPE_OPTIONAL_PARAM) {
|
|
54
|
-
baseScore = OPTIONAL_PARAM_BASE_SCORE;
|
|
55
|
-
optionalParamCount++;
|
|
56
|
-
} else {
|
|
57
|
-
baseScore = WILDCARD_PARAM_BASE_SCORE;
|
|
58
|
-
}
|
|
59
|
-
for (let i2 = index + 1; i2 < parsed.length; i2++) {
|
|
60
|
-
const nextSegment = parsed[i2];
|
|
61
|
-
if (nextSegment.type === path.SEGMENT_TYPE_PATHNAME && nextSegment.value !== "/") {
|
|
62
|
-
hasStaticAfter = true;
|
|
63
|
-
return handleParam(
|
|
64
|
-
segment,
|
|
65
|
-
baseScore + STATIC_AFTER_DYNAMIC_BONUS_SCORE
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return handleParam(segment, baseScore);
|
|
70
|
-
});
|
|
71
|
-
scoredRoutes.push({
|
|
72
|
-
child: d,
|
|
73
|
-
trimmed,
|
|
74
|
-
parsed,
|
|
75
|
-
index: i,
|
|
76
|
-
scores,
|
|
77
|
-
optionalParamCount,
|
|
78
|
-
hasStaticAfter
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
const flatRoutes = scoredRoutes.sort((a, b) => {
|
|
82
|
-
const minLength = Math.min(a.scores.length, b.scores.length);
|
|
83
|
-
for (let i = 0; i < minLength; i++) {
|
|
84
|
-
if (a.scores[i] !== b.scores[i]) {
|
|
85
|
-
return b.scores[i] - a.scores[i];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
if (a.scores.length !== b.scores.length) {
|
|
89
|
-
if (a.optionalParamCount !== b.optionalParamCount) {
|
|
90
|
-
if (a.hasStaticAfter === b.hasStaticAfter) {
|
|
91
|
-
return a.optionalParamCount - b.optionalParamCount;
|
|
92
|
-
} else if (a.hasStaticAfter && !b.hasStaticAfter) {
|
|
93
|
-
return -1;
|
|
94
|
-
} else if (!a.hasStaticAfter && b.hasStaticAfter) {
|
|
95
|
-
return 1;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return b.scores.length - a.scores.length;
|
|
99
|
-
}
|
|
100
|
-
for (let i = 0; i < minLength; i++) {
|
|
101
|
-
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
102
|
-
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return a.index - b.index;
|
|
106
|
-
}).map((d, i) => {
|
|
107
|
-
d.child.rank = i;
|
|
108
|
-
return d.child;
|
|
109
|
-
});
|
|
110
|
-
return flatRoutes;
|
|
111
|
-
}
|
|
112
|
-
function processRouteTree({
|
|
113
|
-
routeTree,
|
|
114
|
-
initRoute
|
|
115
|
-
}) {
|
|
116
|
-
const routesById = {};
|
|
117
|
-
const routesByPath = {};
|
|
118
|
-
const recurseRoutes = (childRoutes) => {
|
|
119
|
-
childRoutes.forEach((childRoute, i) => {
|
|
120
|
-
initRoute?.(childRoute, i);
|
|
121
|
-
const existingRoute = routesById[childRoute.id];
|
|
122
|
-
invariant(
|
|
123
|
-
!existingRoute,
|
|
124
|
-
`Duplicate routes found with id: ${String(childRoute.id)}`
|
|
125
|
-
);
|
|
126
|
-
routesById[childRoute.id] = childRoute;
|
|
127
|
-
if (!childRoute.isRoot && childRoute.path) {
|
|
128
|
-
const trimmedFullPath = path.trimPathRight(childRoute.fullPath);
|
|
129
|
-
if (!routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith("/")) {
|
|
130
|
-
routesByPath[trimmedFullPath] = childRoute;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
const children = childRoute.children;
|
|
134
|
-
if (children?.length) {
|
|
135
|
-
recurseRoutes(children);
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
};
|
|
139
|
-
recurseRoutes([routeTree]);
|
|
140
|
-
const flatRoutes = sortRoutes(Object.values(routesById));
|
|
141
|
-
return { routesById, routesByPath, flatRoutes };
|
|
142
|
-
}
|
|
143
|
-
exports.processRouteTree = processRouteTree;
|
|
144
|
-
//# sourceMappingURL=process-route-tree.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"process-route-tree.cjs","sources":["../../src/process-route-tree.ts"],"sourcesContent":["import invariant from 'tiny-invariant'\nimport {\n SEGMENT_TYPE_OPTIONAL_PARAM,\n SEGMENT_TYPE_PARAM,\n SEGMENT_TYPE_PATHNAME,\n parsePathname,\n trimPathLeft,\n trimPathRight,\n} from './path'\nimport type { Segment } from './path'\nimport type { RouteLike } from './route'\n\nconst SLASH_SCORE = 0.75\nconst STATIC_SEGMENT_SCORE = 1\nconst REQUIRED_PARAM_BASE_SCORE = 0.5\nconst OPTIONAL_PARAM_BASE_SCORE = 0.4\nconst WILDCARD_PARAM_BASE_SCORE = 0.25\nconst STATIC_AFTER_DYNAMIC_BONUS_SCORE = 0.2\nconst BOTH_PRESENCE_BASE_SCORE = 0.05\nconst PREFIX_PRESENCE_BASE_SCORE = 0.02\nconst SUFFIX_PRESENCE_BASE_SCORE = 0.01\nconst PREFIX_LENGTH_SCORE_MULTIPLIER = 0.0002\nconst SUFFIX_LENGTH_SCORE_MULTIPLIER = 0.0001\n\nfunction handleParam(segment: Segment, baseScore: number) {\n if (segment.prefixSegment && segment.suffixSegment) {\n return (\n baseScore +\n BOTH_PRESENCE_BASE_SCORE +\n PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length +\n SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length\n )\n }\n\n if (segment.prefixSegment) {\n return (\n baseScore +\n PREFIX_PRESENCE_BASE_SCORE +\n PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length\n )\n }\n\n if (segment.suffixSegment) {\n return (\n baseScore +\n SUFFIX_PRESENCE_BASE_SCORE +\n SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length\n )\n }\n\n return baseScore\n}\n\nfunction sortRoutes<TRouteLike extends RouteLike>(\n routes: ReadonlyArray<TRouteLike>,\n): Array<TRouteLike> {\n const scoredRoutes: Array<{\n child: TRouteLike\n trimmed: string\n parsed: ReadonlyArray<Segment>\n index: number\n scores: Array<number>\n hasStaticAfter: boolean\n optionalParamCount: number\n }> = []\n\n routes.forEach((d, i) => {\n if (d.isRoot || !d.path) {\n return\n }\n\n const trimmed = trimPathLeft(d.fullPath)\n let parsed = parsePathname(trimmed)\n\n // Removes the leading slash if it is not the only remaining segment\n let skip = 0\n while (parsed.length > skip + 1 && parsed[skip]?.value === '/') {\n skip++\n }\n if (skip > 0) parsed = parsed.slice(skip)\n\n let optionalParamCount = 0\n let hasStaticAfter = false\n const scores = parsed.map((segment, index) => {\n if (segment.value === '/') {\n return SLASH_SCORE\n }\n\n if (segment.type === SEGMENT_TYPE_PATHNAME) {\n return STATIC_SEGMENT_SCORE\n }\n\n let baseScore: number | undefined = undefined\n if (segment.type === SEGMENT_TYPE_PARAM) {\n baseScore = REQUIRED_PARAM_BASE_SCORE\n } else if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {\n baseScore = OPTIONAL_PARAM_BASE_SCORE\n optionalParamCount++\n } else {\n baseScore = WILDCARD_PARAM_BASE_SCORE\n }\n\n // if there is any static segment (that is not an index) after a required / optional param,\n // we will boost this param so it ranks higher than a required/optional param without a static segment after it\n // JUST FOR SORTING, NOT FOR MATCHING\n for (let i = index + 1; i < parsed.length; i++) {\n const nextSegment = parsed[i]!\n if (\n nextSegment.type === SEGMENT_TYPE_PATHNAME &&\n nextSegment.value !== '/'\n ) {\n hasStaticAfter = true\n return handleParam(\n segment,\n baseScore + STATIC_AFTER_DYNAMIC_BONUS_SCORE,\n )\n }\n }\n\n return handleParam(segment, baseScore)\n })\n\n scoredRoutes.push({\n child: d,\n trimmed,\n parsed,\n index: i,\n scores,\n optionalParamCount,\n hasStaticAfter,\n })\n })\n\n const flatRoutes = scoredRoutes\n .sort((a, b) => {\n const minLength = Math.min(a.scores.length, b.scores.length)\n\n // Sort by segment-by-segment score comparison ONLY for the common prefix\n for (let i = 0; i < minLength; i++) {\n if (a.scores[i] !== b.scores[i]) {\n return b.scores[i]! - a.scores[i]!\n }\n }\n\n // If all common segments have equal scores, then consider length and specificity\n if (a.scores.length !== b.scores.length) {\n // If different number of optional parameters, fewer optional parameters wins (more specific)\n // only if both or none of the routes has static segments after the params\n if (a.optionalParamCount !== b.optionalParamCount) {\n if (a.hasStaticAfter === b.hasStaticAfter) {\n return a.optionalParamCount - b.optionalParamCount\n } else if (a.hasStaticAfter && !b.hasStaticAfter) {\n return -1\n } else if (!a.hasStaticAfter && b.hasStaticAfter) {\n return 1\n }\n }\n\n // If same number of optional parameters, longer path wins (for static segments)\n return b.scores.length - a.scores.length\n }\n\n // Sort by min available parsed value for alphabetical ordering\n for (let i = 0; i < minLength; i++) {\n if (a.parsed[i]!.value !== b.parsed[i]!.value) {\n return a.parsed[i]!.value > b.parsed[i]!.value ? 1 : -1\n }\n }\n\n // Sort by original index\n return a.index - b.index\n })\n .map((d, i) => {\n d.child.rank = i\n return d.child\n })\n\n return flatRoutes\n}\n\nexport type ProcessRouteTreeResult<TRouteLike extends RouteLike> = {\n routesById: Record<string, TRouteLike>\n routesByPath: Record<string, TRouteLike>\n flatRoutes: Array<TRouteLike>\n}\n\n/**\n * Build lookup maps and a specificity-sorted flat list from a route tree.\n * Returns `routesById`, `routesByPath`, and `flatRoutes`.\n */\n/**\n * Build lookup maps and a specificity-sorted flat list from a route tree.\n * Returns `routesById`, `routesByPath`, and `flatRoutes`.\n */\nexport function processRouteTree<TRouteLike extends RouteLike>({\n routeTree,\n initRoute,\n}: {\n routeTree: TRouteLike\n initRoute?: (route: TRouteLike, index: number) => void\n}): ProcessRouteTreeResult<TRouteLike> {\n const routesById = {} as Record<string, TRouteLike>\n const routesByPath = {} as Record<string, TRouteLike>\n\n const recurseRoutes = (childRoutes: Array<TRouteLike>) => {\n childRoutes.forEach((childRoute, i) => {\n initRoute?.(childRoute, i)\n\n const existingRoute = routesById[childRoute.id]\n\n invariant(\n !existingRoute,\n `Duplicate routes found with id: ${String(childRoute.id)}`,\n )\n\n routesById[childRoute.id] = childRoute\n\n if (!childRoute.isRoot && childRoute.path) {\n const trimmedFullPath = trimPathRight(childRoute.fullPath)\n if (\n !routesByPath[trimmedFullPath] ||\n childRoute.fullPath.endsWith('/')\n ) {\n routesByPath[trimmedFullPath] = childRoute\n }\n }\n\n const children = childRoute.children as Array<TRouteLike>\n\n if (children?.length) {\n recurseRoutes(children)\n }\n })\n }\n\n recurseRoutes([routeTree])\n\n const flatRoutes = sortRoutes(Object.values(routesById))\n\n return { routesById, routesByPath, flatRoutes }\n}\n"],"names":["trimPathLeft","parsePathname","SEGMENT_TYPE_PATHNAME","SEGMENT_TYPE_PARAM","SEGMENT_TYPE_OPTIONAL_PARAM","i","trimPathRight"],"mappings":"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"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { RouteLike } from './route.cjs';
|
|
2
|
-
export type ProcessRouteTreeResult<TRouteLike extends RouteLike> = {
|
|
3
|
-
routesById: Record<string, TRouteLike>;
|
|
4
|
-
routesByPath: Record<string, TRouteLike>;
|
|
5
|
-
flatRoutes: Array<TRouteLike>;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* Build lookup maps and a specificity-sorted flat list from a route tree.
|
|
9
|
-
* Returns `routesById`, `routesByPath`, and `flatRoutes`.
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* Build lookup maps and a specificity-sorted flat list from a route tree.
|
|
13
|
-
* Returns `routesById`, `routesByPath`, and `flatRoutes`.
|
|
14
|
-
*/
|
|
15
|
-
export declare function processRouteTree<TRouteLike extends RouteLike>({ routeTree, initRoute, }: {
|
|
16
|
-
routeTree: TRouteLike;
|
|
17
|
-
initRoute?: (route: TRouteLike, index: number) => void;
|
|
18
|
-
}): ProcessRouteTreeResult<TRouteLike>;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { RouteLike } from './route.js';
|
|
2
|
-
export type ProcessRouteTreeResult<TRouteLike extends RouteLike> = {
|
|
3
|
-
routesById: Record<string, TRouteLike>;
|
|
4
|
-
routesByPath: Record<string, TRouteLike>;
|
|
5
|
-
flatRoutes: Array<TRouteLike>;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* Build lookup maps and a specificity-sorted flat list from a route tree.
|
|
9
|
-
* Returns `routesById`, `routesByPath`, and `flatRoutes`.
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* Build lookup maps and a specificity-sorted flat list from a route tree.
|
|
13
|
-
* Returns `routesById`, `routesByPath`, and `flatRoutes`.
|
|
14
|
-
*/
|
|
15
|
-
export declare function processRouteTree<TRouteLike extends RouteLike>({ routeTree, initRoute, }: {
|
|
16
|
-
routeTree: TRouteLike;
|
|
17
|
-
initRoute?: (route: TRouteLike, index: number) => void;
|
|
18
|
-
}): ProcessRouteTreeResult<TRouteLike>;
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import invariant from "tiny-invariant";
|
|
2
|
-
import { trimPathRight, trimPathLeft, parsePathname, SEGMENT_TYPE_PATHNAME, SEGMENT_TYPE_PARAM, SEGMENT_TYPE_OPTIONAL_PARAM } from "./path.js";
|
|
3
|
-
const SLASH_SCORE = 0.75;
|
|
4
|
-
const STATIC_SEGMENT_SCORE = 1;
|
|
5
|
-
const REQUIRED_PARAM_BASE_SCORE = 0.5;
|
|
6
|
-
const OPTIONAL_PARAM_BASE_SCORE = 0.4;
|
|
7
|
-
const WILDCARD_PARAM_BASE_SCORE = 0.25;
|
|
8
|
-
const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 0.2;
|
|
9
|
-
const BOTH_PRESENCE_BASE_SCORE = 0.05;
|
|
10
|
-
const PREFIX_PRESENCE_BASE_SCORE = 0.02;
|
|
11
|
-
const SUFFIX_PRESENCE_BASE_SCORE = 0.01;
|
|
12
|
-
const PREFIX_LENGTH_SCORE_MULTIPLIER = 2e-4;
|
|
13
|
-
const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1e-4;
|
|
14
|
-
function handleParam(segment, baseScore) {
|
|
15
|
-
if (segment.prefixSegment && segment.suffixSegment) {
|
|
16
|
-
return baseScore + BOTH_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
|
|
17
|
-
}
|
|
18
|
-
if (segment.prefixSegment) {
|
|
19
|
-
return baseScore + PREFIX_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length;
|
|
20
|
-
}
|
|
21
|
-
if (segment.suffixSegment) {
|
|
22
|
-
return baseScore + SUFFIX_PRESENCE_BASE_SCORE + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
|
|
23
|
-
}
|
|
24
|
-
return baseScore;
|
|
25
|
-
}
|
|
26
|
-
function sortRoutes(routes) {
|
|
27
|
-
const scoredRoutes = [];
|
|
28
|
-
routes.forEach((d, i) => {
|
|
29
|
-
if (d.isRoot || !d.path) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const trimmed = trimPathLeft(d.fullPath);
|
|
33
|
-
let parsed = parsePathname(trimmed);
|
|
34
|
-
let skip = 0;
|
|
35
|
-
while (parsed.length > skip + 1 && parsed[skip]?.value === "/") {
|
|
36
|
-
skip++;
|
|
37
|
-
}
|
|
38
|
-
if (skip > 0) parsed = parsed.slice(skip);
|
|
39
|
-
let optionalParamCount = 0;
|
|
40
|
-
let hasStaticAfter = false;
|
|
41
|
-
const scores = parsed.map((segment, index) => {
|
|
42
|
-
if (segment.value === "/") {
|
|
43
|
-
return SLASH_SCORE;
|
|
44
|
-
}
|
|
45
|
-
if (segment.type === SEGMENT_TYPE_PATHNAME) {
|
|
46
|
-
return STATIC_SEGMENT_SCORE;
|
|
47
|
-
}
|
|
48
|
-
let baseScore = void 0;
|
|
49
|
-
if (segment.type === SEGMENT_TYPE_PARAM) {
|
|
50
|
-
baseScore = REQUIRED_PARAM_BASE_SCORE;
|
|
51
|
-
} else if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {
|
|
52
|
-
baseScore = OPTIONAL_PARAM_BASE_SCORE;
|
|
53
|
-
optionalParamCount++;
|
|
54
|
-
} else {
|
|
55
|
-
baseScore = WILDCARD_PARAM_BASE_SCORE;
|
|
56
|
-
}
|
|
57
|
-
for (let i2 = index + 1; i2 < parsed.length; i2++) {
|
|
58
|
-
const nextSegment = parsed[i2];
|
|
59
|
-
if (nextSegment.type === SEGMENT_TYPE_PATHNAME && nextSegment.value !== "/") {
|
|
60
|
-
hasStaticAfter = true;
|
|
61
|
-
return handleParam(
|
|
62
|
-
segment,
|
|
63
|
-
baseScore + STATIC_AFTER_DYNAMIC_BONUS_SCORE
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return handleParam(segment, baseScore);
|
|
68
|
-
});
|
|
69
|
-
scoredRoutes.push({
|
|
70
|
-
child: d,
|
|
71
|
-
trimmed,
|
|
72
|
-
parsed,
|
|
73
|
-
index: i,
|
|
74
|
-
scores,
|
|
75
|
-
optionalParamCount,
|
|
76
|
-
hasStaticAfter
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
const flatRoutes = scoredRoutes.sort((a, b) => {
|
|
80
|
-
const minLength = Math.min(a.scores.length, b.scores.length);
|
|
81
|
-
for (let i = 0; i < minLength; i++) {
|
|
82
|
-
if (a.scores[i] !== b.scores[i]) {
|
|
83
|
-
return b.scores[i] - a.scores[i];
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
if (a.scores.length !== b.scores.length) {
|
|
87
|
-
if (a.optionalParamCount !== b.optionalParamCount) {
|
|
88
|
-
if (a.hasStaticAfter === b.hasStaticAfter) {
|
|
89
|
-
return a.optionalParamCount - b.optionalParamCount;
|
|
90
|
-
} else if (a.hasStaticAfter && !b.hasStaticAfter) {
|
|
91
|
-
return -1;
|
|
92
|
-
} else if (!a.hasStaticAfter && b.hasStaticAfter) {
|
|
93
|
-
return 1;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return b.scores.length - a.scores.length;
|
|
97
|
-
}
|
|
98
|
-
for (let i = 0; i < minLength; i++) {
|
|
99
|
-
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
100
|
-
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return a.index - b.index;
|
|
104
|
-
}).map((d, i) => {
|
|
105
|
-
d.child.rank = i;
|
|
106
|
-
return d.child;
|
|
107
|
-
});
|
|
108
|
-
return flatRoutes;
|
|
109
|
-
}
|
|
110
|
-
function processRouteTree({
|
|
111
|
-
routeTree,
|
|
112
|
-
initRoute
|
|
113
|
-
}) {
|
|
114
|
-
const routesById = {};
|
|
115
|
-
const routesByPath = {};
|
|
116
|
-
const recurseRoutes = (childRoutes) => {
|
|
117
|
-
childRoutes.forEach((childRoute, i) => {
|
|
118
|
-
initRoute?.(childRoute, i);
|
|
119
|
-
const existingRoute = routesById[childRoute.id];
|
|
120
|
-
invariant(
|
|
121
|
-
!existingRoute,
|
|
122
|
-
`Duplicate routes found with id: ${String(childRoute.id)}`
|
|
123
|
-
);
|
|
124
|
-
routesById[childRoute.id] = childRoute;
|
|
125
|
-
if (!childRoute.isRoot && childRoute.path) {
|
|
126
|
-
const trimmedFullPath = trimPathRight(childRoute.fullPath);
|
|
127
|
-
if (!routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith("/")) {
|
|
128
|
-
routesByPath[trimmedFullPath] = childRoute;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
const children = childRoute.children;
|
|
132
|
-
if (children?.length) {
|
|
133
|
-
recurseRoutes(children);
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
};
|
|
137
|
-
recurseRoutes([routeTree]);
|
|
138
|
-
const flatRoutes = sortRoutes(Object.values(routesById));
|
|
139
|
-
return { routesById, routesByPath, flatRoutes };
|
|
140
|
-
}
|
|
141
|
-
export {
|
|
142
|
-
processRouteTree
|
|
143
|
-
};
|
|
144
|
-
//# sourceMappingURL=process-route-tree.js.map
|