UNPKG

universal-router

Version:

Isomorphic router for JavaScript web applications

161 lines (160 loc) 6.13 kB
"use strict"; /** * Universal Router (https://www.kriasoft.com/universal-router/) * * Copyright (c) 2015-present Kriasoft. * * This source code is licensed under the MIT license found in the * LICENSE.txt file in the root directory of this source tree. */ var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var path_to_regexp_js_1 = require("./path-to-regexp.js"); function decode(val) { try { return decodeURIComponent(val); } catch (_a) { return val; } } function matchRoute(route, baseUrl, options, pathname, parentParams) { var matchResult; var childMatches; var childIndex = 0; return { next: function (routeToSkip) { if (route === routeToSkip) { return { done: true, value: false }; } if (!matchResult) { var rt = route; var end = !rt.children; if (!rt.match) { rt.match = (0, path_to_regexp_js_1.match)(rt.path || '', __assign({ end: end }, options)); } matchResult = rt.match(pathname); if (matchResult) { var path = matchResult.path; matchResult.path = !end && path.charAt(path.length - 1) === '/' ? path.substr(1) : path; matchResult.params = __assign(__assign({}, parentParams), matchResult.params); return { done: false, value: { route: route, baseUrl: baseUrl, path: matchResult.path, params: matchResult.params, }, }; } } if (matchResult && route.children) { while (childIndex < route.children.length) { if (!childMatches) { var childRoute = route.children[childIndex]; childRoute.parent = route; childMatches = matchRoute(childRoute, baseUrl + matchResult.path, options, pathname.substr(matchResult.path.length), matchResult.params); } var childMatch = childMatches.next(routeToSkip); if (!childMatch.done) { return { done: false, value: childMatch.value }; } childMatches = null; childIndex++; } } return { done: true, value: false }; }, }; } function resolveRoute(context, params) { if (typeof context.route.action === 'function') { return context.route.action(context, params); } return undefined; } function isChildRoute(parentRoute, childRoute) { var route = childRoute; while (route) { route = route.parent; if (route === parentRoute) { return true; } } return false; } var UniversalRouterSync = /** @class */ (function () { function UniversalRouterSync(routes, options) { if (!routes || typeof routes !== 'object') { throw new TypeError('Invalid routes'); } this.options = __assign({ decode: decode }, options); this.baseUrl = this.options.baseUrl || ''; this.root = Array.isArray(routes) ? { path: '', children: routes, parent: null } : routes; this.root.parent = null; } /** * Traverses the list of routes in the order they are defined until it finds * the first route that matches provided URL path string and whose action function * returns anything other than `null` or `undefined`. */ UniversalRouterSync.prototype.resolve = function (pathnameOrContext) { var context = __assign(__assign({ router: this }, this.options.context), (typeof pathnameOrContext === 'string' ? { pathname: pathnameOrContext } : pathnameOrContext)); var matchResult = matchRoute(this.root, this.baseUrl, this.options, context.pathname.substr(this.baseUrl.length)); var resolve = this.options.resolveRoute || resolveRoute; var matches; var nextMatches; var currentContext = context; function next(resume, parent, prevResult) { if (parent === void 0) { parent = !matches.done && matches.value.route; } var routeToSkip = prevResult === null && !matches.done && matches.value.route; matches = nextMatches || matchResult.next(routeToSkip); nextMatches = null; if (!resume) { if (matches.done || !isChildRoute(parent, matches.value.route)) { nextMatches = matches; return null; } } if (matches.done) { var error = new Error('Route not found'); error.status = 404; throw error; } currentContext = __assign(__assign({}, context), matches.value); var result = resolve(currentContext, matches.value.params); if (result !== null && result !== undefined) { return result; } return next(resume, parent, result); } context['next'] = next; try { return next(true, this.root); } catch (error) { if (this.options.errorHandler) { return this.options.errorHandler(error, currentContext); } throw error; } }; return UniversalRouterSync; }()); exports.default = UniversalRouterSync;