@tanstack/router-core 1.128.0 → 1.128.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/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +1 -0
- package/dist/cjs/router.cjs +51 -42
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/esm/path.d.ts +1 -0
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/router.js +51 -42
- package/dist/esm/router.js.map +1 -1
- package/package.json +1 -1
- package/src/path.ts +2 -0
- package/src/router.ts +65 -54
package/package.json
CHANGED
package/src/path.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface Segment {
|
|
|
7
7
|
value: string
|
|
8
8
|
prefixSegment?: string
|
|
9
9
|
suffixSegment?: string
|
|
10
|
+
// Indicates if there is a static segment after this required/optional param
|
|
11
|
+
hasStaticAfter?: boolean
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export function joinPaths(paths: Array<string | undefined>) {
|
package/src/router.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { setupScrollRestoration } from './scroll-restoration'
|
|
|
29
29
|
import { defaultParseSearch, defaultStringifySearch } from './searchParams'
|
|
30
30
|
import { rootRouteId } from './root'
|
|
31
31
|
import { isRedirect, redirect } from './redirect'
|
|
32
|
+
import type { Segment } from './path'
|
|
32
33
|
import type { SearchParser, SearchSerializer } from './searchParams'
|
|
33
34
|
import type { AnyRedirect, ResolvedRedirect } from './redirect'
|
|
34
35
|
import type {
|
|
@@ -1819,6 +1820,7 @@ export class RouterCore<
|
|
|
1819
1820
|
this.__store.setState((s) => ({
|
|
1820
1821
|
...s,
|
|
1821
1822
|
status: 'pending',
|
|
1823
|
+
statusCode: 200,
|
|
1822
1824
|
isLoading: true,
|
|
1823
1825
|
location: this.latestLocation,
|
|
1824
1826
|
pendingMatches,
|
|
@@ -3177,6 +3179,27 @@ export type ProcessRouteTreeResult<TRouteLike extends RouteLike> = {
|
|
|
3177
3179
|
routesByPath: Record<string, TRouteLike>
|
|
3178
3180
|
flatRoutes: Array<TRouteLike>
|
|
3179
3181
|
}
|
|
3182
|
+
|
|
3183
|
+
const REQUIRED_PARAM_BASE_SCORE = 0.5
|
|
3184
|
+
const OPTIONAL_PARAM_BASE_SCORE = 0.4
|
|
3185
|
+
const WILDCARD_PARAM_BASE_SCORE = 0.25
|
|
3186
|
+
|
|
3187
|
+
function handleParam(segment: Segment, baseScore: number) {
|
|
3188
|
+
if (segment.prefixSegment && segment.suffixSegment) {
|
|
3189
|
+
return baseScore + 0.05
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
if (segment.prefixSegment) {
|
|
3193
|
+
return baseScore + 0.02
|
|
3194
|
+
}
|
|
3195
|
+
|
|
3196
|
+
if (segment.suffixSegment) {
|
|
3197
|
+
return baseScore + 0.01
|
|
3198
|
+
}
|
|
3199
|
+
|
|
3200
|
+
return baseScore
|
|
3201
|
+
}
|
|
3202
|
+
|
|
3180
3203
|
export function processRouteTree<TRouteLike extends RouteLike>({
|
|
3181
3204
|
routeTree,
|
|
3182
3205
|
initRoute,
|
|
@@ -3223,9 +3246,11 @@ export function processRouteTree<TRouteLike extends RouteLike>({
|
|
|
3223
3246
|
const scoredRoutes: Array<{
|
|
3224
3247
|
child: TRouteLike
|
|
3225
3248
|
trimmed: string
|
|
3226
|
-
parsed:
|
|
3249
|
+
parsed: Array<Segment>
|
|
3227
3250
|
index: number
|
|
3228
3251
|
scores: Array<number>
|
|
3252
|
+
hasStaticAfter: boolean
|
|
3253
|
+
optionalParamCount: number
|
|
3229
3254
|
}> = []
|
|
3230
3255
|
|
|
3231
3256
|
const routes: Array<TRouteLike> = Object.values(routesById)
|
|
@@ -3243,63 +3268,50 @@ export function processRouteTree<TRouteLike extends RouteLike>({
|
|
|
3243
3268
|
parsed.shift()
|
|
3244
3269
|
}
|
|
3245
3270
|
|
|
3246
|
-
|
|
3271
|
+
let optionalParamCount = 0
|
|
3272
|
+
let hasStaticAfter = false
|
|
3273
|
+
const scores = parsed.map((segment, index) => {
|
|
3247
3274
|
if (segment.value === '/') {
|
|
3248
3275
|
return 0.75
|
|
3249
3276
|
}
|
|
3250
3277
|
|
|
3278
|
+
let baseScore: number | undefined = undefined
|
|
3251
3279
|
if (segment.type === 'param') {
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
}
|
|
3259
|
-
|
|
3260
|
-
if (segment.suffixSegment) {
|
|
3261
|
-
return 0.51
|
|
3262
|
-
}
|
|
3263
|
-
|
|
3264
|
-
return 0.5
|
|
3280
|
+
baseScore = REQUIRED_PARAM_BASE_SCORE
|
|
3281
|
+
} else if (segment.type === 'optional-param') {
|
|
3282
|
+
baseScore = OPTIONAL_PARAM_BASE_SCORE
|
|
3283
|
+
optionalParamCount++
|
|
3284
|
+
} else if (segment.type === 'wildcard') {
|
|
3285
|
+
baseScore = WILDCARD_PARAM_BASE_SCORE
|
|
3265
3286
|
}
|
|
3266
3287
|
|
|
3267
|
-
if (
|
|
3268
|
-
if
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
return 0.41
|
|
3278
|
-
}
|
|
3279
|
-
|
|
3280
|
-
return 0.4
|
|
3281
|
-
}
|
|
3282
|
-
|
|
3283
|
-
if (segment.type === 'wildcard') {
|
|
3284
|
-
if (segment.prefixSegment && segment.suffixSegment) {
|
|
3285
|
-
return 0.3
|
|
3286
|
-
}
|
|
3287
|
-
|
|
3288
|
-
if (segment.prefixSegment) {
|
|
3289
|
-
return 0.27
|
|
3290
|
-
}
|
|
3291
|
-
|
|
3292
|
-
if (segment.suffixSegment) {
|
|
3293
|
-
return 0.26
|
|
3288
|
+
if (baseScore) {
|
|
3289
|
+
// if there is any static segment (that is not an index) after a required / optional param,
|
|
3290
|
+
// we will boost this param so it ranks higher than a required/optional param without a static segment after it
|
|
3291
|
+
// JUST FOR SORTING, NOT FOR MATCHING
|
|
3292
|
+
for (let i = index + 1; i < parsed.length; i++) {
|
|
3293
|
+
const nextSegment = parsed[i]!
|
|
3294
|
+
if (nextSegment.type === 'pathname' && nextSegment.value !== '/') {
|
|
3295
|
+
hasStaticAfter = true
|
|
3296
|
+
return handleParam(segment, baseScore + 0.2)
|
|
3297
|
+
}
|
|
3294
3298
|
}
|
|
3295
3299
|
|
|
3296
|
-
return
|
|
3300
|
+
return handleParam(segment, baseScore)
|
|
3297
3301
|
}
|
|
3298
3302
|
|
|
3299
3303
|
return 1
|
|
3300
3304
|
})
|
|
3301
3305
|
|
|
3302
|
-
scoredRoutes.push({
|
|
3306
|
+
scoredRoutes.push({
|
|
3307
|
+
child: d,
|
|
3308
|
+
trimmed,
|
|
3309
|
+
parsed,
|
|
3310
|
+
index: i,
|
|
3311
|
+
scores,
|
|
3312
|
+
optionalParamCount,
|
|
3313
|
+
hasStaticAfter,
|
|
3314
|
+
})
|
|
3303
3315
|
})
|
|
3304
3316
|
|
|
3305
3317
|
const flatRoutes = scoredRoutes
|
|
@@ -3315,17 +3327,16 @@ export function processRouteTree<TRouteLike extends RouteLike>({
|
|
|
3315
3327
|
|
|
3316
3328
|
// If all common segments have equal scores, then consider length and specificity
|
|
3317
3329
|
if (a.scores.length !== b.scores.length) {
|
|
3318
|
-
// Count optional parameters in each route
|
|
3319
|
-
const aOptionalCount = a.parsed.filter(
|
|
3320
|
-
(seg) => seg.type === 'optional-param',
|
|
3321
|
-
).length
|
|
3322
|
-
const bOptionalCount = b.parsed.filter(
|
|
3323
|
-
(seg) => seg.type === 'optional-param',
|
|
3324
|
-
).length
|
|
3325
|
-
|
|
3326
3330
|
// If different number of optional parameters, fewer optional parameters wins (more specific)
|
|
3327
|
-
if
|
|
3328
|
-
|
|
3331
|
+
// only if both or none of the routes has static segments after the params
|
|
3332
|
+
if (a.optionalParamCount !== b.optionalParamCount) {
|
|
3333
|
+
if (a.hasStaticAfter === b.hasStaticAfter) {
|
|
3334
|
+
return a.optionalParamCount - b.optionalParamCount
|
|
3335
|
+
} else if (a.hasStaticAfter && !b.hasStaticAfter) {
|
|
3336
|
+
return -1
|
|
3337
|
+
} else if (!a.hasStaticAfter && b.hasStaticAfter) {
|
|
3338
|
+
return 1
|
|
3339
|
+
}
|
|
3329
3340
|
}
|
|
3330
3341
|
|
|
3331
3342
|
// If same number of optional parameters, longer path wins (for static segments)
|