UNPKG

expresser

Version:

A ready to use Node.js web app wrapper, built on top of Express.

192 lines (191 loc) 7.56 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Routes = void 0; const app_1 = __importDefault(require("./app")); const fs = require("fs"); const jaul = require("jaul"); const logger = require("anyhow"); const settings = require("setmeup").settings; class Routes { static _instance; static get Instance() { return this._instance || (this._instance = new this()); } load = (options) => { let specs; if (!options || !options.handlers) { throw new Error(`Missing options.handlers with the routing functions`); } logger.debug("Routes.load", options.filename, Object.keys(options.handlers)); if (options.specs) { specs = options.specs; } else { if (options.filename == null || options.filename == "") { options.filename = settings.routes.filename; } try { const filename = jaul.io.getFilePath(options.filename); if (filename == null || !fs.existsSync(filename)) { throw new Error(`File ${options.filename} not found.`); } specs = fs.readFileSync(filename, { encoding: settings.general.encoding }).toString(); specs = JSON.parse(specs); } catch (ex) { logger.error("Routes.load", options.filename, ex); throw ex; } } for (let [route, spec] of Object.entries(specs)) { if (typeof spec == "string") { spec = { get: spec }; } for (let [method, handlerKey] of Object.entries(spec)) { const handler = options.handlers[handlerKey]; if (app_1.default[method] == null) { logger.error("Routes.load", options.filename, route, `Invalid method: ${method}`); throw new Error(`Invalid method: ${method}`); } else if (handler == null) { logger.error("Routes.load", options.filename, route, `Invalid handler: ${handlerKey}`); throw new Error(`Invalid handler: ${handlerKey}`); } else { app_1.default[method](route, handler); logger.info("Routes.load", options.filename, route, method, handlerKey); } } } }; loadSwagger = (options) => { let specs; if (!options || !options.handlers) { throw new Error(`Missing options.handlers with the routing functions`); } logger.debug("Routes.loadSwagger", options.filename, Object.keys(options.handlers)); if (options.specs) { specs = options.specs; } else { if (options.filename == null || options.filename == "") { options.filename = settings.routes.swagger.filename; } try { const filename = jaul.io.getFilePath(options.filename); if (filename == null || !fs.existsSync(filename)) { throw new Error(`File ${options.filename} not found.`); } specs = fs.readFileSync(filename, { encoding: settings.general.encoding }).toString(); specs = JSON.parse(specs); } catch (ex) { logger.error("Routes.loadSwagger", options.filename, ex); throw ex; } } if (options.version != null) { specs.info.version = options.version; } for (let [path, pathSpec] of Object.entries(specs.paths)) { path = path.toString().replace(/\/{/g, "/:"); path = path.replace(/\}/g, ""); for (let [method, methodSpec] of Object.entries(pathSpec)) { if (methodSpec == null) { throw new Error(`Missing method spec for ${method} ${path}`); } if (options.handlers[methodSpec.operationId] == null) { throw new Error(`Missing route handler for ${methodSpec.operationId}`); } if (methodSpec.parameters == null) { methodSpec.parameters = []; } logger.info("Routes.loadSwagger", options.filename, method, path, methodSpec.operationId); app_1.default[method](path, (req, res, next) => { try { if (!req.swagger) { req.swagger = {}; } for (let parameterSpec of methodSpec.parameters) { this.castParameter(req, parameterSpec); } options.handlers[methodSpec.operationId](req, res, next); } catch (ex) { logger.error("Routes", method, path, methodSpec.operationId, ex); } }); } } if (settings.routes.swagger.exposeJson) { app_1.default.get("/swagger.json", (_req, res) => res.json(specs)); } }; castParameter = function (req, spec) { try { const { name } = spec; let scope, separator; switch (spec.in) { case "query": scope = "query"; break; case "header": scope = "header"; break; case "path": scope = "params"; break; } if (scope == null) { return; } req.swagger[scope] = req.swagger[scope] || {}; const param = req[scope][name]; if (param == null) { return; } if (spec.type == "string") { if (spec.format == "date" || spec.format == "datetime" || spec.format == "date-time") { req.swagger[scope][name] = new Date(param); } else { req.swagger[scope][name] = param; } } else if (spec.type == "number") { req.swagger[scope][name] = parseFloat(param); } else if (spec.type == "integer") { req.swagger[scope][name] = parseInt(param); } else if (spec.type == "boolean") { req.swagger[scope][name] = param; } else if (spec.type == "array") { switch (spec.collectionFormat) { case "csv": separator = ","; break; case "ssv": separator = " "; break; case "pipes": separator = "|"; break; } if (separator == null) { return; } req.swagger[scope][name] = param.split(separator); } } catch (ex) { logger.error("Routes.castParameter", spec, ex); } }; } exports.Routes = Routes; exports.default = Routes.Instance;