diff --git a/lib/config-loader.js b/lib/config-loader.js index d9b503f..f43fac7 100644 --- a/lib/config-loader.js +++ b/lib/config-loader.js @@ -129,10 +129,28 @@ function mergeAppConfig(target, config, fileName) { function applyCustomConfig(target, config) { for (var key in config) { var value = config[key]; - if (typeof value === 'object') { - return 'override for the option `' + key + '` is not a value type.'; + if (target[key]) { + if (Array.isArray(target[key]) && Array.isArray(value)) { + if (target[key].length == value.length) { + for (var valueIdx in value) { + if (typeof value[valueIdx] === 'object') { + applyCustomConfig(target[key][valueIdx], value[valueIdx]); + } else { + target[key][valueIdx] = value[valueIdx]; + } + } + } else { + return 'override for the option `' + key + + '` is an array and lengths mismatch.'; + } + } else if (typeof target[key] === 'object' && typeof value === 'object') { + applyCustomConfig(target[key], value); + } else { + target[key] = value; + } + } else { + target[key] = value; } - target[key] = value; } return null; // no error } diff --git a/test/compiler.test.js b/test/compiler.test.js index ee712d1..d5c18cc 100644 --- a/test/compiler.test.js +++ b/test/compiler.test.js @@ -125,24 +125,82 @@ describe('compiler', function() { expect(db).to.have.property('fromJs', true); }); - it('refuses to merge Object properties', function() { + it('merges Object properties', function() { + var nestedValue = { key: 'value' }; appdir.createConfigFilesSync(); appdir.writeConfigFileSync('datasources.local.json', { - db: { nested: { key: 'value' } } + db: { nested: nestedValue } }); - expect(function() { boot.compile(appdir.PATH); }) - .to.throw(/`nested` is not a value type/); + var instructions = boot.compile(appdir.PATH); + + var db = instructions.dataSources.db; + expect(db).to.have.property('nested'); + expect(db.nested).to.eql(nestedValue); }); - it('refuses to merge Array properties', function() { + it('merges nested Object properties', function() { + var nestedValue = 'http://api.test.com'; appdir.createConfigFilesSync(); appdir.writeConfigFileSync('datasources.local.json', { - db: { nested: ['value'] } + rest: { + operations: [ + { + template: { + url: nestedValue + } + } + ] + } + }); + + var instructions = boot.compile(appdir.PATH); + + var rest = instructions.dataSources.rest; + expect(rest).to.have.property('operations'); + expect(rest.operations[0]).to.have.property('template'); + expect(rest.operations[0].template).to.have.property('url'); + expect(rest.operations[0].template.method).to.eql('POST'); + expect(rest.operations[0].template.url).to.eql(nestedValue); + }); + + it('merges Array properties', function() { + var nestedValue = ['value']; + appdir.createConfigFilesSync(); + appdir.writeConfigFileSync('datasources.local.json', { + db: { nested: nestedValue } + }); + + var instructions = boot.compile(appdir.PATH); + + var db = instructions.dataSources.db; + expect(db).to.have.property('nested'); + expect(db.nested).to.eql(nestedValue); + }); + + it('errors on mismatched arrays', function() { + var nestedValue = 'http://api.test.com'; + appdir.createConfigFilesSync(); + appdir.writeConfigFileSync('datasources.local.json', { + rest: { + operations: [ + { + template: { + url: nestedValue + } + }, + { + template: { + method: 'GET', + url: nestedValue + } + } + ] + } }); expect(function() { boot.compile(appdir.PATH); }) - .to.throw(/`nested` is not a value type/); + .to.throw(/an array and lengths mismatch/); }); it('merges app configs from multiple files', function() { diff --git a/test/helpers/appdir.js b/test/helpers/appdir.js index 1a31be5..579e675 100644 --- a/test/helpers/appdir.js +++ b/test/helpers/appdir.js @@ -28,6 +28,16 @@ appdir.createConfigFilesSync = function(appConfig, dataSources, models) { db: { connector: 'memory', defaultForType: 'db' + }, + rest: { + connector: 'rest', + operations: [ + { + template: { + method: 'POST' + } + } + ] } }, dataSources); appdir.writeConfigFileSync ('datasources.json', dataSources);