appolo
Version:
nodejs server framework
275 lines (204 loc) • 8.57 kB
text/typescript
import http = require('http');
import https = require('https');
import {IOptions} from "./interfaces/IOptions";
import {
Events as AgentEvents, Hooks, Methods,
IApp as IAgentApp,
MiddlewareHandlerErrorOrAny,
MiddlewareHandlerOrAny
} from "appolo-agent";
import {
Define,
EventDispatcher,
Events as EngineEvents,
IApp as IEngineApp,
IClass,
IEnv,
Injector
} from "appolo-engine";
import {ModuleFn} from "appolo-engine/lib/modules/modules";
import {Launcher} from "./launcher/launcher";
import {Route} from "./routes/route";
import {IController} from "./controller/IController";
import {Controller} from "./controller/controller";
import {StaticController} from "./controller/staticController";
import {IResponse} from "./interfaces/IResponse";
import {MiddlewareHandlerParams} from "appolo-agent/lib/types";
import {IRequest} from "./interfaces/IRequest";
import {NextFn} from "appolo-agent/index";
import {IMiddlewareCtr, MiddlewareType, RequestContextSymbol} from "./interfaces/IMiddleware";
import {Events} from "./interfaces/events";
import {Plugin} from "./interfaces/IDefinition";
import {Util} from "./util/util";
import {invokeMiddleWare, invokeMiddleWareError} from "./routes/invokeActionMiddleware";
import {RouterDefinitionsSymbol} from "./decorators/decorators";
export class App extends EventDispatcher implements IAgentApp, IEngineApp {
private _launcher: Launcher;
constructor(options: IOptions) {
super();
this._launcher = new Launcher(options, this);
this.injector.addObject("app", this, true);
this._launcher.agent.requestApp = this;
}
public static create(options: IOptions): App {
return new App(options);
};
public get exportedClasses(): { fn: Function, path: string, define: Define }[] {
return this.exported
}
public get exported(): { fn: Function, path: string, define: Define }[] {
return this._launcher.engine.exported;
}
public get exportedRoot(): { fn: Function, path: string, define: Define }[] {
return this._launcher.engine.exportedRoot;
}
public getRoute<T extends IController>(path: string, method: Methods): Route<T> {
return this._launcher.router.getRoute(path, method)
}
public async launch(): Promise<App> {
await this._launcher.launch();
return this;
}
public get options(): IOptions {
return this._launcher.options
}
// public enableContext(contextCtr?: typeof Context) {
//
// let context = namespace.create(RequestContextSymbol, contextCtr);
//
// this.injector.addObject("context", context);
//
// context.initialize();
//
// this.use((req: IRequest, res: IResponse, next: NextFn) => context.scope(next))
// }
// public getContext() {
// return namespace.get(RequestContextSymbol);
// }
public use(path?: (string | MiddlewareHandlerOrAny | IMiddlewareCtr), ...middleware: (MiddlewareHandlerOrAny | IMiddlewareCtr)[]): this {
return this._addMiddleware(path, middleware, false)
}
public error(path?: (string | MiddlewareHandlerErrorOrAny | IMiddlewareCtr), ...middleware: (string | MiddlewareHandlerErrorOrAny | IMiddlewareCtr)[]): this {
return this._addMiddleware(path, middleware, true)
}
private _addMiddleware(path: string | MiddlewareHandlerErrorOrAny | MiddlewareHandlerOrAny | IMiddlewareCtr, middleware: (string | MiddlewareHandlerErrorOrAny | MiddlewareHandlerOrAny | IMiddlewareCtr)[], error: boolean): this {
if (typeof path !== "string") {
middleware.unshift(path)
}
for (let i = 0; i < middleware.length; i++) {
let id = Util.getClassId(middleware[i]);
if (id) {
middleware[i] = error ? invokeMiddleWareError(id) : invokeMiddleWare(id)
}
}
if (error) {
this._launcher.agent.error(...middleware as MiddlewareHandlerErrorOrAny[]);
} else {
if (typeof path === "string") {
middleware.unshift(path)
}
this._launcher.agent.use(...middleware as MiddlewareHandlerErrorOrAny[]);
}
return this;
}
public addHook(name: Hooks.OnError, ...hook: (string | MiddlewareHandlerErrorOrAny | IMiddlewareCtr)[]): this
public addHook(name: Hooks.OnResponse | Hooks.PreMiddleware | Hooks.PreHandler | Hooks.OnRequest, ...hook: (string | MiddlewareHandlerErrorOrAny | IMiddlewareCtr)[]): this
public addHook(name: Hooks.OnSend, ...hook: (string | MiddlewareHandlerOrAny | IMiddlewareCtr)[]): this
public addHook(name: Hooks, ...hooks: (string | MiddlewareHandlerParams | IMiddlewareCtr)[]): this {
hooks = Util.convertMiddlewareHooks(name, hooks);
this._launcher.agent.addHook(name as any, ...(hooks as any));
return this
}
public module(...moduleFn: ModuleFn[]): Promise<any> {
return this._launcher.engine.module(...moduleFn)
}
public moduleAt(index: number): App {
return this.children[index]
}
public viewEngine(fn: (path: string, options?: { cache?: boolean, [otherOptions: string]: any }) => Promise<string>, ext: string = "html", cache: boolean = true): void {
this._launcher.options.viewEngine = fn;
this._launcher.options.viewExt = ext;
this._launcher.options.viewCache = cache;
}
public set(name: keyof IOptions, value: any) {
this._launcher.options[name as any] = value;
}
public async reset() {
await this._launcher.reset();
}
public register(id: string | IClass, type?: IClass): Define {
return this._launcher.engine.register(id, type)
}
public get injector(): Injector {
return this._launcher.engine.injector;
}
public get container(): Injector {
return this._launcher.engine.injector;
}
public get env(): IEnv {
return this._launcher.engine.env;
}
public get environment(): IEnv {
return this._launcher.engine.env;
}
public route<T extends IController>(controller: string | typeof Controller | typeof StaticController): Route<T> {
let route = new Route(controller);
this._launcher.router.addRoute(route);
return route
}
public addRouteFromClass(klass: typeof Controller) {
this._launcher.addRoute(klass)
}
public get parent(): App {
return this._launcher.engine.parent as App;
}
public get root(): App {
return this._launcher.engine.root as App;
}
public get children(): App[] {
return this._launcher.engine.children as App[];
}
public get(path: string, ...handler: MiddlewareHandlerParams[]): this {
this._launcher.agent.get(path, ...handler);
return this;
}
public post(path: string, ...handler: MiddlewareHandlerParams[]): this {
this._launcher.agent.post(path, ...handler);
return this;
}
public delete(path: string, ...handler: MiddlewareHandlerParams[]): this {
this._launcher.agent.post(path, ...handler);
return this;
}
public patch(path: string, ...handler: MiddlewareHandlerParams[]): this {
this._launcher.agent.patch(path, ...handler);
return this;
}
public get server(): http.Server | https.Server {
return this._launcher.agent.server
}
public handle = (request: http.IncomingMessage, response: http.ServerResponse) => {
this._launcher.agent.handle(request, response)
}
public on(event: Events | string, fn: (...args: any[]) => any, scope?: any): void {
if (event in EngineEvents) {
this._launcher.engine.on(event as EngineEvents, fn, scope)
} else if (event in AgentEvents) {
this._launcher.agent.on(event as AgentEvents, fn, scope)
} else {
super.on(event.toString(), fn, scope)
}
}
public once(event: Events | string, fn?: (...args: any[]) => any, scope?: any): Promise<any> | void {
if (event in EngineEvents) {
this._launcher.engine.once(event as EngineEvents, fn, scope)
} else if (event in AgentEvents) {
this._launcher.agent.once(event as AgentEvents, fn, scope)
} else {
super.once(event.toString(), fn, scope)
}
}
public plugin(plugin: Plugin, options: any) {
this._launcher.plugin(plugin, options);
}
}