Skip to content

Commit

Permalink
Allow provided config object to extend other configs
Browse files Browse the repository at this point in the history
  • Loading branch information
rcoy-v committed Feb 20, 2017
1 parent 57a8490 commit 10851a9
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 1 deletion.
7 changes: 7 additions & 0 deletions .editorconfig
@@ -0,0 +1,7 @@
root = true

[*.js]
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
37 changes: 37 additions & 0 deletions lib/apply-extends.js
@@ -0,0 +1,37 @@
var fs = require('fs')
var path = require('path')
var assign = require('./assign')
var YError = require('./yerror')

var previouslyVisitedConfigs = []

function checkForCircularExtends (path) {
if (previouslyVisitedConfigs.indexOf(path) > -1) {
throw new YError("Circular extended configurations: '" + path + "'.")
}
}

function applyExtends (config, cwd, subKey) {
var defaultConfig = {}

if (config.hasOwnProperty('extends')) {
var pathToDefault = path.join(cwd, config.extends)

checkForCircularExtends(pathToDefault)

previouslyVisitedConfigs.push(pathToDefault)
delete config.extends

defaultConfig = JSON.parse(fs.readFileSync(pathToDefault, 'utf8'))
if (subKey) {
defaultConfig = defaultConfig[subKey] || {}
}
defaultConfig = applyExtends(defaultConfig, path.dirname(pathToDefault), subKey)
}

previouslyVisitedConfigs = []

return assign(defaultConfig, config)
}

module.exports = applyExtends
4 changes: 4 additions & 0 deletions test/fixtures/extends/circular_1.json
@@ -0,0 +1,4 @@
{
"a": 44,
"extends": "./circular_2.json"
}
4 changes: 4 additions & 0 deletions test/fixtures/extends/circular_2.json
@@ -0,0 +1,4 @@
{
"b": "any",
"extends": "./circular_1.json"
}
5 changes: 5 additions & 0 deletions test/fixtures/extends/config_1.json
@@ -0,0 +1,5 @@
{
"a": 30,
"b": 22,
"extends": "./config_2.json"
}
3 changes: 3 additions & 0 deletions test/fixtures/extends/config_2.json
@@ -0,0 +1,3 @@
{
"z": 15
}
6 changes: 6 additions & 0 deletions test/fixtures/extends/packageA/package.json
@@ -0,0 +1,6 @@
{
"foo": {
"a": 80,
"extends": "../packageB/package.json"
}
}
6 changes: 6 additions & 0 deletions test/fixtures/extends/packageB/package.json
@@ -0,0 +1,6 @@
{
"foo": {
"a": 90,
"b": "riffiwobbles"
}
}
29 changes: 29 additions & 0 deletions test/yargs.js
Expand Up @@ -5,6 +5,7 @@ var fs = require('fs')
var path = require('path')
var checkOutput = require('./helpers/utils').checkOutput
var yargs = require('../')
var YError = require('../lib/yerror')

require('chai').should()

Expand Down Expand Up @@ -1155,6 +1156,27 @@ describe('yargs dsl tests', function () {
argv.foo.should.equal(1)
argv.bar.should.equal(2)
})

describe('extends', function () {
it('applies default configurations when given config object', function () {
var argv = yargs
.config({
extends: './test/fixtures/extends/config_1.json',
a: 1
})
.argv

argv.a.should.equal(1)
argv.b.should.equal(22)
argv.z.should.equal(15)
})

it('protects against circular extended configurations', function () {
expect(function () {
yargs.config({extends: './test/fixtures/extends/circular_1.json'})
}).to.throw(YError)
})
})
})

describe('normalize', function () {
Expand Down Expand Up @@ -1411,6 +1433,13 @@ describe('yargs dsl tests', function () {

argv.foo.should.equal('a')
})

it('should apply default configurations from extended packages', function () {
var argv = yargs().pkgConf('foo', 'test/fixtures/extends/packageA').argv

argv.a.should.equal(80)
argv.b.should.equals('riffiwobbles')
})
})

describe('skipValidation', function () {
Expand Down
5 changes: 4 additions & 1 deletion yargs.js
Expand Up @@ -9,6 +9,7 @@ const Validation = require('./lib/validation')
const Y18n = require('y18n')
const objFilter = require('./lib/obj-filter')
const setBlocking = require('set-blocking')
const applyExtends = require('./lib/apply-extends')
const YError = require('./lib/yerror')

var exports = module.exports = Yargs
Expand Down Expand Up @@ -304,6 +305,7 @@ function Yargs (processArgs, cwd, parentRequire) {
argsert('[object|string] [string|function] [function]', [key, msg, parseFn], arguments.length)
// allow a config object to be provided directly.
if (typeof key === 'object') {
key = applyExtends(key, cwd)
options.configObjects = (options.configObjects || []).concat(key)
return self
}
Expand All @@ -319,6 +321,7 @@ function Yargs (processArgs, cwd, parentRequire) {
;(Array.isArray(key) ? key : [key]).forEach(function (k) {
options.config[k] = parseFn || true
})

return self
}

Expand Down Expand Up @@ -473,7 +476,7 @@ function Yargs (processArgs, cwd, parentRequire) {

// If an object exists in the key, add it to options.configObjects
if (obj[key] && typeof obj[key] === 'object') {
conf = obj[key]
conf = applyExtends(obj[key], path, key)
options.configObjects = (options.configObjects || []).concat(conf)
}

Expand Down

0 comments on commit 10851a9

Please sign in to comment.