From d939b8ee01777111c2dacfdf87c76f56da751157 Mon Sep 17 00:00:00 2001 From: Seba Date: Sat, 9 Apr 2016 10:14:23 -0300 Subject: [PATCH] feat(environment): Support nested options in environment variables It uses the '__' syntax to indicate nested properties, based on prior art from https://github.com/indexzero/nconf#env and https://github.com/dominictarr/rc. Closes yargs/yargs#332 --- index.js | 13 ++++++++++--- test/yargs-parser.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 4a50d6aa..7d5f1af2 100644 --- a/index.js +++ b/index.js @@ -444,9 +444,16 @@ function parse (args, opts) { var prefix = typeof envPrefix === 'string' ? envPrefix : '' Object.keys(process.env).forEach(function (envVar) { if (prefix === '' || envVar.lastIndexOf(prefix, 0) === 0) { - var key = camelCase(envVar.substring(prefix.length)) - if (((configOnly && flags.configs[key]) || !configOnly) && (!(key in argv) || flags.defaulted[key])) { - setArg(key, process.env[envVar]) + // get array of nested keys and convert them to camel case + var keys = envVar.split('__').map(function (key, i) { + if (i === 0) { + key = key.substring(prefix.length) + } + return camelCase(key) + }) + + if (((configOnly && flags.configs[keys.join('.')]) || !configOnly) && (!hasKey(argv, keys) || flags.defaulted[keys.join('.')])) { + setArg(keys.join('.'), process.env[envVar]) } } }) diff --git a/test/yargs-parser.js b/test/yargs-parser.js index a602742b..2597637b 100644 --- a/test/yargs-parser.js +++ b/test/yargs-parser.js @@ -1536,6 +1536,39 @@ describe('yargs-parser', function () { result.should.have.property('truthy') result.z.should.equal(55) }) + + it('should apply all nested env vars', function () { + process.env.TEST_A = 'a' + process.env.TEST_NESTED_OPTION__FOO = 'baz' + process.env.TEST_NESTED_OPTION__BAR = 'bar' + var result = parser(['--nestedOption.foo', 'bar'], { + envPrefix: 'TEST' + }) + + result.should.have.property('a', 'a') + result.should.have.property('nestedOption').and.deep.equal({ + foo: 'bar', + bar: 'bar' + }) + }) + + it('should apply nested env var if argv value is using default value', function () { + process.env.TEST_A = 'a' + process.env.TEST_NESTED_OPTION__FOO = 'baz' + process.env.TEST_NESTED_OPTION__BAR = 'bar' + var result = parser([], { + envPrefix: 'TEST', + default: { + 'nestedOption.foo': 'banana' + } + }) + + result.should.have.property('a', 'a') + result.should.have.property('nestedOption').and.deep.equal({ + foo: 'baz', + bar: 'bar' + }) + }) }) describe('configuration', function () {