tachijs
Version:
Highly testable dead simple web server written in Typescript
120 lines • 4.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const express_1 = tslib_1.__importDefault(require("express"));
const decorators_1 = require("./decorators");
const BaseController_1 = require("./BaseController");
const results_1 = require("./results");
const Injector_1 = require("./Injector");
function tachijs(options) {
const { app = express_1.default(), controllers = [], container = {}, before, after } = options;
return new TachiJSApp(app, controllers, container, before, after).build();
}
exports.tachijs = tachijs;
class TachiJSApp {
constructor(app, controllers, container, before, after) {
this.app = app;
this.controllers = controllers;
this.container = container;
this.before = before;
this.after = after;
this.injector = new Injector_1.Injector(container);
}
build() {
const { app, before, after, controllers } = this;
if (before != null)
before(app);
controllers.map(ControllerConstructor => {
const controllerMeta = decorators_1.getControllerMeta(ControllerConstructor);
if (controllerMeta == null)
throw new Error(`Please apply @controller decorator to "${ControllerConstructor.name}".`);
const router = express_1.default.Router(controllerMeta.routerOptions);
this.bindControllerRoutes(router, ControllerConstructor, controllerMeta);
app.use(controllerMeta.path, router);
});
if (after != null)
after(app);
return app;
}
bindControllerRoutes(router, ControllerConstructor, controllerMeta) {
const methodList = decorators_1.getHttpMethodMetaList(ControllerConstructor);
methodList.map(methodMeta => {
const handler = this.makeRequestHandler(ControllerConstructor, methodMeta);
this.bindHandler(router, controllerMeta, methodMeta, handler);
});
}
makeRequestHandler(ControllerConstructor, methodMeta) {
return async (req, res, next) => {
try {
const controller = this.injector.instantiate(ControllerConstructor);
if (controller instanceof BaseController_1.BaseController) {
controller.context = {
req,
res,
inject: (key) => {
return this.injector.inject(key);
}
};
}
const method = controller[methodMeta.propertyKey];
const paramMetaList = decorators_1.getHandlerParamMetaList(controller.constructor, methodMeta.propertyKey);
const args = [];
await Promise.all(paramMetaList.map(async (paramMeta) => {
args[paramMeta.index] = await paramMeta.selector(req, res, next, paramMeta);
}));
const result = await method.bind(controller)(...args);
if (result instanceof results_1.BaseResult) {
await result.execute(req, res, next);
return;
}
if (!res.finished) {
res.send(result);
}
return;
}
catch (error) {
next(error);
return;
}
};
}
bindHandler(router, controllerMeta, methodMeta, handler) {
const before = [
...(controllerMeta.middleware.before || []),
...(methodMeta.middleware.before || [])
];
const after = [
...(methodMeta.middleware.after || []),
...(controllerMeta.middleware.after || [])
];
switch (methodMeta.method) {
case 'get':
router.get(methodMeta.path, ...before, handler, ...after);
break;
case 'post':
router.post(methodMeta.path, ...before, handler, ...after);
break;
case 'put':
router.put(methodMeta.path, ...before, handler, ...after);
break;
case 'patch':
router.patch(methodMeta.path, ...before, handler, ...after);
break;
case 'delete':
router.delete(methodMeta.path, ...before, handler, ...after);
break;
case 'options':
router.options(methodMeta.path, ...before, handler, ...after);
break;
case 'head':
router.head(methodMeta.path, ...before, handler, ...after);
break;
case 'all':
router.all(methodMeta.path, ...before, handler, ...after);
break;
default:
throw new Error(`"${methodMeta.method}" is not a valid method.`);
}
}
}
//# sourceMappingURL=tachijs.js.map