Merge pull request #200 from strongloop/globalize-2.x
Globalize Loopback-boot
This commit is contained in:
commit
13a049412a
|
@ -16,3 +16,5 @@ generated-instructions*.json
|
||||||
checkstyle.xml
|
checkstyle.xml
|
||||||
loopback-boot-*.tgz
|
loopback-boot-*.tgz
|
||||||
/test/sandbox/
|
/test/sandbox/
|
||||||
|
intl/*
|
||||||
|
!intl/en/
|
||||||
|
|
4
index.js
4
index.js
|
@ -3,6 +3,10 @@
|
||||||
// This file is licensed under the MIT License.
|
// This file is licensed under the MIT License.
|
||||||
// License text available at https://opensource.org/licenses/MIT
|
// License text available at https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
// Strong globalize
|
||||||
|
var SG = require('strong-globalize');
|
||||||
|
SG.SetRootDir(__dirname);
|
||||||
|
|
||||||
var ConfigLoader = require('./lib/config-loader');
|
var ConfigLoader = require('./lib/config-loader');
|
||||||
var compile = require('./lib/compiler');
|
var compile = require('./lib/compiler');
|
||||||
var execute = require('./lib/executor');
|
var execute = require('./lib/executor');
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"ec551b6f2fafd8d40af801ebe5bb09f6": "Discarding {{middleware}} instructions, {{loopback}} client does not support {{middleware}}.",
|
||||||
|
"1e5fea50eef843cbffd1d438494912c8": "Cannot resolve path \"{0}\"",
|
||||||
|
"34319676975b1abf107da7a056abb434": "Invalid normalization format - \"{0}\"",
|
||||||
|
"46e3ab0ef1149ce0a171b5fac2612ea3": "{{Middleware}} \"{0}\" not found: {1}",
|
||||||
|
"79e93b2a95e969788590c14e26bb2c1b": "The data in {{model-config.json}} is in the unsupported 1.x format.",
|
||||||
|
"978a25819e71602cad691dbe7ba17592": "{0} config must be a valid JSON object",
|
||||||
|
"be2dcdab7aa493ed8d77287eb45cfec8": "cannot require directory contents without directory name",
|
||||||
|
"2634623ad4b2c5902f6c6bb25e68b733": "WARNING: Main {{config}} file \"{0}.json\" is missing",
|
||||||
|
"4ed668e9187650d898acf97707df445a": "The {{phase}} \"{0}\" is not defined in the main config.",
|
||||||
|
"6de7e97f033f2cf477297b3d05a93608": "The {{middleware}} \"{0}\" in phase \"{1}\"is not defined in the main config.",
|
||||||
|
"94a0c7d5ab6462f7892b90c63f316f42": "invalid array: {0}",
|
||||||
|
"ec34cc58612cb654742e4cd0a57aca78": "Cannot apply {0}: {1}",
|
||||||
|
"0b91d122f6459c8bbe7865be0936fc4a": "{{app.restBasePath}} is required",
|
||||||
|
"1cda77c9954be299bb7154f73cb6ab74": "{{instructions.middleware.phases}} must be an {{array}}",
|
||||||
|
"22549489736fb0d7eba5a4b08977505f": "{{app.host}} must be a {{string}}",
|
||||||
|
"4c581cc529a7aeda620d5c4b4ef5cfa8": "{{app.restApiRoot}} must start with \"/\"",
|
||||||
|
"6037512314fac9d12af6c654a3804823": "Built-in model {0} should have been defined",
|
||||||
|
"69746d336c89bf4bb371a6c2fe56304d": "{0} does not resolve to a valid value, returned as {1}. \"{2}\" must be resolvable in Environment variable or by app.get().",
|
||||||
|
"70654dc6eb565613a33344efed3de998": "Failed loading boot script: {0}\n{1}",
|
||||||
|
"b078ccd043437a258581e387f93dc1a5": "The `{{app}}` is powered by an incompatible {{loopback}} version {0}. Supported versions: {1}",
|
||||||
|
"e8d29edfb313cfe64f5c96cc7d3d5b4b": "When using {{loopback-boot}} with {{loopback}} <1.9, the {{loopback}} module must be available for `{{require('loopback')}}`.",
|
||||||
|
"f48405e7c61c3d665b601c9ba41da424": "{{app.port}} must be a {{string}} or {{number}}",
|
||||||
|
"fa2a7d5137c8891693f9515d48f5b7d7": "{{app.restApiRoot}} must be a {{string}}"
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var commondir = require('commondir');
|
var commondir = require('commondir');
|
||||||
var cloneDeep = require('lodash').cloneDeep;
|
var cloneDeep = require('lodash').cloneDeep;
|
||||||
|
var g = require('strong-globalize')();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add boot instructions to a browserify bundler.
|
* Add boot instructions to a browserify bundler.
|
||||||
|
@ -85,9 +86,9 @@ function bundleInstructions(instructions, bundler) {
|
||||||
var hasMiddleware = instructions.middleware.phases.length ||
|
var hasMiddleware = instructions.middleware.phases.length ||
|
||||||
instructions.middleware.middleware.length;
|
instructions.middleware.middleware.length;
|
||||||
if (hasMiddleware) {
|
if (hasMiddleware) {
|
||||||
console.warn(
|
g.warn(
|
||||||
'Discarding middleware instructions,' +
|
'Discarding {{middleware}} instructions,' +
|
||||||
' loopback client does not support middleware.');
|
' {{loopback}} client does not support {{middleware}}.');
|
||||||
}
|
}
|
||||||
delete instructions.middleware;
|
delete instructions.middleware;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ var ConfigLoader = require('./config-loader');
|
||||||
var debug = require('debug')('loopback:boot:compiler');
|
var debug = require('debug')('loopback:boot:compiler');
|
||||||
var Module = require('module');
|
var Module = require('module');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
var g = require('strong-globalize')();
|
||||||
|
|
||||||
var FILE_EXTENSION_JSON = '.json';
|
var FILE_EXTENSION_JSON = '.json';
|
||||||
|
|
||||||
|
@ -120,7 +121,7 @@ module.exports = function compile(options) {
|
||||||
function assertIsValidConfig(name, config) {
|
function assertIsValidConfig(name, config) {
|
||||||
if (config) {
|
if (config) {
|
||||||
assert(typeof config === 'object',
|
assert(typeof config === 'object',
|
||||||
name + ' config must be a valid JSON object');
|
g.f('%s config must be a valid JSON object', name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +136,8 @@ function assertIsValidModelConfig(config) {
|
||||||
|
|
||||||
if (unsupported) {
|
if (unsupported) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'The data in model-config.json is in the unsupported 1.x format.');
|
g.f('The data in {{model-config.json}}' +
|
||||||
|
' is in the unsupported 1.x format.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +151,7 @@ function assertIsValidModelConfig(config) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function findScripts(dir, extensions) {
|
function findScripts(dir, extensions) {
|
||||||
assert(dir, 'cannot require directory contents without directory name');
|
assert(dir, g.f('cannot require directory contents without directory name'));
|
||||||
|
|
||||||
var files = tryReadDir(dir);
|
var files = tryReadDir(dir);
|
||||||
extensions = extensions || _.keys(require.extensions);
|
extensions = extensions || _.keys(require.extensions);
|
||||||
|
@ -357,7 +359,7 @@ function findModelDefinitions(rootDir, sources) {
|
||||||
function resolveAppPath(rootDir, relativePath, resolveOptions) {
|
function resolveAppPath(rootDir, relativePath, resolveOptions) {
|
||||||
var resolvedPath = tryResolveAppPath(rootDir, relativePath, resolveOptions);
|
var resolvedPath = tryResolveAppPath(rootDir, relativePath, resolveOptions);
|
||||||
if (resolvedPath === undefined && !resolveOptions.optional) {
|
if (resolvedPath === undefined && !resolveOptions.optional) {
|
||||||
var err = new Error('Cannot resolve path "' + relativePath + '"');
|
var err = new Error(g.f('Cannot resolve path "%s"', relativePath));
|
||||||
err.code = 'PATH_NOT_FOUND';
|
err.code = 'PATH_NOT_FOUND';
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
@ -482,7 +484,7 @@ function buildMiddlewareInstructions(rootDir, config) {
|
||||||
// if a non-optional middleware is not resolvable, it will throw
|
// if a non-optional middleware is not resolvable, it will throw
|
||||||
// at resolveAppPath() and not reach here
|
// at resolveAppPath() and not reach here
|
||||||
if (!resolved.sourceFile) {
|
if (!resolved.sourceFile) {
|
||||||
return console.log('Middleware "%s" not found: %s',
|
return g.log('{{Middleware}} "%s" not found: %s',
|
||||||
middleware,
|
middleware,
|
||||||
resolved.optional
|
resolved.optional
|
||||||
);
|
);
|
||||||
|
@ -812,8 +814,8 @@ function normalizeMixinName(str, options) {
|
||||||
return normalization(str);
|
return normalization(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
var err = new Error('Invalid normalization format - "' +
|
var err = new Error(g.f('Invalid normalization format - "%s"',
|
||||||
normalization + '"');
|
normalization));
|
||||||
err.code = 'INVALID_NORMALIZATION_FORMAT';
|
err.code = 'INVALID_NORMALIZATION_FORMAT';
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var debug = require('debug')('loopback:boot:config-loader');
|
var debug = require('debug')('loopback:boot:config-loader');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var g = require('strong-globalize')();
|
||||||
|
|
||||||
var ConfigLoader = exports;
|
var ConfigLoader = exports;
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ function findConfigFiles(appRootDir, env, name) {
|
||||||
var master = ifExists(name + '.json');
|
var master = ifExists(name + '.json');
|
||||||
if (!master && (ifExistsWithAnyExt(name + '.local') ||
|
if (!master && (ifExistsWithAnyExt(name + '.local') ||
|
||||||
ifExistsWithAnyExt(name + '.' + env))) {
|
ifExistsWithAnyExt(name + '.' + env))) {
|
||||||
console.warn('WARNING: Main config file "' + name + '.json" is missing');
|
g.warn('WARNING: Main {{config}} file "%s.json" is missing', name);
|
||||||
}
|
}
|
||||||
if (!master) return [];
|
if (!master) return [];
|
||||||
|
|
||||||
|
@ -153,21 +154,21 @@ function mergeConfigurations(configObjects, mergeFn) {
|
||||||
function mergeDataSourceConfig(target, config, fileName) {
|
function mergeDataSourceConfig(target, config, fileName) {
|
||||||
var err = mergeObjects(target, config);
|
var err = mergeObjects(target, config);
|
||||||
if (err) {
|
if (err) {
|
||||||
throw new Error('Cannot apply ' + fileName + ': ' + err);
|
throw new Error(g.f('Cannot apply %s: %s', fileName, err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeModelConfig(target, config, fileName) {
|
function mergeModelConfig(target, config, fileName) {
|
||||||
var err = mergeObjects(target, config);
|
var err = mergeObjects(target, config);
|
||||||
if (err) {
|
if (err) {
|
||||||
throw new Error('Cannot apply ' + fileName + ': ' + err);
|
throw new Error(g.f('Cannot apply %s: %s', fileName, err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeAppConfig(target, config, fileName) {
|
function mergeAppConfig(target, config, fileName) {
|
||||||
var err = mergeObjects(target, config);
|
var err = mergeObjects(target, config);
|
||||||
if (err) {
|
if (err) {
|
||||||
throw new Error('Cannot apply ' + fileName + ': ' + err);
|
throw new Error(g.f('Cannot apply %s: %s', fileName, err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,16 +178,16 @@ function mergeMiddlewareConfig(target, config, fileName) {
|
||||||
if (phase in target) {
|
if (phase in target) {
|
||||||
err = mergePhaseConfig(target[phase], config[phase], phase);
|
err = mergePhaseConfig(target[phase], config[phase], phase);
|
||||||
} else {
|
} else {
|
||||||
err = 'The phase "' + phase + '" is not defined in the main config.';
|
err = g.f('The {{phase}} "%s" is not defined in the main config.', phase);
|
||||||
}
|
}
|
||||||
if (err)
|
if (err)
|
||||||
throw new Error('Cannot apply ' + fileName + ': ' + err);
|
throw new Error(g.f('Cannot apply %s: %s', fileName, err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeNamedItems(arr1, arr2, key) {
|
function mergeNamedItems(arr1, arr2, key) {
|
||||||
assert(Array.isArray(arr1), 'invalid array: ' + arr1);
|
assert(Array.isArray(arr1), g.f('invalid array: %s', arr1));
|
||||||
assert(Array.isArray(arr2), 'invalid array: ' + arr2);
|
assert(Array.isArray(arr2), g.f('invalid array: %s', arr2));
|
||||||
key = key || 'name';
|
key = key || 'name';
|
||||||
var result = [].concat(arr1);
|
var result = [].concat(arr1);
|
||||||
for (var i = 0, n = arr2.length; i < n; i++) {
|
for (var i = 0, n = arr2.length; i < n; i++) {
|
||||||
|
@ -236,8 +237,8 @@ function mergePhaseConfig(target, config, phase) {
|
||||||
err = mergeObjects(targetMiddleware, configMiddleware);
|
err = mergeObjects(targetMiddleware, configMiddleware);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = 'The middleware "' + mw + '" in phase "' + phase + '"' +
|
err = g.f('The {{middleware}} "%s" in phase "%s"' +
|
||||||
'is not defined in the main config.';
|
'is not defined in the main config.', mw, phase);
|
||||||
}
|
}
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
}
|
}
|
||||||
|
@ -246,7 +247,7 @@ function mergePhaseConfig(target, config, phase) {
|
||||||
function mergeComponentConfig(target, config, fileName) {
|
function mergeComponentConfig(target, config, fileName) {
|
||||||
var err = mergeObjects(target, config);
|
var err = mergeObjects(target, config);
|
||||||
if (err) {
|
if (err) {
|
||||||
throw new Error('Cannot apply ' + fileName + ': ' + err);
|
throw new Error(g.f('Cannot apply %s: %s', fileName, err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ var debug = require('debug')('loopback:boot:executor');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var format = require('util').format;
|
var format = require('util').format;
|
||||||
|
var g = require('strong-globalize')();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute bootstrap instructions gathered by `boot.compile`.
|
* Execute bootstrap instructions gathered by `boot.compile`.
|
||||||
|
@ -72,9 +73,10 @@ function patchAppLoopback(app) {
|
||||||
app.loopback = require('loopback');
|
app.loopback = require('loopback');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code === 'MODULE_NOT_FOUND') {
|
if (err.code === 'MODULE_NOT_FOUND') {
|
||||||
console.error(
|
g.error(
|
||||||
'When using loopback-boot with loopback <1.9, ' +
|
'When using {{loopback-boot}} with {{loopback}} <1.9, ' +
|
||||||
'the loopback module must be available for `require(\'loopback\')`.');
|
'the {{loopback}} module must be available ' +
|
||||||
|
'for `{{require(\'loopback\')}}`.');
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
@ -89,8 +91,8 @@ function assertLoopBackVersion(app) {
|
||||||
// while loopback-boot treats pre-releases the same way as regular versions
|
// while loopback-boot treats pre-releases the same way as regular versions
|
||||||
var version = (loopback.version || '1.0.0').replace(/-.*$/, '');
|
var version = (loopback.version || '1.0.0').replace(/-.*$/, '');
|
||||||
if (!semver.satisfies(version, RANGE)) {
|
if (!semver.satisfies(version, RANGE)) {
|
||||||
var msg = format(
|
var msg = g.f(
|
||||||
'The `app` is powered by an incompatible loopback version %s. ' +
|
'The `{{app}}` is powered by an incompatible {{loopback}} version %s. ' +
|
||||||
'Supported versions: %s',
|
'Supported versions: %s',
|
||||||
loopback.version || '(unknown)',
|
loopback.version || '(unknown)',
|
||||||
RANGE);
|
RANGE);
|
||||||
|
@ -117,7 +119,7 @@ function setHost(app, instructions) {
|
||||||
app.get('host');
|
app.get('host');
|
||||||
|
|
||||||
if (host !== undefined) {
|
if (host !== undefined) {
|
||||||
assert(typeof host === 'string', 'app.host must be a string');
|
assert(typeof host === 'string', g.f('{{app.host}} must be a {{string}}'));
|
||||||
app.set('host', host);
|
app.set('host', host);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +143,7 @@ function setPort(app, instructions) {
|
||||||
if (port !== undefined) {
|
if (port !== undefined) {
|
||||||
var portType = typeof port;
|
var portType = typeof port;
|
||||||
assert(portType === 'string' || portType === 'number',
|
assert(portType === 'string' || portType === 'number',
|
||||||
'app.port must be a string or number');
|
g.f('{{app.port}} must be a {{string}} or {{number}}'));
|
||||||
app.set('port', port);
|
app.set('port', port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,11 +158,11 @@ function setApiRoot(app, instructions) {
|
||||||
app.get('restApiRoot') ||
|
app.get('restApiRoot') ||
|
||||||
'/api';
|
'/api';
|
||||||
|
|
||||||
assert(restApiRoot !== undefined, 'app.restBasePath is required');
|
assert(restApiRoot !== undefined, g.f('{{app.restBasePath}} is required'));
|
||||||
assert(typeof restApiRoot === 'string',
|
assert(typeof restApiRoot === 'string',
|
||||||
'app.restApiRoot must be a string');
|
g.f('{{app.restApiRoot}} must be a {{string}}'));
|
||||||
assert(/^\//.test(restApiRoot),
|
assert(/^\//.test(restApiRoot),
|
||||||
'app.restApiRoot must start with "/"');
|
g.f('{{app.restApiRoot}} must start with "/"'));
|
||||||
app.set('restApiRoot', restApiRoot);
|
app.set('restApiRoot', restApiRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,12 +232,12 @@ function defineModels(app, instructions) {
|
||||||
if (!data.definition) {
|
if (!data.definition) {
|
||||||
model = registry.getModel(name);
|
model = registry.getModel(name);
|
||||||
if (!model) {
|
if (!model) {
|
||||||
throw new Error('Cannot configure unknown model ' + name);
|
throw new Error(g.f('Cannot configure unknown model %s', name));
|
||||||
}
|
}
|
||||||
debug('Configuring existing model %s', name);
|
debug('Configuring existing model %s', name);
|
||||||
} else if (isBuiltinLoopBackModel(app, data)) {
|
} else if (isBuiltinLoopBackModel(app, data)) {
|
||||||
model = registry.getModel(name);
|
model = registry.getModel(name);
|
||||||
assert(model, 'Built-in model ' + name + ' should have been defined');
|
assert(model, g.f('Built-in model %s should have been defined', name));
|
||||||
debug('Configuring built-in LoopBack model %s', name);
|
debug('Configuring built-in LoopBack model %s', name);
|
||||||
} else {
|
} else {
|
||||||
debug('Creating new model %s %j', name, data.definition);
|
debug('Creating new model %s %j', name, data.definition);
|
||||||
|
@ -295,7 +297,7 @@ function runScripts(app, list, callback) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed loading boot script: %s\n%s', filepath, err.stack);
|
g.error('Failed loading boot script: %s\n%s', filepath, err.stack);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -326,7 +328,7 @@ function setupMiddleware(app, instructions) {
|
||||||
// Phases can be empty
|
// Phases can be empty
|
||||||
var phases = instructions.middleware.phases || [];
|
var phases = instructions.middleware.phases || [];
|
||||||
assert(Array.isArray(phases),
|
assert(Array.isArray(phases),
|
||||||
'instructions.middleware.phases must be an array');
|
g.f('{{instructions.middleware.phases}} must be an {{array}}'));
|
||||||
|
|
||||||
var middleware = instructions.middleware.middleware;
|
var middleware = instructions.middleware.middleware;
|
||||||
assert(Array.isArray(middleware),
|
assert(Array.isArray(middleware),
|
||||||
|
@ -375,7 +377,7 @@ function getUpdatedConfigObject(app, config, opts) {
|
||||||
// it will now return `undefined`, for the use case of
|
// it will now return `undefined`, for the use case of
|
||||||
// dynamic datasources url:`undefined` to fallback to other parameters
|
// dynamic datasources url:`undefined` to fallback to other parameters
|
||||||
configVariable = undefined;
|
configVariable = undefined;
|
||||||
console.warn('%s does not resolve to a valid value, returned as %s. ' +
|
g.warn('%s does not resolve to a valid value, returned as %s. ' +
|
||||||
'"%s" must be resolvable in Environment variable or by app.get().',
|
'"%s" must be resolvable in Environment variable or by app.get().',
|
||||||
param, configVariable, varName);
|
param, configVariable, varName);
|
||||||
debug('Dynamic Configuration: Cannot resolve variable for `%s`, ' +
|
debug('Dynamic Configuration: Cannot resolve variable for `%s`, ' +
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
"debug": "^2.0.0",
|
"debug": "^2.0.0",
|
||||||
"lodash": "^3.6.0",
|
"lodash": "^3.6.0",
|
||||||
"semver": "^4.1.0",
|
"semver": "^4.1.0",
|
||||||
|
"strong-globalize": "^2.6.2",
|
||||||
"toposort": "^0.2.10"
|
"toposort": "^0.2.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
Loading…
Reference in New Issue