UNPKG

@v4fire/client

Version:

V4Fire client core library

202 lines (154 loc) • 4.56 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ /** * This package provides a router engine that stores its state completely in memory * @packageDescription */ import { EventEmitter2 as EventEmitter } from 'eventemitter2'; import { deprecate } from 'core/functools/deprecation'; import { Route, Router, TransitionParams, HistoryClearFilter, getRoute } from 'core/router'; import type bRouter from 'base/b-router/b-router'; let historyLog: Route[] = [], historyLogPointer: CanUndef<number> = undefined; /** * Returns complete history log */ export function getHistory(): Route[] { return historyLog; } /** * Returns a position of the current history entry or `undefined` if the history is empty */ export function getCurrentHistoryEntryPointer(): CanUndef<number> { return historyLogPointer; } /** * Creates an in-memory engine for `bRouter` component * @param ctx */ export default function createRouter(ctx: bRouter): Router { const emitter = new EventEmitter({maxListeners: 1e3, newListener: false}); return Object.mixin<Router>({withAccessors: true}, Object.create(emitter), <Router>{ get route(): CanUndef<Route> { if (historyLogPointer !== undefined) { return historyLog[historyLogPointer]; } return undefined; }, get page(): CanUndef<Route> { deprecate({name: 'page', type: 'accessor', renamedTo: 'route'}); return this.route; }, get history(): Route[] { if (historyLogPointer === undefined) { return []; } return historyLog.slice(0, historyLogPointer + 1); }, id(page: string): string { return page; }, push(route: string, params?: TransitionParams): Promise<void> { let newRoute = getRoute(route, ctx.routes, {defaultRoute: ctx.defaultRoute}); if (newRoute == null) { return Promise.reject(); } newRoute = Object.mixin(true, {}, newRoute, params); if (historyLogPointer === undefined) { historyLog = [newRoute]; historyLogPointer = 0; } else if (historyLogPointer === historyLog.length - 1) { historyLog.push(newRoute); historyLogPointer++; } else { historyLog = historyLog.slice(0, historyLogPointer + 1); historyLog.push(newRoute); historyLogPointer++; } return Promise.resolve(); }, replace(route: string, params?: TransitionParams): Promise<void> { let newRoute = getRoute(route, ctx.routes, {defaultRoute: ctx.defaultRoute}); if (newRoute == null) { return Promise.reject(); } newRoute = Object.mixin(true, {}, newRoute, params); if (historyLogPointer === undefined) { historyLog = [newRoute]; historyLogPointer = 0; } else { historyLog[historyLogPointer] = newRoute; } return Promise.resolve(); }, go, forward(): void { return go(1); }, back(): void { return go(-1); }, clear(filterFn?: HistoryClearFilter): Promise<void> { return clear(filterFn); }, clearTmp(): Promise<void> { return clear( (route) => Object.isTruly(route.params.tmp) || Object.isTruly(route.query.tmp) || Object.isTruly(route.meta.tmp) ); } }); function clear(filterFn?: HistoryClearFilter): Promise<void> { if (filterFn == null) { historyLog = []; historyLogPointer = undefined; } else { const filter = (log: Route[]): Route[] => log.filter((item) => !Object.isTruly(filterFn(item))); if (historyLogPointer == null) { historyLog = filter(historyLog); } else { const backHistoryLog = filter(historyLog.slice(0, historyLogPointer + 1)), forwardHistoryLog = filter(historyLog.slice(historyLogPointer + 1)); historyLogPointer = backHistoryLog.length === 0 ? undefined : backHistoryLog.length - 1; historyLog = backHistoryLog.concat(forwardHistoryLog); } } if (historyLogPointer == null) { ctx.field.set('routeStore', undefined); ctx.r.route = undefined; } return Promise.resolve(); } function go(delta: number): void { const newHistoryLogPointer = (historyLogPointer ?? -1) + delta; if (newHistoryLogPointer < -1 || newHistoryLogPointer > historyLog.length - 1) { return; } historyLogPointer = newHistoryLogPointer === -1 ? undefined : newHistoryLogPointer; if (historyLogPointer !== undefined) { const route = historyLog[historyLogPointer]; ctx.emitTransition(route.name, route, 'event').catch(stderr); } else { ctx.field.set('routeStore', undefined); ctx.r.route = undefined; } } }