import * as Koa from 'koa';
import * as Debug from 'debug';
import * as bodyParser from 'koa-bodyparser';
import override from '../middleware/override';
import timer from '../decorators/timer';
import overlander from '../middleware/overlander';
import { createServer as http } from 'http';
import { createServer as https } from 'https';
import { IOverlandSettings, IAppConstructor, IControllerConstructor, IServers } from '../interfaces/index';
const debug = Debug('overland:core');
export default class Overland extends Koa {
/**
* Settings object.
*/
public apps: Map<string, IAppConstructor> = new Map();
public controllers: Map<string, IControllerConstructor> = new Map();
public engine: any;
public settings: IOverlandSettings;
public helpers: { [key: string]: Function } = {};
public keys: string[];
public createRenderContext(ctx: any, data: any): any {
const app = ctx.state.controller.app;
const thisHelpers = this.helpers[app];
const helpers = Object.assign({}, this.helpers, thisHelpers);
const __ = ctx.i18n ? ctx.i18n.__ .bind(ctx.i18n) : s => s;
return Object.assign({ __ }, data, helpers);
}
/**
* Loads middleware, routes, etc.
*/
@timer('boot')
public async boot(): Promise<this> {
const { keys, middleware, apps } = this.settings;
Eif (keys) {
this.keys = keys;
}
debug(`loading middleware`);
// Load core middleware (overlander, override);
debug(` - core`);
this.use(overlander(this));
this.use(override(this));
// Load contrib middleware
debug(` - contrib`);
this.use(bodyParser());
// Load user middleware
debug(` - user`);
for (const fn of middleware) {
this.use(fn);
}
// put app Ctors in map
for (const App of apps) {
this.apps.set(App.app, App);
}
// reduce all controllers to single array, add to map
apps.map(App => App.controllers)
.reduce((a, ctrls) => a.concat(ctrls), [])
.filter(a => !!a)
.forEach(ctrl => this.controllers.set(`${ ctrl.app }.${ ctrl.controller }`, ctrl));
// load user apps
debug(`loading apps`);
const promises = apps.map(App => {
const app = new App();
debug(` - ${ App.app }`);
return app.init(this);
});
await Promise.all(promises);
return this;
}
public serve(): IServers {
const servers = { http: undefined, https: undefined };
// boot https server (only if SSL config provided, unnecessary for rev. proxy setup)
Eif (this.settings.ssl) {
debug(`https listening on ${ this.settings.ports.https }`);
servers.https = https(this.settings.ssl, this.callback()).listen(this.settings.ports.https);
}
// boot http server
debug(`http listening on ${ this.settings.ports.http }`);
servers.http = http(this.callback()).listen(this.settings.ports.http);
// return servers to user
return servers;
}
public use(middleware) {
debug(` - use ${ middleware.name || '-' }`);
return super.use(middleware);
}
constructor(settings: IOverlandSettings) {
super();
this.settings = settings;
}
}
|