loopback-boot/lib/plugins/application.js

148 lines
3.9 KiB
JavaScript

var util = require('util');
var assert = require('assert');
var semver = require('semver');
var format = require('util').format;
var PluginBase = require('../plugin-base');
module.exports = function(options) {
return new Application(options);
};
function Application(options) {
PluginBase.call(this, options, 'application', 'config');
}
util.inherits(Application, PluginBase);
function patchAppLoopback(app) {
if (app.loopback) return;
// app.loopback was introduced in 1.9.0
// patch the app object to make loopback-boot work with older versions too
try {
app.loopback = require('loopback');
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') {
console.error(
'When using loopback-boot with loopback <1.9, ' +
'the loopback module must be available for `require(\'loopback\')`.');
}
throw err;
}
}
function assertLoopBackVersion(app) {
var RANGE = '1.x || 2.x || ^3.0.0-alpha';
var loopback = app.loopback;
// remove any pre-release tag from the version string,
// because semver has special treatment of pre-release versions,
// while loopback-boot treats pre-releases the same way as regular versions
var version = (loopback.version || '1.0.0').replace(/-.*$/, '');
if (!semver.satisfies(version, RANGE)) {
var msg = format(
'The `app` is powered by an incompatible loopback version %s. ' +
'Supported versions: %s',
loopback.version || '(unknown)',
RANGE);
throw new Error(msg);
}
}
function setEnv(app, env) {
if (env !== undefined)
app.set('env', env);
}
function setHost(app, appConfig) {
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var host =
process.env.npm_config_host ||
process.env.OPENSHIFT_SLS_IP ||
process.env.OPENSHIFT_NODEJS_IP ||
process.env.HOST ||
process.env.VCAP_APP_HOST ||
appConfig.host ||
process.env.npm_package_config_host ||
app.get('host');
if (host !== undefined) {
assert(typeof host === 'string', 'app.host must be a string');
app.set('host', host);
}
}
function setPort(app, appConfig) {
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var port = find([
process.env.npm_config_port,
process.env.OPENSHIFT_SLS_PORT,
process.env.OPENSHIFT_NODEJS_PORT,
process.env.PORT,
process.env.VCAP_APP_PORT,
appConfig.port,
process.env.npm_package_config_port,
app.get('port'),
3000,
], function(p) {
return p != null;
});
if (port !== undefined) {
var portType = typeof port;
assert(portType === 'string' || portType === 'number',
'app.port must be a string or number');
app.set('port', port);
}
}
function find(array, predicate) {
return array.filter(predicate)[0];
}
function setApiRoot(app, appConfig) {
var restApiRoot =
appConfig.restApiRoot ||
app.get('restApiRoot') ||
'/api';
assert(restApiRoot !== undefined, 'app.restBasePath is required');
assert(typeof restApiRoot === 'string',
'app.restApiRoot must be a string');
assert(/^\//.test(restApiRoot),
'app.restApiRoot must start with "/"');
app.set('restApiRoot', restApiRoot);
}
function applyAppConfig(app, appConfig) {
for (var configKey in appConfig) {
var cur = app.get(configKey);
if (cur === undefined || cur === null) {
app.set(configKey, appConfig[configKey]);
}
}
}
Application.prototype.starting = function(context) {
var app = context.app;
app.booting = true;
patchAppLoopback(app);
assertLoopBackVersion(app);
var appConfig = context.instructions.application;
setEnv(app, context.instructions.env || this.options.env);
setHost(app, appConfig);
setPort(app, appConfig);
setApiRoot(app, appConfig);
applyAppConfig(app, appConfig);
};
Application.prototype.started = function(context, done) {
var app = context.app;
app.booting = false;
process.nextTick(function() {
app.emit('booted');
done();
});
};