UNPKG

appolo

Version:
192 lines (128 loc) 5.14 kB
"use strict"; import {App as Engine, Events as EngineEvents} from 'appolo-engine'; import {Agent} from 'appolo-agent'; import {Router} from '../routes/router'; import * as path from 'path'; import {Objects, Strings} from 'appolo-utils'; import {IOptions} from "../interfaces/IOptions"; import { RouterControllerSymbol, RouterDefinitionsClassSymbol, RouterDefinitionsCompiledSymbol, RouterDefinitionsSymbol } from "../decorators/decorators"; import {Route} from "../routes/route"; import {IController} from "../controller/IController"; import {Util} from "../util/util"; import {decorate} from "../routes/decorate"; import {App} from "../app"; import {Plugin} from "../interfaces/IDefinition"; let Defaults: IOptions = { startMessage: "Appolo Server listening on port: ${port} version:${version} environment: ${environment}", startServer: true, errorStack: false, errorMessage: true, maxRouteCache: 10000, qsParser: "qs", urlParser: "fast", viewExt: "html", viewEngine: null, viewFolder: "src/views" }; export class Launcher { private readonly _engine: Engine; private readonly _agent: Agent; private readonly _options: IOptions; private readonly _port: number; private readonly _router: Router; private _plugins: { plugin: Plugin, options: any }[] = []; constructor(options: IOptions, private _app: App) { this._options = Objects.defaults({}, options || {}, Defaults); this._engine = new Engine(this._options); this._agent = new Agent(this._options); this._port = this._getPort(); this._engine.injector.addObject("httpServer", this._agent.server); this._agent.decorate(decorate); this._router = new Router(this._engine.env, this._engine.injector, this._options, this._agent); } public get engine(): Engine { return this._engine; } public get options(): IOptions { return this._options; } public get agent(): Agent { return this._agent; } public get router(): Router { return this._router; } public async launch(): Promise<void> { this._engine.on(EngineEvents.InjectRegister, this.addRoute, this); this._app.on(EngineEvents.ModuleExport, this.addRoute, this); await this._engine.launch(); await this.loadCustomConfigurations(); this._router.initialize(); await this._agent.listen(this._port); this._logServerMessage(); } public addRoute(fn: Function) { if (!Util.isClass(fn)) { return } let routeData = Reflect.getMetadata(RouterDefinitionsSymbol, fn); let routeAbstract: Route<IController> = Reflect.getMetadata(RouterDefinitionsClassSymbol, fn); if (!routeData || !Reflect.hasOwnMetadata(RouterControllerSymbol, fn)) { return } routeData = Objects.cloneDeep(routeData); Object.keys(routeData).forEach((key: string) => { let route: Route<IController> = routeData[key]; route = route.clone(); //add abstract route if (routeAbstract) { routeAbstract = routeAbstract.clone(); Util.reverseMiddleware(routeAbstract.definition); route.abstract(routeAbstract.definition); } let prefix = Reflect.getOwnMetadata(RouterControllerSymbol, fn); //add prefix to routes if (prefix) { (route.definition.path || []).forEach((_path, index) => { route.definition.path[index] = path.join("/", prefix, _path); }) } //override the controller in case we inherit it route.definition.controller = Util.getControllerName(fn as any); Reflect.defineMetadata(RouterDefinitionsCompiledSymbol, route, fn, key); this._router.addRoute(route); }) } protected _getPort(): number { return process.env.APP_PORT || process.env.PORT || this._options.port || this._engine.env.port || 8080; } protected async loadCustomConfigurations() { let allPath = path.join(this._options.root, 'config/middlewares/all.js'), environmentPath = path.join(this._options.root, 'config/middlewares/', this._options.environment + '.js'); await Util.loadPathWithArgs([allPath, environmentPath], this._engine.injector); } private _logServerMessage() { let msg = Strings.replaceFormat(this._options.startMessage, { port: this._port, version: this._engine.env.version, environment: this._engine.env.type }); Util.logger(this._engine.injector).info(msg) } public async reset() { this._engine.reset(); await this._agent.close(); this._app = null; this._plugins.length = 0; this._router.reset(); process.removeAllListeners(); } public plugin(plugin: Plugin, options: any) { this._plugins.push({plugin, options}); } }