@tanstack/router-core 0.0.1-alpha.2 → 0.0.1-alpha.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/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js +30 -0
- package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +1 -0
- package/build/cjs/packages/router-core/src/index.js +72 -54
- package/build/cjs/packages/router-core/src/index.js.map +1 -1
- package/build/esm/index.js +85 -55
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +60 -35
- package/build/types/index.d.ts +49 -34
- package/build/umd/index.development.js +81 -52
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +219 -142
- package/src/createRoutes.test.ts +0 -328
package/src/index.ts
CHANGED
|
@@ -7,9 +7,10 @@ import {
|
|
|
7
7
|
History,
|
|
8
8
|
HashHistory,
|
|
9
9
|
} from 'history'
|
|
10
|
-
import
|
|
10
|
+
import invariant from 'tiny-invariant'
|
|
11
11
|
|
|
12
12
|
export { createHashHistory, createBrowserHistory, createMemoryHistory }
|
|
13
|
+
export { invariant }
|
|
13
14
|
|
|
14
15
|
import { decode, encode } from './qss'
|
|
15
16
|
|
|
@@ -62,6 +63,7 @@ export interface FrameworkGenerics {
|
|
|
62
63
|
|
|
63
64
|
export interface RouteConfig<
|
|
64
65
|
TId extends string = string,
|
|
66
|
+
TRouteId extends string = string,
|
|
65
67
|
TPath extends string = string,
|
|
66
68
|
TFullPath extends string = string,
|
|
67
69
|
TRouteLoaderData extends AnyLoaderData = AnyLoaderData,
|
|
@@ -80,9 +82,11 @@ export interface RouteConfig<
|
|
|
80
82
|
TKnownChildren = unknown,
|
|
81
83
|
> {
|
|
82
84
|
id: TId
|
|
85
|
+
routeId: TRouteId
|
|
83
86
|
path: NoInfer<TPath>
|
|
84
87
|
fullPath: TFullPath
|
|
85
88
|
options: RouteOptions<
|
|
89
|
+
TRouteId,
|
|
86
90
|
TPath,
|
|
87
91
|
TRouteLoaderData,
|
|
88
92
|
TLoaderData,
|
|
@@ -104,6 +108,7 @@ export interface RouteConfig<
|
|
|
104
108
|
createChildRoute: CreateRouteConfigFn<
|
|
105
109
|
false,
|
|
106
110
|
TId,
|
|
111
|
+
TFullPath,
|
|
107
112
|
TLoaderData,
|
|
108
113
|
TFullSearchSchema,
|
|
109
114
|
TAllParams
|
|
@@ -113,6 +118,7 @@ export interface RouteConfig<
|
|
|
113
118
|
: { error: 'Invalid route detected'; route: TNewChildren },
|
|
114
119
|
) => RouteConfig<
|
|
115
120
|
TId,
|
|
121
|
+
TRouteId,
|
|
116
122
|
TPath,
|
|
117
123
|
TFullPath,
|
|
118
124
|
TRouteLoaderData,
|
|
@@ -133,10 +139,12 @@ export interface RouteConfig<
|
|
|
133
139
|
type CreateRouteConfigFn<
|
|
134
140
|
TIsRoot extends boolean = false,
|
|
135
141
|
TParentId extends string = string,
|
|
142
|
+
TParentPath extends string = string,
|
|
136
143
|
TParentAllLoaderData extends AnyLoaderData = {},
|
|
137
144
|
TParentSearchSchema extends AnySearchSchema = {},
|
|
138
145
|
TParentParams extends AnyPathParams = {},
|
|
139
146
|
> = <
|
|
147
|
+
TRouteId extends string,
|
|
140
148
|
TPath extends string,
|
|
141
149
|
TRouteLoaderData extends AnyLoaderData,
|
|
142
150
|
TActionPayload,
|
|
@@ -152,10 +160,16 @@ type CreateRouteConfigFn<
|
|
|
152
160
|
? Record<ParsePathParams<TPath>, string>
|
|
153
161
|
: NoInfer<TParams>,
|
|
154
162
|
TKnownChildren extends RouteConfig[] = RouteConfig[],
|
|
163
|
+
TResolvedId extends string = string extends TRouteId
|
|
164
|
+
? string extends TPath
|
|
165
|
+
? string
|
|
166
|
+
: TPath
|
|
167
|
+
: TRouteId,
|
|
155
168
|
>(
|
|
156
169
|
options?: TIsRoot extends true
|
|
157
170
|
? Omit<
|
|
158
171
|
RouteOptions<
|
|
172
|
+
TRouteId,
|
|
159
173
|
TPath,
|
|
160
174
|
TRouteLoaderData,
|
|
161
175
|
Expand<TParentAllLoaderData & DeepAwaited<NoInfer<TRouteLoaderData>>>,
|
|
@@ -171,6 +185,7 @@ type CreateRouteConfigFn<
|
|
|
171
185
|
'path'
|
|
172
186
|
> & { path?: never }
|
|
173
187
|
: RouteOptions<
|
|
188
|
+
TRouteId,
|
|
174
189
|
TPath,
|
|
175
190
|
TRouteLoaderData,
|
|
176
191
|
Expand<TParentAllLoaderData & DeepAwaited<NoInfer<TRouteLoaderData>>>,
|
|
@@ -186,10 +201,12 @@ type CreateRouteConfigFn<
|
|
|
186
201
|
children?: TKnownChildren,
|
|
187
202
|
isRoot?: boolean,
|
|
188
203
|
parentId?: string,
|
|
204
|
+
parentPath?: string,
|
|
189
205
|
) => RouteConfig<
|
|
190
|
-
|
|
206
|
+
RoutePrefix<TParentId, TResolvedId>,
|
|
207
|
+
TResolvedId,
|
|
191
208
|
TPath,
|
|
192
|
-
|
|
209
|
+
string extends TPath ? '' : RoutePath<RoutePrefix<TParentPath, TPath>>,
|
|
193
210
|
TRouteLoaderData,
|
|
194
211
|
Expand<TParentAllLoaderData & DeepAwaited<NoInfer<TRouteLoaderData>>>,
|
|
195
212
|
TActionPayload,
|
|
@@ -208,11 +225,10 @@ export const createRouteConfig: CreateRouteConfigFn<true> = (
|
|
|
208
225
|
children,
|
|
209
226
|
isRoot = true,
|
|
210
227
|
parentId,
|
|
228
|
+
parentPath,
|
|
211
229
|
) => {
|
|
212
230
|
if (isRoot) {
|
|
213
231
|
;(options as any).path = rootRouteId
|
|
214
|
-
} else {
|
|
215
|
-
warning(!options.path, 'Routes must have a path property.')
|
|
216
232
|
}
|
|
217
233
|
|
|
218
234
|
// Strip the root from parentIds
|
|
@@ -220,14 +236,16 @@ export const createRouteConfig: CreateRouteConfigFn<true> = (
|
|
|
220
236
|
parentId = ''
|
|
221
237
|
}
|
|
222
238
|
|
|
223
|
-
let path =
|
|
239
|
+
let path: undefined | string = isRoot ? rootRouteId : options.path
|
|
224
240
|
|
|
225
241
|
// If the path is anything other than an index path, trim it up
|
|
226
|
-
if (path !== '/') {
|
|
242
|
+
if (path && path !== '/') {
|
|
227
243
|
path = trimPath(path)
|
|
228
244
|
}
|
|
229
245
|
|
|
230
|
-
|
|
246
|
+
const routeId = path || (options as { id?: string }).id
|
|
247
|
+
|
|
248
|
+
let id = joinPaths([parentId, routeId])
|
|
231
249
|
|
|
232
250
|
if (path === rootRouteId) {
|
|
233
251
|
path = '/'
|
|
@@ -237,10 +255,12 @@ export const createRouteConfig: CreateRouteConfigFn<true> = (
|
|
|
237
255
|
id = joinPaths(['/', id])
|
|
238
256
|
}
|
|
239
257
|
|
|
240
|
-
const fullPath =
|
|
258
|
+
const fullPath =
|
|
259
|
+
id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]))
|
|
241
260
|
|
|
242
261
|
return {
|
|
243
262
|
id: id as any,
|
|
263
|
+
routeId: routeId as any,
|
|
244
264
|
path: path as any,
|
|
245
265
|
fullPath: fullPath as any,
|
|
246
266
|
options: options as any,
|
|
@@ -249,10 +269,11 @@ export const createRouteConfig: CreateRouteConfigFn<true> = (
|
|
|
249
269
|
createRouteConfig(
|
|
250
270
|
options,
|
|
251
271
|
cb((childOptions: any) =>
|
|
252
|
-
createRouteConfig(childOptions, undefined, false, id),
|
|
272
|
+
createRouteConfig(childOptions, undefined, false, id, fullPath),
|
|
253
273
|
),
|
|
254
274
|
false,
|
|
255
275
|
parentId,
|
|
276
|
+
parentPath,
|
|
256
277
|
),
|
|
257
278
|
}
|
|
258
279
|
}
|
|
@@ -271,6 +292,8 @@ export interface AnyRouteConfig
|
|
|
271
292
|
any,
|
|
272
293
|
any,
|
|
273
294
|
any,
|
|
295
|
+
any,
|
|
296
|
+
any,
|
|
274
297
|
any
|
|
275
298
|
> {}
|
|
276
299
|
|
|
@@ -289,6 +312,7 @@ export interface AnyRouteConfigWithChildren<TChildren>
|
|
|
289
312
|
any,
|
|
290
313
|
any,
|
|
291
314
|
any,
|
|
315
|
+
any,
|
|
292
316
|
TChildren
|
|
293
317
|
> {}
|
|
294
318
|
|
|
@@ -297,7 +321,8 @@ export interface AnyAllRouteInfo {
|
|
|
297
321
|
routeInfo: AnyRouteInfo
|
|
298
322
|
routeInfoById: Record<string, AnyRouteInfo>
|
|
299
323
|
routeInfoByFullPath: Record<string, AnyRouteInfo>
|
|
300
|
-
|
|
324
|
+
routeIds: any
|
|
325
|
+
routePaths: any
|
|
301
326
|
}
|
|
302
327
|
|
|
303
328
|
export interface DefaultAllRouteInfo {
|
|
@@ -305,7 +330,8 @@ export interface DefaultAllRouteInfo {
|
|
|
305
330
|
routeInfo: RouteInfo
|
|
306
331
|
routeInfoById: Record<string, RouteInfo>
|
|
307
332
|
routeInfoByFullPath: Record<string, RouteInfo>
|
|
308
|
-
|
|
333
|
+
routeIds: string
|
|
334
|
+
routePaths: string
|
|
309
335
|
}
|
|
310
336
|
|
|
311
337
|
export interface AllRouteInfo<TRouteConfig extends AnyRouteConfig = RouteConfig>
|
|
@@ -325,20 +351,27 @@ export interface RoutesInfoInner<
|
|
|
325
351
|
any,
|
|
326
352
|
any,
|
|
327
353
|
any,
|
|
354
|
+
any,
|
|
355
|
+
any,
|
|
328
356
|
any
|
|
329
357
|
> = RouteInfo,
|
|
358
|
+
TRouteInfoById = {
|
|
359
|
+
[TInfo in TRouteInfo as TInfo['id']]: TInfo
|
|
360
|
+
},
|
|
361
|
+
TRouteInfoByFullPath = {
|
|
362
|
+
[TInfo in TRouteInfo as TInfo['fullPath'] extends RootRouteId
|
|
363
|
+
? never
|
|
364
|
+
: string extends TInfo['fullPath']
|
|
365
|
+
? never
|
|
366
|
+
: TInfo['fullPath']]: TInfo
|
|
367
|
+
},
|
|
330
368
|
> {
|
|
331
369
|
routeConfig: TRouteConfig
|
|
332
370
|
routeInfo: TRouteInfo
|
|
333
|
-
routeInfoById:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
[TInfo in TRouteInfo as TInfo['id'] extends RootRouteId
|
|
338
|
-
? never
|
|
339
|
-
: RouteIdToPath<TInfo['id']>]: TInfo
|
|
340
|
-
}
|
|
341
|
-
fullPath: RouteIdToPath<TRouteInfo['id']>
|
|
371
|
+
routeInfoById: TRouteInfoById
|
|
372
|
+
routeInfoByFullPath: TRouteInfoByFullPath
|
|
373
|
+
routeIds: keyof TRouteInfoById
|
|
374
|
+
routePaths: keyof TRouteInfoByFullPath
|
|
342
375
|
}
|
|
343
376
|
|
|
344
377
|
export interface AnyRoute extends Route<any, any> {}
|
|
@@ -356,6 +389,7 @@ export interface AnyRouteInfo
|
|
|
356
389
|
any,
|
|
357
390
|
any,
|
|
358
391
|
any,
|
|
392
|
+
any,
|
|
359
393
|
any
|
|
360
394
|
> {}
|
|
361
395
|
|
|
@@ -363,7 +397,7 @@ export interface AnyRouteInfo
|
|
|
363
397
|
// [E in T as E[TKey]]: E
|
|
364
398
|
// }
|
|
365
399
|
|
|
366
|
-
type
|
|
400
|
+
type RoutePath<T extends string> = T extends RootRouteId
|
|
367
401
|
? '/'
|
|
368
402
|
: TrimPathRight<`${T}`>
|
|
369
403
|
|
|
@@ -397,6 +431,7 @@ export type ValueKeys<O> = Extract<keyof O, PropertyKey>
|
|
|
397
431
|
|
|
398
432
|
export type RouteConfigRoute<TRouteConfig> = TRouteConfig extends RouteConfig<
|
|
399
433
|
infer TId,
|
|
434
|
+
infer TRouteId,
|
|
400
435
|
infer TPath,
|
|
401
436
|
infer TFullPath,
|
|
402
437
|
infer TRouteLoaderData,
|
|
@@ -411,10 +446,11 @@ export type RouteConfigRoute<TRouteConfig> = TRouteConfig extends RouteConfig<
|
|
|
411
446
|
infer TAllParams,
|
|
412
447
|
any
|
|
413
448
|
>
|
|
414
|
-
? string extends
|
|
449
|
+
? string extends TRouteId
|
|
415
450
|
? never
|
|
416
451
|
: RouteInfo<
|
|
417
452
|
TId,
|
|
453
|
+
TRouteId,
|
|
418
454
|
TPath,
|
|
419
455
|
TFullPath,
|
|
420
456
|
TRouteLoaderData,
|
|
@@ -432,8 +468,9 @@ export type RouteConfigRoute<TRouteConfig> = TRouteConfig extends RouteConfig<
|
|
|
432
468
|
|
|
433
469
|
export interface RouteInfo<
|
|
434
470
|
TId extends string = string,
|
|
471
|
+
TRouteId extends string = string,
|
|
435
472
|
TPath extends string = string,
|
|
436
|
-
TFullPath extends
|
|
473
|
+
TFullPath extends string = string,
|
|
437
474
|
TRouteLoaderData extends AnyLoaderData = {},
|
|
438
475
|
TLoaderData extends AnyLoaderData = {},
|
|
439
476
|
TActionPayload = unknown,
|
|
@@ -449,6 +486,7 @@ export interface RouteInfo<
|
|
|
449
486
|
TAllParams extends AnyPathParams = {},
|
|
450
487
|
> {
|
|
451
488
|
id: TId
|
|
489
|
+
routeId: TRouteId
|
|
452
490
|
path: TPath
|
|
453
491
|
fullPath: TFullPath
|
|
454
492
|
routeLoaderData: TRouteLoaderData
|
|
@@ -461,6 +499,7 @@ export interface RouteInfo<
|
|
|
461
499
|
params: TParams
|
|
462
500
|
allParams: TAllParams
|
|
463
501
|
options: RouteOptions<
|
|
502
|
+
TRouteId,
|
|
464
503
|
TPath,
|
|
465
504
|
TRouteLoaderData,
|
|
466
505
|
TLoaderData,
|
|
@@ -484,14 +523,16 @@ type DeepAwaited<T> = T extends Promise<infer A>
|
|
|
484
523
|
export const rootRouteId = '__root__' as const
|
|
485
524
|
export type RootRouteId = typeof rootRouteId
|
|
486
525
|
|
|
487
|
-
type
|
|
526
|
+
type RoutePrefix<
|
|
488
527
|
TPrefix extends string,
|
|
489
|
-
|
|
490
|
-
> = string extends
|
|
528
|
+
TId extends string,
|
|
529
|
+
> = string extends TId
|
|
491
530
|
? RootRouteId
|
|
492
|
-
:
|
|
493
|
-
? '/'
|
|
494
|
-
|
|
531
|
+
: TId extends string
|
|
532
|
+
? `${TPrefix}/${TId}` extends '/'
|
|
533
|
+
? '/'
|
|
534
|
+
: `/${TrimPathLeft<`${TrimPathRight<TPrefix>}/${TrimPath<TId>}`>}`
|
|
535
|
+
: never
|
|
495
536
|
|
|
496
537
|
type CleanPath<T extends string> = T extends `${infer L}//${infer R}`
|
|
497
538
|
? CleanPath<`${CleanPath<L>}/${CleanPath<R>}`>
|
|
@@ -621,6 +662,7 @@ export type ParentParams<TParentParams> = AnyPathParams extends TParentParams
|
|
|
621
662
|
}
|
|
622
663
|
|
|
623
664
|
export type RouteOptions<
|
|
665
|
+
TRouteId extends string = string,
|
|
624
666
|
TPath extends string = string,
|
|
625
667
|
TRouteLoaderData extends AnyLoaderData = {},
|
|
626
668
|
TLoaderData extends AnyLoaderData = {},
|
|
@@ -635,9 +677,15 @@ export type RouteOptions<
|
|
|
635
677
|
string
|
|
636
678
|
>,
|
|
637
679
|
TAllParams extends AnyPathParams = {},
|
|
638
|
-
> =
|
|
639
|
-
|
|
640
|
-
|
|
680
|
+
> = (
|
|
681
|
+
| {
|
|
682
|
+
// The path to match (relative to the nearest parent `Route` component or root basepath)
|
|
683
|
+
path: TPath
|
|
684
|
+
}
|
|
685
|
+
| {
|
|
686
|
+
id: TRouteId
|
|
687
|
+
}
|
|
688
|
+
) & {
|
|
641
689
|
// If true, this route will be matched as case-sensitive
|
|
642
690
|
caseSensitive?: boolean
|
|
643
691
|
validateSearch?: SearchSchemaValidator<TSearchSchema, TParentSearchSchema>
|
|
@@ -654,20 +702,20 @@ export type RouteOptions<
|
|
|
654
702
|
// // An array of child routes
|
|
655
703
|
// children?: Route<any, any, any, any>[]
|
|
656
704
|
} & (
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
) &
|
|
705
|
+
| {
|
|
706
|
+
parseParams?: never
|
|
707
|
+
stringifyParams?: never
|
|
708
|
+
}
|
|
709
|
+
| {
|
|
710
|
+
// Parse params optionally receives path params as strings and returns them in a parsed format (like a number or boolean)
|
|
711
|
+
parseParams: (
|
|
712
|
+
rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,
|
|
713
|
+
) => TParams
|
|
714
|
+
stringifyParams: (
|
|
715
|
+
params: TParams,
|
|
716
|
+
) => Record<ParsePathParams<TPath>, string>
|
|
717
|
+
}
|
|
718
|
+
) &
|
|
671
719
|
RouteLoaders<
|
|
672
720
|
// Route Loaders (see below) can be inline on the route, or resolved async
|
|
673
721
|
TRouteLoaderData,
|
|
@@ -924,7 +972,7 @@ type RoutesById<TAllRouteInfo extends AnyAllRouteInfo> = {
|
|
|
924
972
|
}
|
|
925
973
|
|
|
926
974
|
// type RoutesByPath<TAllRouteInfo extends AnyAllRouteInfo> = {
|
|
927
|
-
// [K in TAllRouteInfo['
|
|
975
|
+
// [K in TAllRouteInfo['routePaths']]: Route<
|
|
928
976
|
// TAllRouteInfo,
|
|
929
977
|
// TAllRouteInfo['routeInfoByFullPath'][K]
|
|
930
978
|
// >
|
|
@@ -934,16 +982,16 @@ export type ValidFromPath<
|
|
|
934
982
|
TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
|
|
935
983
|
> =
|
|
936
984
|
| undefined
|
|
937
|
-
| (string extends TAllRouteInfo['
|
|
985
|
+
| (string extends TAllRouteInfo['routePaths']
|
|
938
986
|
? string
|
|
939
|
-
: TAllRouteInfo['
|
|
987
|
+
: TAllRouteInfo['routePaths'])
|
|
940
988
|
|
|
941
989
|
// type ValidToPath<
|
|
942
990
|
// TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
|
|
943
991
|
// TFrom = undefined,
|
|
944
992
|
// > = TFrom extends undefined
|
|
945
|
-
// ? TAllRouteInfo['
|
|
946
|
-
// : LooseAutocomplete<'.' | TAllRouteInfo['
|
|
993
|
+
// ? TAllRouteInfo['routePaths'] | `...unsafe-relative-path (cast "as any")`
|
|
994
|
+
// : LooseAutocomplete<'.' | TAllRouteInfo['routePaths']>
|
|
947
995
|
|
|
948
996
|
export interface Router<
|
|
949
997
|
TRouteConfig extends AnyRouteConfig = RouteConfig,
|
|
@@ -1506,64 +1554,88 @@ export function createRouter<
|
|
|
1506
1554
|
...(router.state.pending?.matches ?? []),
|
|
1507
1555
|
]
|
|
1508
1556
|
|
|
1509
|
-
const recurse = async (
|
|
1510
|
-
|
|
1511
|
-
parentMatch?: RouteMatch,
|
|
1512
|
-
): Promise<void> => {
|
|
1557
|
+
const recurse = async (routes: Route<any, any>[]): Promise<void> => {
|
|
1558
|
+
const parentMatch = last(matches)
|
|
1513
1559
|
let params = parentMatch?.params ?? {}
|
|
1514
1560
|
|
|
1515
1561
|
const filteredRoutes = router.options.filterRoutes?.(routes) ?? routes
|
|
1516
1562
|
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1563
|
+
let foundRoutes: Route[] = []
|
|
1564
|
+
|
|
1565
|
+
const findMatchInRoutes = (parentRoutes: Route[], routes: Route[]) => {
|
|
1566
|
+
routes.some((route) => {
|
|
1567
|
+
if (!route.routePath && route.childRoutes?.length) {
|
|
1568
|
+
return findMatchInRoutes(
|
|
1569
|
+
[...foundRoutes, route],
|
|
1570
|
+
route.childRoutes,
|
|
1571
|
+
)
|
|
1572
|
+
}
|
|
1525
1573
|
|
|
1526
|
-
|
|
1527
|
-
|
|
1574
|
+
const fuzzy = !!(
|
|
1575
|
+
route.routePath !== '/' || route.childRoutes?.length
|
|
1576
|
+
)
|
|
1528
1577
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1578
|
+
const matchParams = matchPathname(pathname, {
|
|
1579
|
+
to: route.fullPath,
|
|
1580
|
+
fuzzy,
|
|
1581
|
+
caseSensitive:
|
|
1582
|
+
route.options.caseSensitive ?? router.options.caseSensitive,
|
|
1583
|
+
})
|
|
1584
|
+
|
|
1585
|
+
if (matchParams) {
|
|
1586
|
+
let parsedParams
|
|
1587
|
+
|
|
1588
|
+
try {
|
|
1589
|
+
parsedParams =
|
|
1590
|
+
route.options.parseParams?.(matchParams!) ?? matchParams
|
|
1591
|
+
} catch (err) {
|
|
1592
|
+
if (opts?.strictParseParams) {
|
|
1593
|
+
throw err
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
params = {
|
|
1598
|
+
...params,
|
|
1599
|
+
...parsedParams,
|
|
1535
1600
|
}
|
|
1536
1601
|
}
|
|
1537
1602
|
|
|
1538
|
-
|
|
1539
|
-
...
|
|
1540
|
-
...parsedParams,
|
|
1603
|
+
if (!!matchParams) {
|
|
1604
|
+
foundRoutes = [...parentRoutes, route]
|
|
1541
1605
|
}
|
|
1542
|
-
}
|
|
1543
1606
|
|
|
1544
|
-
|
|
1545
|
-
|
|
1607
|
+
return !!foundRoutes.length
|
|
1608
|
+
})
|
|
1609
|
+
|
|
1610
|
+
return !!foundRoutes.length
|
|
1611
|
+
}
|
|
1546
1612
|
|
|
1547
|
-
|
|
1613
|
+
findMatchInRoutes([], filteredRoutes)
|
|
1614
|
+
|
|
1615
|
+
if (!foundRoutes.length) {
|
|
1548
1616
|
return
|
|
1549
1617
|
}
|
|
1550
1618
|
|
|
1551
|
-
|
|
1552
|
-
|
|
1619
|
+
foundRoutes.forEach((foundRoute) => {
|
|
1620
|
+
const interpolatedPath = interpolatePath(foundRoute.routePath, params)
|
|
1621
|
+
const matchId = interpolatePath(foundRoute.routeId, params, true)
|
|
1553
1622
|
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1623
|
+
const match =
|
|
1624
|
+
existingMatches.find((d) => d.matchId === matchId) ||
|
|
1625
|
+
router.preloadCache[matchId]?.match ||
|
|
1626
|
+
createRouteMatch(router, foundRoute, {
|
|
1627
|
+
matchId,
|
|
1628
|
+
params,
|
|
1629
|
+
pathname: joinPaths([pathname, interpolatedPath]),
|
|
1630
|
+
})
|
|
1631
|
+
|
|
1632
|
+
matches.push(match)
|
|
1633
|
+
})
|
|
1562
1634
|
|
|
1563
|
-
|
|
1635
|
+
const foundRoute = last(foundRoutes)!
|
|
1564
1636
|
|
|
1565
|
-
if (
|
|
1566
|
-
recurse(
|
|
1637
|
+
if (foundRoute.childRoutes?.length) {
|
|
1638
|
+
recurse(foundRoute.childRoutes)
|
|
1567
1639
|
}
|
|
1568
1640
|
}
|
|
1569
1641
|
|
|
@@ -1690,14 +1762,10 @@ export function createRouter<
|
|
|
1690
1762
|
isExternal = true
|
|
1691
1763
|
} catch (e) {}
|
|
1692
1764
|
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
)
|
|
1698
|
-
}
|
|
1699
|
-
return
|
|
1700
|
-
}
|
|
1765
|
+
invariant(
|
|
1766
|
+
!isExternal,
|
|
1767
|
+
'Attempting to navigate to external url with router.navigate!',
|
|
1768
|
+
)
|
|
1701
1769
|
|
|
1702
1770
|
return router._navigate({
|
|
1703
1771
|
from: fromString,
|
|
@@ -1867,6 +1935,7 @@ export interface Route<
|
|
|
1867
1935
|
TRouteInfo extends AnyRouteInfo = RouteInfo,
|
|
1868
1936
|
> {
|
|
1869
1937
|
routeId: TRouteInfo['id']
|
|
1938
|
+
routeRouteId: TRouteInfo['routeId']
|
|
1870
1939
|
routePath: TRouteInfo['path']
|
|
1871
1940
|
fullPath: TRouteInfo['fullPath']
|
|
1872
1941
|
parentRoute?: AnyRoute
|
|
@@ -1874,23 +1943,21 @@ export interface Route<
|
|
|
1874
1943
|
options: RouteOptions
|
|
1875
1944
|
router: Router<TAllRouteInfo['routeConfig'], TAllRouteInfo>
|
|
1876
1945
|
buildLink: <TTo extends string = '.'>(
|
|
1877
|
-
options:
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
// > &
|
|
1882
|
-
Omit<LinkOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>, 'from'>,
|
|
1946
|
+
options: Omit<
|
|
1947
|
+
LinkOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>,
|
|
1948
|
+
'from'
|
|
1949
|
+
>,
|
|
1883
1950
|
) => LinkInfo
|
|
1884
1951
|
matchRoute: <
|
|
1885
1952
|
TTo extends string = '.',
|
|
1886
1953
|
TResolved extends string = ResolveRelativePath<TRouteInfo['id'], TTo>,
|
|
1887
1954
|
>(
|
|
1888
|
-
matchLocation:
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1955
|
+
matchLocation: CheckRelativePath<
|
|
1956
|
+
TAllRouteInfo,
|
|
1957
|
+
TRouteInfo['fullPath'],
|
|
1958
|
+
NoInfer<TTo>
|
|
1959
|
+
> &
|
|
1960
|
+
Omit<ToOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>, 'from'>,
|
|
1894
1961
|
opts?: MatchRouteOptions,
|
|
1895
1962
|
) => RouteInfoByPath<TAllRouteInfo, TResolved>['allParams']
|
|
1896
1963
|
navigate: <TTo extends string = '.'>(
|
|
@@ -1921,12 +1988,12 @@ export function createRoute<
|
|
|
1921
1988
|
// ]).replace(new RegExp(`^${rootRouteId}`), '')
|
|
1922
1989
|
// ) as TRouteInfo['id']
|
|
1923
1990
|
|
|
1924
|
-
const { id
|
|
1991
|
+
const { id, routeId, path: routePath, fullPath } = routeConfig
|
|
1925
1992
|
|
|
1926
1993
|
const action =
|
|
1927
|
-
router.state.actions[
|
|
1994
|
+
router.state.actions[id] ||
|
|
1928
1995
|
(() => {
|
|
1929
|
-
router.state.actions[
|
|
1996
|
+
router.state.actions[id] = {
|
|
1930
1997
|
pending: [],
|
|
1931
1998
|
submit: async <T, U>(
|
|
1932
1999
|
submission: T,
|
|
@@ -1976,11 +2043,12 @@ export function createRoute<
|
|
|
1976
2043
|
}
|
|
1977
2044
|
},
|
|
1978
2045
|
}
|
|
1979
|
-
return router.state.actions[
|
|
2046
|
+
return router.state.actions[id]!
|
|
1980
2047
|
})()
|
|
1981
2048
|
|
|
1982
2049
|
let route: Route<TAllRouteInfo, TRouteInfo> = {
|
|
1983
|
-
routeId,
|
|
2050
|
+
routeId: id,
|
|
2051
|
+
routeRouteId: routeId,
|
|
1984
2052
|
routePath,
|
|
1985
2053
|
fullPath,
|
|
1986
2054
|
options,
|
|
@@ -2099,7 +2167,8 @@ export type ToOptions<
|
|
|
2099
2167
|
from?: TFrom
|
|
2100
2168
|
// // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
|
|
2101
2169
|
// fromCurrent?: boolean
|
|
2102
|
-
} &
|
|
2170
|
+
} & CheckPath<TAllRouteInfo, NoInfer<TResolvedTo>> &
|
|
2171
|
+
SearchParamOptions<TAllRouteInfo, TFrom, TResolvedTo> &
|
|
2103
2172
|
PathParamOptions<TAllRouteInfo, TFrom, TResolvedTo>
|
|
2104
2173
|
|
|
2105
2174
|
export type ToPathOption<
|
|
@@ -2109,7 +2178,7 @@ export type ToPathOption<
|
|
|
2109
2178
|
> =
|
|
2110
2179
|
| TTo
|
|
2111
2180
|
| RelativeToPathAutoComplete<
|
|
2112
|
-
TAllRouteInfo['
|
|
2181
|
+
TAllRouteInfo['routePaths'],
|
|
2113
2182
|
NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
|
|
2114
2183
|
NoInfer<TTo> & string
|
|
2115
2184
|
>
|
|
@@ -2121,7 +2190,7 @@ export type ToIdOption<
|
|
|
2121
2190
|
> =
|
|
2122
2191
|
| TTo
|
|
2123
2192
|
| RelativeToPathAutoComplete<
|
|
2124
|
-
TAllRouteInfo['
|
|
2193
|
+
TAllRouteInfo['routeIds'],
|
|
2125
2194
|
NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
|
|
2126
2195
|
NoInfer<TTo> & string
|
|
2127
2196
|
>
|
|
@@ -2151,23 +2220,33 @@ export type CheckRelativePath<
|
|
|
2151
2220
|
TTo,
|
|
2152
2221
|
> = TTo extends string
|
|
2153
2222
|
? TFrom extends string
|
|
2154
|
-
? ResolveRelativePath<TFrom, TTo> extends TAllRouteInfo['
|
|
2223
|
+
? ResolveRelativePath<TFrom, TTo> extends TAllRouteInfo['routePaths']
|
|
2155
2224
|
? {}
|
|
2156
2225
|
: {
|
|
2157
2226
|
Error: `${TFrom} + ${TTo} resolves to ${ResolveRelativePath<
|
|
2158
2227
|
TFrom,
|
|
2159
2228
|
TTo
|
|
2160
2229
|
>}, which is not a valid route path.`
|
|
2161
|
-
'Valid Route Paths': TAllRouteInfo['
|
|
2230
|
+
'Valid Route Paths': TAllRouteInfo['routePaths']
|
|
2162
2231
|
}
|
|
2163
2232
|
: {}
|
|
2164
2233
|
: {}
|
|
2165
2234
|
|
|
2166
|
-
export type
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2235
|
+
export type CheckPath<TAllRouteInfo extends AnyAllRouteInfo, TPath> = Exclude<
|
|
2236
|
+
TPath,
|
|
2237
|
+
TAllRouteInfo['routePaths']
|
|
2238
|
+
> extends never
|
|
2239
|
+
? {}
|
|
2240
|
+
: CheckPathError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routePaths']>>
|
|
2241
|
+
|
|
2242
|
+
export type CheckPathError<TAllRouteInfo extends AnyAllRouteInfo, TInvalids> = {
|
|
2243
|
+
Error: `${TInvalids extends string
|
|
2244
|
+
? TInvalids
|
|
2245
|
+
: never} is not a valid route path.`
|
|
2246
|
+
'Valid Route Paths': TAllRouteInfo['routePaths']
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
|
|
2171
2250
|
? TTo extends string
|
|
2172
2251
|
? TTo extends '.'
|
|
2173
2252
|
? TFrom
|
|
@@ -2215,21 +2294,19 @@ type SearchParamOptions<
|
|
|
2215
2294
|
TTo,
|
|
2216
2295
|
TFromSchema = RouteInfoByPath<TAllRouteInfo, TFrom>['fullSearchSchema'],
|
|
2217
2296
|
TToSchema = RouteInfoByPath<TAllRouteInfo, TTo>['fullSearchSchema'],
|
|
2218
|
-
> =
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
search: SearchReducer<TFromSchema, TToSchema>
|
|
2232
|
-
}
|
|
2297
|
+
> = StartsWith<TFrom, TTo> extends true // If the next route search extend or cover the from route, params will be optional
|
|
2298
|
+
? {
|
|
2299
|
+
search?: SearchReducer<TFromSchema, TToSchema>
|
|
2300
|
+
}
|
|
2301
|
+
: // Optional search params? Allow it
|
|
2302
|
+
keyof PickRequired<TToSchema> extends never
|
|
2303
|
+
? {
|
|
2304
|
+
search?: SearchReducer<TFromSchema, TToSchema>
|
|
2305
|
+
}
|
|
2306
|
+
: {
|
|
2307
|
+
// Must have required search params, enforce it
|
|
2308
|
+
search: SearchReducer<TFromSchema, TToSchema>
|
|
2309
|
+
}
|
|
2233
2310
|
|
|
2234
2311
|
type SearchReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
|
|
2235
2312
|
|