UNPKG

neweb

Version:

[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Coverage percentage][coveralls-image]][coveralls-url] [![experimental](http://badges.github.io/stability-badges/dist/ex

92 lines (88 loc) 3.23 kB
import o, { Onemitter } from "onemitter"; import { parse } from "url"; import { IApplication, IRequest, IRoute, IRoutePage, IRoutePageFrame, IRouter, } from "./../typings"; export interface IFramesBasedRouter { app: IApplication; } class FramesBasedRouter implements IRouter { protected basePath = "/"; protected routeEmitter: Onemitter<IRoute>; constructor(protected config: IFramesBasedRouter) { this.routeEmitter = o(); } public async navigate({ request }: { request: IRequest; }) { try { const page = await this.resolvePage({ url: request.url }); this.routeEmitter.emit({ type: "page", page, }); } catch (e) { this.routeEmitter.emit({ type: "notFound", text: e.toString(), }); } } public onNewRoute(cb: (route: IRoute) => void) { this.routeEmitter.addListener(cb); } public waitRoute() { return this.routeEmitter.wait(); } public dispose() { this.routeEmitter.removeAllListeners(); } protected async resolvePage({ url: rawUrl }: { url: string; }): Promise<IRoutePage> { const url = parse(rawUrl); if (!url.pathname) { throw new Error("Url should contain path: " + url); } const pathname = this.basePath ? url.pathname.substr(this.basePath.length) : url.pathname; const framesNames = pathname.split("_").map((frameName) => frameName || "index"); const isExistings = (await Promise.all(framesNames.map((frameName) => this.config.app.hasFrame(frameName)))); for (const [index, isExisting] of isExistings.entries()) { if (!isExisting) { throw new Error("Not found frame " + framesNames[index]); } } const params = url.query ? this.parseParams(url.query) : []; const page: IRoutePage = { url: rawUrl, rootFrame: this.getPageRouteFrame(framesNames, params), }; return page; } protected getPageRouteFrame(framesNames: string[], params: any[], index = 0): IRoutePageFrame { return { name: framesNames[index], params: params[index], frames: framesNames[index + 1] ? { children: this.getPageRouteFrame(framesNames, params, index + 1), } : {}, }; } protected parseParams(query: string) { const queryParams = query.split("&"); const params: Array<{ [index: string]: string }> = []; for (const param of queryParams) { const [paramFullName, paramValue] = param.split("="); const [frameShortName, paramName] = paramFullName.split("_"); const frameNumber = parseInt(frameShortName.substr(1), 10); if (!params[frameNumber]) { params[frameNumber] = {}; } params[frameNumber][paramName] = decodeURIComponent(paramValue); } return params; } } export default FramesBasedRouter;