@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.
- package/dist/cjs/fileRoute.d.cts +6 -2
- package/dist/cjs/index.cjs +3 -0
- 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 +18 -1
- package/dist/cjs/path.cjs +130 -16
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +17 -0
- package/dist/cjs/redirect.cjs +17 -14
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/redirect.d.cts +13 -7
- package/dist/cjs/route.cjs +12 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +17 -18
- package/dist/cjs/router.cjs +290 -211
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +46 -3
- package/dist/cjs/typePrimitives.d.cts +2 -2
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +2 -0
- package/dist/esm/fileRoute.d.ts +6 -2
- package/dist/esm/index.d.ts +6 -6
- package/dist/esm/index.js +5 -2
- package/dist/esm/link.d.ts +18 -1
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/path.d.ts +17 -0
- package/dist/esm/path.js +130 -16
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/redirect.d.ts +13 -7
- package/dist/esm/redirect.js +17 -14
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/route.d.ts +17 -18
- package/dist/esm/route.js +12 -1
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +46 -3
- package/dist/esm/router.js +293 -214
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/typePrimitives.d.ts +2 -2
- package/dist/esm/utils.d.ts +2 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/fileRoute.ts +90 -1
- package/src/index.ts +14 -6
- package/src/link.ts +97 -11
- package/src/path.ts +181 -16
- package/src/redirect.ts +37 -22
- package/src/route.ts +119 -39
- package/src/router.ts +393 -269
- package/src/typePrimitives.ts +2 -2
- package/src/utils.ts +14 -0
package/src/path.ts
CHANGED
|
@@ -5,6 +5,9 @@ import type { AnyPathParams } from './route'
|
|
|
5
5
|
export interface Segment {
|
|
6
6
|
type: 'pathname' | 'param' | 'wildcard'
|
|
7
7
|
value: string
|
|
8
|
+
// Add a new property to store the static segment if present
|
|
9
|
+
prefixSegment?: string
|
|
10
|
+
suffixSegment?: string
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
export function joinPaths(paths: Array<string | undefined>) {
|
|
@@ -137,10 +140,52 @@ export function resolvePath({
|
|
|
137
140
|
}
|
|
138
141
|
}
|
|
139
142
|
|
|
140
|
-
const
|
|
143
|
+
const segmentValues = baseSegments.map((segment) => {
|
|
144
|
+
if (segment.type === 'param') {
|
|
145
|
+
const param = segment.value.substring(1)
|
|
146
|
+
if (segment.prefixSegment && segment.suffixSegment) {
|
|
147
|
+
return `${segment.prefixSegment}{$${param}}${segment.suffixSegment}`
|
|
148
|
+
} else if (segment.prefixSegment) {
|
|
149
|
+
return `${segment.prefixSegment}{$${param}}`
|
|
150
|
+
} else if (segment.suffixSegment) {
|
|
151
|
+
return `{$${param}}${segment.suffixSegment}`
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (segment.type === 'wildcard') {
|
|
155
|
+
if (segment.prefixSegment && segment.suffixSegment) {
|
|
156
|
+
return `${segment.prefixSegment}{$}${segment.suffixSegment}`
|
|
157
|
+
} else if (segment.prefixSegment) {
|
|
158
|
+
return `${segment.prefixSegment}{$}`
|
|
159
|
+
} else if (segment.suffixSegment) {
|
|
160
|
+
return `{$}${segment.suffixSegment}`
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return segment.value
|
|
164
|
+
})
|
|
165
|
+
const joined = joinPaths([basepath, ...segmentValues])
|
|
141
166
|
return cleanPath(joined)
|
|
142
167
|
}
|
|
143
168
|
|
|
169
|
+
const PARAM_RE = /^\$.{1,}$/ // $paramName
|
|
170
|
+
const PARAM_W_CURLY_BRACES_RE = /^(.*?)\{(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/ // prefix{$paramName}suffix
|
|
171
|
+
const WILDCARD_RE = /^\$$/ // $
|
|
172
|
+
const WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\{\$\}(.*)$/ // prefix{$}suffix
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Required: `/foo/$bar` ✅
|
|
176
|
+
* Prefix and Suffix: `/foo/prefix${bar}suffix` ✅
|
|
177
|
+
* Wildcard: `/foo/$` ✅
|
|
178
|
+
* Wildcard with Prefix and Suffix: `/foo/prefix{$}suffix` ✅
|
|
179
|
+
*
|
|
180
|
+
* Future:
|
|
181
|
+
* Optional: `/foo/{-bar}`
|
|
182
|
+
* Optional named segment: `/foo/{bar}`
|
|
183
|
+
* Optional named segment with Prefix and Suffix: `/foo/prefix{-bar}suffix`
|
|
184
|
+
* Escape special characters:
|
|
185
|
+
* - `/foo/[$]` - Static route
|
|
186
|
+
* - `/foo/[$]{$foo} - Dynamic route with a static prefix of `$`
|
|
187
|
+
* - `/foo/{$foo}[$]` - Dynamic route with a static suffix of `$`
|
|
188
|
+
*/
|
|
144
189
|
export function parsePathname(pathname?: string): Array<Segment> {
|
|
145
190
|
if (!pathname) {
|
|
146
191
|
return []
|
|
@@ -167,20 +212,55 @@ export function parsePathname(pathname?: string): Array<Segment> {
|
|
|
167
212
|
|
|
168
213
|
segments.push(
|
|
169
214
|
...split.map((part): Segment => {
|
|
170
|
-
|
|
215
|
+
// Check for wildcard with curly braces: prefix{$}suffix
|
|
216
|
+
const wildcardBracesMatch = part.match(WILDCARD_W_CURLY_BRACES_RE)
|
|
217
|
+
if (wildcardBracesMatch) {
|
|
218
|
+
const prefix = wildcardBracesMatch[1]
|
|
219
|
+
const suffix = wildcardBracesMatch[2]
|
|
171
220
|
return {
|
|
172
221
|
type: 'wildcard',
|
|
173
|
-
value:
|
|
222
|
+
value: '$',
|
|
223
|
+
prefixSegment: prefix || undefined,
|
|
224
|
+
suffixSegment: suffix || undefined,
|
|
174
225
|
}
|
|
175
226
|
}
|
|
176
227
|
|
|
177
|
-
|
|
228
|
+
// Check for the new parameter format: prefix{$paramName}suffix
|
|
229
|
+
const paramBracesMatch = part.match(PARAM_W_CURLY_BRACES_RE)
|
|
230
|
+
if (paramBracesMatch) {
|
|
231
|
+
const prefix = paramBracesMatch[1]
|
|
232
|
+
const paramName = paramBracesMatch[2]
|
|
233
|
+
const suffix = paramBracesMatch[3]
|
|
178
234
|
return {
|
|
179
235
|
type: 'param',
|
|
180
|
-
value:
|
|
236
|
+
value: '' + paramName,
|
|
237
|
+
prefixSegment: prefix || undefined,
|
|
238
|
+
suffixSegment: suffix || undefined,
|
|
181
239
|
}
|
|
182
240
|
}
|
|
183
241
|
|
|
242
|
+
// Check for bare parameter format: $paramName (without curly braces)
|
|
243
|
+
if (PARAM_RE.test(part)) {
|
|
244
|
+
const paramName = part.substring(1)
|
|
245
|
+
return {
|
|
246
|
+
type: 'param',
|
|
247
|
+
value: '$' + paramName,
|
|
248
|
+
prefixSegment: undefined,
|
|
249
|
+
suffixSegment: undefined,
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Check for bare wildcard: $ (without curly braces)
|
|
254
|
+
if (WILDCARD_RE.test(part)) {
|
|
255
|
+
return {
|
|
256
|
+
type: 'wildcard',
|
|
257
|
+
value: '$',
|
|
258
|
+
prefixSegment: undefined,
|
|
259
|
+
suffixSegment: undefined,
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Handle regular pathname segment
|
|
184
264
|
return {
|
|
185
265
|
type: 'pathname',
|
|
186
266
|
value: part.includes('%25')
|
|
@@ -248,9 +328,13 @@ export function interpolatePath({
|
|
|
248
328
|
interpolatedPathSegments.map((segment) => {
|
|
249
329
|
if (segment.type === 'wildcard') {
|
|
250
330
|
usedParams._splat = params._splat
|
|
331
|
+
const segmentPrefix = segment.prefixSegment || ''
|
|
332
|
+
const segmentSuffix = segment.suffixSegment || ''
|
|
251
333
|
const value = encodeParam('_splat')
|
|
252
|
-
if (leaveWildcards)
|
|
253
|
-
|
|
334
|
+
if (leaveWildcards) {
|
|
335
|
+
return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`
|
|
336
|
+
}
|
|
337
|
+
return `${segmentPrefix}${value}${segmentSuffix}`
|
|
254
338
|
}
|
|
255
339
|
|
|
256
340
|
if (segment.type === 'param') {
|
|
@@ -259,11 +343,14 @@ export function interpolatePath({
|
|
|
259
343
|
isMissingParams = true
|
|
260
344
|
}
|
|
261
345
|
usedParams[key] = params[key]
|
|
346
|
+
|
|
347
|
+
const segmentPrefix = segment.prefixSegment || ''
|
|
348
|
+
const segmentSuffix = segment.suffixSegment || ''
|
|
262
349
|
if (leaveParams) {
|
|
263
350
|
const value = encodeParam(segment.value)
|
|
264
|
-
return `${segment.value}${value ?? ''}`
|
|
351
|
+
return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`
|
|
265
352
|
}
|
|
266
|
-
return encodeParam(key) ?? 'undefined'
|
|
353
|
+
return `${segmentPrefix}${encodeParam(key) ?? 'undefined'}${segmentSuffix}`
|
|
267
354
|
}
|
|
268
355
|
|
|
269
356
|
return segment.value
|
|
@@ -390,9 +477,57 @@ export function matchByPath(
|
|
|
390
477
|
|
|
391
478
|
if (routeSegment) {
|
|
392
479
|
if (routeSegment.type === 'wildcard') {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
480
|
+
// Capture all remaining segments for a wildcard
|
|
481
|
+
const remainingBaseSegments = baseSegments.slice(i)
|
|
482
|
+
|
|
483
|
+
let _splat: string
|
|
484
|
+
|
|
485
|
+
// If this is a wildcard with prefix/suffix, we need to handle the first segment specially
|
|
486
|
+
if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
|
|
487
|
+
if (!baseSegment) return false
|
|
488
|
+
|
|
489
|
+
const prefix = routeSegment.prefixSegment || ''
|
|
490
|
+
const suffix = routeSegment.suffixSegment || ''
|
|
491
|
+
|
|
492
|
+
// Check if the base segment starts with prefix and ends with suffix
|
|
493
|
+
const baseValue = baseSegment.value
|
|
494
|
+
if ('prefixSegment' in routeSegment) {
|
|
495
|
+
if (!baseValue.startsWith(prefix)) {
|
|
496
|
+
return false
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if ('suffixSegment' in routeSegment) {
|
|
500
|
+
if (
|
|
501
|
+
!baseSegments[baseSegments.length - 1]?.value.endsWith(suffix)
|
|
502
|
+
) {
|
|
503
|
+
return false
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
let rejoinedSplat = decodeURI(
|
|
508
|
+
joinPaths(remainingBaseSegments.map((d) => d.value)),
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
// Remove the prefix and suffix from the rejoined splat
|
|
512
|
+
if (prefix && rejoinedSplat.startsWith(prefix)) {
|
|
513
|
+
rejoinedSplat = rejoinedSplat.slice(prefix.length)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (suffix && rejoinedSplat.endsWith(suffix)) {
|
|
517
|
+
rejoinedSplat = rejoinedSplat.slice(
|
|
518
|
+
0,
|
|
519
|
+
rejoinedSplat.length - suffix.length,
|
|
520
|
+
)
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
_splat = rejoinedSplat
|
|
524
|
+
} else {
|
|
525
|
+
// If no prefix/suffix, just rejoin the remaining segments
|
|
526
|
+
_splat = decodeURI(
|
|
527
|
+
joinPaths(remainingBaseSegments.map((d) => d.value)),
|
|
528
|
+
)
|
|
529
|
+
}
|
|
530
|
+
|
|
396
531
|
// TODO: Deprecate *
|
|
397
532
|
params['*'] = _splat
|
|
398
533
|
params['_splat'] = _splat
|
|
@@ -426,11 +561,41 @@ export function matchByPath(
|
|
|
426
561
|
if (baseSegment.value === '/') {
|
|
427
562
|
return false
|
|
428
563
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
564
|
+
|
|
565
|
+
let _paramValue: string
|
|
566
|
+
|
|
567
|
+
// If this param has prefix/suffix, we need to extract the actual parameter value
|
|
568
|
+
if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
|
|
569
|
+
const prefix = routeSegment.prefixSegment || ''
|
|
570
|
+
const suffix = routeSegment.suffixSegment || ''
|
|
571
|
+
|
|
572
|
+
// Check if the base segment starts with prefix and ends with suffix
|
|
573
|
+
const baseValue = baseSegment.value
|
|
574
|
+
if (prefix && !baseValue.startsWith(prefix)) {
|
|
575
|
+
return false
|
|
576
|
+
}
|
|
577
|
+
if (suffix && !baseValue.endsWith(suffix)) {
|
|
578
|
+
return false
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
let paramValue = baseValue
|
|
582
|
+
if (prefix && paramValue.startsWith(prefix)) {
|
|
583
|
+
paramValue = paramValue.slice(prefix.length)
|
|
584
|
+
}
|
|
585
|
+
if (suffix && paramValue.endsWith(suffix)) {
|
|
586
|
+
paramValue = paramValue.slice(
|
|
587
|
+
0,
|
|
588
|
+
paramValue.length - suffix.length,
|
|
589
|
+
)
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
_paramValue = decodeURIComponent(paramValue)
|
|
593
|
+
} else {
|
|
594
|
+
// If no prefix/suffix, just decode the base segment value
|
|
595
|
+
_paramValue = decodeURIComponent(baseSegment.value)
|
|
433
596
|
}
|
|
597
|
+
|
|
598
|
+
params[routeSegment.value.substring(1)] = _paramValue
|
|
434
599
|
}
|
|
435
600
|
}
|
|
436
601
|
|
package/src/redirect.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { NavigateOptions } from './link'
|
|
2
2
|
import type { AnyRouter, RegisteredRouter } from './router'
|
|
3
|
-
import type { PickAsRequired } from './utils'
|
|
4
3
|
|
|
5
4
|
export type AnyRedirect = Redirect<any, any, any, any, any>
|
|
6
5
|
|
|
@@ -13,6 +12,17 @@ export type Redirect<
|
|
|
13
12
|
TTo extends string | undefined = undefined,
|
|
14
13
|
TMaskFrom extends string = TFrom,
|
|
15
14
|
TMaskTo extends string = '.',
|
|
15
|
+
> = Response & {
|
|
16
|
+
options: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>
|
|
17
|
+
redirectHandled?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type RedirectOptions<
|
|
21
|
+
TRouter extends AnyRouter = RegisteredRouter,
|
|
22
|
+
TFrom extends string = string,
|
|
23
|
+
TTo extends string | undefined = undefined,
|
|
24
|
+
TMaskFrom extends string = TFrom,
|
|
25
|
+
TMaskTo extends string = '.',
|
|
16
26
|
> = {
|
|
17
27
|
href?: string
|
|
18
28
|
/**
|
|
@@ -42,12 +52,7 @@ export type ResolvedRedirect<
|
|
|
42
52
|
TTo extends string = '',
|
|
43
53
|
TMaskFrom extends string = TFrom,
|
|
44
54
|
TMaskTo extends string = '',
|
|
45
|
-
> =
|
|
46
|
-
Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,
|
|
47
|
-
'code' | 'statusCode' | 'headers'
|
|
48
|
-
> & {
|
|
49
|
-
href: string
|
|
50
|
-
}
|
|
55
|
+
> = Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>
|
|
51
56
|
|
|
52
57
|
export function redirect<
|
|
53
58
|
TRouter extends AnyRouter = RegisteredRouter,
|
|
@@ -56,30 +61,40 @@ export function redirect<
|
|
|
56
61
|
const TMaskFrom extends string = TFrom,
|
|
57
62
|
const TMaskTo extends string = '',
|
|
58
63
|
>(
|
|
59
|
-
opts:
|
|
64
|
+
opts: RedirectOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,
|
|
60
65
|
): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> {
|
|
61
|
-
;(opts as any).isRedirect = true
|
|
62
66
|
opts.statusCode = opts.statusCode || opts.code || 307
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const headers = new Headers(opts.headers || {})
|
|
68
|
+
|
|
69
|
+
const response = new Response(null, {
|
|
70
|
+
status: opts.statusCode,
|
|
71
|
+
headers,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
;(response as Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>).options =
|
|
75
|
+
opts
|
|
71
76
|
|
|
72
77
|
if (opts.throw) {
|
|
73
|
-
throw
|
|
78
|
+
throw response
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
return
|
|
81
|
+
return response as Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
export function isRedirect(obj: any): obj is AnyRedirect {
|
|
80
|
-
return !!obj
|
|
85
|
+
return obj instanceof Response && !!(obj as any).options
|
|
81
86
|
}
|
|
82
87
|
|
|
83
|
-
export function isResolvedRedirect(
|
|
84
|
-
|
|
88
|
+
export function isResolvedRedirect(
|
|
89
|
+
obj: any,
|
|
90
|
+
): obj is AnyRedirect & { options: { href: string } } {
|
|
91
|
+
return isRedirect(obj) && !!obj.options.href
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function parseRedirect(obj: any) {
|
|
95
|
+
if (typeof obj === 'object' && obj.isSerializedRedirect) {
|
|
96
|
+
return redirect(obj)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return undefined
|
|
85
100
|
}
|
package/src/route.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import invariant from 'tiny-invariant'
|
|
1
2
|
import { joinPaths, trimPathLeft } from './path'
|
|
2
3
|
import { notFound } from './not-found'
|
|
3
4
|
import { rootRouteId } from './root'
|
|
@@ -20,6 +21,8 @@ import type {
|
|
|
20
21
|
Constrain,
|
|
21
22
|
Expand,
|
|
22
23
|
IntersectAssign,
|
|
24
|
+
LooseAsyncReturnType,
|
|
25
|
+
LooseReturnType,
|
|
23
26
|
NoInfer,
|
|
24
27
|
} from './utils'
|
|
25
28
|
import type {
|
|
@@ -150,27 +153,24 @@ export type ResolveSearchSchema<TSearchValidator> =
|
|
|
150
153
|
? ResolveSearchSchemaFn<TSearchValidator['parse']>
|
|
151
154
|
: ResolveSearchSchemaFn<TSearchValidator>
|
|
152
155
|
|
|
153
|
-
export type
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
? never
|
|
157
|
-
: '_splat'
|
|
158
|
-
: '_splat'
|
|
156
|
+
export type ResolveRequiredParams<TPath extends string, T> = {
|
|
157
|
+
[K in ParsePathParams<TPath>['required']]: T
|
|
158
|
+
}
|
|
159
159
|
|
|
160
|
-
export
|
|
161
|
-
|
|
160
|
+
export type ResolveOptionalParams<TPath extends string, T> = {
|
|
161
|
+
[K in ParsePathParams<TPath>['optional']]?: T
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
export type ResolveParams<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
export type ResolveParams<
|
|
165
|
+
TPath extends string,
|
|
166
|
+
T = string,
|
|
167
|
+
> = ResolveRequiredParams<TPath, T> & ResolveOptionalParams<TPath, T>
|
|
168
168
|
|
|
169
169
|
export type ParseParamsFn<in out TPath extends string, in out TParams> = (
|
|
170
|
-
rawParams: ResolveParams<TPath
|
|
171
|
-
) => TParams extends
|
|
170
|
+
rawParams: Expand<ResolveParams<TPath>>,
|
|
171
|
+
) => TParams extends ResolveParams<TPath, any>
|
|
172
172
|
? TParams
|
|
173
|
-
:
|
|
173
|
+
: ResolveParams<TPath, any>
|
|
174
174
|
|
|
175
175
|
export type StringifyParamsFn<in out TPath extends string, in out TParams> = (
|
|
176
176
|
params: TParams,
|
|
@@ -270,20 +270,6 @@ export type TrimPathRight<T extends string> = T extends '/'
|
|
|
270
270
|
? TrimPathRight<U>
|
|
271
271
|
: T
|
|
272
272
|
|
|
273
|
-
export type LooseReturnType<T> = T extends (
|
|
274
|
-
...args: Array<any>
|
|
275
|
-
) => infer TReturn
|
|
276
|
-
? TReturn
|
|
277
|
-
: never
|
|
278
|
-
|
|
279
|
-
export type LooseAsyncReturnType<T> = T extends (
|
|
280
|
-
...args: Array<any>
|
|
281
|
-
) => infer TReturn
|
|
282
|
-
? TReturn extends Promise<infer TReturn>
|
|
283
|
-
? TReturn
|
|
284
|
-
: TReturn
|
|
285
|
-
: never
|
|
286
|
-
|
|
287
273
|
export type ContextReturnType<TContextFn> = unknown extends TContextFn
|
|
288
274
|
? TContextFn
|
|
289
275
|
: LooseReturnType<TContextFn> extends never
|
|
@@ -448,7 +434,7 @@ export interface RouteExtensions<in out TId, in out TFullPath> {
|
|
|
448
434
|
}
|
|
449
435
|
|
|
450
436
|
export type RouteLazyFn<TRoute extends AnyRoute> = (
|
|
451
|
-
lazyFn: () => Promise<LazyRoute
|
|
437
|
+
lazyFn: () => Promise<LazyRoute<TRoute>>,
|
|
452
438
|
) => TRoute
|
|
453
439
|
|
|
454
440
|
export type RouteAddChildrenFn<
|
|
@@ -602,7 +588,26 @@ export interface Route<
|
|
|
602
588
|
>
|
|
603
589
|
isRoot: TParentRoute extends AnyRoute ? true : false
|
|
604
590
|
_componentsPromise?: Promise<Array<void>>
|
|
605
|
-
lazyFn?: () => Promise<
|
|
591
|
+
lazyFn?: () => Promise<
|
|
592
|
+
LazyRoute<
|
|
593
|
+
Route<
|
|
594
|
+
TParentRoute,
|
|
595
|
+
TPath,
|
|
596
|
+
TFullPath,
|
|
597
|
+
TCustomId,
|
|
598
|
+
TId,
|
|
599
|
+
TSearchValidator,
|
|
600
|
+
TParams,
|
|
601
|
+
TRouterContext,
|
|
602
|
+
TRouteContextFn,
|
|
603
|
+
TBeforeLoadFn,
|
|
604
|
+
TLoaderDeps,
|
|
605
|
+
TLoaderFn,
|
|
606
|
+
TChildren,
|
|
607
|
+
TFileRouteTypes
|
|
608
|
+
>
|
|
609
|
+
>
|
|
610
|
+
>
|
|
606
611
|
_lazyPromise?: Promise<void>
|
|
607
612
|
rank: number
|
|
608
613
|
to: TrimPathRight<TFullPath>
|
|
@@ -621,7 +626,24 @@ export interface Route<
|
|
|
621
626
|
TBeforeLoadFn
|
|
622
627
|
>,
|
|
623
628
|
) => this
|
|
624
|
-
lazy: RouteLazyFn<
|
|
629
|
+
lazy: RouteLazyFn<
|
|
630
|
+
Route<
|
|
631
|
+
TParentRoute,
|
|
632
|
+
TPath,
|
|
633
|
+
TFullPath,
|
|
634
|
+
TCustomId,
|
|
635
|
+
TId,
|
|
636
|
+
TSearchValidator,
|
|
637
|
+
TParams,
|
|
638
|
+
TRouterContext,
|
|
639
|
+
TRouteContextFn,
|
|
640
|
+
TBeforeLoadFn,
|
|
641
|
+
TLoaderDeps,
|
|
642
|
+
TLoaderFn,
|
|
643
|
+
TChildren,
|
|
644
|
+
TFileRouteTypes
|
|
645
|
+
>
|
|
646
|
+
>
|
|
625
647
|
addChildren: RouteAddChildrenFn<
|
|
626
648
|
TParentRoute,
|
|
627
649
|
TPath,
|
|
@@ -960,7 +982,7 @@ type AssetFnContextOptions<
|
|
|
960
982
|
TLoaderDeps
|
|
961
983
|
>
|
|
962
984
|
params: ResolveAllParamsFromParent<TParentRoute, TParams>
|
|
963
|
-
loaderData
|
|
985
|
+
loaderData?: ResolveLoaderData<TLoaderFn>
|
|
964
986
|
}
|
|
965
987
|
|
|
966
988
|
export interface DefaultUpdatableRouteOptionsExtensions {
|
|
@@ -1070,9 +1092,20 @@ export interface UpdatableRouteOptions<
|
|
|
1070
1092
|
TLoaderDeps
|
|
1071
1093
|
>,
|
|
1072
1094
|
) => void
|
|
1073
|
-
headers?: (
|
|
1074
|
-
|
|
1075
|
-
|
|
1095
|
+
headers?: (
|
|
1096
|
+
ctx: AssetFnContextOptions<
|
|
1097
|
+
TRouteId,
|
|
1098
|
+
TFullPath,
|
|
1099
|
+
TParentRoute,
|
|
1100
|
+
TParams,
|
|
1101
|
+
TSearchValidator,
|
|
1102
|
+
TLoaderFn,
|
|
1103
|
+
TRouterContext,
|
|
1104
|
+
TRouteContextFn,
|
|
1105
|
+
TBeforeLoadFn,
|
|
1106
|
+
TLoaderDeps
|
|
1107
|
+
>,
|
|
1108
|
+
) => Record<string, string>
|
|
1076
1109
|
head?: (
|
|
1077
1110
|
ctx: AssetFnContextOptions<
|
|
1078
1111
|
TRouteId,
|
|
@@ -1336,7 +1369,26 @@ export class BaseRoute<
|
|
|
1336
1369
|
children?: TChildren
|
|
1337
1370
|
originalIndex?: number
|
|
1338
1371
|
rank!: number
|
|
1339
|
-
lazyFn?: () => Promise<
|
|
1372
|
+
lazyFn?: () => Promise<
|
|
1373
|
+
LazyRoute<
|
|
1374
|
+
Route<
|
|
1375
|
+
TParentRoute,
|
|
1376
|
+
TPath,
|
|
1377
|
+
TFullPath,
|
|
1378
|
+
TCustomId,
|
|
1379
|
+
TId,
|
|
1380
|
+
TSearchValidator,
|
|
1381
|
+
TParams,
|
|
1382
|
+
TRouterContext,
|
|
1383
|
+
TRouteContextFn,
|
|
1384
|
+
TBeforeLoadFn,
|
|
1385
|
+
TLoaderDeps,
|
|
1386
|
+
TLoaderFn,
|
|
1387
|
+
TChildren,
|
|
1388
|
+
TFileRouteTypes
|
|
1389
|
+
>
|
|
1390
|
+
>
|
|
1391
|
+
>
|
|
1340
1392
|
_lazyPromise?: Promise<void>
|
|
1341
1393
|
_componentsPromise?: Promise<Array<void>>
|
|
1342
1394
|
|
|
@@ -1409,7 +1461,8 @@ export class BaseRoute<
|
|
|
1409
1461
|
if (isRoot) {
|
|
1410
1462
|
this._path = rootRouteId as TPath
|
|
1411
1463
|
} else if (!this.parentRoute) {
|
|
1412
|
-
|
|
1464
|
+
invariant(
|
|
1465
|
+
false,
|
|
1413
1466
|
`Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,
|
|
1414
1467
|
)
|
|
1415
1468
|
}
|
|
@@ -1449,6 +1502,16 @@ export class BaseRoute<
|
|
|
1449
1502
|
this._ssr = options?.ssr ?? opts.defaultSsr ?? true
|
|
1450
1503
|
}
|
|
1451
1504
|
|
|
1505
|
+
clone = (other: typeof this) => {
|
|
1506
|
+
this._path = other._path
|
|
1507
|
+
this._id = other._id
|
|
1508
|
+
this._fullPath = other._fullPath
|
|
1509
|
+
this._to = other._to
|
|
1510
|
+
this._ssr = other._ssr
|
|
1511
|
+
this.options.getParentRoute = other.options.getParentRoute
|
|
1512
|
+
this.children = other.children
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1452
1515
|
addChildren: RouteAddChildrenFn<
|
|
1453
1516
|
TParentRoute,
|
|
1454
1517
|
TPath,
|
|
@@ -1562,7 +1625,24 @@ export class BaseRoute<
|
|
|
1562
1625
|
return this
|
|
1563
1626
|
}
|
|
1564
1627
|
|
|
1565
|
-
lazy: RouteLazyFn<
|
|
1628
|
+
lazy: RouteLazyFn<
|
|
1629
|
+
Route<
|
|
1630
|
+
TParentRoute,
|
|
1631
|
+
TPath,
|
|
1632
|
+
TFullPath,
|
|
1633
|
+
TCustomId,
|
|
1634
|
+
TId,
|
|
1635
|
+
TSearchValidator,
|
|
1636
|
+
TParams,
|
|
1637
|
+
TRouterContext,
|
|
1638
|
+
TRouteContextFn,
|
|
1639
|
+
TBeforeLoadFn,
|
|
1640
|
+
TLoaderDeps,
|
|
1641
|
+
TLoaderFn,
|
|
1642
|
+
TChildren,
|
|
1643
|
+
TFileRouteTypes
|
|
1644
|
+
>
|
|
1645
|
+
> = (lazyFn) => {
|
|
1566
1646
|
this.lazyFn = lazyFn
|
|
1567
1647
|
return this
|
|
1568
1648
|
}
|