* Error used when rejecting a navigation because of a redirection. Contains
* information about where we where trying to go and where we are going instead
*/
-export class RedirectError extends Error {
+export class NavigationGuardRedirect extends Error {
from: RouteLocationNormalized
to: RouteLocation
constructor(from: RouteLocationNormalized, to: RouteLocation) {
// call all listeners
const navigationInfo = {
type:
- // TODO: we should save somekind of id to detect the navigation type
state.forward && from.fullPath === state.forward.fullPath
? NavigationType.back
: NavigationType.forward,
export function parseQuery(search: string): HistoryQuery {
// TODO: optimize by using a for loop
const hasLeadingIM = search[0] === '?'
- return (hasLeadingIM ? search.slice(1) : search).split('&').reduce(
- (query: HistoryQuery, entry: string) => {
- const [key, value] = entry.split('=')
- if (key in query) {
- // an extra variable for ts types
- let currentValue = query[key]
- if (!Array.isArray(currentValue)) {
- currentValue = query[key] = [currentValue]
- }
- currentValue.push(value)
- } else {
- query[key] = value
+ const query: HistoryQuery = {}
+ const searchParams = (hasLeadingIM ? search.slice(1) : search).split('&')
+ for (let i = 0; i < searchParams.length; ++i) {
+ const [key, value] = searchParams[i].split('=')
+ if (key in query) {
+ // an extra variable for ts types
+ let currentValue = query[key]
+ if (!Array.isArray(currentValue)) {
+ currentValue = query[key] = [currentValue]
}
-
- return query
- },
- {} as HistoryQuery
- )
+ currentValue.push(value)
+ } else {
+ query[key] = value
+ }
+ }
+ return query
}
/**
let path = parent.record.path
// only add the / delimiter if the child path isn't empty
if (recordCopy.path) path += '/'
- path += record.path // TODO: check for trailing slash?
+ path += record.path
recordCopy.path = path
}
}
resolve: pathToRegexp.compile(recordCopy.path),
}
- // TODO: if children use option end: false ?
// TODO: why is the isArray check necessary for ts?
if ('children' in record && Array.isArray(record.children)) {
for (const childRecord of record.children) {
} from './types/index'
import { guardToPromiseFn, extractComponentsGuards } from './utils'
-import { RedirectError } from './errors'
+import { NavigationGuardRedirect } from './errors'
export interface RouterOptions {
history: BaseHistory
this.matcher = new RouterMatcher(options.routes)
this.history.listen((to, from, info) => {
- // TODO: check navigation guards
const matchedRoute = this.matchLocation(to, this.currentRoute)
// console.log({ to, matchedRoute })
- // TODO: navigate
+ // TODO: navigate & guards
this.currentRoute = {
...to,
try {
await this.navigate(toLocation, this.currentRoute)
} catch (error) {
- if (error instanceof RedirectError) {
+ if (error instanceof NavigationGuardRedirect) {
// TODO: setup redirect stack
return this.push(error.to)
} else {
to: RouteLocationNormalized,
from: RouteLocationNormalized
): Promise<TODO> {
- // TODO: Will probably need to be some kind of queue in the future that allows to remove
- // elements and other stuff
let guards: Lazy<any>[]
// TODO: is it okay to resolve all matched component or should we do it in order
} from '../types'
import { isRouteLocation } from './index'
-import { RedirectError } from '../errors'
+import { NavigationGuardRedirect } from '../errors'
export function guardToPromiseFn(
guard: NavigationGuard,
// TODO: handle callback
if (valid === false) reject(new Error('Aborted'))
else if (isRouteLocation(valid)) {
- // TODO: redirect
- reject(new RedirectError(to, valid))
+ reject(new NavigationGuardRedirect(to, valid))
} else resolve()
}