@tdsoft/express-routing-wrapper
Version:
Package gives you level of abstraction/wrapping of express router(s), endpoints and middlewares, additionally defining subrouters makes tree structure possible and easily discoverable by root router.
89 lines (74 loc) • 3.11 kB
JavaScript
const express = require("express");
const logger = console; // temporary
class ApiRouter {
constructor(basePath) {
this.basePath = basePath;
this.expressRouter = express.Router({mergeParams: true});
this.subRouters = [];
this.endpoints = {};
this.middlewares = [];
}
subRouter(apiRouter) {
this._passAccessCallback(apiRouter);
this.subRouters.push(apiRouter);
this.expressRouter.use(apiRouter.basePath, apiRouter.expressRouter);
}
use(middleware) {
this._passAccessCallback(middleware);
if (typeof middleware === "function") {
this.middlewares.push(middleware && middleware.name);
this.expressRouter.use(middleware)
} else {
this.middlewares.push(middleware);
this.expressRouter.use(middleware.expressFn.bind(middleware))
}
}
_passAccessCallback(routerMiddlewareEndpoint) {
const middlewareOrEndpoint = routerMiddlewareEndpoint.def;
if (this.accessCallback)
if (!middlewareOrEndpoint && !routerMiddlewareEndpoint.accessCallback
&& routerMiddlewareEndpoint.applyAccessCallback) {
routerMiddlewareEndpoint.applyAccessCallback(this.accessCallback);
}
else if (routerMiddlewareEndpoint.access && !routerMiddlewareEndpoint.access.cb) {
routerMiddlewareEndpoint.access.cb = this.accessCallback;
}
}
applyAccessCallback(callback) {
this.accessCallback = callback;
this.subRouters
.filter(router => !router.accessCallback)
.forEach(router => router.applyAccessCallback(this.accessCallback));
Object.keys(this.endpoints).forEach(eptKey => {
if (!this.endpoints[eptKey].def.access.cb) this.endpoints[eptKey].def.access.cb = this.accessCallback;
});
}
_addEndpoint(method = "GET", path, apiEndpoint) {
this._passAccessCallback(apiEndpoint);
const methodLower = method.toLowerCase();
this.endpoints[`${path}/${method}`] = apiEndpoint;
apiEndpoint.method = method;
return this.expressRouter[methodLower](path, apiEndpoint.expressFn.bind(apiEndpoint));
}
get(path, apiEndpoint, expressCb) {
if (expressCb) apiEndpoint.cb = expressCb;
return this._addEndpoint("GET", path, apiEndpoint)
}
post(path, apiEndpoint, expressCb) {
if (expressCb) apiEndpoint.cb = expressCb;
return this._addEndpoint("POST", path, apiEndpoint)
}
put(path, apiEndpoint, expressCb) {
if (expressCb) apiEndpoint.cb = expressCb;
return this._addEndpoint("PUT", path, apiEndpoint)
}
delete(path, apiEndpoint, expressCb) {
if (expressCb) apiEndpoint.cb = expressCb;
return this._addEndpoint("DELETE", path, apiEndpoint)
}
param(paramName, paramCb) {
// TODO: Additional stuff for docummentaton? How to handle it properly?
return this.expressRouter.param(paramName, paramCb);
}
}
module.exports = ApiRouter;