UNPKG

@dechamp/express-auto-route

Version:

An express auto route module which allows routes and middleware to be configured via config file.

124 lines (101 loc) 3.49 kB
import joi from "@hapi/joi"; import moduleImporter from "./moduleImporter"; import { RequestParamHandler } from "express"; export interface AutoRoutePropsConfigs { routeBasePath?: string; } export interface AutoRouteProps { server: any; callbackHandler: any; configs?: AutoRoutePropsConfigs; } export enum Methods { GET = "GET", POST = "POST", HEAD = "HEAD", PUT = "PUT", DELETE = "DELETE", USE = "USE", } export interface Route { id: string; method: Methods; path: string; modulePath: string; requestJsonSchema?: { body: string; }; responseJsonSchema?: string; middleware?: RequestParamHandler[]; } class AutoRoute<AutoRouteProps> { private readonly server: any; private readonly callbackHandler: any; private readonly configs?: AutoRoutePropsConfigs = {}; constructor(server, callbackHandler, configs) { this.server = server; this.callbackHandler = callbackHandler; this.configs = configs; } async mount(routes: Route[]): Promise<string[]> { this._guardParams(routes); return Promise.all(routes.map(async route => this._addRoute(route))); } _guardParams(routes) { joi.assert( routes, joi.array().items( joi.object({ id: joi.string().required(), method: joi.string() .regex(/^GET|POST|HEAD|PUT|DELETE|USE$/) .required(), path: joi.string().min(1).required(), modulePath: joi.string().min(1).required(), }).unknown(true), ).required(), ); } async _addRoute(route) { try { const {method, path, middleware = []} = route; const autoRouteCallback = await this._buildCallback(route); if (middleware.length) { const middlewareCallbacks: any[] = await this._buildMiddlewareCallbacks(middleware); this.server[method.toLowerCase()](path, ...middlewareCallbacks, ...autoRouteCallback); } else { this.server[method.toLowerCase()](path, ...autoRouteCallback); } return `${route.id}: mounted`; } catch (error) { return `${route.id} did not mount due to ${error.message}`; } } async _buildCallback(route) { let callbacks: ((req: any, res: any, next: any) => any)[] = []; if (this.callbackHandler) { callbacks = this.callbackHandler.buildCallback(route); } const {modulePath} = route; const callbackModule = await this._buildMiddlewareCallback(modulePath); if (callbackModule) { const callback = (req, res, next) => { req.config = { route, }; callbackModule(req, res, next); }; callbacks.push(callback); } return callbacks; } async _buildMiddlewareCallbacks(middlewares: string[]): Promise<any[]> { return Promise.all(middlewares.map(async middleware => this._buildMiddlewareCallback(middleware))); } async _buildMiddlewareCallback(middlewarePath: string): Promise<(req: any, res: any, next: () => any) => any> { return moduleImporter(middlewarePath, (this.configs && this.configs.routeBasePath)); } } export { AutoRoute };