Skip to content

Commit b879e54

Browse files
committed
feat: support partial locations
1 parent 1f717fb commit b879e54

File tree

8 files changed

+276
-219
lines changed

8 files changed

+276
-219
lines changed

packages/router/src/experimental/router.ts

+30-17
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ import {
8383
routerKey,
8484
routerViewLocationKey,
8585
} from '../injectionSymbols'
86+
import { MatcherLocationAsPathAbsolute } from '../new-route-resolver/matcher-location'
8687

8788
/**
8889
* resolve, reject arguments of Promise constructor
@@ -406,6 +407,11 @@ export interface EXPERIMENTAL_RouteRecordRaw extends NEW_MatcherRecordRaw {
406407
* Arbitrary data attached to the record.
407408
*/
408409
meta?: RouteMeta
410+
411+
components?: Record<string, unknown>
412+
component?: unknown
413+
414+
redirect?: unknown
409415
}
410416

411417
// TODO: is it worth to have 2 types for the undefined values?
@@ -510,6 +516,15 @@ export function experimental_createRouter(
510516
return !!matcher.getMatcher(name)
511517
}
512518

519+
function locationAsObject(
520+
to: RouteLocationRaw | RouteLocationNormalized,
521+
currentLocation: string = currentRoute.value.path
522+
): Exclude<RouteLocationRaw, string> | RouteLocationNormalized {
523+
return typeof to === 'string'
524+
? parseURL(parseQuery, to, currentLocation)
525+
: to
526+
}
527+
513528
function resolve(
514529
rawLocation: RouteLocationRaw,
515530
currentLocation?: RouteLocationNormalizedLoaded
@@ -522,6 +537,11 @@ export function experimental_createRouter(
522537
currentLocation && assign({}, currentLocation || currentRoute.value)
523538
// currentLocation = assign({}, currentLocation || currentRoute.value)
524539

540+
const locationObject = locationAsObject(
541+
rawLocation,
542+
currentRoute.value.path
543+
)
544+
525545
if (__DEV__) {
526546
if (!isRouteLocation(rawLocation)) {
527547
warn(
@@ -531,12 +551,9 @@ export function experimental_createRouter(
531551
return resolve({})
532552
}
533553

534-
if (
535-
typeof rawLocation === 'object' &&
536-
!rawLocation.hash?.startsWith('#')
537-
) {
554+
if (!locationObject.hash?.startsWith('#')) {
538555
warn(
539-
`A \`hash\` should always start with the character "#". Replace "${rawLocation.hash}" with "#${rawLocation.hash}".`
556+
`A \`hash\` should always start with the character "#". Replace "${locationObject.hash}" with "#${locationObject.hash}".`
540557
)
541558
}
542559
}
@@ -555,16 +572,20 @@ export function experimental_createRouter(
555572

556573
const matchedRoute = matcher.resolve(
557574
// FIXME: should be ok
558-
// @ts-expect-error: too many overlads
559-
rawLocation,
560-
currentLocation
575+
// locationObject as MatcherLocationAsPathRelative,
576+
// locationObject as MatcherLocationAsRelative,
577+
// locationObject as MatcherLocationAsName, // TODO: this one doesn't allow an undefined currentLocation, the other ones work
578+
locationObject as MatcherLocationAsPathAbsolute,
579+
currentLocation as unknown as NEW_LocationResolved<EXPERIMENTAL_RouteRecordNormalized>
561580
)
562581
const href = routerHistory.createHref(matchedRoute.fullPath)
563582

564583
if (__DEV__) {
565584
if (href.startsWith('//')) {
566585
warn(
567-
`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`
586+
`Location ${JSON.stringify(
587+
rawLocation
588+
)} resolved to "${href}". A resolved location cannot start with multiple slashes.`
568589
)
569590
}
570591
if (!matchedRoute.matched.length) {
@@ -581,14 +602,6 @@ export function experimental_createRouter(
581602
})
582603
}
583604

584-
function locationAsObject(
585-
to: RouteLocationRaw | RouteLocationNormalized
586-
): Exclude<RouteLocationRaw, string> | RouteLocationNormalized {
587-
return typeof to === 'string'
588-
? parseURL(parseQuery, to, currentRoute.value.path)
589-
: assign({}, to)
590-
}
591-
592605
function checkCanceledNavigation(
593606
to: RouteLocationNormalized,
594607
from: RouteLocationNormalized

packages/router/src/location.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ export function parseURL(
7777
hash = location.slice(hashPos, location.length)
7878
}
7979

80-
// TODO(major): path ?? location
8180
path = resolveRelativePath(
81+
// TODO(major): path ?? location
8282
path != null
8383
? path
8484
: // empty path means a relative query or hash `?foo=f`, `#thing`

packages/router/src/new-route-resolver/matcher-location.ts

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ export interface MatcherLocationAsPathRelative {
3838
*/
3939
params?: undefined
4040
}
41+
42+
// TODO: does it make sense to support absolute paths objects?
43+
4144
export interface MatcherLocationAsPathAbsolute
4245
extends MatcherLocationAsPathRelative {
4346
path: `/${string}`

0 commit comments

Comments
 (0)