Skip to content

Commit

Permalink
feat: support partial locations
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Jan 8, 2025
1 parent 1f717fb commit b879e54
Show file tree
Hide file tree
Showing 8 changed files with 276 additions and 219 deletions.
47 changes: 30 additions & 17 deletions packages/router/src/experimental/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ import {
routerKey,
routerViewLocationKey,
} from '../injectionSymbols'
import { MatcherLocationAsPathAbsolute } from '../new-route-resolver/matcher-location'

/**
* resolve, reject arguments of Promise constructor
Expand Down Expand Up @@ -406,6 +407,11 @@ export interface EXPERIMENTAL_RouteRecordRaw extends NEW_MatcherRecordRaw {
* Arbitrary data attached to the record.
*/
meta?: RouteMeta

components?: Record<string, unknown>
component?: unknown

redirect?: unknown
}

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

function locationAsObject(
to: RouteLocationRaw | RouteLocationNormalized,
currentLocation: string = currentRoute.value.path
): Exclude<RouteLocationRaw, string> | RouteLocationNormalized {
return typeof to === 'string'
? parseURL(parseQuery, to, currentLocation)
: to
}

function resolve(
rawLocation: RouteLocationRaw,
currentLocation?: RouteLocationNormalizedLoaded
Expand All @@ -522,6 +537,11 @@ export function experimental_createRouter(
currentLocation && assign({}, currentLocation || currentRoute.value)
// currentLocation = assign({}, currentLocation || currentRoute.value)

const locationObject = locationAsObject(
rawLocation,
currentRoute.value.path
)

if (__DEV__) {
if (!isRouteLocation(rawLocation)) {
warn(
Expand All @@ -531,12 +551,9 @@ export function experimental_createRouter(
return resolve({})
}

if (
typeof rawLocation === 'object' &&
!rawLocation.hash?.startsWith('#')
) {
if (!locationObject.hash?.startsWith('#')) {
warn(
`A \`hash\` should always start with the character "#". Replace "${rawLocation.hash}" with "#${rawLocation.hash}".`
`A \`hash\` should always start with the character "#". Replace "${locationObject.hash}" with "#${locationObject.hash}".`
)
}
}
Expand All @@ -555,16 +572,20 @@ export function experimental_createRouter(

const matchedRoute = matcher.resolve(
// FIXME: should be ok
// @ts-expect-error: too many overlads
rawLocation,
currentLocation
// locationObject as MatcherLocationAsPathRelative,
// locationObject as MatcherLocationAsRelative,
// locationObject as MatcherLocationAsName, // TODO: this one doesn't allow an undefined currentLocation, the other ones work
locationObject as MatcherLocationAsPathAbsolute,
currentLocation as unknown as NEW_LocationResolved<EXPERIMENTAL_RouteRecordNormalized>
)
const href = routerHistory.createHref(matchedRoute.fullPath)

if (__DEV__) {
if (href.startsWith('//')) {
warn(
`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`
`Location ${JSON.stringify(
rawLocation
)} resolved to "${href}". A resolved location cannot start with multiple slashes.`
)
}
if (!matchedRoute.matched.length) {
Expand All @@ -581,14 +602,6 @@ export function experimental_createRouter(
})
}

function locationAsObject(
to: RouteLocationRaw | RouteLocationNormalized
): Exclude<RouteLocationRaw, string> | RouteLocationNormalized {
return typeof to === 'string'
? parseURL(parseQuery, to, currentRoute.value.path)
: assign({}, to)
}

function checkCanceledNavigation(
to: RouteLocationNormalized,
from: RouteLocationNormalized
Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ export function parseURL(
hash = location.slice(hashPos, location.length)
}

// TODO(major): path ?? location
path = resolveRelativePath(
// TODO(major): path ?? location
path != null
? path
: // empty path means a relative query or hash `?foo=f`, `#thing`
Expand Down
3 changes: 3 additions & 0 deletions packages/router/src/new-route-resolver/matcher-location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export interface MatcherLocationAsPathRelative {
*/
params?: undefined
}

// TODO: does it make sense to support absolute paths objects?

export interface MatcherLocationAsPathAbsolute
extends MatcherLocationAsPathRelative {
path: `/${string}`
Expand Down
Loading

0 comments on commit b879e54

Please sign in to comment.