123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- import express, {Express} from 'express';
- import { Middleware, Route, HttpMethod, HttpHandler } from '../base/http';
- import { RouteNotSetException } from '../base/exceptions';
- import { IncorrectMethodException } from '../base/exceptions';
- import { Logger, Message, MessageTypes } from '../base/logger';
- import { ServerProperties } from './ServerProperties';
- import { i18nLoader, $$ } from '../base/i18n';
- import path from 'path';
- import fs from 'fs';
- import { InvalidMiddlewareException } from '../base/exceptions';
- import { InvalidRouteException } from '../base/exceptions';
- import { ServerNotInitializedException } from '../base/exceptions';
- /** @sealed */
- class Server {
- private instance: Express;
- private readonly port: number;
- private readonly logger: Logger;
- private i18n: i18nLoader;
- public static readonly i18nDefaultPath = '../resources/i18n.json';
- public static readonly defaultMiddlewaresPath = '../middlewares';
- public static readonly defaultRoutesPath = '../routes';
- private readonly httpHandlers: {[key: string]: HttpHandler};
- private initialized: boolean;
- private readonly i18nPath?: string;
- private readonly middlewaresPath?: string;
- private readonly routesPath?: string;
- private readonly viewEngine?: string;
- private readonly viewsPath?: string;
- private readonly options?: {[key: string]: any};
- public constructor(properties: ServerProperties) {
- this.instance = express();
- this.port = properties.port;
- this.i18n = i18nLoader.getInstance();
- if(properties.locale)
- this.i18n.setLocale(properties.locale);
- this.logger = new Logger();
- this.httpHandlers = {};
- this.i18nPath = properties.i18nPath;
- this.middlewaresPath = properties.middlewaresPath;
- this.routesPath = properties.routesPath;
- this.viewEngine = properties.viewEngine;
- this.viewsPath = properties.viewsPath;
- this.options = properties.options;
- this.initialized = false;
- }
- public async init(): Promise<Server> {
- if(this.viewEngine)
- this.instance.set('view engine', this.viewEngine);
- if(this.viewsPath)
- this.instance.set('views', this.viewsPath);
- this.i18n.load(path.resolve(__dirname, Server.i18nDefaultPath));
- await this.registerMiddlewares(path.resolve(__dirname, Server.defaultMiddlewaresPath));
- await this.registerRoutes(path.resolve(__dirname, Server.defaultRoutesPath));
- await this.postInit();
- this.initialized = true;
- return this;
- }
- private async postInit(): Promise<void> {
- if(this.i18nPath)
- this.i18n.load(this.i18nPath);
- if(this.middlewaresPath)
- await this.registerMiddlewares(this.middlewaresPath);
- if(this.routesPath)
- await this.registerRoutes(this.routesPath);
- }
- private processHttpHandlers(): void {
- const handlers: HttpHandler[] = [];
- for(const key in this.httpHandlers)
- handlers.push(this.httpHandlers[key]);
- handlers.sort((a, b) => a.getOrder() - b.getOrder());
- for(const handler of handlers) {
- if(handler instanceof Middleware)
- this.addMiddleware(handler);
- else if (handler instanceof Route)
- this.addRoute(handler);
- }
- }
- public addMiddleware(middleware: Middleware): Server {
- if(middleware.getRoute() != null)
- this.instance.use(<string>middleware.getRoute(), middleware.getAction());
- else
- this.instance.use(middleware.getAction());
- return this;
- }
- public addRoute(route: Route): Server {
- if(route.getRoute() == null)
- throw new RouteNotSetException();
- switch(route.getMethod()) {
- case HttpMethod.GET:
- return this.get(route);
- case HttpMethod.POST:
- return this.post(route);
- default:
- throw new IncorrectMethodException();
- }
- }
- public logInfo(message: string): void {
- this.logger.getLogger().info(message);
- }
- public logError(message: string): void {
- this.logger.getLogger().error(message);
- }
- public logWarn(message: string): void {
- this.logger.getLogger().warn(message);
- }
- public log(message: Message): void {
- switch(message.type) {
- case MessageTypes.WARNING:
- return this.logWarn(message.text);
- case MessageTypes.ERROR:
- return this.logError(message.text);
- default:
- return this.logInfo(message.text);
- }
- }
- private get(route: Route): Server {
- this.instance.get(<string>route.getRoute(), route.getAction());
- return this;
- }
- private post(route: Route): Server {
- this.instance.post(<string>route.getRoute(), route.getAction());
- return this;
- }
- public async registerRoutes(dir: string): Promise<Server> {
- const files = fs.readdirSync(dir);
- for(const file of files) {
- if(/\.js$/.test(file)) {
- const {default: RouteClass} = await import(path.join(dir, file));
- if(RouteClass.prototype instanceof Route) {
- this.httpHandlers[RouteClass.name] = <HttpHandler>new RouteClass(this);
- } else throw new InvalidRouteException(file);
- }
- }
- return this;
- }
- public async registerMiddlewares(dir: string): Promise<Server> {
- const files = fs.readdirSync(dir);
- for(const file of files) {
- if(/\.js$/.test(file)) {
- const {default: MiddlewareClass} = await import(path.join(dir, file));
- if(MiddlewareClass.prototype instanceof Middleware) {
- this.httpHandlers[MiddlewareClass.name] = <HttpHandler>new MiddlewareClass(this);
- } else throw new InvalidMiddlewareException(file);
- }
- }
- return this;
- }
- public getLogger(): Logger {
- return this.logger;
- }
- public i18nLoad(path: string): Server {
- this.i18n.load(path);
- return this;
- }
- public getOption(key: string): any {
- return this.options ? this.options[key] || null : null;
- }
- public start(callback?: () => any): void {
- if(!this.initialized)
- throw new ServerNotInitializedException();
- this.processHttpHandlers();
- const cb = (): void => {
- this.logInfo($$('org.crazydoctor.expressts.start', { 'port': this.port }));
- if(callback) callback();
- };
- this.instance.listen(this.port, cb);
- }
- }
- export { Server };
|