From 3f0061d2b9ede708071049a4163222825d676dbd Mon Sep 17 00:00:00 2001 From: legodude17 Date: Sun, 14 Aug 2016 13:42:25 -0700 Subject: [PATCH 1/3] Adds support for #82's conclusion. 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. --- index.js | 25 +++++++------ lib/utils.js | 48 +++++++++++++++++++------ package.json | 7 ++-- test/extensions.js | 87 ++++++++++++++++++++++++++++++++++++++++++++++ test/ini.js | 9 +++-- test/test.js | 2 ++ 6 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 test/extensions.js diff --git a/index.js b/index.js index 6f8f113..d72db4e 100755 --- a/index.js +++ b/index.js @@ -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) @@ -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, diff --git a/lib/utils.js b/lib/utils.js index ae6dec0..a018b79 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -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 () { @@ -100,4 +129,3 @@ var find = exports.find = function () { } return find(process.cwd(), rel) } - diff --git a/package.json b/package.json index 38991a7..230123b 100644 --- a/package.json +++ b/package.json @@ -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", @@ -25,5 +25,8 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~1.0.4" + }, + "devDependencies": { + } } diff --git a/test/extensions.js b/test/extensions.js new file mode 100644 index 0000000..03a503b --- /dev/null +++ b/test/extensions.js @@ -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) diff --git a/test/ini.js b/test/ini.js index e6857f8..5ddbf0a 100644 --- a/test/ini.js +++ b/test/ini.js @@ -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}) - diff --git a/test/test.js b/test/test.js index 4f63351..78b4295 100644 --- a/test/test.js +++ b/test/test.js @@ -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, { From 4c89a4141b03cc3304fa223a85ad564ac66ee94e Mon Sep 17 00:00:00 2001 From: legodude17 Date: Sun, 14 Aug 2016 14:14:02 -0700 Subject: [PATCH 2/3] Add yaml to dev deps --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 230123b..f3a517f 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,6 @@ "strip-json-comments": "~1.0.4" }, "devDependencies": { - + "yaml": "^0.3.0" } } From 4c9069dd62e67dc2133af4035a7ed74018afa135 Mon Sep 17 00:00:00 2001 From: legodude17 Date: Mon, 15 Aug 2016 07:49:19 -0700 Subject: [PATCH 3/3] Expose parsers and parse --- index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index d72db4e..4acaf59 100755 --- a/index.js +++ b/index.js @@ -50,7 +50,7 @@ module.exports = function (name, defaults, argv, parsers) { }) if (env.config) addConfigFile(env.config) if (argv.config) addConfigFile(argv.config) - + return deepExtend.apply(null, configs.concat([ env, argv, @@ -58,6 +58,9 @@ module.exports = function (name, defaults, argv, parsers) { ])) } +module.exports.parsers = cc.parsers; +module.exports.parse = cc.parse; + if(!module.parent) { console.log( JSON.stringify(module.exports(process.argv[2]), false, 2)