151 lines
3.3 KiB
JavaScript
151 lines
3.3 KiB
JavaScript
'use strict';
|
|
|
|
const errors = require('errors');
|
|
const express = require('express');
|
|
const negotiate = require('express-negotiate');
|
|
const path = require('path');
|
|
const autoLoad = require('./config/container-autoload');
|
|
|
|
/**
|
|
* Determine the appropriate path to a module relative to the 'app' folder
|
|
*
|
|
* @private
|
|
* @param {string} modulePath - the raw path to the module
|
|
* @return {string} - the normalized path to the module
|
|
*/
|
|
function normalizeIncludePath(modulePath) {
|
|
const basePath = path.resolve(path.join(__dirname, '../'));
|
|
|
|
let includePath = modulePath;
|
|
|
|
// Allow referencing local modules without using a ./
|
|
// eg. util/route-loader instead of ./util/route-loader
|
|
if (
|
|
modulePath.includes('/') &&
|
|
! (modulePath.startsWith('./') || modulePath.includes(__dirname))
|
|
) {
|
|
includePath = path.join(__dirname, modulePath);
|
|
}
|
|
|
|
return includePath;
|
|
}
|
|
|
|
/**
|
|
* Container for keeping track of dependencies
|
|
*/
|
|
class Container {
|
|
constructor() {
|
|
const app = express();
|
|
let container = new Map();
|
|
|
|
// Save the base app object
|
|
container.set('app', app);
|
|
|
|
// Preload some configured modules
|
|
autoLoad.map((module) => {
|
|
let moduleMap = module;
|
|
|
|
// Normalize config into [key, value]
|
|
if (! Array.isArray(module)) {
|
|
moduleMap = [module, module];
|
|
}
|
|
|
|
// Actually require the module
|
|
moduleMap[1] = require(normalizeIncludePath(moduleMap[1]));
|
|
|
|
container.set.apply(container, moduleMap);
|
|
});
|
|
|
|
this._container = container;
|
|
}
|
|
|
|
/**
|
|
* Determine if an item exists in the container
|
|
*
|
|
* @param {string} name - name of the item
|
|
* @return {boolean} - whether the item exists in the container
|
|
*/
|
|
has(name) {
|
|
return this._container.has(name);
|
|
}
|
|
|
|
/**
|
|
* Return an existing object instance
|
|
*
|
|
* @param {string} name - name of the item
|
|
* @return {Object|undefined} - the item, or undefined if it doesn't exist
|
|
*/
|
|
get(name) {
|
|
if (this.has(name)) {
|
|
return this._container.get(name);
|
|
}
|
|
|
|
return this._require(name);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a base library instance
|
|
*
|
|
* @param {string} name - name of the base module
|
|
* @returns {*} - the base module
|
|
*/
|
|
getBase(name) {
|
|
return this.get(`base/${name}`);
|
|
}
|
|
|
|
/**
|
|
* Get a helper library instance
|
|
*
|
|
* @param {string} name - name of the helper module
|
|
* @return {*} - the helper instance
|
|
*/
|
|
getHelper(name) {
|
|
return this.get(`helpers/${name}`);
|
|
}
|
|
|
|
/**
|
|
* Get a model
|
|
* @param {string} name - the name of the model module
|
|
* @returns {*} - the model
|
|
*/
|
|
getModel(name) {
|
|
return this.get(`models/${name}`);
|
|
}
|
|
|
|
/**
|
|
* Set an object in the container
|
|
*
|
|
* @param {string} name - name to associate with object
|
|
* @param {Object} object - item to keep track of
|
|
* @return {Container} - the container instance
|
|
*/
|
|
set(name, object) {
|
|
this._container.set(name, object);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Does a native require, relative to the lib folder,
|
|
* and returns the value
|
|
*
|
|
* @private
|
|
* @param {string} modulePath - name of the module to require
|
|
* @return {*} - the value returned from require
|
|
*/
|
|
_require(modulePath) {
|
|
// If the value is already saved, just return it
|
|
if (this.has(modulePath)) {
|
|
return this.get(modulePath);
|
|
}
|
|
|
|
// Save the item for later
|
|
let item = require(normalizeIncludePath(modulePath));
|
|
this.set(modulePath, item);
|
|
|
|
return item;
|
|
}
|
|
}
|
|
|
|
module.exports = new Container();
|