Skip to content

Commit

Permalink
Adds support for dominictarr#82's conclusion.
Browse files Browse the repository at this point in the history
This adds support for the file extensions and for parsers
by specific extension. All tests pass and a new one was
added to test the extensions.
  • Loading branch information
legodude17 committed Aug 14, 2016
1 parent 132062d commit 3f0061d
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 27 deletions.
25 changes: 15 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var home = win
? process.env.USERPROFILE
: process.env.HOME

module.exports = function (name, defaults, argv, parse) {
module.exports = function (name, defaults, argv, parsers) {
if('string' !== typeof name)
throw new Error('rc(name): name *must* be string')
if(!argv)
Expand All @@ -18,34 +18,39 @@ module.exports = function (name, defaults, argv, parse) {
? cc.json(defaults) : defaults
) || {}

parse = parse || cc.parse
parsers = parsers || cc.parsers

var env = cc.env(name + '_')

var configs = [defaults]
var configFiles = []
function addConfigFile (file) {
if (configFiles.indexOf(file) >= 0) return
var fileConfig = cc.file(file)
if (fileConfig) {
configs.push(parse(fileConfig))
configs.push(cc.parse(fileConfig, file, parsers))
configFiles.push(file)
}
}

// which files do we look at?
if (!win)
[join(etc, name, 'config'),
join(etc, name + 'rc')].forEach(addConfigFile)
[join(etc, name, 'config')].concat(Object.keys(parsers).map(function (v) {
return [etc, '.' + name + 'rc.' + v.toLowerCase()]
})).forEach(addConfigFile)
if (home)
[join(home, '.config', name, 'config'),
join(home, '.config', name),
join(home, '.' + name, 'config'),
join(home, '.' + name + 'rc')].forEach(addConfigFile)
addConfigFile(cc.find('.'+name+'rc'))
join(home, '.' + name, 'config')].concat(Object.keys(parsers).map(function (v) {
return [home, '.' + name + 'rc.' + v.toLowerCase()]
})).forEach(addConfigFile)
Object.keys(parsers).map(function (v) {
return v.toLowerCase();
}).forEach(function (v) {
addConfigFile(cc.find('.' + name + 'rc' + (v ? '.' + v : '')))
})
if (env.config) addConfigFile(env.config)
if (argv.config) addConfigFile(argv.config)

return deepExtend.apply(null, configs.concat([
env,
argv,
Expand Down
48 changes: 38 additions & 10 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,46 @@ var ini = require('ini')
var path = require('path')
var stripJsonComments = require('strip-json-comments')

var parse = exports.parse = function (content) {

//if it ends in .json or starts with { then it must be json.
//must be done this way, because ini accepts everything.
//can't just try and parse it and let it throw if it's not ini.
//everything is ini. even json with a syntax error.
var parsers = exports.parsers = {
'': function (content) {
try {
return JSON.parse(stripJsonComments(content));
} catch (e) {
return ini.parse(content)
}
},
'json': function (content) {
try {
return JSON.parse(stripJsonComments(content));
} catch (e) {
return null;
}
},
'ini': function (content) {
return ini.parse(content)
}
};

if(/^\s*{/.test(content))
return JSON.parse(stripJsonComments(content))
return ini.parse(content)
function getExt(file) {
var ext = file.split('.').pop()
if (ext.slice(-2) === 'rc') {
return '';
}
return ext;
}

var parse = exports.parse = function (contents, file, ps) {
var ext
if (file) {
ext = getExt(file)
} else {
ext = ''
}
ps = ps || parsers
if (typeof ps[ext] !== 'function') {
throw new Error('Extension ' + ext + ' does not have a parser. Valid parsers: ' + Object.keys(ps).join(', '))
}
return ps[ext](contents)
}

var file = exports.file = function () {
Expand Down Expand Up @@ -100,4 +129,3 @@ var find = exports.find = function () {
}
return find(process.cwd(), rel)
}

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "rc",
"version": "1.1.6",
"version": "2.1.6",
"description": "hardwired configuration loader",
"main": "index.js",
"browserify": "browser.js",
"scripts": {
"test": "set -e; node test/test.js; node test/ini.js; node test/nested-env-vars.js"
"test": "set -e; node test/test.js; node test/ini.js; node test/nested-env-vars.js; node test/extensions.js"
},
"repository": {
"type": "git",
Expand All @@ -25,5 +25,8 @@
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~1.0.4"
},
"devDependencies": {

}
}
87 changes: 87 additions & 0 deletions test/extensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

var n = 'rc'+Math.random()
var assert = require('assert')
var yaml = require('yaml')
var fs = require('fs')
var path = require('path')
var jsonrc = path.resolve('.' + n + 'rc.json');

console.log('---extensions---\n\n')

process.env[n + '_envOption'] = 42

fs.writeFileSync(jsonrc, [
'{',
'// json overrides default',
'"option": false,',
'/* env overrides json */',
'"envOption": 24',
'}'
].join('\n'));

var commentedJSON = require('../')(n, {
option: true
})

fs.unlinkSync(jsonrc);

console.log('Commented:', commentedJSON, commentedJSON.configs)

assert.equal(commentedJSON.option, false)
assert.equal(commentedJSON.envOption, 42)

assert.equal(commentedJSON.config, jsonrc)
assert.equal(commentedJSON.configs.length, 1)
assert.equal(commentedJSON.configs[0], jsonrc)

var inirc = path.resolve('.' + n + 'rc.ini');

fs.writeFileSync(inirc, [
'; ini overrides default',
'option=false',
'; env overrides ini',
'envOption=24'
].join('\n'));

var ini = require('../')(n, {
option: true
})

fs.unlinkSync(inirc);

console.log(ini)

assert.equal(ini.option, false)
assert.equal(ini.envOption, 42)

assert.equal(ini.config, inirc)
assert.equal(ini.configs.length, 1)
assert.equal(ini.configs[0], inirc)

var yamlrc = path.resolve('.' + n + 'rc.yaml');

fs.writeFileSync(yamlrc, [
'---',
' envOption: 24',
' option: false',
''
].join('\n'));

var yamlconfig = require('../')(n, {
option: true
}, false, {
'yaml': function (contents) {
return yaml.eval(contents)
}
})

fs.unlinkSync(yamlrc);

console.log(yamlconfig)

assert.equal(yamlconfig.option, false)
assert.equal(yamlconfig.envOption, 42)

assert.equal(yamlconfig.config, yamlrc)
assert.equal(yamlconfig.configs.length, 1)
assert.equal(yamlconfig.configs[0], yamlrc)
9 changes: 4 additions & 5 deletions test/ini.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ var cc =require('../lib/utils')
var INI = require('ini')
var assert = require('assert')

function test(obj) {
console.log('---ini---\n\n')

function test(obj) {
var _json, _ini
var json = cc.parse (_json = JSON.stringify(obj))
var ini = cc.parse (_ini = INI.stringify(obj))
var json = cc.parse(_json = JSON.stringify(obj))
var ini = cc.parse(_ini = INI.stringify(obj))
console.log(_ini, _json)
assert.deepEqual(json, ini)
}


test({hello: true})

2 changes: 2 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
var n = 'rc'+Math.random()
var assert = require('assert')

console.log('---Main test---\n\n')

process.env[n+'_envOption'] = 42

var config = require('../')(n, {
Expand Down

0 comments on commit 3f0061d

Please sign in to comment.