@tanstack/router-core 1.120.5 → 1.121.0-alpha.3
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 +19 -18
- package/dist/cjs/router.cjs +268 -195
- 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 +3 -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 +19 -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 +271 -198
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/typePrimitives.d.ts +2 -2
- package/dist/esm/utils.d.ts +3 -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 +109 -39
- package/src/router.ts +373 -250
- package/src/typePrimitives.ts +2 -2
- package/src/utils.ts +15 -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'
|
|
@@ -17,9 +18,12 @@ import type { AnyRouter, RegisteredRouter } from './router'
|
|
|
17
18
|
import type { BuildLocationFn, NavigateFn } from './RouterProvider'
|
|
18
19
|
import type {
|
|
19
20
|
Assign,
|
|
21
|
+
Awaitable,
|
|
20
22
|
Constrain,
|
|
21
23
|
Expand,
|
|
22
24
|
IntersectAssign,
|
|
25
|
+
LooseAsyncReturnType,
|
|
26
|
+
LooseReturnType,
|
|
23
27
|
NoInfer,
|
|
24
28
|
} from './utils'
|
|
25
29
|
import type {
|
|
@@ -150,27 +154,24 @@ export type ResolveSearchSchema<TSearchValidator> =
|
|
|
150
154
|
? ResolveSearchSchemaFn<TSearchValidator['parse']>
|
|
151
155
|
: ResolveSearchSchemaFn<TSearchValidator>
|
|
152
156
|
|
|
153
|
-
export type
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
? never
|
|
157
|
-
: '_splat'
|
|
158
|
-
: '_splat'
|
|
157
|
+
export type ResolveRequiredParams<TPath extends string, T> = {
|
|
158
|
+
[K in ParsePathParams<TPath>['required']]: T
|
|
159
|
+
}
|
|
159
160
|
|
|
160
|
-
export
|
|
161
|
-
|
|
161
|
+
export type ResolveOptionalParams<TPath extends string, T> = {
|
|
162
|
+
[K in ParsePathParams<TPath>['optional']]?: T
|
|
162
163
|
}
|
|
163
164
|
|
|
164
|
-
export type ResolveParams<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
export type ResolveParams<
|
|
166
|
+
TPath extends string,
|
|
167
|
+
T = string,
|
|
168
|
+
> = ResolveRequiredParams<TPath, T> & ResolveOptionalParams<TPath, T>
|
|
168
169
|
|
|
169
170
|
export type ParseParamsFn<in out TPath extends string, in out TParams> = (
|
|
170
|
-
rawParams: ResolveParams<TPath
|
|
171
|
-
) => TParams extends
|
|
171
|
+
rawParams: Expand<ResolveParams<TPath>>,
|
|
172
|
+
) => TParams extends ResolveParams<TPath, any>
|
|
172
173
|
? TParams
|
|
173
|
-
:
|
|
174
|
+
: ResolveParams<TPath, any>
|
|
174
175
|
|
|
175
176
|
export type StringifyParamsFn<in out TPath extends string, in out TParams> = (
|
|
176
177
|
params: TParams,
|
|
@@ -270,20 +271,6 @@ export type TrimPathRight<T extends string> = T extends '/'
|
|
|
270
271
|
? TrimPathRight<U>
|
|
271
272
|
: T
|
|
272
273
|
|
|
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
274
|
export type ContextReturnType<TContextFn> = unknown extends TContextFn
|
|
288
275
|
? TContextFn
|
|
289
276
|
: LooseReturnType<TContextFn> extends never
|
|
@@ -448,7 +435,7 @@ export interface RouteExtensions<in out TId, in out TFullPath> {
|
|
|
448
435
|
}
|
|
449
436
|
|
|
450
437
|
export type RouteLazyFn<TRoute extends AnyRoute> = (
|
|
451
|
-
lazyFn: () => Promise<LazyRoute
|
|
438
|
+
lazyFn: () => Promise<LazyRoute<TRoute>>,
|
|
452
439
|
) => TRoute
|
|
453
440
|
|
|
454
441
|
export type RouteAddChildrenFn<
|
|
@@ -602,7 +589,26 @@ export interface Route<
|
|
|
602
589
|
>
|
|
603
590
|
isRoot: TParentRoute extends AnyRoute ? true : false
|
|
604
591
|
_componentsPromise?: Promise<Array<void>>
|
|
605
|
-
lazyFn?: () => Promise<
|
|
592
|
+
lazyFn?: () => Promise<
|
|
593
|
+
LazyRoute<
|
|
594
|
+
Route<
|
|
595
|
+
TParentRoute,
|
|
596
|
+
TPath,
|
|
597
|
+
TFullPath,
|
|
598
|
+
TCustomId,
|
|
599
|
+
TId,
|
|
600
|
+
TSearchValidator,
|
|
601
|
+
TParams,
|
|
602
|
+
TRouterContext,
|
|
603
|
+
TRouteContextFn,
|
|
604
|
+
TBeforeLoadFn,
|
|
605
|
+
TLoaderDeps,
|
|
606
|
+
TLoaderFn,
|
|
607
|
+
TChildren,
|
|
608
|
+
TFileRouteTypes
|
|
609
|
+
>
|
|
610
|
+
>
|
|
611
|
+
>
|
|
606
612
|
_lazyPromise?: Promise<void>
|
|
607
613
|
rank: number
|
|
608
614
|
to: TrimPathRight<TFullPath>
|
|
@@ -621,7 +627,24 @@ export interface Route<
|
|
|
621
627
|
TBeforeLoadFn
|
|
622
628
|
>,
|
|
623
629
|
) => this
|
|
624
|
-
lazy: RouteLazyFn<
|
|
630
|
+
lazy: RouteLazyFn<
|
|
631
|
+
Route<
|
|
632
|
+
TParentRoute,
|
|
633
|
+
TPath,
|
|
634
|
+
TFullPath,
|
|
635
|
+
TCustomId,
|
|
636
|
+
TId,
|
|
637
|
+
TSearchValidator,
|
|
638
|
+
TParams,
|
|
639
|
+
TRouterContext,
|
|
640
|
+
TRouteContextFn,
|
|
641
|
+
TBeforeLoadFn,
|
|
642
|
+
TLoaderDeps,
|
|
643
|
+
TLoaderFn,
|
|
644
|
+
TChildren,
|
|
645
|
+
TFileRouteTypes
|
|
646
|
+
>
|
|
647
|
+
>
|
|
625
648
|
addChildren: RouteAddChildrenFn<
|
|
626
649
|
TParentRoute,
|
|
627
650
|
TPath,
|
|
@@ -1083,7 +1106,7 @@ export interface UpdatableRouteOptions<
|
|
|
1083
1106
|
TBeforeLoadFn,
|
|
1084
1107
|
TLoaderDeps
|
|
1085
1108
|
>,
|
|
1086
|
-
) => Record<string, string
|
|
1109
|
+
) => Awaitable<Record<string, string>>
|
|
1087
1110
|
head?: (
|
|
1088
1111
|
ctx: AssetFnContextOptions<
|
|
1089
1112
|
TRouteId,
|
|
@@ -1097,11 +1120,11 @@ export interface UpdatableRouteOptions<
|
|
|
1097
1120
|
TBeforeLoadFn,
|
|
1098
1121
|
TLoaderDeps
|
|
1099
1122
|
>,
|
|
1100
|
-
) => {
|
|
1123
|
+
) => Awaitable<{
|
|
1101
1124
|
links?: AnyRouteMatch['links']
|
|
1102
1125
|
scripts?: AnyRouteMatch['headScripts']
|
|
1103
1126
|
meta?: AnyRouteMatch['meta']
|
|
1104
|
-
}
|
|
1127
|
+
}>
|
|
1105
1128
|
scripts?: (
|
|
1106
1129
|
ctx: AssetFnContextOptions<
|
|
1107
1130
|
TRouteId,
|
|
@@ -1115,7 +1138,7 @@ export interface UpdatableRouteOptions<
|
|
|
1115
1138
|
TBeforeLoadFn,
|
|
1116
1139
|
TLoaderDeps
|
|
1117
1140
|
>,
|
|
1118
|
-
) => AnyRouteMatch['scripts']
|
|
1141
|
+
) => Awaitable<AnyRouteMatch['scripts']>
|
|
1119
1142
|
ssr?: boolean
|
|
1120
1143
|
codeSplitGroupings?: Array<
|
|
1121
1144
|
Array<
|
|
@@ -1347,7 +1370,26 @@ export class BaseRoute<
|
|
|
1347
1370
|
children?: TChildren
|
|
1348
1371
|
originalIndex?: number
|
|
1349
1372
|
rank!: number
|
|
1350
|
-
lazyFn?: () => Promise<
|
|
1373
|
+
lazyFn?: () => Promise<
|
|
1374
|
+
LazyRoute<
|
|
1375
|
+
Route<
|
|
1376
|
+
TParentRoute,
|
|
1377
|
+
TPath,
|
|
1378
|
+
TFullPath,
|
|
1379
|
+
TCustomId,
|
|
1380
|
+
TId,
|
|
1381
|
+
TSearchValidator,
|
|
1382
|
+
TParams,
|
|
1383
|
+
TRouterContext,
|
|
1384
|
+
TRouteContextFn,
|
|
1385
|
+
TBeforeLoadFn,
|
|
1386
|
+
TLoaderDeps,
|
|
1387
|
+
TLoaderFn,
|
|
1388
|
+
TChildren,
|
|
1389
|
+
TFileRouteTypes
|
|
1390
|
+
>
|
|
1391
|
+
>
|
|
1392
|
+
>
|
|
1351
1393
|
_lazyPromise?: Promise<void>
|
|
1352
1394
|
_componentsPromise?: Promise<Array<void>>
|
|
1353
1395
|
|
|
@@ -1420,7 +1462,8 @@ export class BaseRoute<
|
|
|
1420
1462
|
if (isRoot) {
|
|
1421
1463
|
this._path = rootRouteId as TPath
|
|
1422
1464
|
} else if (!this.parentRoute) {
|
|
1423
|
-
|
|
1465
|
+
invariant(
|
|
1466
|
+
false,
|
|
1424
1467
|
`Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,
|
|
1425
1468
|
)
|
|
1426
1469
|
}
|
|
@@ -1460,6 +1503,16 @@ export class BaseRoute<
|
|
|
1460
1503
|
this._ssr = options?.ssr ?? opts.defaultSsr ?? true
|
|
1461
1504
|
}
|
|
1462
1505
|
|
|
1506
|
+
clone = (other: typeof this) => {
|
|
1507
|
+
this._path = other._path
|
|
1508
|
+
this._id = other._id
|
|
1509
|
+
this._fullPath = other._fullPath
|
|
1510
|
+
this._to = other._to
|
|
1511
|
+
this._ssr = other._ssr
|
|
1512
|
+
this.options.getParentRoute = other.options.getParentRoute
|
|
1513
|
+
this.children = other.children
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1463
1516
|
addChildren: RouteAddChildrenFn<
|
|
1464
1517
|
TParentRoute,
|
|
1465
1518
|
TPath,
|
|
@@ -1573,7 +1626,24 @@ export class BaseRoute<
|
|
|
1573
1626
|
return this
|
|
1574
1627
|
}
|
|
1575
1628
|
|
|
1576
|
-
lazy: RouteLazyFn<
|
|
1629
|
+
lazy: RouteLazyFn<
|
|
1630
|
+
Route<
|
|
1631
|
+
TParentRoute,
|
|
1632
|
+
TPath,
|
|
1633
|
+
TFullPath,
|
|
1634
|
+
TCustomId,
|
|
1635
|
+
TId,
|
|
1636
|
+
TSearchValidator,
|
|
1637
|
+
TParams,
|
|
1638
|
+
TRouterContext,
|
|
1639
|
+
TRouteContextFn,
|
|
1640
|
+
TBeforeLoadFn,
|
|
1641
|
+
TLoaderDeps,
|
|
1642
|
+
TLoaderFn,
|
|
1643
|
+
TChildren,
|
|
1644
|
+
TFileRouteTypes
|
|
1645
|
+
>
|
|
1646
|
+
> = (lazyFn) => {
|
|
1577
1647
|
this.lazyFn = lazyFn
|
|
1578
1648
|
return this
|
|
1579
1649
|
}
|