hash?: string
/**
- * A path is ignored if `name` is provided.
+ * @deprecated This is ignored when `name` is provided
*/
path?: undefined
}
-export interface MatcherLocationAsPath {
+export interface MatcherLocationAsPathRelative {
path: string
query?: LocationQueryRaw
hash?: string
+ /**
+ * @deprecated This is ignored when `path` is provided
+ */
name?: undefined
+ /**
+ * @deprecated This is ignored when `path` (instead of `name`) is provided
+ */
params?: undefined
}
+export interface MatcherLocationAsPathAbsolute
+ extends MatcherLocationAsPathRelative {
+ path: `/${string}`
+}
export interface MatcherLocationAsRelative {
params?: MatcherParamsFormatted
query?: LocationQueryRaw
hash?: string
+ /**
+ * @deprecated This location is relative to the next parameter. This `name` will be ignored.
+ */
name?: undefined
+ /**
+ * @deprecated This location is relative to the next parameter. This `path` will be ignored.
+ */
path?: undefined
}
import { parseURL, stringifyURL } from '../location'
import type {
MatcherLocationAsNamed,
+ MatcherLocationAsPathAbsolute,
+ MatcherLocationAsPathRelative,
MatcherLocationAsRelative,
MatcherParamsFormatted,
} from './matcher-location'
resolve(location: MatcherLocationAsNamed): NEW_LocationResolved
/**
- * Resolves a location by its path. Any required query must be passed.
+ * Resolves a location by its absolute path (starts with `/`). Any required query must be passed.
* @param location - The location to resolve.
*/
- // resolve(location: MatcherLocationAsPath): NEW_MatcherLocationResolved
+ resolve(location: MatcherLocationAsPathAbsolute): NEW_LocationResolved
+
+ resolve(
+ location: MatcherLocationAsPathRelative,
+ currentLocation: NEW_LocationResolved
+ ): NEW_LocationResolved
+
// NOTE: in practice, this overload can cause bugs. It's better to use named locations
/**
addRoute(matcher: Matcher, parent?: MatcherNormalized): MatcherNormalized
removeRoute(matcher: MatcherNormalized): void
clearRoutes(): void
+
+ /**
+ * Get a list of all matchers.
+ * Previously named `getRoutes()`
+ */
+ getMatchers(): MatcherNormalized[]
+
+ /**
+ * Get a matcher by its name.
+ * Previously named `getRecordMatcher()`
+ */
+ getMatcher(name: MatcherName): MatcherNormalized | undefined
}
type MatcherResolveArgs =
| [absoluteLocation: `/${string}`]
| [relativeLocation: string, currentLocation: NEW_LocationResolved]
+ | [absoluteLocation: MatcherLocationAsPathAbsolute]
+ | [
+ relativeLocation: MatcherLocationAsPathRelative,
+ currentLocation: NEW_LocationResolved
+ ]
| [location: MatcherLocationAsNamed]
| [
relativeLocation: MatcherLocationAsRelative,
MatcherRecordRaw,
MatcherPattern
> {
+ // TODO: we also need an array that has the correct order
const matchers = new Map<MatcherName, MatcherPattern>()
// TODO: allow custom encode/decode functions
// string location, e.g. '/foo', '../bar', 'baz', '?page=1'
if (typeof location === 'string') {
+ // parseURL handles relative paths
const url = parseURL(parseQuery, location, currentLocation?.path)
let matcher: MatcherPattern | undefined
// }
parsedParams = { ...pathParams, ...queryParams, ...hashParams }
- // console.log('parsedParams', parsedParams)
if (parsedParams) break
} catch (e) {
hash: url.hash,
matched,
}
+ // TODO: handle object location { path, query, hash }
} else {
// relative location or by name
if (__DEV__ && location.name == null && currentLocation == null) {
matchers.clear()
}
+ function getMatchers() {
+ return Array.from(matchers.values())
+ }
+
+ function getMatcher(name: MatcherName) {
+ return matchers.get(name)
+ }
+
return {
resolve,
addRoute,
removeRoute,
clearRoutes,
+ getMatcher,
+ getMatchers,
}
}