BREAKING CHANGE: Renamed types by removing suffix Normalized and using Raw instead
- `RouteLocation` -> `RouteLocationRaw`
- `RouteLocationNormalized` -> `RouteLocation`
- `RouteLocationNormalized` is now a location that can be displayed (not a static redirect)
- `RouteLocationNormalizedResolved` -> `RouteLocationNormalizedLoaded`
- `RouteRecord` -> `RouteRecordRaw`
- `RouteRecordNormalized` -> `RouteRecord`
- `RouteRecordNormalized` is now a record that is not a static redirect
import {
START_LOCATION_NORMALIZED,
RouteQueryAndHash,
- MatcherLocation,
+ MatcherLocationRaw,
RouteLocationNormalized,
+ RouteLocation,
} from '../src/types'
import { createMemoryHistory } from '../src'
import { mount, tick } from './mount'
// fix the aliasOf
records.homeAlias = { aliasOf: records.home } as RouteRecordNormalized
-records.parentAlias = { aliasOf: records.parent } as RouteRecordNormalized
+records.parentAlias = {
+ aliasOf: records.parent,
+} as RouteRecordNormalized
records.childAlias = { aliasOf: records.child } as RouteRecordNormalized
const locations: Record<
{
string: string
normalized: RouteLocationNormalized
- toResolve?: MatcherLocation & Required<RouteQueryAndHash>
+ toResolve?: MatcherLocationRaw & Required<RouteQueryAndHash>
}
> = {
basic: {
function factory(
currentLocation: RouteLocationNormalized,
propsData: any,
- resolvedLocation: RouteLocationNormalized,
+ resolvedLocation: RouteLocation,
template: string = `<RouterLink :to="to">a link</RouterLink>`
) {
const router = {
import { createRouter as newRouter, createMemoryHistory } from '../src'
import { ErrorTypes } from '../src/errors'
import { components, tick } from './utils'
-import { RouteRecord } from '../src/types'
+import { RouteRecordRaw } from '../src/types'
-const routes: RouteRecord[] = [
+const routes: RouteRecordRaw[] = [
{ path: '/', component: components.Home },
{ path: '/foo', component: components.Foo, name: 'Foo' },
{ path: '/to-foo', redirect: '/foo' },
import { extractComponentsGuards } from '../src/utils'
-import { START_LOCATION_NORMALIZED, RouteRecord } from '../src/types'
+import { START_LOCATION_NORMALIZED, RouteRecordRaw } from '../src/types'
import { components } from './utils'
import { normalizeRouteRecord } from '../src/matcher'
+import { RouteRecordNormalized } from 'src/matcher/types'
const beforeRouteEnter = jest.fn()
const to = START_LOCATION_NORMALIZED
const from = START_LOCATION_NORMALIZED
-const NoGuard: RouteRecord = { path: '/', component: components.Home }
-const SingleGuard: RouteRecord = {
+const NoGuard: RouteRecordRaw = { path: '/', component: components.Home }
+const SingleGuard: RouteRecordRaw = {
path: '/',
component: { ...components.Home, beforeRouteEnter },
}
-const SingleGuardNamed: RouteRecord = {
+const SingleGuardNamed: RouteRecordRaw = {
path: '/',
components: {
default: { ...components.Home, beforeRouteEnter },
})
async function checkGuards(
- components: Exclude<RouteRecord, { redirect: any }>[],
+ components: Exclude<RouteRecordRaw, { redirect: any }>[],
n: number,
guardsLength: number = n
) {
beforeRouteEnter.mockClear()
const guards = await extractComponentsGuards(
// type is fine as we excluded RouteRecordRedirect in components argument
- components.map(normalizeRouteRecord),
+ components.map(normalizeRouteRecord) as RouteRecordNormalized[],
'beforeRouteEnter',
to,
from
import { RouterOptions, createRouter as newRouter } from '../../src/router'
import fakePromise from 'faked-promise'
import { createDom, noGuard } from '../utils'
-import { RouteRecord, NavigationGuard } from '../../src/types'
+import { RouteRecordRaw, NavigationGuard } from '../../src/types'
import { createWebHistory } from '../../src'
function createRouter(
- options: Partial<RouterOptions> & { routes: RouteRecord[] }
+ options: Partial<RouterOptions> & { routes: RouteRecordRaw[] }
) {
return newRouter({
history: createWebHistory(),
nestedNestedParam: jest.fn(),
}
-const routes: RouteRecord[] = [
+const routes: RouteRecordRaw[] = [
{ path: '/', component: Home },
{ path: '/foo', component: Foo },
{
import { RouterOptions, createRouter as newRouter } from '../../src/router'
import { createDom, noGuard } from '../utils'
-import { RouteRecord } from '../../src/types'
+import { RouteRecordRaw } from '../../src/types'
import { createWebHistory } from '../../src'
// TODO: refactor in utils
function createRouter(
- options: Partial<RouterOptions> & { routes: RouteRecord[] }
+ options: Partial<RouterOptions> & { routes: RouteRecordRaw[] }
) {
return newRouter({
history: createWebHistory(),
}
const beforeRouteLeave = jest.fn()
-const routes: RouteRecord[] = [
+const routes: RouteRecordRaw[] = [
{ path: '/', component: Home },
{ path: '/foo', component: Foo },
{
import fakePromise from 'faked-promise'
import { createDom, noGuard } from '../utils'
import { createRouter as newRouter, createWebHistory } from '../../src'
-import { RouteRecord } from '../../src/types'
+import { RouteRecordRaw } from '../../src/types'
function createRouter(
options: Partial<import('../../src/router').RouterOptions> & {
- routes: import('../../src/types').RouteRecord[]
+ routes: import('../../src/types').RouteRecordRaw[]
}
) {
return newRouter({
const Foo = { template: `<div>Foo</div>` }
const beforeRouteUpdate = jest.fn()
-const routes: RouteRecord[] = [
+const routes: RouteRecordRaw[] = [
{ path: '/', component: Home },
{ path: '/foo', component: Foo },
{
import { createDom } from '../utils'
import { createWebHistory, createRouter as newRouter } from '../../src'
+import { RouteRecordRaw } from 'src/types'
function createRouter(
options: Partial<import('../../src/router').RouterOptions> & {
- routes: import('../../src/types').RouteRecord[]
+ routes: import('../../src/types').RouteRecordRaw[]
}
) {
return newRouter({
const Foo = { template: `<div>Foo</div>` }
const Nested = { template: `<div>Nested<router-view/></div>` }
-/** @type {import('../../src/types').RouteRecord[]} */
-const routes = [
+const routes: RouteRecordRaw[] = [
{ path: '/', component: Home },
{ path: '/foo', component: Foo },
{
import { RouterOptions } from '../../src/router'
import fakePromise from 'faked-promise'
import { createDom, tick, noGuard } from '../utils'
-import { RouteRecord, RouteLocation } from '../../src/types'
+import { RouteRecordRaw, RouteLocationRaw } from '../../src/types'
import { createWebHistory, createRouter as newRouter } from '../../src'
function createRouter(
- options: Partial<RouterOptions> & { routes: RouteRecord[] }
+ options: Partial<RouterOptions> & { routes: RouteRecordRaw[] }
) {
return newRouter({
history: createWebHistory(),
const Foo = { template: `<div>Foo</div>` }
const Nested = { template: `<div>Nested<router-view/></div>` }
-const routes: RouteRecord[] = [
+const routes: RouteRecordRaw[] = [
{ path: '/', component: Home },
{ path: '/foo', component: Foo },
{ path: '/other', component: Foo },
expect(router.currentRoute.value.fullPath).toBe('/other')
})
- async function assertRedirect(redirectFn: (i: string) => RouteLocation) {
+ async function assertRedirect(redirectFn: (i: string) => RouteLocationRaw) {
const spy = jest.fn()
const router = createRouter({ routes })
await router.push('/')
import { RouterOptions, createRouter as newRouter } from '../../src/router'
import fakePromise from 'faked-promise'
import { createDom, noGuard, tick } from '../utils'
-import { RouteRecord } from '../../src/types'
+import { RouteRecordRaw } from '../../src/types'
import { createWebHistory } from '../../src'
function createRouter(
- options: Partial<RouterOptions> & { routes: RouteRecord[] }
+ options: Partial<RouterOptions> & { routes: RouteRecordRaw[] }
) {
return newRouter({
history: createWebHistory(),
nestedNestedParam: jest.fn(),
}
-const routes: RouteRecord[] = [
+const routes: RouteRecordRaw[] = [
{ path: '/', component: Home },
{ path: '/home', component: Home, beforeEnter },
{ path: '/foo', component: Foo },
import { createRouterMatcher } from '../../src/matcher'
-import { MatcherLocationNormalized } from '../../src/types'
+import { MatcherLocation } from '../../src/types'
-const currentLocation = { path: '/' } as MatcherLocationNormalized
+const currentLocation = { path: '/' } as MatcherLocation
// @ts-ignore
const component: RouteComponent = null
})
expect(record).toEqual({
- beforeEnter: expect.any(Function),
- children: [],
aliasOf: undefined,
components: {},
- leaveGuards: [],
- instances: {},
meta: { foo: true },
name: 'name',
path: '/redirect',
- props: false,
+ redirect: '/home',
})
})
})
})
- it('transforms a redirect record into a beforeEnter guard', () => {
- const record = normalizeRouteRecord({
- path: '/redirect',
- redirect: '/home',
- })
- expect(record).toEqual({
- beforeEnter: expect.any(Function),
- children: [],
- aliasOf: undefined,
- components: {},
- leaveGuards: [],
- instances: {},
- meta: {},
- name: undefined,
- path: '/redirect',
- props: false,
- })
- })
-
- it('beforeEnter is called with the string redirect', () => {
- const record = normalizeRouteRecord({
- path: '/redirect',
- redirect: '/home',
- })
+ // TODO: move to router
+ it.todo('beforeEnter is called with the string redirect')
- let spy = jest.fn()
- ;(record.beforeEnter as Function)({} as any, {} as any, spy)
- expect(spy).toHaveBeenCalledTimes(1)
- expect(spy).toHaveBeenCalledWith('/home')
- })
+ it.todo('beforeEnter is called with object redirect')
- it('beforeEnter is called with object redirect', () => {
- const record = normalizeRouteRecord({
- path: '/redirect',
- redirect: { name: 'home' },
- })
-
- let spy = jest.fn()
- ;(record.beforeEnter as Function)({} as any, {} as any, spy)
- expect(spy).toHaveBeenCalledTimes(1)
- expect(spy).toHaveBeenCalledWith({ name: 'home' })
- })
-
- it('function redirect is invoked by beforeEnter', () => {
- const redirect = jest.fn(() => '/home')
- const record = normalizeRouteRecord({
- path: '/redirect',
- redirect,
- })
-
- let spy = jest.fn()
- ;(record.beforeEnter as Function)(
- { path: '/redirect' } as any,
- {} as any,
- spy
- )
- expect(redirect).toHaveBeenCalledTimes(1)
- expect(redirect).toHaveBeenCalledWith({ path: '/redirect' })
- expect(spy).toHaveBeenCalledTimes(1)
- expect(spy).toHaveBeenCalledWith('/home')
- })
+ it.todo('function redirect is invoked by beforeEnter')
})
import {
START_LOCATION_NORMALIZED,
RouteComponent,
- RouteRecord,
+ RouteRecordRaw,
+ MatcherLocationRaw,
MatcherLocation,
- MatcherLocationNormalized,
} from '../../src/types'
import { MatcherLocationNormalizedLoose } from '../utils'
describe('Router Matcher', () => {
describe('resolve', () => {
function assertRecordMatch(
- record: RouteRecord | RouteRecord[],
- location: MatcherLocation,
+ record: RouteRecordRaw | RouteRecordRaw[],
+ location: MatcherLocationRaw,
resolved: Partial<MatcherLocationNormalizedLoose>,
- start: MatcherLocationNormalized = START_LOCATION_NORMALIZED
+ start: MatcherLocation = START_LOCATION_NORMALIZED
) {
record = Array.isArray(record) ? record : [record]
const matcher = createRouterMatcher(record, {})
resolved.params = resolved.params || {}
}
- const startCopy = {
+ const startCopy: MatcherLocation = {
...start,
matched: start.matched.map(m => ({
...normalizeRouteRecord(m),
aliasOf: m.aliasOf,
- })),
+ })) as MatcherLocation['matched'],
}
// make matched non enumerable
* @returns error
*/
function assertErrorMatch(
- record: RouteRecord | RouteRecord[],
- location: MatcherLocation,
- start: MatcherLocationNormalized = START_LOCATION_NORMALIZED
+ record: RouteRecordRaw | RouteRecordRaw[],
+ location: MatcherLocationRaw,
+ start: MatcherLocation = START_LOCATION_NORMALIZED
): any {
try {
assertRecordMatch(record, location, {}, start)
name: 'nested',
path: '/foo',
params: {},
- matched: [Foo, { ...Nested, path: `${Foo.path}` }].map(
- normalizeRouteRecord
- ),
+ matched: [Foo, { ...Nested, path: `${Foo.path}` }],
}
)
})
name: 'nested',
path: '/nested',
params: {},
- matched: [Parent, { ...Nested, path: `/nested` }].map(
- normalizeRouteRecord
- ),
+ matched: [Parent, { ...Nested, path: `/nested` }],
}
)
})
name: 'nested',
path: '/parent/nested',
params: {},
- matched: [Parent, { ...Nested, path: `/parent/nested` }].map(
- normalizeRouteRecord
- ),
+ matched: [Parent, { ...Nested, path: `/parent/nested` }],
}
)
})
} from 'vue'
import * as runtimeDom from '@vue/runtime-dom'
import { compile } from '@vue/compiler-dom'
-import { Router, RouteLocationNormalizedResolved } from '../src'
+import { Router, RouteLocationNormalizedLoaded } from '../src'
import { routerKey, routeLocationKey } from '../src/utils/injectionSymbols'
export function mount(
const app = createApp(ComponentWithoutTemplate as any, rootProps)
const reactiveRoute = {} as {
- [k in keyof RouteLocationNormalizedResolved]: ComputedRef<
- RouteLocationNormalizedResolved[k]
+ [k in keyof RouteLocationNormalizedLoaded]: ComputedRef<
+ RouteLocationNormalizedLoaded[k]
>
}
for (let key in router.currentRoute.value) {
import { ErrorTypes } from '../src/errors'
import { createDom, components, tick } from './utils'
import {
- RouteRecord,
- RouteLocation,
+ RouteRecordRaw,
+ RouteLocationRaw,
START_LOCATION_NORMALIZED,
} from '../src/types'
-const routes: RouteRecord[] = [
+const routes: RouteRecordRaw[] = [
{ path: '/', component: components.Home, name: 'home' },
{ path: '/home', redirect: '/' },
{
{ path: '/to-foo2', redirect: '/to-foo' },
{ path: '/p/:p', name: 'Param', component: components.Bar },
{ path: '/to-p/:p', redirect: to => `/p/${to.params.p}` },
+ { path: '/before-leave', component: components.BeforeLeave },
{
path: '/inc-query-hash',
redirect: to => ({
describe('navigation', () => {
async function checkNavigationCancelledOnPush(
- target?: RouteLocation | false | ((vm: any) => void)
+ target?: RouteLocationRaw | false | ((vm: any) => void)
) {
const [p1, r1] = fakePromise()
const [p2, r2] = fakePromise()
})
async function checkNavigationCancelledOnPopstate(
- target?: RouteLocation | false | ((vm: any) => void)
+ target?: RouteLocationRaw | false | ((vm: any) => void)
) {
const [p1, r1] = fakePromise()
const [p2, r2] = fakePromise()
})
})
+ it('only triggers guards once with a redirect option', async () => {
+ const history = createMemoryHistory()
+ const router = createRouter({ history, routes })
+ const spy = jest.fn((to, from, next) => next())
+ router.beforeEach(spy)
+ await router.push('/to-foo')
+ expect(spy).toHaveBeenCalledTimes(1)
+ expect(spy).toHaveBeenCalledWith(
+ expect.objectContaining({ path: '/foo' }),
+ expect.objectContaining({ path: '/' }),
+ expect.any(Function)
+ )
+ })
+
it('handles a double redirect from route record', async () => {
const history = createMemoryHistory()
const router = createRouter({ history, routes })
it('can pass on query and hash when redirecting', async () => {
const history = createMemoryHistory()
const router = createRouter({ history, routes })
- const loc = await router.push('/inc-query-hash?n=3#fa')
+ await router.push('/inc-query-hash?n=3#fa')
+ const loc = router.currentRoute.value
expect(loc).toMatchObject({
name: 'Foo',
query: {
import { createRouter as newRouter } from '../src/router'
import { createDom, components } from './utils'
-import { RouteRecord } from '../src/types'
+import { RouteRecordRaw } from '../src/types'
import { createMemoryHistory } from '../src'
import * as encoding from '../src/utils/encoding'
jest.mock('../src/utils/encoding')
-const routes: RouteRecord[] = [
+const routes: RouteRecordRaw[] = [
{ path: '/', name: 'home', component: components.Home },
{ path: '/%25', name: 'percent', component: components.Home },
{ path: '/to-p/:p', redirect: to => `/p/${to.params.p}` },
import {
NavigationGuard,
RouteRecordMultipleViews,
- MatcherLocationNormalized,
+ MatcherLocation,
RouteLocationNormalized,
- RouteRecordCommon,
+ _RouteRecordBase,
RouteComponent,
} from '../src/types'
import { h, resolveComponent, ComponentOptions } from 'vue'
> {
leaveGuards?: any
instances: Record<string, any>
- props?: RouteRecordCommon['props']
+ props?: _RouteRecordBase['props']
aliasOf: RouteRecordViewLoose | undefined
}
path: string
// record?
params: any
- redirectedFrom?: Partial<MatcherLocationNormalized>
+ redirectedFrom?: Partial<MatcherLocation>
meta: any
matched: Partial<RouteRecordViewLoose>[]
}
path: string
// record?
params: any
- redirectedFrom?: Partial<MatcherLocationNormalized>
+ redirectedFrom?: Partial<MatcherLocation>
meta: any
matched: Partial<RouteRecordViewLoose>[]
instances: Record<string, any>
])
},
},
+ BeforeLeave: {
+ render: () => h('div', {}, 'before leave'),
+ beforeRouteLeave(to, from, next) {
+ next()
+ },
+ } as RouteComponent,
}
- run: yarn run test:types
- run: yarn run test:unit --maxWorkers=2
- run: yarn build
+ - run: yarn build:dts
- run:
name: Send code coverage
reactive,
unref,
} from 'vue'
-import { RouteLocation, RouteLocationNormalized, VueUseOptions } from '../types'
+import { RouteLocationRaw, VueUseOptions, RouteLocation } from '../types'
import { isSameLocationObject, isSameRouteRecord } from '../utils'
import { routerKey } from '../utils/injectionSymbols'
-import { RouteRecordNormalized } from '../matcher/types'
+import { RouteRecord } from '../matcher/types'
interface LinkProps {
- to: RouteLocation
+ to: RouteLocationRaw
// TODO: refactor using extra options allowed in router.push
replace?: boolean
}
const activeRecordIndex = computed<number>(() => {
// TODO: handle children with empty path: they should relate to their parent
- const currentMatched: RouteRecordNormalized | undefined =
+ const currentMatched: RouteRecord | undefined =
route.value.matched[route.value.matched.length - 1]
if (!currentMatched) return -1
return currentRoute.value.matched.findIndex(
name: 'RouterLink',
props: {
to: {
- type: [String, Object] as PropType<RouteLocation>,
+ type: [String, Object] as PropType<RouteLocationRaw>,
required: true,
},
},
}
function includesParams(
- outter: RouteLocationNormalized['params'],
- inner: RouteLocationNormalized['params']
+ outter: RouteLocation['params'],
+ inner: RouteLocation['params']
): boolean {
for (let key in inner) {
let innerValue = inner[key]
SetupContext,
toRefs,
} from 'vue'
-import {
- RouteLocationMatched,
- VueUseOptions,
- RouteLocationNormalizedResolved,
-} from '../types'
+import { VueUseOptions, RouteLocationNormalizedLoaded } from '../types'
import {
matchedRouteKey,
viewDepthKey,
} from '../utils/injectionSymbols'
interface ViewProps {
- route: RouteLocationNormalizedResolved
+ route: RouteLocationNormalizedLoaded
name: string
}
const matchedRoute = computed(
() =>
- unref(options.route).matched[depth] as RouteLocationMatched | undefined
+ unref(options.route).matched[depth] as
+ | ViewProps['route']['matched'][any]
+ | undefined
)
const ViewComponent = computed(
() =>
import {
+ MatcherLocationRaw,
MatcherLocation,
- MatcherLocationNormalized,
- RouteLocation,
+ RouteLocationRaw,
RouteLocationNormalized,
} from './types'
export interface MatcherError extends RouterErrorBase {
type: ErrorTypes.MATCHER_NOT_FOUND
- location: MatcherLocation
- currentLocation?: MatcherLocationNormalized
+ location: MatcherLocationRaw
+ currentLocation?: MatcherLocation
}
export interface NavigationError extends RouterErrorBase {
export interface NavigationRedirectError
extends Omit<NavigationError, 'to' | 'type'> {
type: ErrorTypes.NAVIGATION_GUARD_REDIRECT
- to: RouteLocation
+ to: RouteLocationRaw
}
// DEV only debug messages
const propertiesToLog = ['params', 'query', 'hash'] as const
-function stringifyRoute(to: RouteLocation): string {
+function stringifyRoute(to: RouteLocationRaw): string {
if (typeof to === 'string') return to
if ('path' in to) return to.path
const location = {} as Record<string, unknown>
export { RouterHistory } from './history/common'
-export { RouteRecordNormalized } from './matcher/types'
+export { RouteRecord, RouteRecordNormalized } from './matcher/types'
export {
- RouteLocation,
- RouteLocationMatched,
+ RouteLocationRaw,
RouteLocationNormalized,
- RouteLocationNormalizedResolved,
+ RouteLocationNormalizedLoaded,
START_LOCATION_NORMALIZED as START_LOCATION,
RouteParams,
+ RouteLocationMatched,
RouteLocationOptions,
- RouteRecord,
+ RouteRecordRaw,
NavigationGuard,
PostNavigationGuard,
} from './types'
-import {
- RouteRecord,
- MatcherLocation,
- MatcherLocationNormalized,
-} from '../types'
+import { RouteRecordRaw, MatcherLocationRaw, MatcherLocation } from '../types'
import { createRouterError, ErrorTypes, MatcherError } from '../errors'
import { createRouteRecordMatcher, RouteRecordMatcher } from './path-matcher'
-import { RouteRecordNormalized } from './types'
+import { RouteRecordRedirect, RouteRecordNormalized } from './types'
import {
PathParams,
comparePathParserScore,
let noop = () => {}
interface RouterMatcher {
- addRoute: (record: RouteRecord, parent?: RouteRecordMatcher) => () => void
+ addRoute: (record: RouteRecordRaw, parent?: RouteRecordMatcher) => () => void
removeRoute: {
(matcher: RouteRecordMatcher): void
- (name: Required<RouteRecord>['name']): void
+ (name: Required<RouteRecordRaw>['name']): void
}
getRoutes: () => RouteRecordMatcher[]
getRecordMatcher: (
- name: Required<RouteRecord>['name']
+ name: Required<RouteRecordRaw>['name']
) => RouteRecordMatcher | undefined
resolve: (
- location: MatcherLocation,
- currentLocation: MatcherLocationNormalized
- ) => MatcherLocationNormalized
+ location: MatcherLocationRaw,
+ currentLocation: MatcherLocation
+ ) => MatcherLocation
}
export function createRouterMatcher(
- routes: RouteRecord[],
+ routes: RouteRecordRaw[],
globalOptions: PathParserOptions
): RouterMatcher {
// normalized ordered array of matchers
// TODO: add routes to children of parent
function addRoute(
- record: Readonly<RouteRecord>,
+ record: RouteRecordRaw,
parent?: RouteRecordMatcher,
originalRecord?: RouteRecordMatcher
) {
mainNormalizedRecord.aliasOf = originalRecord && originalRecord.record
const options: PathParserOptions = { ...globalOptions, ...record.options }
// generate an array of records to correctly handle aliases
- const normalizedRecords: RouteRecordNormalized[] = [mainNormalizedRecord]
+ const normalizedRecords: typeof mainNormalizedRecord[] = [
+ mainNormalizedRecord,
+ ]
if ('alias' in record) {
const aliases =
typeof record.alias === 'string' ? [record.alias] : record.alias!
aliasOf: originalRecord
? originalRecord.record
: mainNormalizedRecord,
- })
+ // the aliases are always of the same kind as the original since they
+ // are defined on the same record
+ } as typeof mainNormalizedRecord)
}
}
if (originalMatcher !== matcher) originalMatcher.alias.push(matcher)
}
- let children = mainNormalizedRecord.children
- for (let i = 0; i < children.length; i++) {
- addRoute(
- children[i],
- matcher,
- originalRecord && originalRecord.children[i]
- )
+ // only non redirect records have children
+ if ('children' in mainNormalizedRecord) {
+ let children = mainNormalizedRecord.children
+ for (let i = 0; i < children.length; i++) {
+ addRoute(
+ children[i],
+ matcher,
+ originalRecord && originalRecord.children[i]
+ )
+ }
}
// if there was no original record, then the first one was not an alias and all
/**
* Resolves a location. Gives access to the route record that corresponds to the actual path as well as filling the corresponding params objects
- * @param location - MatcherLocation to resolve to a url
- * @param currentLocation - MatcherLocationNormalized of the current location
+ *
+ * @param location - MatcherLocationRaw to resolve to a url
+ * @param currentLocation - MatcherLocation of the current location
*/
function resolve(
- location: Readonly<MatcherLocation>,
- currentLocation: Readonly<MatcherLocationNormalized>
- ): MatcherLocationNormalized {
+ location: Readonly<MatcherLocationRaw>,
+ currentLocation: Readonly<MatcherLocation>
+ ): MatcherLocation {
let matcher: RouteRecordMatcher | undefined
let params: PathParams = {}
- let path: MatcherLocationNormalized['path']
- let name: MatcherLocationNormalized['name']
+ let path: MatcherLocation['path']
+ let name: MatcherLocation['name']
if ('name' in location && location.name) {
matcher = matcherMap.get(location.name)
path = matcher.stringify(params)
}
- const matched: MatcherLocationNormalized['matched'] = []
- let parentMatcher: RouteRecordMatcher | void = matcher
+ const matched: MatcherLocation['matched'] = []
+ let parentMatcher: RouteRecordMatcher | undefined = matcher
while (parentMatcher) {
// reversed order so parents are at the beginning
- // const { record } = parentMatcher
+
// TODO: check resolving child routes by path when parent has an alias
matched.unshift(parentMatcher.record)
parentMatcher = parentMatcher.parent
}
/**
- * Normalizes a RouteRecord. Transforms the `redirect` option into a `beforeEnter`
+ * Normalizes a RouteRecordRaw. Transforms the `redirect` option into a `beforeEnter`
* @param record
* @returns the normalized version
*/
export function normalizeRouteRecord(
- record: Readonly<RouteRecord>
-): RouteRecordNormalized {
- let components: RouteRecordNormalized['components']
- let beforeEnter: RouteRecordNormalized['beforeEnter']
- if ('redirect' in record) {
- components = {}
- let { redirect } = record
- beforeEnter = (to, from, next) => {
- next(typeof redirect === 'function' ? redirect(to) : redirect)
- }
- } else {
- components =
- 'components' in record ? record.components : { default: record.component }
- beforeEnter = record.beforeEnter
- }
-
- return {
+ record: RouteRecordRaw
+): RouteRecordNormalized | RouteRecordRedirect {
+ const commonInitialValues = {
path: record.path,
- components,
- // record is an object and if it has a children property, it's an array
- children: (record as any).children || [],
name: record.name,
- beforeEnter,
- props: record.props || false,
meta: record.meta || {},
- leaveGuards: [],
- instances: {},
aliasOf: undefined,
+ components: {},
+ }
+
+ if ('redirect' in record) {
+ return {
+ ...commonInitialValues,
+ redirect: record.redirect,
+ }
+ } else {
+ return {
+ ...commonInitialValues,
+ beforeEnter: record.beforeEnter,
+ props: record.props || false,
+ children: record.children || [],
+ instances: {},
+ leaveGuards: [],
+ components:
+ 'components' in record
+ ? record.components
+ : { default: record.component },
+ }
}
}
-import { RouteRecordNormalized } from './types'
+import { RouteRecord } from './types'
import {
tokensToParser,
PathParser,
import { tokenizePath } from './path-tokenizer'
export interface RouteRecordMatcher extends PathParser {
- record: RouteRecordNormalized
+ record: RouteRecord
parent: RouteRecordMatcher | undefined
children: RouteRecordMatcher[]
// aliases that must be removed when removing this record
}
export function createRouteRecordMatcher(
- record: Readonly<RouteRecordNormalized>,
+ record: Readonly<RouteRecord>,
parent: RouteRecordMatcher | undefined,
options?: PathParserOptions
): RouteRecordMatcher {
const parser = tokensToParser(tokenizePath(record.path), options)
-
const matcher: RouteRecordMatcher = {
...parser,
record,
import {
RouteRecordMultipleViews,
NavigationGuard,
- RouteRecordCommon,
+ _RouteRecordBase,
+ RouteRecordRedirectRaw,
} from '../types'
+import { ComponentPublicInstance } from 'vue'
// normalize component/components into components and make every property always present
export interface RouteRecordNormalized {
components: RouteRecordMultipleViews['components']
children: Exclude<RouteRecordMultipleViews['children'], void>
meta: Exclude<RouteRecordMultipleViews['meta'], void>
- props: Exclude<RouteRecordCommon['props'], void>
+ props: Exclude<_RouteRecordBase['props'], void>
beforeEnter: RouteRecordMultipleViews['beforeEnter']
leaveGuards: NavigationGuard<undefined>[]
- // TODO: should be ComponentPublicInstance but breaks Immutable type
- instances: Record<string, {} | undefined | null>
+ instances: Record<string, ComponentPublicInstance | undefined | null>
+ // can only be of of the same type as this record
aliasOf: RouteRecordNormalized | undefined
}
+
+export interface RouteRecordRedirect {
+ path: RouteRecordMultipleViews['path']
+ name: RouteRecordMultipleViews['name']
+ redirect: RouteRecordRedirectRaw['redirect']
+ // can only be of of the same type as this record
+ aliasOf: RouteRecordRedirect | undefined
+ meta: Exclude<RouteRecordMultipleViews['meta'], void>
+ // this object will always be empty but it simplifies things
+ components: RouteRecordMultipleViews['components']
+}
+
+export type RouteRecord = RouteRecordNormalized | RouteRecordRedirect
import { NavigationGuard } from './types'
import { inject, getCurrentInstance, warn } from 'vue'
-import { RouteRecordNormalized } from './matcher/types'
import { matchedRouteKey } from './utils/injectionSymbols'
export function onBeforeRouteLeave(leaveGuard: NavigationGuard) {
return
}
- const activeRecord: RouteRecordNormalized | undefined = inject(
- matchedRouteKey,
- {} as any
- ).value
+ const activeRecord = inject(matchedRouteKey, {} as any).value
if (!activeRecord) {
__DEV__ &&
import {
RouteLocationNormalized,
- RouteRecord,
- RouteLocation,
+ RouteRecordRaw,
+ RouteLocationRaw,
NavigationGuard,
PostNavigationGuard,
START_LOCATION_NORMALIZED,
Lazy,
TODO,
- MatcherLocationNormalized,
- RouteLocationNormalizedResolved,
+ MatcherLocation,
+ RouteLocationNormalizedLoaded,
+ RouteLocation,
} from './types'
import {
RouterHistory,
reactive,
ComputedRef,
} from 'vue'
-import { RouteRecordNormalized } from './matcher/types'
+import { RouteRecord, RouteRecordNormalized } from './matcher/types'
import { Link } from './components/Link'
import { View } from './components/View'
import { routerKey, routeLocationKey } from './utils/injectionSymbols'
interface ScrollBehavior {
(
to: RouteLocationNormalized,
- from: RouteLocationNormalizedResolved,
+ from: RouteLocationNormalizedLoaded,
savedPosition: ScrollToPosition | null
): ScrollPosition | Promise<ScrollPosition>
}
export interface RouterOptions {
history: RouterHistory
- routes: RouteRecord[]
+ routes: RouteRecordRaw[]
scrollBehavior?: ScrollBehavior
parseQuery?: typeof originalParseQuery
stringifyQuery?: typeof originalStringifyQuery
export interface Router {
history: RouterHistory
- currentRoute: Ref<RouteLocationNormalizedResolved>
+ currentRoute: Ref<RouteLocationNormalizedLoaded>
- addRoute(parentName: string, route: RouteRecord): () => void
- addRoute(route: RouteRecord): () => void
+ addRoute(parentName: string, route: RouteRecordRaw): () => void
+ addRoute(route: RouteRecordRaw): () => void
removeRoute(name: string): void
- getRoutes(): RouteRecordNormalized[]
+ getRoutes(): RouteRecord[]
- resolve(to: RouteLocation): RouteLocationNormalized
- createHref(to: RouteLocationNormalized): string
- push(to: RouteLocation): Promise<RouteLocationNormalizedResolved>
- replace(to: RouteLocation): Promise<RouteLocationNormalizedResolved>
+ resolve(to: RouteLocationRaw): RouteLocation
+ createHref(to: RouteLocation): string
+ push(to: RouteLocationRaw): Promise<TODO>
+ replace(to: RouteLocationRaw): Promise<TODO>
beforeEach(guard: NavigationGuard<undefined>): () => void
afterEach(guard: PostNavigationGuard): () => void
const beforeGuards = useCallbacks<NavigationGuard<undefined>>()
const afterGuards = useCallbacks<PostNavigationGuard>()
- const currentRoute = ref<RouteLocationNormalizedResolved>(
+ const currentRoute = ref<RouteLocationNormalizedLoaded>(
START_LOCATION_NORMALIZED
)
- let pendingLocation: RouteLocationNormalized = START_LOCATION_NORMALIZED
+ let pendingLocation: RouteLocation = START_LOCATION_NORMALIZED
if (isClient && 'scrollRestoration' in window.history) {
window.history.scrollRestoration = 'manual'
}
- function createHref(to: RouteLocationNormalized): string {
+ function createHref(to: RouteLocation): string {
return history.base + to.fullPath
}
const encodeParams = applyToParams.bind(null, encodeParam)
const decodeParams = applyToParams.bind(null, decode)
- function addRoute(parentOrRoute: string | RouteRecord, route?: RouteRecord) {
+ function addRoute(
+ parentOrRoute: string | RouteRecordRaw,
+ route?: RouteRecordRaw
+ ) {
let parent: Parameters<typeof matcher['addRoute']>[1] | undefined
- let record: RouteRecord
+ let record: RouteRecordRaw
if (typeof parentOrRoute === 'string') {
parent = matcher.getRecordMatcher(parentOrRoute)
record = route!
}
}
- function getRoutes(): RouteRecordNormalized[] {
+ function getRoutes() {
return matcher.getRoutes().map(routeMatcher => routeMatcher.record)
}
function resolve(
- location: RouteLocation,
- currentLocation?: RouteLocationNormalizedResolved
- ): RouteLocationNormalized {
+ location: RouteLocationRaw,
+ currentLocation?: RouteLocationNormalizedLoaded
+ ): RouteLocation {
// const objectLocation = routerLocationAsObject(location)
currentLocation = currentLocation || currentRoute.value
if (typeof location === 'string') {
}
}
- let matchedRoute: MatcherLocationNormalized = // relative or named location, path is ignored
+ let matchedRoute: MatcherLocation = // relative or named location, path is ignored
// for same reason TS thinks location.params can be undefined
matcher.resolve(
'params' in location
}
}
- function push(
- // TODO: should not allow normalized version
- to: RouteLocation | RouteLocationNormalized
- ): Promise<RouteLocationNormalizedResolved> {
+ function push(to: RouteLocationRaw | RouteLocation): Promise<TODO> {
return pushWithRedirect(to, undefined)
}
- function replace(to: RouteLocation | RouteLocationNormalized) {
+ function replace(to: RouteLocationRaw | RouteLocationNormalized) {
const location = typeof to === 'string' ? { path: to } : to
return push({ ...location, replace: true })
}
async function pushWithRedirect(
- to: RouteLocation | RouteLocationNormalized,
- redirectedFrom: RouteLocationNormalized | undefined
+ to: RouteLocationRaw | RouteLocation,
+ redirectedFrom: RouteLocation | undefined
): Promise<TODO> {
- const toLocation: RouteLocationNormalized = (pendingLocation =
+ const targetLocation: RouteLocation = (pendingLocation =
// Some functions will pass a normalized location and we don't need to resolve it again
typeof to === 'object' && 'matched' in to ? to : resolve(to))
const from = currentRoute.value
const force: boolean | undefined = to.force
// TODO: should we throw an error as the navigation was aborted
- if (!force && isSameRouteLocation(from, toLocation)) return from
+ if (!force && isSameRouteLocation(from, targetLocation)) return from
+
+ const lastMatched =
+ targetLocation.matched[targetLocation.matched.length - 1]
+ if (lastMatched && 'redirect' in lastMatched) {
+ const { redirect } = lastMatched
+ return pushWithRedirect(
+ typeof redirect === 'function' ? redirect(targetLocation) : redirect,
+ // keep original redirectedFrom if it exists
+ redirectedFrom || targetLocation
+ )
+ }
+
+ // if it was a redirect we already called `pushWithRedirect` above
+ const toLocation = targetLocation as RouteLocationNormalized
toLocation.redirectedFrom = redirectedFrom
}
finalizeNavigation(
- toLocation as RouteLocationNormalizedResolved,
+ toLocation as RouteLocationNormalizedLoaded,
from,
true,
// RouteLocationNormalized will give undefined
- (to as RouteLocation).replace === true,
+ (to as RouteLocationRaw).replace === true,
data
)
async function navigate(
to: RouteLocationNormalized,
- from: RouteLocationNormalizedResolved
+ from: RouteLocationNormalizedLoaded
): Promise<TODO> {
let guards: Lazy<any>[]
// TODO: add tests
// this should be done only if the navigation succeeds
// if we redirect, it shouldn't be done because we don't know
- for (const record of leavingRecords) {
+ for (const record of leavingRecords as RouteRecordNormalized[]) {
// free the references
record.instances = {}
}
* - Calls the scrollBehavior
*/
function finalizeNavigation(
- toLocation: RouteLocationNormalizedResolved,
- from: RouteLocationNormalizedResolved,
+ toLocation: RouteLocationNormalizedLoaded,
+ from: RouteLocationNormalizedLoaded,
isPush: boolean,
replace?: boolean,
data?: HistoryState
// attach listener to history to trigger navigations
history.listen(async (to, _from, info) => {
// TODO: try catch to correctly log the matcher error
- const toLocation = resolve(to.fullPath)
+ // cannot be a redirect route because it was in history
+ const toLocation = resolve(to.fullPath) as RouteLocationNormalized
// console.log({ to, matchedRoute })
pendingLocation = toLocation
await navigate(toLocation, from)
finalizeNavigation(
// after navigation, all matched components are resolved
- toLocation as RouteLocationNormalizedResolved,
+ toLocation as RouteLocationNormalizedLoaded,
from,
false
)
// Scroll behavior
async function handleScroll(
- to: RouteLocationNormalizedResolved,
- from: RouteLocationNormalizedResolved,
+ to: RouteLocationNormalizedLoaded,
+ from: RouteLocationNormalizedLoaded,
scrollPosition?: ScrollToPosition
) {
if (!scrollBehavior) return
})
const reactiveRoute = {} as {
- [k in keyof RouteLocationNormalizedResolved]: ComputedRef<
- RouteLocationNormalizedResolved[k]
+ [k in keyof RouteLocationNormalizedLoaded]: ComputedRef<
+ RouteLocationNormalizedLoaded[k]
>
}
for (let key in START_LOCATION_NORMALIZED) {
function extractChangingRecords(
to: RouteLocationNormalized,
- from: RouteLocationNormalizedResolved
+ from: RouteLocationNormalizedLoaded
) {
const leavingRecords: RouteRecordNormalized[] = []
const updatingRecords: RouteRecordNormalized[] = []
return [leavingRecords, updatingRecords, enteringRecords]
}
-function isSameRouteLocation(
- a: RouteLocationNormalized,
- b: RouteLocationNormalized
-): boolean {
+function isSameRouteLocation(a: RouteLocation, b: RouteLocation): boolean {
let aLastIndex = a.matched.length - 1
let bLastIndex = b.matched.length - 1
Ref,
ComputedRef,
} from 'vue'
-import { RouteRecordNormalized } from '../matcher/types'
+import { RouteRecord, RouteRecordNormalized } from '../matcher/types'
import { HistoryState } from '../history/common'
export type Lazy<T> = () => Promise<T>
state?: HistoryState
}
-// User level location
-export type RouteLocation =
+/**
+ * User-level route location
+ */
+export type RouteLocationRaw =
| string
| (RouteQueryAndHash & LocationAsPath & RouteLocationOptions)
| (RouteQueryAndHash & LocationAsName & RouteLocationOptions)
| (RouteQueryAndHash & LocationAsRelative & RouteLocationOptions)
export interface RouteLocationMatched extends RouteRecordNormalized {
+ // components cannot be Lazy<RouteComponent>
components: Record<string, RouteComponent>
}
-// A matched record cannot be a redirection and must contain
-
-// matched contains resolved components
-export interface RouteLocationNormalizedResolved {
+/**
+ * Base properties for a normalized route location
+ *
+ * @internal
+ */
+export interface _RouteLocationBase {
path: string
fullPath: string
query: LocationQuery
hash: string
name: string | null | undefined
params: RouteParams
- matched: RouteLocationMatched[] // non-enumerable
- redirectedFrom: RouteLocationNormalized | undefined
+ // TODO: make it an array?
+ redirectedFrom: RouteLocation | undefined
meta: Record<string | number | symbol, any>
}
-export interface RouteLocationNormalized {
- path: string
- fullPath: string
- query: LocationQuery
- hash: string
- name: string | null | undefined
- params: RouteParams
+// matched contains resolved components
+/**
+ * {@link RouteLocationRaw} with
+ */
+export interface RouteLocationNormalizedLoaded extends _RouteLocationBase {
+ /**
+ * Array of {@link RouteLocationMatched} containing only plain components (any
+ * lazy-loaded components have been loaded and were replaced inside of the
+ * `components` object) so it can be directly used to display routes. It
+ * cannot contain redirect records either
+ */
+ matched: RouteLocationMatched[] // non-enumerable
+}
+
+/**
+ * {@link RouteLocationRaw} resolved using the matcher
+ */
+export interface RouteLocation extends _RouteLocationBase {
+ /**
+ * Array of {@link RouteRecord} containing components as they were
+ * passed when adding records. It can also contain redirect records. This
+ * can't be used directly
+ */
+ matched: RouteRecord[] // non-enumerable
+}
+
+/**
+ * Similar to {@link RouteLocation} but its
+ * {@link RouteLocationNormalized.matched} cannot contain redirect records
+ */
+export interface RouteLocationNormalized extends _RouteLocationBase {
+ /**
+ * Array of {@link RouteRecordNormalized}
+ */
matched: RouteRecordNormalized[] // non-enumerable
- // TODO: make it an array?
- redirectedFrom: RouteLocationNormalized | undefined
- meta: Record<string | number | symbol, any>
}
// interface PropsTransformer {
// }
// export interface RouterLocation<PT extends PropsTransformer> {
-// record: RouteRecord<PT>
+// record: RouteRecordRaw<PT>
// path: string
// params: ReturnType<PT>
// }
/**
* Guard called when the router is navigating away from the current route
* that is rendering this component.
- * @param to - RouteLocation we are navigating to
- * @param from - RouteLocation we are navigating from
+ * @param to - RouteLocationRaw we are navigating to
+ * @param from - RouteLocationRaw we are navigating from
* @param next - function to validate, cancel or modify (by redirectering) the navigation
*/
beforeRouteLeave?: NavigationGuard
* Guard called whenever the route that renders this component has changed but
* it is reused for the new route. This allows you to guard for changes in params,
* the query or the hash.
- * @param to - RouteLocation we are navigating to
- * @param from - RouteLocation we are navigating from
+ * @param to - RouteLocationRaw we are navigating to
+ * @param from - RouteLocationRaw we are navigating from
* @param next - function to validate, cancel or modify (by redirectering) the navigation
*/
beforeRouteUpdate?: NavigationGuard
export type RawRouteComponent = RouteComponent | Lazy<RouteComponent>
// TODO: could this be moved to matcher?
-export interface RouteRecordCommon {
+/**
+ * Common properties among all kind of {@link RouteRecordRaw}
+ */
+export interface _RouteRecordBase {
+ /**
+ * Path of the record. Should start with `/` unless the record is the child of
+ * another record.
+ */
path: string
+ /**
+ * Aliases for the record. Allows defining extra paths that will behave like a
+ * copy of the record. Allows having paths shorthands like `/users/:id` and
+ * `/u/:id`. All `alias` and `path` values must share the same params.
+ */
alias?: string | string[]
+ /**
+ * Name for the route record.
+ */
name?: string
+ /**
+ * Allow passing down params as props to the component rendered by `router-view`.
+ */
props?:
| boolean
| Record<string, any>
| ((to: RouteLocationNormalized) => Record<string, any>)
// TODO: beforeEnter has no effect with redirect, move and test
beforeEnter?: NavigationGuard<undefined> | NavigationGuard<undefined>[]
+ /**
+ * Arbitraty data attached to the record.
+ */
meta?: Record<string | number | symbol, any>
// TODO: only allow a subset?
// TODO: RFC: remove this and only allow global options
}
export type RouteRecordRedirectOption =
- | RouteLocation
- | ((to: RouteLocationNormalized) => RouteLocation)
-export interface RouteRecordRedirect extends RouteRecordCommon {
+ | RouteLocationRaw
+ | ((to: RouteLocation) => RouteLocationRaw)
+export interface RouteRecordRedirectRaw extends _RouteRecordBase {
redirect: RouteRecordRedirectOption
beforeEnter?: never
component?: never
components?: never
}
-export interface RouteRecordSingleView extends RouteRecordCommon {
+export interface RouteRecordSingleView extends _RouteRecordBase {
component: RawRouteComponent
- children?: RouteRecord[]
+ children?: RouteRecordRaw[]
}
-export interface RouteRecordMultipleViews extends RouteRecordCommon {
+export interface RouteRecordMultipleViews extends _RouteRecordBase {
components: Record<string, RawRouteComponent>
- children?: RouteRecord[]
+ children?: RouteRecordRaw[]
}
-export type RouteRecord =
+export type RouteRecordRaw =
| RouteRecordSingleView
| RouteRecordMultipleViews
- | RouteRecordRedirect
+ | RouteRecordRedirectRaw
-export const START_LOCATION_NORMALIZED: RouteLocationNormalizedResolved = markNonReactive(
+export const START_LOCATION_NORMALIZED: RouteLocationNormalizedLoaded = markNonReactive(
{
path: '/',
name: undefined,
// Matcher types
// the matcher doesn't care about query and hash
-export type MatcherLocation =
+export type MatcherLocationRaw =
| LocationAsPath
| LocationAsName
| LocationAsRelative
-// TODO: should probably be the other way around: RouteLocationNormalized extending from MatcherLocationNormalized
-export interface MatcherLocationNormalized
+// TODO: should probably be the other way around: RouteLocationNormalized extending from MatcherLocation
+export interface MatcherLocation
extends Pick<
- RouteLocationNormalized,
+ RouteLocation,
'name' | 'path' | 'params' | 'matched' | 'meta'
> {}
-// used when the route records requires a redirection
-// with a function call. The matcher isn't able to do it
-// by itself, so it dispatches the information so the router
-// can pick it up
-export interface MatcherLocationRedirect {
- redirect: RouteRecordRedirectOption
- normalizedLocation: MatcherLocationNormalized
-}
-
// TODO: remove any to type vm and use a generic that comes from the component
// where the navigation guard callback is defined
export interface NavigationGuardCallback {
(): void
- (location: RouteLocation): void
+ (location: RouteLocationRaw): void
(valid: boolean): void
(cb: (vm: any) => void): void
}
-import { RouteLocation } from './index'
+import { RouteLocationRaw } from './index'
-export function isRouteLocation(route: any): route is RouteLocation {
+export function isRouteLocation(route: any): route is RouteLocationRaw {
return typeof route === 'string' || (route && typeof route === 'object')
}
import { inject } from 'vue'
import { routerKey, routeLocationKey } from './utils/injectionSymbols'
import { Router } from './router'
-import { RouteLocationNormalizedResolved } from './types'
+import { RouteLocationNormalizedLoaded } from './types'
export function useRouter(): Router {
return inject(routerKey)!
}
-export function useRoute(): RouteLocationNormalizedResolved {
+export function useRoute(): RouteLocationNormalizedLoaded {
return inject(routeLocationKey)!
}
NavigationGuard,
RouteLocationNormalized,
NavigationGuardCallback,
- RouteLocation,
- RouteLocationNormalizedResolved,
+ RouteLocationRaw,
+ RouteLocationNormalizedLoaded,
NavigationGuardNextCallback,
+ isRouteLocation,
} from '../types'
-import { isRouteLocation } from '../types'
import {
createRouterError,
ErrorTypes,
export function guardToPromiseFn(
guard: NavigationGuard<undefined>,
to: RouteLocationNormalized,
- from: RouteLocationNormalizedResolved,
+ from: RouteLocationNormalizedLoaded,
instance?: undefined
): () => Promise<void>
export function guardToPromiseFn<
>(
guard: NavigationGuard<ThisType>,
to: RouteLocationNormalized,
- from: RouteLocationNormalizedResolved,
+ from: RouteLocationNormalizedLoaded,
instance: ThisType
): () => Promise<void> {
return () =>
new Promise((resolve, reject) => {
const next: NavigationGuardCallback = (
- valid?: boolean | RouteLocation | NavigationGuardNextCallback
+ valid?: boolean | RouteLocationRaw | NavigationGuardNextCallback
) => {
if (valid === false)
reject(
RouteLocationNormalized,
RouteParams,
RouteComponent,
- RouteLocationNormalizedResolved,
+ RouteLocationNormalizedLoaded,
} from '../types'
import { guardToPromiseFn } from './guardToPromiseFn'
-import { RouteRecordNormalized } from '../matcher/types'
+import { RouteRecord, RouteRecordNormalized } from '../matcher/types'
import { LocationQueryValue } from './query'
import { hasSymbol } from './injectionSymbols'
matched: RouteRecordNormalized[],
guardType: GuardType,
to: RouteLocationNormalized,
- from: RouteLocationNormalizedResolved
+ from: RouteLocationNormalizedLoaded
) {
const guards: Array<() => Promise<void>> = []
return newParams
}
-export function isSameRouteRecord(
- a: RouteRecordNormalized,
- b: RouteRecordNormalized
-): boolean {
+export function isSameRouteRecord(a: RouteRecord, b: RouteRecord): boolean {
// since the original record has an undefined value for aliasOf
// but all aliases point to the original record, this will always compare
// the original record
import { InjectionKey, ComputedRef } from 'vue'
-import { RouteLocationMatched, RouteLocationNormalizedResolved } from '../types'
+import { RouteLocationNormalizedLoaded } from '../types'
import { Router } from '../router'
+import { RouteRecordNormalized } from '../matcher/types'
export const hasSymbol =
typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol'
// rvlm = Router View Location Matched
export const matchedRouteKey = PolySymbol('rvlm') as InjectionKey<
- ComputedRef<RouteLocationMatched | undefined>
+ ComputedRef<RouteRecordNormalized | undefined>
>
// rvd = Router View Depth
export const viewDepthKey = PolySymbol('rvd') as InjectionKey<number>
export const routerKey = PolySymbol('r') as InjectionKey<Router>
// rt = route location
export const routeLocationKey = PolySymbol('rl') as InjectionKey<
- RouteLocationNormalizedResolved
+ RouteLocationNormalizedLoaded
>
/**
* Loose {@link LocationQuery} object that can be passed to functions like
* {@link Router.push} and {@link Router.replace} or anywhere when creating a
- * {@link RouteLocation}
+ * {@link RouteLocationRaw}
*
* @public
*/