140 lines
18 KiB
JavaScript
140 lines
18 KiB
JavaScript
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
|
});
|
||
|
};
|
||
|
import express from 'express';
|
||
|
import { BadRequestError, HttpError, NotFoundHttpError, ServerError, ServiceUnavailableHttpError } from "./HttpError";
|
||
|
import { lib } from "nunjucks";
|
||
|
import Logger from "./Logger";
|
||
|
import WebSocketListener from "./WebSocketListener";
|
||
|
var TemplateError = lib.TemplateError;
|
||
|
import Controller from "./Controller";
|
||
|
export default class Application {
|
||
|
constructor(version) {
|
||
|
this.controllers = [];
|
||
|
this.webSocketListeners = {};
|
||
|
this.components = [];
|
||
|
this.ready = false;
|
||
|
this.version = version;
|
||
|
}
|
||
|
use(thing) {
|
||
|
if (thing instanceof Controller) {
|
||
|
this.controllers.push(thing);
|
||
|
}
|
||
|
else if (thing instanceof WebSocketListener) {
|
||
|
const path = thing.path();
|
||
|
this.webSocketListeners[path] = thing;
|
||
|
Logger.info(`Added websocket listener on ${path}`);
|
||
|
}
|
||
|
else {
|
||
|
this.components.push(thing);
|
||
|
}
|
||
|
}
|
||
|
start() {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
Logger.info(`${this.constructor.name} v${this.version} - hi`);
|
||
|
process.once('SIGINT', () => {
|
||
|
this.stop().catch(console.error);
|
||
|
});
|
||
|
// Register all components and alike
|
||
|
yield this.init();
|
||
|
// Init express
|
||
|
const app = express();
|
||
|
const router = express.Router({});
|
||
|
app.use(router);
|
||
|
// Error handler
|
||
|
app.use((err, req, res, next) => {
|
||
|
if (res.headersSent) {
|
||
|
return next(err);
|
||
|
}
|
||
|
let errorID;
|
||
|
let logStr = `${req.method} ${req.originalUrl} - `;
|
||
|
if (err instanceof BadRequestError || err instanceof ServiceUnavailableHttpError) {
|
||
|
logStr += `${err.errorCode} ${err.name}`;
|
||
|
errorID = Logger.silentError(err, logStr);
|
||
|
}
|
||
|
else {
|
||
|
errorID = Logger.error(err, logStr + `500 Internal Error`, err);
|
||
|
}
|
||
|
let httpError;
|
||
|
if (err instanceof HttpError) {
|
||
|
httpError = err;
|
||
|
}
|
||
|
else if (err instanceof TemplateError && err.cause instanceof HttpError) {
|
||
|
httpError = err.cause;
|
||
|
}
|
||
|
else {
|
||
|
httpError = new ServerError('Internal server error.', err);
|
||
|
}
|
||
|
res.status(httpError.errorCode);
|
||
|
res.format({
|
||
|
html: () => {
|
||
|
res.render('errors/' + httpError.errorCode + '.njk', {
|
||
|
error_code: httpError.errorCode,
|
||
|
error_message: httpError.message,
|
||
|
error_instructions: httpError.instructions,
|
||
|
error_id: errorID,
|
||
|
});
|
||
|
},
|
||
|
json: () => {
|
||
|
res.json({
|
||
|
status: 'error',
|
||
|
code: httpError.errorCode,
|
||
|
message: httpError.message,
|
||
|
instructions: httpError.instructions,
|
||
|
error_id: errorID,
|
||
|
});
|
||
|
},
|
||
|
default: () => {
|
||
|
res.type('txt').send(`${httpError.errorCode} - ${httpError.message}\n\n${httpError.instructions}\n\nError ID: ${errorID}`);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
// Start all components
|
||
|
for (const component of this.components) {
|
||
|
yield component.start(app, router);
|
||
|
}
|
||
|
// Routes
|
||
|
this.routes(router);
|
||
|
this.ready = true;
|
||
|
});
|
||
|
}
|
||
|
stop() {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
Logger.info('Stopping application...');
|
||
|
for (const component of this.components) {
|
||
|
yield component.stop();
|
||
|
}
|
||
|
Logger.info(`${this.constructor.name} v${this.version} - bye`);
|
||
|
});
|
||
|
}
|
||
|
routes(rootRouter) {
|
||
|
for (const controller of this.controllers) {
|
||
|
if (controller.hasGlobalHandlers()) {
|
||
|
controller.setupGlobalHandlers(rootRouter);
|
||
|
Logger.info(`Registered global middlewares for controller ${controller.constructor.name}`);
|
||
|
}
|
||
|
}
|
||
|
for (const controller of this.controllers) {
|
||
|
const router = express.Router();
|
||
|
controller.setupRoutes(router);
|
||
|
rootRouter.use(controller.getRoutesPrefix(), router);
|
||
|
Logger.info(`> Registered routes for controller ${controller.constructor.name}`);
|
||
|
}
|
||
|
rootRouter.use((req) => {
|
||
|
throw new NotFoundHttpError('page', req.originalUrl);
|
||
|
});
|
||
|
}
|
||
|
getWebSocketListeners() {
|
||
|
return this.webSocketListeners;
|
||
|
}
|
||
|
isReady() {
|
||
|
return this.ready;
|
||
|
}
|
||
|
}
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXBwbGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbIkFwcGxpY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sT0FBa0QsTUFBTSxTQUFTLENBQUM7QUFDekUsT0FBTyxFQUNILGVBQWUsRUFDZixTQUFTLEVBQ1QsaUJBQWlCLEVBQ2pCLFdBQVcsRUFDWCwyQkFBMkIsRUFDOUIsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFDLEdBQUcsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUM3QixPQUFPLE1BQU0sTUFBTSxVQUFVLENBQUM7QUFDOUIsT0FBTyxpQkFBaUIsTUFBTSxxQkFBcUIsQ0FBQztBQUVwRCxJQUFPLGFBQWEsR0FBRyxHQUFHLENBQUMsYUFBYSxDQUFDO0FBQ3pDLE9BQU8sVUFBVSxNQUFNLGNBQWMsQ0FBQztBQUV0QyxNQUFNLENBQUMsT0FBTyxPQUFnQixXQUFXO0lBUXJDLFlBQXNCLE9BQWU7UUFOcEIsZ0JBQVcsR0FBaUIsRUFBRSxDQUFDO1FBQy9CLHVCQUFrQixHQUF1QyxFQUFFLENBQUM7UUFDNUQsZUFBVSxHQUFnQyxFQUFFLENBQUM7UUFFdEQsVUFBSyxHQUFZLEtBQUssQ0FBQztRQUczQixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztJQUMzQixDQUFDO0lBSVMsR0FBRyxDQUFDLEtBQWlFO1FBQzNFLElBQUksS0FBSyxZQUFZLFVBQVUsRUFBRTtZQUM3QixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUNoQzthQUFNLElBQUksS0FBSyxZQUFZLGlCQUFpQixFQUFFO1lBQzNDLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO1lBQ3RDLE1BQU0sQ0FBQyxJQUFJLENBQUMsK0JBQStCLElBQUksRUFB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
|