Resolve ${var} values in middleware.json
App variables can now be specified in middleware.json using the ${var} format. The value of var is looked up using app.get(). This allows loopback.rest and other loopback middleware which require app variables, to be loaded declaratively using middleware.json.
This commit is contained in:
parent
674a8da693
commit
8b475a97b2
|
@ -316,10 +316,50 @@ function setupMiddleware(app, instructions) {
|
|||
}
|
||||
assert(typeof factory === 'function',
|
||||
'Middleware factory must be a function');
|
||||
data.config = getUpdatedConfigObject(data.config, app);
|
||||
app.middlewareFromConfig(factory, data.config);
|
||||
});
|
||||
}
|
||||
|
||||
function getUpdatedConfigObject(config, app) {
|
||||
|
||||
var DYNAMIC_CONFIG_PARAM = /\$\{(\w+)\}$/;
|
||||
|
||||
function getConfigVariable(param) {
|
||||
var configVariable = param;
|
||||
var match = configVariable.match(DYNAMIC_CONFIG_PARAM);
|
||||
if (match) {
|
||||
var appValue = app.get(match[1]);
|
||||
if (appValue !== undefined) {
|
||||
configVariable = appValue;
|
||||
} else {
|
||||
console.warn('%s does not resolve to a valid value. ' +
|
||||
'"%s" must be resolvable by app.get().', param, match[1]);
|
||||
}
|
||||
}
|
||||
return configVariable;
|
||||
}
|
||||
|
||||
function interpolateVariables(config) {
|
||||
var interpolated = {};
|
||||
Object.keys(config).forEach(function(configKey) {
|
||||
var value = config[configKey];
|
||||
if (Array.isArray(value)) {
|
||||
interpolated[configKey] = value.map(getConfigVariable);
|
||||
} else if (typeof value === 'string') {
|
||||
interpolated[configKey] = getConfigVariable(value);
|
||||
} else if (typeof value === 'object' && Object.keys(value).length) {
|
||||
interpolated[configKey] = interpolateVariables(value);
|
||||
} else {
|
||||
interpolated[configKey] = value;
|
||||
}
|
||||
});
|
||||
return interpolated;
|
||||
}
|
||||
|
||||
return interpolateVariables(config);
|
||||
}
|
||||
|
||||
function setupComponents(app, instructions) {
|
||||
instructions.components.forEach(function(data) {
|
||||
debug('Configuring component %j', data.sourceFile);
|
||||
|
|
|
@ -292,7 +292,7 @@ describe('executor', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe ('for mixins', function() {
|
||||
describe('for mixins', function() {
|
||||
var options;
|
||||
beforeEach(function() {
|
||||
appdir.writeFileSync('custom-mixins/example.js',
|
||||
|
@ -425,6 +425,77 @@ describe('executor', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('with middleware.json', function() {
|
||||
|
||||
it('should parse a simple config variable', function(done) {
|
||||
boot.execute(app, simpleMiddlewareConfig('routes',
|
||||
{ path: '${restApiRoot}' }
|
||||
));
|
||||
|
||||
supertest(app).get('/').end(function(err, res) {
|
||||
if (err) return done(err);
|
||||
expect(res.body.path).to.equal(app.get('restApiRoot'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse multiple config variables', function(done) {
|
||||
boot.execute(app, simpleMiddlewareConfig('routes',
|
||||
{ path: '${restApiRoot}', env: '${env}' }
|
||||
));
|
||||
|
||||
supertest(app).get('/').end(function(err, res) {
|
||||
if (err) return done(err);
|
||||
expect(res.body.path).to.equal(app.get('restApiRoot'));
|
||||
expect(res.body.env).to.equal(app.get('env'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse config variables in an array', function(done) {
|
||||
boot.execute(app, simpleMiddlewareConfig('routes',
|
||||
{ paths: ['${restApiRoot}'] }
|
||||
));
|
||||
|
||||
supertest(app).get('/').end(function(err, res) {
|
||||
if (err) return done(err);
|
||||
expect(res.body.paths).to.eql(
|
||||
[app.get('restApiRoot')]
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse config variables in an object', function(done) {
|
||||
boot.execute(app, simpleMiddlewareConfig('routes',
|
||||
{ info: { path: '${restApiRoot}' } }
|
||||
));
|
||||
|
||||
supertest(app).get('/').end(function(err, res) {
|
||||
if (err) return done(err);
|
||||
expect(res.body.info).to.eql({
|
||||
path: app.get('restApiRoot')
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse config variables in a nested object', function(done) {
|
||||
boot.execute(app, simpleMiddlewareConfig('routes',
|
||||
{ nested: { info: { path: '${restApiRoot}' } } }
|
||||
));
|
||||
|
||||
supertest(app).get('/').end(function(err, res) {
|
||||
if (err) return done(err);
|
||||
expect(res.body.nested).to.eql({
|
||||
info: { path: app.get('restApiRoot') }
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('calls function exported by boot/init.js', function() {
|
||||
var file = appdir.writeFileSync('boot/init.js',
|
||||
'module.exports = function(app) { app.fnCalled = true; };');
|
||||
|
@ -583,6 +654,23 @@ describe('executor', function() {
|
|||
});
|
||||
});
|
||||
|
||||
function simpleMiddlewareConfig(phase, params) {
|
||||
return someInstructions({
|
||||
middleware: {
|
||||
phases: [phase],
|
||||
middleware: [
|
||||
{
|
||||
sourceFile: path.join(__dirname, './fixtures/simple-middleware.js'),
|
||||
config: {
|
||||
phase: phase,
|
||||
params: params
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function assertValidDataSource(dataSource) {
|
||||
// has methods
|
||||
assert.isFunc(dataSource, 'createModel');
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = function(params) {
|
||||
return function(req, res, next) {
|
||||
res.send(params);
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue