neura-express-app
Version:
Basic express application starter with some common utilities.
125 lines (124 loc) • 4.91 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NeuraApp = void 0;
const http_1 = __importDefault(require("http"));
const express_1 = __importDefault(require("express"));
const http_terminator_1 = require("http-terminator");
const app_error_1 = require("./errors/app.error");
const api_error_1 = require("./errors/api.error");
const express_2 = __importDefault(require("express"));
const cookie_parser_1 = __importDefault(require("cookie-parser"));
class NeuraApp {
constructor(config, container) {
this.config = config;
this.container = container;
this.started = false;
this.middlewaresInitialized = false;
this.app = (0, express_1.default)();
this.httpServer = new http_1.default.Server(this.app);
const logger = container.get("logger");
if (!logger) {
throw new app_error_1.NeuraAppError("logger-not-defined", "Can't find logger in container!", false);
}
this.logger = logger;
this.httpTerminator = (0, http_terminator_1.createHttpTerminator)({
server: this.httpServer,
});
}
get HttpServer() {
return this.httpServer;
}
get ExpressApp() {
return this.app;
}
addController(instance) {
if (!this.middlewaresInitialized) {
if (this.config.bodyParserEnabled) {
this.addMiddleware((0, cookie_parser_1.default)());
this.addMiddleware(express_2.default.json());
this.addMiddleware(express_2.default.urlencoded({ extended: false }));
}
if (this.config.logHttpRequests) {
this.app.use((req, _res, next) => {
this.logger.info(`[App]: New request`, {
method: req.method,
url: req.url,
body: req.body,
query: req.query,
});
next();
});
}
this.middlewaresInitialized = true;
}
const routePrefix = instance.getRouterPrefix();
const router = instance.getRouter();
const constructorName = instance?.constructor?.name;
if (routePrefix) {
this.app.use(routePrefix, router);
this.logger.debug(`[App]: Controller added: ${constructorName} on base url: ${routePrefix}`);
return;
}
this.logger.debug(`[App]: Controller added: ${constructorName}`);
this.app.use(router);
}
addMiddleware(handler) {
this.logger.debug(`[App]: Middleware added: ${handler.name}`);
this.app.use(handler);
}
listen() {
// Make sure application was not already started
if (this.started) {
throw new app_error_1.NeuraAppError("app-started-multiple-times", "Application was already started", false);
}
// If route was not found, handle it
this.app.use((req, _res) => {
throw new api_error_1.NotFoundError(`HTTP Not found: ${req.method} on ${req.url}`);
});
// If error was thrown, handle it
this.app.use((error, req, res, _next) => {
this.logger.warn("ErrorMiddleware: API error occurs", error);
// Handle validation errors
if (error instanceof api_error_1.ValidationRequestError) {
return res.status(error.status).send({
code: error.status,
error: error.message,
data: error.data,
});
}
// Handle other API errors
if (error instanceof api_error_1.NeuraAPIError) {
return res.status(error.status).send({
code: error.status,
error: error.message,
});
}
// Unknown error, return 500
return res.status(500).send({
code: 500,
message: "Something went wrong!",
});
});
return new Promise((res, _rej) => {
this.httpServer.listen(this.config.port, () => {
this.started = true;
this.httpServer.on("close", () => {
this.logger.info(`[HttpServer]: Closed`);
});
this.logger.info(`[HttpServer]: Listening at http://localhost:${this.config.port}`);
res();
});
});
}
async close() {
if (this.started) {
// HttpTerminator will terminate all pending connections
await this.httpTerminator.terminate();
}
this.logger.info("[Application]: Closed");
}
}
exports.NeuraApp = NeuraApp;