@devp0nt/route0 1.0.0-next.57 → 1.0.0-next.59
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/index.cjs +18 -4
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +13 -13
- package/dist/esm/index.d.ts +13 -13
- package/dist/esm/index.js +18 -4
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.test.ts +13 -0
- package/src/index.ts +42 -29
package/src/index.test.ts
CHANGED
|
@@ -960,6 +960,7 @@ describe('getLocation', () => {
|
|
|
960
960
|
unmatched: false,
|
|
961
961
|
ancestor: true,
|
|
962
962
|
descendant: false,
|
|
963
|
+
params: {},
|
|
963
964
|
})
|
|
964
965
|
expect(Route0.create('/prefix/:x/some').getLocation('/prefix/xxx/some/extra/path')).toMatchObject({
|
|
965
966
|
known: true,
|
|
@@ -967,6 +968,7 @@ describe('getLocation', () => {
|
|
|
967
968
|
unmatched: false,
|
|
968
969
|
ancestor: true,
|
|
969
970
|
descendant: false,
|
|
971
|
+
params: { x: 'xxx' },
|
|
970
972
|
})
|
|
971
973
|
expect(Route0.create('/:y/:x/some').getLocation('/prefix/xxx/some/extra/path')).toMatchObject({
|
|
972
974
|
known: true,
|
|
@@ -974,6 +976,7 @@ describe('getLocation', () => {
|
|
|
974
976
|
unmatched: false,
|
|
975
977
|
ancestor: true,
|
|
976
978
|
descendant: false,
|
|
979
|
+
params: { y: 'prefix', x: 'xxx' },
|
|
977
980
|
})
|
|
978
981
|
})
|
|
979
982
|
|
|
@@ -984,6 +987,7 @@ describe('getLocation', () => {
|
|
|
984
987
|
unmatched: false,
|
|
985
988
|
ancestor: false,
|
|
986
989
|
descendant: true,
|
|
990
|
+
params: {},
|
|
987
991
|
})
|
|
988
992
|
expect(Route0.create('/prefix/some/extra/:id').getLocation('/prefix/some')).toMatchObject({
|
|
989
993
|
known: true,
|
|
@@ -991,6 +995,7 @@ describe('getLocation', () => {
|
|
|
991
995
|
unmatched: false,
|
|
992
996
|
ancestor: false,
|
|
993
997
|
descendant: true,
|
|
998
|
+
params: {},
|
|
994
999
|
})
|
|
995
1000
|
expect(Route0.create('/:prefix/some/extra/:id').getLocation('/prefix/some')).toMatchObject({
|
|
996
1001
|
known: true,
|
|
@@ -998,6 +1003,7 @@ describe('getLocation', () => {
|
|
|
998
1003
|
unmatched: false,
|
|
999
1004
|
ancestor: false,
|
|
1000
1005
|
descendant: true,
|
|
1006
|
+
params: { prefix: 'prefix' },
|
|
1001
1007
|
})
|
|
1002
1008
|
})
|
|
1003
1009
|
|
|
@@ -1280,6 +1286,13 @@ describe('getLocation', () => {
|
|
|
1280
1286
|
expect(loc.exact).toBe(true)
|
|
1281
1287
|
expect(loc.route).toBe('/b/:c')
|
|
1282
1288
|
})
|
|
1289
|
+
|
|
1290
|
+
it('any RoutesPretty type suitable to any RoutesPretty stype', () => {
|
|
1291
|
+
Routes.create({
|
|
1292
|
+
home: '/',
|
|
1293
|
+
v: '/b',
|
|
1294
|
+
}) satisfies RoutesPretty
|
|
1295
|
+
})
|
|
1283
1296
|
})
|
|
1284
1297
|
})
|
|
1285
1298
|
|
package/src/index.ts
CHANGED
|
@@ -719,19 +719,20 @@ export class Route0<TDefinition extends string> {
|
|
|
719
719
|
const exactRe = new RegExp(`^${this.getRegexBaseString()}$`)
|
|
720
720
|
const ancestorRe = new RegExp(`^${this.getRegexBaseString()}(?:/.*)?$`) // route matches the beginning of the URL (may have more)
|
|
721
721
|
const exactMatch = pathname.match(exactRe)
|
|
722
|
+
const ancestorMatch = pathname.match(ancestorRe)
|
|
723
|
+
const exact = !!exactMatch
|
|
724
|
+
const ancestor = !exact && !!ancestorMatch
|
|
722
725
|
|
|
723
|
-
//
|
|
724
|
-
|
|
725
|
-
|
|
726
|
+
// Parse params for exact and ancestor matches.
|
|
727
|
+
const paramsMatch = exactMatch || (ancestor ? ancestorMatch : null)
|
|
728
|
+
if (paramsMatch) {
|
|
729
|
+
const values = paramsMatch.slice(1, 1 + paramNames.length)
|
|
726
730
|
const params = Object.fromEntries(paramNames.map((n, i) => [n, decodeURIComponent(values[i] ?? '')]))
|
|
727
731
|
location.params = params
|
|
728
732
|
} else {
|
|
729
733
|
location.params = {}
|
|
730
734
|
}
|
|
731
735
|
|
|
732
|
-
const exact = !!exactMatch
|
|
733
|
-
const ancestor = !exact && ancestorRe.test(pathname)
|
|
734
|
-
|
|
735
736
|
// "descendant": the URL is a prefix of the route definition (params match any single segment)
|
|
736
737
|
const getParts = (path: string) => (path === '/' ? ['/'] : path.split('/').filter(Boolean))
|
|
737
738
|
const defParts = getParts(def)
|
|
@@ -758,6 +759,21 @@ export class Route0<TDefinition extends string> {
|
|
|
758
759
|
const descendant = !exact && isPrefix
|
|
759
760
|
const unmatched = !exact && !ancestor && !descendant
|
|
760
761
|
|
|
762
|
+
// For descendant matches, include only params that are already determined
|
|
763
|
+
// by the current (shorter) pathname prefix.
|
|
764
|
+
if (descendant) {
|
|
765
|
+
const descendantParams: Record<string, string> = {}
|
|
766
|
+
for (let i = 0; i < pathParts.length; i++) {
|
|
767
|
+
const defPart = defParts[i]
|
|
768
|
+
const pathPart = pathParts[i]
|
|
769
|
+
if (!defPart || !pathPart) continue
|
|
770
|
+
if (defPart.startsWith(':')) {
|
|
771
|
+
descendantParams[defPart.slice(1)] = decodeURIComponent(pathPart)
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
location.params = descendantParams
|
|
775
|
+
}
|
|
776
|
+
|
|
761
777
|
return {
|
|
762
778
|
...location,
|
|
763
779
|
known: true,
|
|
@@ -992,7 +1008,7 @@ export class Route0<TDefinition extends string> {
|
|
|
992
1008
|
* `Routes.create()` accepts either plain string definitions or route objects
|
|
993
1009
|
* and returns a "pretty" object with direct route access + helper methods under `._`.
|
|
994
1010
|
*/
|
|
995
|
-
export class Routes<const T extends RoutesRecord =
|
|
1011
|
+
export class Routes<const T extends RoutesRecord = any> {
|
|
996
1012
|
_routes: RoutesRecordHydrated<T>
|
|
997
1013
|
_pathsOrdering: string[]
|
|
998
1014
|
_keysOrdering: string[]
|
|
@@ -1178,27 +1194,24 @@ export type RouteConfigInput = {
|
|
|
1178
1194
|
/** User-provided routes map (plain definitions or route instances). */
|
|
1179
1195
|
export type RoutesRecord = Record<string, AnyRoute | string>
|
|
1180
1196
|
/** Same as `RoutesRecord` but all values normalized to callable routes. */
|
|
1181
|
-
export type RoutesRecordHydrated<TRoutesRecord extends RoutesRecord =
|
|
1197
|
+
export type RoutesRecordHydrated<TRoutesRecord extends RoutesRecord = any> = {
|
|
1182
1198
|
[K in keyof TRoutesRecord]: CallableRoute<TRoutesRecord[K]>
|
|
1183
1199
|
}
|
|
1184
|
-
/** Public shape returned by `Routes.create()`. */
|
|
1185
|
-
export type RoutesPretty<TRoutesRecord extends RoutesRecord =
|
|
1200
|
+
/** Public shape returned by `Routes.create()`. Default `any` so `satisfies RoutesPretty` accepts any created routes. */
|
|
1201
|
+
export type RoutesPretty<TRoutesRecord extends RoutesRecord = any> = RoutesRecordHydrated<TRoutesRecord> &
|
|
1186
1202
|
Omit<
|
|
1187
1203
|
Routes<TRoutesRecord>,
|
|
1188
1204
|
'_routes' | '_getLocation' | '_override' | '_pathsOrdering' | '_keysOrdering' | '_ordered'
|
|
1189
1205
|
>
|
|
1190
|
-
export type ExtractRoutesKeys<TRoutes extends RoutesPretty
|
|
1191
|
-
TRoutes
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
: TRoutes extends RoutesRecord
|
|
1200
|
-
? TRoutes[TKey]
|
|
1201
|
-
: never
|
|
1206
|
+
export type ExtractRoutesKeys<TRoutes extends RoutesPretty | RoutesRecord> = TRoutes extends RoutesPretty
|
|
1207
|
+
? Extract<keyof TRoutes['_']['routes'], string>
|
|
1208
|
+
: TRoutes extends RoutesRecord
|
|
1209
|
+
? Extract<keyof TRoutes, string>
|
|
1210
|
+
: never
|
|
1211
|
+
export type ExtractRoute<
|
|
1212
|
+
TRoutes extends RoutesPretty | RoutesRecord,
|
|
1213
|
+
TKey extends ExtractRoutesKeys<TRoutes>,
|
|
1214
|
+
> = TRoutes extends RoutesPretty ? TRoutes['_']['routes'][TKey] : TRoutes extends RoutesRecord ? TRoutes[TKey] : never
|
|
1202
1215
|
|
|
1203
1216
|
// public utils
|
|
1204
1217
|
|
|
@@ -1414,7 +1427,7 @@ export type UnmatchedLocationState<TRoute extends AnyRoute | string = AnyRoute |
|
|
|
1414
1427
|
known: true
|
|
1415
1428
|
route: Definition<TRoute>
|
|
1416
1429
|
params: Record<never, never>
|
|
1417
|
-
searchParams:
|
|
1430
|
+
searchParams: Record<string, string | undefined>
|
|
1418
1431
|
exact: false
|
|
1419
1432
|
ancestor: false
|
|
1420
1433
|
descendant: false
|
|
@@ -1441,7 +1454,7 @@ export type ExactLocation<TRoute extends AnyRoute | string = AnyRoute | string>
|
|
|
1441
1454
|
export type AncestorLocationState<TRoute extends AnyRoute | string = AnyRoute | string> = {
|
|
1442
1455
|
known: true
|
|
1443
1456
|
route: Definition<TRoute>
|
|
1444
|
-
params:
|
|
1457
|
+
params: ParamsOutput<TRoute>
|
|
1445
1458
|
searchParams: LooseSearchOutput<TRoute>
|
|
1446
1459
|
exact: false
|
|
1447
1460
|
ancestor: true
|
|
@@ -1451,11 +1464,11 @@ export type AncestorLocationState<TRoute extends AnyRoute | string = AnyRoute |
|
|
|
1451
1464
|
export type AncestorLocation<TRoute extends AnyRoute | string = AnyRoute | string> =
|
|
1452
1465
|
IsAny<TRoute> extends true ? any : _GeneralLocation & AncestorLocationState<TRoute>
|
|
1453
1466
|
|
|
1454
|
-
/**
|
|
1467
|
+
/** It is when route not match at all, but params match. */
|
|
1455
1468
|
export type WeakAncestorLocationState<TRoute extends AnyRoute | string = AnyRoute | string> = {
|
|
1456
1469
|
known: true
|
|
1457
1470
|
route: Definition<TRoute>
|
|
1458
|
-
params:
|
|
1471
|
+
params: ParamsOutput<TRoute>
|
|
1459
1472
|
searchParams: LooseSearchOutput<TRoute>
|
|
1460
1473
|
exact: false
|
|
1461
1474
|
ancestor: true
|
|
@@ -1469,7 +1482,7 @@ export type WeakAncestorLocation<TRoute extends AnyRoute | string = AnyRoute | s
|
|
|
1469
1482
|
export type DescendantLocationState<TRoute extends AnyRoute | string = AnyRoute | string> = {
|
|
1470
1483
|
known: true
|
|
1471
1484
|
route: Definition<TRoute>
|
|
1472
|
-
params: ParamsOutput<TRoute
|
|
1485
|
+
params: Partial<ParamsOutput<TRoute>>
|
|
1473
1486
|
searchParams: LooseSearchOutput<TRoute>
|
|
1474
1487
|
exact: false
|
|
1475
1488
|
ancestor: false
|
|
@@ -1479,11 +1492,11 @@ export type DescendantLocationState<TRoute extends AnyRoute | string = AnyRoute
|
|
|
1479
1492
|
export type DescendantLocation<TRoute extends AnyRoute | string = AnyRoute | string> =
|
|
1480
1493
|
IsAny<TRoute> extends true ? any : _GeneralLocation & DescendantLocationState
|
|
1481
1494
|
|
|
1482
|
-
/**
|
|
1495
|
+
/** It is when route not match at all, but params partially match. */
|
|
1483
1496
|
export type WeakDescendantLocationState<TRoute extends AnyRoute | string = AnyRoute | string> = {
|
|
1484
1497
|
known: true
|
|
1485
1498
|
route: Definition<TRoute>
|
|
1486
|
-
params: ParamsOutput<TRoute
|
|
1499
|
+
params: Partial<ParamsOutput<TRoute>>
|
|
1487
1500
|
searchParams: LooseSearchOutput<TRoute>
|
|
1488
1501
|
exact: false
|
|
1489
1502
|
ancestor: false
|