All files / core Overland.ts

100% Statements 57/57
75% Branches 6/8
100% Functions 11/11
100% Lines 55/55
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 1115x 5x 5x 5x 5x 5x 5x 5x     5x   5x         10x 10x     10x       2x 2x 2x 2x 2x             5x 9x   9x 9x     9x     9x 9x 9x     9x 9x     9x 9x 9x       9x 9x       9x 9x 9x 9x     9x 9x 9x 9x 9x     9x 9x       1x     1x 1x 1x       1x 1x     1x       36x 36x       10x 10x      
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;
  }
}