All files / core App.ts

100% Statements 32/32
70% Branches 7/10
100% Functions 18/18
100% Lines 32/32
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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173  5x                             36x             2x   2x 2x     2x 2x 2x 2x       2x 2x 2x 2x           3x       1x                     2x             2x 2x                   6x 5x 5x               11x       5x 5x 5x         3x       2x 1x 1x         2x                                                                                                                 10x       5x  
import Overland from './Overland';
import { camel, title } from 'change-case';
import { IControllerConstructor, ITaskConstructor, IModelConstructor, IRouter } from '../interfaces/index';
 
// The App class serves as Overland's entry point into a sub-application.
abstract class App {
 
  // Most important for this file is the app name. This is stored in a private `_app` variable
  // so we can apply it to various objects that are provided to the app configuration. This
  // allows us to transparently add information about the app to its components that might not
  // otherwise hold any reference to this subapplication.
 
  /**
   * Returns the machine-readable app name.
   */
  public static get app() {
    return this._app || camel(this.name.replace('App', ''));
  }
 
  /**
   * Sets router `app` property to the machine-readable app name.
   */
  public static set app(name: string) {
    this._app = name;
    // add app name to router
    Eif (this._router) {
      this._router.app = name;
    }
    // add app name to models.
    Eif (this._models) {
      this._models = this._models.map(model => {
        model.app = name;
        return model;
      });
    }
    // add app name to controllers
    Eif (this._controllers) {
        this._controllers = this._controllers.map(ctrl => {
          ctrl.app = name;
          return ctrl;
        });
    }
  }
 
  public static get label() {
    return this._label ? this._label : title(this.app);
  }
 
  public static set label(label: string) {
    this._label = label;
  }
 
  // An example of this pattern is visible with the `routes` property. We want to be able to
  // determine the app the router is coming from when we `use()` it in another router (so it
  // can prepend the app name to the route targets).
 
  /**
   * Returns the router.
   */
  static get routes() {
    return this._router;
  }
 
  /**
   * Sets router `app` property to the machine-readable app name.
   */
  static set routes(router: IRouter) {
    router.app = this.app;
    this._router = router;
  }
 
  // Same with controllers. This saves us the pain of doing this on every request, instead
  // doing it on app creation.
 
  /**
   * Sets controllers' `app` property to the machine-readable app name.
   */
  static set controllers(ctrls: IControllerConstructor[]) {
    this._controllers = ctrls.map(ctrl => {
      ctrl.app = this.app;
      return ctrl;
    });
  }
 
  /**
   * Returns the `_controllers` hash.
   */
  static get controllers(): IControllerConstructor[] {
    return this._controllers;
  }
 
  static set tasks(tasks: ITaskConstructor[]) {
    this._tasks = tasks.map(task => {
      task.app = this.app;
      return task;
    });
  }
 
  static get tasks(): ITaskConstructor[] {
    return this._tasks;
  }
 
  static set models(models: IModelConstructor[]) {
    this._models = models.map(model => {
      model.app = this.app;
      return model;
    });
  }
 
  static get models(): IModelConstructor[] {
    return this._models;
  }
 
  public static meta: any;
  public static engine: any;
 
  // The App should also provide information about the directory that views are in - it makes
  // the most sense to keep them with a site's component applications. Overland's render
  // middleware will look here first for a view, then in `${ siteRoot }/views/${ app }`.
 
  /**
   * View directory for the application.
   */
  public static views: string;
 
  /**
   * Machine-readable application name; required.
   */
  private static _app: string;
 
  /**
   * Human-readable application name; optional.
   */
  private static _label: string;
 
  /**
   * Routes for the application.
   */
  private static _router: IRouter;
 
  /**
   * Controllers for the application.
   */
  private static _controllers: IControllerConstructor[];
 
  /**
   * Models for the application.
   */
  private static _models: IModelConstructor[];
  private static _tasks: ITaskConstructor[];
 
  public app: string;
  public engine: Function;
  public label: string;
  public views: string;
  public meta: any;
  public controllers: IControllerConstructor[];
  public models: IModelConstructor[];
 
  // Apps can optionally be made with an asychronous instance method called `init()` that takes
  // the Overland instance as a parameter and can be used to perform various operations on
  // startup.
 
  /**
   * An async initialize function to be overridden.
   */
  public async init(app: Overland): Promise<any> {
    return;
  }
}
 
export { App as default };