@eolme/vma-router
Version:
Router for VK Mini Apps
164 lines (131 loc) • 3.21 kB
text/typescript
import { error } from '../utils/report';
import type {
Page,
View,
Panel,
Modal,
Popout,
RouteLike,
RouteParams,
Structure,
RouteList
} from '../types';
import { buildPage, matchPage, parsePath, MatchedPath } from '../utils/route';
import hasOwn from '../utils/hasOwn';
export const VIEW_MAIN = 'view_main';
export const PANEL_MAIN = 'panel_main';
export const PAGE_MAIN = '/';
class Route {
private static _next: number = 0;
readonly id: number;
uri: string;
page: Page;
view: View;
panel: Panel;
history: Structure[];
modal: Modal;
get hasModal() {
return typeof this.modal === 'string';
}
popout: Popout;
get hasPopout() {
return typeof this.popout === 'string';
}
get hasOverlay() {
return this.hasModal || this.hasPopout;
}
private _params: RouteParams = {};
get params(): Readonly<RouteParams> {
return this._params;
}
set params(value) {
this._params = {
...this._params,
...value
};
}
index: number = -1;
constructor(
panel: Panel = PANEL_MAIN,
view: View = VIEW_MAIN,
modal: Modal = null,
popout: Popout = null,
params: RouteParams = {}
) {
this.id = Route._next++;
this.panel = panel;
this.view = view;
this.modal = modal;
this.popout = popout;
this.params = params;
}
clone() {
return new Route(
this.panel,
this.view,
this.modal,
this.popout,
this.params
);
}
isSameWith(route: RouteLike) {
return (
this.panel === route.panel &&
this.view === route.view &&
this.modal === route.modal &&
this.popout === route.popout
);
}
compile(page: Page) {
this.page = page;
this.uri = buildPage(page, this.params);
}
static buildFromLocation(routeList: RouteList, path: string) {
const parsedPath = parsePath(path);
let match: MatchedPath = null;
const page = Object.keys(routeList).find((page: Page) => {
match = matchPage(page, parsedPath.url);
return match && match.exact;
});
if (!match) {
error('Builder cant find route for ' + path);
}
const route = routeList[page];
if (!route) {
error('Builder cant find route for ' + path);
}
const build = route.clone();
build.params = match.params;
build.compile(page);
return build;
}
static buildFromPage(routeList: RouteList, page: Page, params: RouteParams = {}) {
const route = routeList[page];
if (!route) {
error('Builder cant find route for ' + page);
}
const build = route.clone();
build.params = params;
build.compile(page);
return build;
}
static buildFromState(routeList: RouteList, state: RouteLike) {
if (!state.page) {
error('Builder cant resolve page for ' + state);
}
const route = routeList[state.page];
if (!route) {
error('Builder cant find route for ' + state.page);
}
const build = route.clone();
Object.keys(state).forEach((key) => {
if (hasOwn(build, key)) {
build[key] = route[key];
}
});
build.compile(state.page);
return build;
}
}
export { Route };
export default Route;