UNPKG

@vortex-js/core

Version:

A simple and powerful role-based access control (RBAC) middleware for Express.js, designed to be easy to use and integrate with your existing applications. It provides a flexible way to manage user permissions and roles, making it ideal for building secur

191 lines (190 loc) 7.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const uuid_1 = require("uuid"); const errors_1 = require("../errors"); // eslint-disable-next-line @typescript-eslint/no-explicit-any class Route { constructor(r) { this.id = (0, uuid_1.v4)(); this.method = r.method; this.path = r.path; this.middlewares = r.middlewares; this.name = r.name ? r.name : `[${this.method}] ${this.path}`; this.description = r.description ? r.description : ""; this.rai = r.rai; this.roles = r.roles; this.postman = r.postman ? r.postman : { body: {}, params: [] }; /** * All the required fields must gevin * throw an error if not */ if (!this.method) { throw new errors_1.InvalidRouteError("Route instance must have a method"); } if (!this.path) { throw new errors_1.InvalidRouteError("Route instance must have a path"); } if (!this.rai) { throw new errors_1.InvalidRouteError("Route instance must have a rai"); } if (!this.roles) { throw new errors_1.InvalidRouteError("Route instance must have a roles"); } if (!Array.isArray(this.middlewares)) { throw new errors_1.InvalidRouteError("Route instance middlewares must be an array"); } } /** * This function is used to register a module to the route * so that we can use the module name in the route * and also to access the module config if needed */ registerModule(module) { this.module = module; /** * If the module has a name, we can set it to the route */ if (module.name) { this.name = `${module.name} - ${this.name}`; } } buildRoute(router, route, prefix) { /** * After Making sure that the route is an instance of Routes * we need : * - check if the route has any params if so we need to add them to the router * - call the buildRouter method of the Routes class */ if (route.params) { if (Array.isArray(route.params)) { route.params.forEach((param) => { if (param.path) { if (typeof param.method === "function") { /** * Make sure that the param.path dosn't ':' in the beginning */ if (param.path[0] === ":") { param.path = param.path.slice(1); } router.param(param.path, param.method); } else { throw new errors_1.InvalidRouteError(` INVALID params FIELD: params must have a method PREFIX: ${route.prefix} PARAM: [ ... { PATH: ${param.path}, METHOD: null } ... ] `); } } else { throw new errors_1.InvalidRouteError(` INVALID params FIELD: params must have a path PREFIX: ${route.prefix} `); } }); } else { throw new errors_1.InvalidRouteError(` INVALID params FIELD: params must be an array PREFIX: ${route.prefix} `); } } /** * We check that all the middlewares are valid function * and if not we throw an error */ this.middlewares.forEach((middleware) => { if (typeof middleware !== "function") { throw new errors_1.InvalidRouteError(` INVALID MIDDLEWARE FIELD: middleware must be a function PATH: ${prefix.path + this.path} METHOD: ${this.method} RESOURCE: ${this.rai} MIDDLEWARES: [${this.middlewares.map((m) => typeof m === "function" ? " function " : " null ")}] `); } }); /** * Here we can use the switch case to handle the routes * based on the method */ switch (this.method) { case "GET": router.get(prefix.path + this.path, ...this.middlewares); break; case "POST": router.post(prefix.path + this.path, ...this.middlewares); break; case "PUT": router.put(prefix.path + this.path, ...this.middlewares); break; case "DELETE": router.delete(prefix.path + this.path, ...this.middlewares); break; } } /** * This function is used to generate the route for postman collection (route = request) */ generateRoute(pathPrefix = "") { let fullPath = pathPrefix + this.path; // Extract all express's router parameters from the path // This is to replace the parameters with Postman's variable syntax // For example, if the path is "/users/:userId", it will be replaced with "/users/{{ userId }}" const expressRouterParamRegex = /:([a-zA-Z0-9_]+)/g; // Extract path parameters from the route path fullPath = fullPath.replace(expressRouterParamRegex, "{{ $1 }}"); // Remove trailing slashes from the path const urlParts = fullPath.split("?")[0]; // Create an array of path segments, filtering out empty segments // This is to ensure that the path is correctly formatted for Postman // and does not contain any empty segments that could cause issues const pathSegments = urlParts .split("/") .filter((segment) => segment !== ""); // Construct Postman URL object const postmanUrl = { raw: `{{base_url}}${urlParts}`, host: ["{{base_url}}"], path: pathSegments, }; // Add query parameters if (this.postman && this.postman.params && this.postman.params?.length > 0) { postmanUrl.query = this.postman.params.map((param) => ({ key: param.key, value: param.value, description: param.description || "", })); } // Construct request body let postmanBody = {}; if (["POST", "PUT", "PATCH"].includes(this.method.toUpperCase()) && this.postman?.body) { postmanBody = { mode: "raw", raw: JSON.stringify(this.postman.body, null, 2), options: { raw: { language: "json" } }, }; } return { name: this.name, request: { method: this.method.toUpperCase(), url: postmanUrl, description: this.description, body: postmanBody, }, }; } } exports.default = Route;