UNPKG

@nasriya/hypercloud

Version:

Nasriya HyperCloud is a lightweight Node.js HTTP2 framework.

166 lines (165 loc) 7.11 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const route_1 = __importDefault(require("./assets/route")); const staticRoute_1 = __importDefault(require("./assets/staticRoute")); class RoutesManager { #_stack = { routes: [], static: [], all: [] }; #_utils = Object.freeze({ match: { subDomain: (subDomain, route) => { if (route.subDomain === '*') { return true; } if (route.caseSensitive) { return route.subDomain === subDomain; } else { return route.subDomain.toLowerCase() === subDomain.toLowerCase(); } }, routePath: (path, route) => { const response = { valid: false, hasParams: false, params: {} }; if (route.path[0] === '*') { response.valid = true; return response; } if (route.path.length !== path.length) { return response; } for (let i = 0; i < path.length; i++) { const reqPath = path[i]; const routePath = route.path[i]; const paramsRegex = /<:.*?>/g; const matches = [...routePath.matchAll(paramsRegex)].flat(); if (matches.length > 0) { response.hasParams = true; let rtPath = routePath; let rqPath = reqPath; for (let i = 0; i < matches.length; i++) { const match = matches[i]; const param = match.substring(2, match.length - 1); rtPath = rtPath.replace(match, ''); // Next param const nxtParam = matches[i + 1]; if (nxtParam) { /** * If there's another parameter, determine the separator based * on the starting index of the next parameter */ /** * The separator is a string that starts from the beginning * and ends at the starting index of the next parameter */ const separator = rtPath.substring(0, rtPath.indexOf(nxtParam)); const sepIndex = rqPath.indexOf(separator); if (sepIndex > -1) { // If the separator is present in the request path, extract the value from it then remove it from the `rqPath`. const value = rqPath.substring(0, sepIndex); rqPath = rqPath.replace(value, '').replace(separator, ''); response.params[param] = value; } else { // If the separator doesn't exist in the request path, this means the request doesn't match the route's criteria return response; } } else { // If no additional parameters available, assign the rest of the path as a value response.params[param] = rqPath; } } } else { if (route.caseSensitive) { if (reqPath !== routePath) { return response; } } else { if (reqPath.toLowerCase() !== routePath.toLowerCase()) { return response; } } } } response.valid = true; return response; }, staticPath: (path, route) => { if (path.length === 0 || path.length < route.path.length) { return false; } if (route.path.length === 0) { return true; } if (route.path.length > 0) { const reqPath = path.join('/'); const routePath = route.path.join('/'); if (route.caseSensitive) { return reqPath.startsWith(routePath); } else { return reqPath.toLowerCase().startsWith(routePath.toLowerCase()); } } } } }); /**Add a route to the stack */ add(route) { if (route instanceof route_1.default || route instanceof staticRoute_1.default) { if (route instanceof route_1.default) { this.#_stack.routes.push(route); } if (route instanceof staticRoute_1.default) { this.#_stack.static.push(route); } this.#_stack.all = [...this.#_stack.static, ...this.#_stack.routes]; } else { throw new TypeError(`Unable to add route to the routes stack: The provided route is not an instance of Route.`); } } /** * Use an incoming {@link HyperCloudRequest} to get all matching routes * @param {HyperCloudRequest} request * @returns {(Route|StaticRoute)[]} */ match(request) { const subDomain = request.subDomain || '*'; const path = request.path || []; return this.#_stack.all.filter(route => { if (route.method !== 'USE' && route.method !== request.method) { return false; } if (!this.#_utils.match.subDomain(subDomain, route)) { return false; } if (route instanceof route_1.default) { const pathRes = this.#_utils.match.routePath(path, route); if (pathRes.valid) { if (pathRes.hasParams) { route.params = pathRes.params; } } else { return false; } } if (route instanceof staticRoute_1.default) { if (!this.#_utils.match.staticPath(path, route)) { return false; } } return true; }); } } exports.default = RoutesManager;