@tanstack/router-core 1.120.5 → 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 +15 -14
- package/dist/cjs/router.cjs +231 -155
- 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 +15 -14
- 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 +234 -158
- 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 +104 -35
- package/src/router.ts +332 -209
- 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,
|
|
@@ -1347,7 +1369,26 @@ export class BaseRoute<
|
|
|
1347
1369
|
children?: TChildren
|
|
1348
1370
|
originalIndex?: number
|
|
1349
1371
|
rank!: number
|
|
1350
|
-
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
|
+
>
|
|
1351
1392
|
_lazyPromise?: Promise<void>
|
|
1352
1393
|
_componentsPromise?: Promise<Array<void>>
|
|
1353
1394
|
|
|
@@ -1420,7 +1461,8 @@ export class BaseRoute<
|
|
|
1420
1461
|
if (isRoot) {
|
|
1421
1462
|
this._path = rootRouteId as TPath
|
|
1422
1463
|
} else if (!this.parentRoute) {
|
|
1423
|
-
|
|
1464
|
+
invariant(
|
|
1465
|
+
false,
|
|
1424
1466
|
`Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,
|
|
1425
1467
|
)
|
|
1426
1468
|
}
|
|
@@ -1460,6 +1502,16 @@ export class BaseRoute<
|
|
|
1460
1502
|
this._ssr = options?.ssr ?? opts.defaultSsr ?? true
|
|
1461
1503
|
}
|
|
1462
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
|
+
|
|
1463
1515
|
addChildren: RouteAddChildrenFn<
|
|
1464
1516
|
TParentRoute,
|
|
1465
1517
|
TPath,
|
|
@@ -1573,7 +1625,24 @@ export class BaseRoute<
|
|
|
1573
1625
|
return this
|
|
1574
1626
|
}
|
|
1575
1627
|
|
|
1576
|
-
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) => {
|
|
1577
1646
|
this.lazyFn = lazyFn
|
|
1578
1647
|
return this
|
|
1579
1648
|
}
|