From ea14a6a1c44fc4f50ce943d3a30b606f53a58e2d Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 14:27:20 +0100 Subject: [PATCH 001/108] add support for single file linting --- lib/lint.js | 17 +++++++++++++++++ test/files/lint/invalid.cjson | 3 +++ test/files/lint/valid.cjson | 3 +++ test/lib/lint.spec.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 lib/lint.js create mode 100644 test/files/lint/invalid.cjson create mode 100644 test/files/lint/valid.cjson create mode 100644 test/lib/lint.spec.js diff --git a/lib/lint.js b/lib/lint.js new file mode 100644 index 0000000..08496e2 --- /dev/null +++ b/lib/lint.js @@ -0,0 +1,17 @@ +var fs = require('fs'); +var cjson = require('cjson'); + +module.exports = function oconfLint(path, callback) { + fs.readFile(path, 'utf-8', function (err, data) { + if (err) { + return callback(err); + } + + try { + cjson.parse(data); + } catch (e) { + return callback(e); + } + callback(); + }); +}; diff --git a/test/files/lint/invalid.cjson b/test/files/lint/invalid.cjson new file mode 100644 index 0000000..c1ec2f7 --- /dev/null +++ b/test/files/lint/invalid.cjson @@ -0,0 +1,3 @@ +{ + "foo": "bar +} diff --git a/test/files/lint/valid.cjson b/test/files/lint/valid.cjson new file mode 100644 index 0000000..c8c4105 --- /dev/null +++ b/test/files/lint/valid.cjson @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} diff --git a/test/lib/lint.spec.js b/test/lib/lint.spec.js new file mode 100644 index 0000000..54dac7c --- /dev/null +++ b/test/lib/lint.spec.js @@ -0,0 +1,30 @@ +/* global describe, it */ +var lint = require('../../lib/lint'); +var expect = require('unexpected'); +var Path = require('path'); + +function testFile(filename) { + return Path.resolve(__dirname, '..', 'files', 'lint', filename); +} + + +describe('lib/lint', function () { + it('should export a function', function () { + expect(lint, 'to be a function'); + }); + it('should not complain when given a valid file', function (done) { + lint(testFile('valid.cjson'), function (err) { + expect(err, 'to be undefined'); + done(); + }); + }); + it('should complain when given an invalid file', function (done) { + lint(testFile('invalid.cjson'), function (err) { + expect(err, 'to be an', Error); + expect(err, 'to satisfy', { + message: /^Parse error on line 2:/ + }); + done(); + }); + }); +}); From f1838449081f728bb5c2316e6f30b75ade9b968a Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 14:39:36 +0100 Subject: [PATCH 002/108] refactor tests --- test/lib/lint.spec.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/test/lib/lint.spec.js b/test/lib/lint.spec.js index 54dac7c..de58446 100644 --- a/test/lib/lint.spec.js +++ b/test/lib/lint.spec.js @@ -1,9 +1,16 @@ /* global describe, it */ -var lint = require('../../lib/lint'); -var expect = require('unexpected'); var Path = require('path'); +var lint = require('../../lib/lint'); +var expect = require('unexpected') + .clone() + .addAssertion('to be an error', function (expect, subject, value) { + expect(subject, 'to be an', Error); + expect(subject, 'to satisfy', { + message: value + }); + }); -function testFile(filename) { +function testData(filename) { return Path.resolve(__dirname, '..', 'files', 'lint', filename); } @@ -12,18 +19,21 @@ describe('lib/lint', function () { it('should export a function', function () { expect(lint, 'to be a function'); }); + it('should throw an error if path does not exist', function (done) { + lint(testData('nonExistant.cjson'), function (err) { + expect(err, 'to be an error', /^ENOENT/); + done(); + }); + }); it('should not complain when given a valid file', function (done) { - lint(testFile('valid.cjson'), function (err) { + lint(testData('valid.cjson'), function (err) { expect(err, 'to be undefined'); done(); }); }); it('should complain when given an invalid file', function (done) { - lint(testFile('invalid.cjson'), function (err) { - expect(err, 'to be an', Error); - expect(err, 'to satisfy', { - message: /^Parse error on line 2:/ - }); + lint(testData('invalid.cjson'), function (err) { + expect(err, 'to be an error', /^Parse error on line 2:/); done(); }); }); From 7bcce1fbf223a987e9e8a7628da1b063d56e8c39 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:00:44 +0100 Subject: [PATCH 003/108] add support for linting whole directories. currently, it recursing into all subdirectories when linting directories. --- lib/lint.js | 35 ++++++++++++++++++------ package.json | 3 ++ test/files/lint/invalidDirectory/1.cjson | 3 ++ test/files/lint/invalidDirectory/2.cjson | 3 ++ test/files/lint/validDirectory/1.cjson | 3 ++ test/files/lint/validDirectory/2.cjson | 3 ++ test/lib/lint.spec.js | 17 ++++++++++++ 7 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 test/files/lint/invalidDirectory/1.cjson create mode 100644 test/files/lint/invalidDirectory/2.cjson create mode 100644 test/files/lint/validDirectory/1.cjson create mode 100644 test/files/lint/validDirectory/2.cjson diff --git a/lib/lint.js b/lib/lint.js index 08496e2..1505bdb 100644 --- a/lib/lint.js +++ b/lib/lint.js @@ -1,17 +1,34 @@ var fs = require('fs'); var cjson = require('cjson'); +var passError = require('passerror'); +var glob = require('glob'); +var async = require('async'); +var Path = require('path'); -module.exports = function oconfLint(path, callback) { - fs.readFile(path, 'utf-8', function (err, data) { - if (err) { - return callback(err); - } - +function lintFile(path, cb) { + fs.readFile(path, 'utf-8', passError(cb, function (data) { try { cjson.parse(data); } catch (e) { - return callback(e); + e.file = path; + return cb(e); + } + cb(); + })); +} + + +module.exports = function oconfLint(path, callback) { + fs.stat(path, passError(callback, function (stat) { + if (stat.isDirectory()) { + glob('**/*.cjson', { cwd: path }, passError(callback, function (files) { + var resolvedFiles = files.map(function (partialPath) { + return Path.resolve(path, partialPath); + }); + async.eachSeries(resolvedFiles, lintFile, callback); + })); + } else { + return lintFile(path, callback); } - callback(); - }); + })); }; diff --git a/package.json b/package.json index 3d0da18..4beaf26 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,12 @@ "travis": "npm run lint && npm run test && npm run coverage" }, "dependencies": { + "async": "0.9.0", "cjson": "0.3.0", + "glob": "4.4.1", "minimatch": "2.0.1", "optimist": "0.6.1", + "passerror": "1.1.0", "underscore": "*" }, "devDependencies": { diff --git a/test/files/lint/invalidDirectory/1.cjson b/test/files/lint/invalidDirectory/1.cjson new file mode 100644 index 0000000..c8c4105 --- /dev/null +++ b/test/files/lint/invalidDirectory/1.cjson @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} diff --git a/test/files/lint/invalidDirectory/2.cjson b/test/files/lint/invalidDirectory/2.cjson new file mode 100644 index 0000000..c1ec2f7 --- /dev/null +++ b/test/files/lint/invalidDirectory/2.cjson @@ -0,0 +1,3 @@ +{ + "foo": "bar +} diff --git a/test/files/lint/validDirectory/1.cjson b/test/files/lint/validDirectory/1.cjson new file mode 100644 index 0000000..c8c4105 --- /dev/null +++ b/test/files/lint/validDirectory/1.cjson @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} diff --git a/test/files/lint/validDirectory/2.cjson b/test/files/lint/validDirectory/2.cjson new file mode 100644 index 0000000..c8c4105 --- /dev/null +++ b/test/files/lint/validDirectory/2.cjson @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} diff --git a/test/lib/lint.spec.js b/test/lib/lint.spec.js index de58446..c95d4c6 100644 --- a/test/lib/lint.spec.js +++ b/test/lib/lint.spec.js @@ -37,4 +37,21 @@ describe('lib/lint', function () { done(); }); }); + describe('should be able to lint a directory', function () { + it('should not complain if no invalid files are found', function (done) { + lint(testData('validDirectory'), function (err) { + expect(err, 'to be undefined'); + done(); + }); + }); + it('should complain if at least one file is invalid', function (done) { + lint(testData('invalidDirectory'), function (err) { + expect(err, 'to satisfy', { + message: /^Parse error on line 2:/, + file: /invalidDirectory\/2.cjson$/ + }); + done(); + }); + }); + }); }); From 13685dad397e04c85a4861a21fc5f9f3b6ba1b6b Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:13:49 +0100 Subject: [PATCH 004/108] add oconf-lint and remove --lint option from oconf --- bin/oconf | 25 +++++++++++-------------- bin/oconf-lint | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 14 deletions(-) create mode 100755 bin/oconf-lint diff --git a/bin/oconf b/bin/oconf index cc9b50a..a5dbfae 100755 --- a/bin/oconf +++ b/bin/oconf @@ -22,11 +22,10 @@ var oconf = require('../lib/index'), .usage('Usage: $0 [--lint] [--bare] [--allowmissing] [--ignore ] [path.to.value...]') .argv; +// TODO: Remove this check for the lint option in v4. if (argv.lint) { - console.warn( - 'The option --lint is deprecated and will be replaced by', - 'a standalone binary with release 3.0.0 of oconf.' - ); + console.warn('The option --lint is replaced by oconf-lint.'); + process.exit(1); } try { @@ -48,18 +47,16 @@ try { config = config[arg]; }); - if (!argv.lint) { - if (argv.bare) { - if (Array.isArray(config)) { - util.puts(config.join(' ')); - } else if (typeof config === 'object' && config) { - util.puts(JSON.stringify(config)); - } else { - util.puts(config); - } + if (argv.bare) { + if (Array.isArray(config)) { + util.puts(config.join(' ')); + } else if (typeof config === 'object' && config) { + util.puts(JSON.stringify(config)); } else { - util.puts(JSON.stringify(config, false, 4)); + util.puts(config); } + } else { + util.puts(JSON.stringify(config, false, 4)); } } catch (error) { console.error("Error:", error.message); diff --git a/bin/oconf-lint b/bin/oconf-lint new file mode 100755 index 0000000..35d6eb7 --- /dev/null +++ b/bin/oconf-lint @@ -0,0 +1,20 @@ +#!/usr/bin/env node +var argv = require('optimist') + .demand(1) + .usage('Usage: $0 path [..., path]') + .argv; + +var files = argv._.map(function (path) { + return require('path').resolve(process.cwd(), path); +}); + +require('async').eachSeries(files, require('../lib/lint'), function (err) { + if (err) { + console.error(err.file, '\n'); + console.error(err.message); + process.exit(1); + } else { + console.warn('No linting errors found.'); + process.exit(0); + } +}); From 7a892017500e11836e917b4f93f7e4c4b19fd08d Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:20:24 +0100 Subject: [PATCH 005/108] README: fix typo in link to travis --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fc532c8..b4001d3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ OConf ===== [[![NPM version](https://badge.fury.io/js/oconf.svg)](http://badge.fury.io/js/oconf) -![Build Status](https://travis-ci.org/One-com/node-oconf.svg)](https://travis-ci.org/One-com/node-oconf) +[![Build Status](https://travis-ci.org/One-com/node-oconf.svg)](https://travis-ci.org/One-com/node-oconf) [![Coverage Status](https://coveralls.io/repos/One-com/node-oconf/badge.svg)](https://coveralls.io/r/One-com/node-oconf) [![Dependency Status](https://david-dm.org/One-com/node-oconf.png)](https://david-dm.org/One-com/node-oconf) From bda85c8fe90bb40cfc4cec4705b11968367064ae Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:21:08 +0100 Subject: [PATCH 006/108] README: fix another misplaced bracket in badge links --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b4001d3..59c582f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ OConf ===== -[[![NPM version](https://badge.fury.io/js/oconf.svg)](http://badge.fury.io/js/oconf) +[![NPM version](https://badge.fury.io/js/oconf.svg)](http://badge.fury.io/js/oconf) [![Build Status](https://travis-ci.org/One-com/node-oconf.svg)](https://travis-ci.org/One-com/node-oconf) [![Coverage Status](https://coveralls.io/repos/One-com/node-oconf/badge.svg)](https://coveralls.io/r/One-com/node-oconf) [![Dependency Status](https://david-dm.org/One-com/node-oconf.png)](https://david-dm.org/One-com/node-oconf) From 938d85cca2839c29868c3e202f3aee2241328aff Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:22:16 +0100 Subject: [PATCH 007/108] README: link directly to npmjs.com --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59c582f..bf6ee58 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ OConf ===== -[![NPM version](https://badge.fury.io/js/oconf.svg)](http://badge.fury.io/js/oconf) +[![NPM version](https://badge.fury.io/js/oconf.svg)](http://npmjs.com/package/oconf) [![Build Status](https://travis-ci.org/One-com/node-oconf.svg)](https://travis-ci.org/One-com/node-oconf) [![Coverage Status](https://coveralls.io/repos/One-com/node-oconf/badge.svg)](https://coveralls.io/r/One-com/node-oconf) [![Dependency Status](https://david-dm.org/One-com/node-oconf.png)](https://david-dm.org/One-com/node-oconf) From 6f1672dd28094b2803eb85c625040c19c4038604 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:23:09 +0100 Subject: [PATCH 008/108] README: link directory to npmjs via https (last one, I hope :<) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf6ee58..a7a359e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ OConf ===== -[![NPM version](https://badge.fury.io/js/oconf.svg)](http://npmjs.com/package/oconf) +[![NPM version](https://badge.fury.io/js/oconf.svg)](https://npmjs.com/package/oconf) [![Build Status](https://travis-ci.org/One-com/node-oconf.svg)](https://travis-ci.org/One-com/node-oconf) [![Coverage Status](https://coveralls.io/repos/One-com/node-oconf/badge.svg)](https://coveralls.io/r/One-com/node-oconf) [![Dependency Status](https://david-dm.org/One-com/node-oconf.png)](https://david-dm.org/One-com/node-oconf) From aec913a7bb53beaa247a91327f7684b8ecb7b83d Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:43:24 +0100 Subject: [PATCH 009/108] oconf-extract-value: add --allowmissing option --- bin/oconf-extract-option | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bin/oconf-extract-option b/bin/oconf-extract-option index 12537a3..bf0fac0 100755 --- a/bin/oconf-extract-option +++ b/bin/oconf-extract-option @@ -15,6 +15,10 @@ var argp = optimist alias: 'help', default: false, }) + .option('allowmissing', { + type: 'boolean', + default: false + }) .boolean(['j', 'h']) .demand(1) .usage('Usage: $0 '); @@ -39,6 +43,9 @@ function _getKey(keyname, testObj) { // Is it an object -- and does it have the key if (testObj !== new Object(testObj) || !(key in testObj)) { + if (argv.allowmissing) { + process.exit(0); + } throw new Error('Key ' + key + ' not found in ' + JSON.stringify(testObj)); } From a55346012684d788f67d96698806ef6a14ec3d80 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:48:33 +0100 Subject: [PATCH 010/108] bin/oconf: remove support to extract options --- bin/oconf | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/bin/oconf b/bin/oconf index 5fe354e..21a3f94 100755 --- a/bin/oconf +++ b/bin/oconf @@ -12,14 +12,16 @@ var oconf = require('../lib/index'), .option('ignore', { type: 'string' }) + // TODO: Remove this option in v4. .option('bare', { type: 'boolean' }) + // TODO: Remove this option in v4. .option('allowmissing', { type: 'boolean' }) .demand(1) - .usage('Usage: $0 [--lint] [--bare] [--allowmissing] [--ignore ] [path.to.value...]') + .usage('Usage: $0 [--lint] [--ignore ] ') .argv; // TODO: Remove this check for the lint option in v4. @@ -36,37 +38,14 @@ try { return item.split('.'); })); - if (pathToValue.length > 0) { - console.warn( - 'Usage of oconf to print configuration values like below, is deprecated.', - 'For example: "oconf file.cjson path.to.value".', - 'In version 3.0.0 it will be removed. You can use oconf-extract-option instead.\n' - ); + // TODO: Remove this check in v4. + if (argv.allowmissing || argv.bare || pathToValue.length > 0) { + console.warn('oconf no longer supports extracting values this way. Use oconf-extract-option instead.'); + process.exit(1); } - pathToValue.forEach(function (arg) { - if (!config || typeof config !== 'object' || !(arg in config)) { - if (argv.allowmissing) { - process.exit(0); - } else { - throw new Error('No such value: ' + pathToValue.join('.')); - } - } - config = config[arg]; - }); - - if (argv.bare) { - if (Array.isArray(config)) { - util.puts(config.join(' ')); - } else if (typeof config === 'object' && config) { - util.puts(JSON.stringify(config)); - } else { - util.puts(config); - } - } else { - util.puts(JSON.stringify(config, false, 4)); - } + util.puts(JSON.stringify(config, false, 4)); } catch (error) { console.error("Error:", error.message); process.exit(1); From 1baf0714fe6a245835fd0a2d3e2190fb6f72d720 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:51:44 +0100 Subject: [PATCH 011/108] add notes about --lint cleanup in v4 and clean up optimist output --- bin/oconf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/oconf b/bin/oconf index 21a3f94..a5d5fc7 100755 --- a/bin/oconf +++ b/bin/oconf @@ -5,9 +5,9 @@ var oconf = require('../lib/index'), util = require('util'), _ = require('underscore'), argv = require('optimist') + // TODO: Remove this option in v4. .option('lint', { - type: 'boolean', - default: false + type: 'boolean' }) .option('ignore', { type: 'string' @@ -21,7 +21,7 @@ var oconf = require('../lib/index'), type: 'boolean' }) .demand(1) - .usage('Usage: $0 [--lint] [--ignore ] ') + .usage('Usage: $0 [--ignore ] ') .argv; // TODO: Remove this check for the lint option in v4. From 21b66e1a64c6868c81925fa50af5972cae6d9b25 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:52:50 +0100 Subject: [PATCH 012/108] clean up code in bin/oconf related to extraction of options --- bin/oconf | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/bin/oconf b/bin/oconf index a5d5fc7..6186147 100755 --- a/bin/oconf +++ b/bin/oconf @@ -31,12 +31,8 @@ if (argv.lint) { } try { - var args = argv._.splice(1), - config = oconf.load(argv._[0], {ignore: argv.ignore}), - // Normalize oconf ... foo.bar quux => ['foo', 'bar', 'quux'] - pathToValue = _.flatten(args.map(function (item) { - return item.split('.'); - })); + var config = oconf.load(argv._[0], {ignore: argv.ignore}), + pathToValue = argv._.splice(1); // TODO: Remove this check in v4. if (argv.allowmissing || argv.bare || pathToValue.length > 0) { @@ -44,7 +40,6 @@ try { process.exit(1); } - util.puts(JSON.stringify(config, false, 4)); } catch (error) { console.error("Error:", error.message); From a3c806be902884ca10cb900147caa10aaca2658e Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:53:37 +0100 Subject: [PATCH 013/108] oconf-extract-option: exit with status 1 in case of an error. --- bin/oconf-extract-option | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/oconf-extract-option b/bin/oconf-extract-option index bf0fac0..9f243e2 100755 --- a/bin/oconf-extract-option +++ b/bin/oconf-extract-option @@ -73,4 +73,5 @@ try { util.puts(data); } catch (error) { console.error("Error:", error.message); + process.exit(1); } From 225d0966d7d3c8aceacb56f37a61a76812b7ee3c Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 15:55:02 +0100 Subject: [PATCH 014/108] 3.0.0 fixes #16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 886525a..b1b6f7b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Morten Siebuhr ", "name": "oconf", "description": "Configuration", - "version": "2.2.0", + "version": "3.0.0", "repository": { "type": "git", "url": "https://github.com/One-com/node-oconf.git" From ac351dd69331aab75885c1010b15eb35698f25e1 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:01:19 +0100 Subject: [PATCH 015/108] update the readme --- README.md | 59 +++++++++++++++++++++++++------------------------------ 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index a7a359e..fb412f4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -OConf -===== +# OConf [![NPM version](https://badge.fury.io/js/oconf.svg)](https://npmjs.com/package/oconf) [![Build Status](https://travis-ci.org/One-com/node-oconf.svg)](https://travis-ci.org/One-com/node-oconf) @@ -15,8 +14,7 @@ Load cjson (JSON + c-style) commentaries, with inheritance-sugar on top: "value": 50 } -Format ------- +## Format The basic idea is to experiment with applying `#include`-statements recusively inside JSON/cJSON documents: @@ -49,8 +47,7 @@ Will result in a config with: The extension of objects also work recursively, so setting a single sub-key somewhere doesn't override the entire thing. -Structure ---------- +## Structure There are no restrictions in how includes work (except no loops). Usually a structure like this is used: @@ -63,12 +60,11 @@ structure like this is used: * `/etc/$WORKNAME/$PROJECTNAME-secrets.cjson` inherits the machine-specific things and typically adds production secrets. -Binary ------- +## Binary To help resolve configuration on the command line oconf exports a CLI -tool called oconf. In it's simplest form it takes a path to an cjson -file, and outputs the resolved JSON object. +tool called oconf. It takes a path to an cjson file, and outputs the +resolved JSON object. ``` $ oconf config.cjson @@ -80,42 +76,41 @@ file, and outputs the resolved JSON object. } ``` -Oconf also takes a `--lint` option. It will make oconf not output any -of the resolved configuration, but only exit with an error in case of -any formatting errors in the files. +You can lint your configuration files by using `oconf-lint`. It will +not output any of the resolved configuration, but only exit with an +error in case of any formatting errors in the files. ``` - $ oconf --lint config.cjson + $ oconf-lint config.cjson ``` -You can supply a path to a value as well: +By using `oconf-extract-option` you can supply a path to a value as +well: ``` - $ oconf config.cjson obj.foo -"bar" + $ oconf-extract-option config.cjson obj.foo +bar ``` -The output from the above is the JSON.stringified format. If you need -to pass it into another cli program, you'd most likely want it as a -string literal and not quoted. That can be achieved like this: +The output from the above is the raw data. That is useful when you +need to pass the configuration to other CLI tools. If you need the +JSON formatted data, you can pass the `--json` option. ``` - $ oconf --bare config.cjson obj.foo -bar + $ oconf-extract-option --json config.cjson obj.foo +"bar" ``` -If the key is missing oconf will exit with exit code 1. If you need to -overwrite that behaviour you can pass the `--allowmissing` flag to -oconf which will make it exit with status code 0 if no value is found -at the given path. +If the key is missing `oconf-extract-option` will exit with status +code 1. If you need to overwrite that behaviour you can pass the +`--allowmissing` flag to oconf which will make it exit with status +code 0 if no value is found at the given path. -Tests ------ +## Tests Download/clone, run `npm install` and then `npm test`. -License -------- +## License -The software is provided under the Modified BSD License; See LICENSE for -further details. +The software is provided under the Modified BSD License; See +[LICENSE](LICENSE) for further details. From 62a3735a959fcfa11988d96440fb313fdc9578b7 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:01:30 +0100 Subject: [PATCH 016/108] 3.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1b6f7b..8c7d1b0 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Morten Siebuhr ", "name": "oconf", "description": "Configuration", - "version": "3.0.0", + "version": "3.0.1", "repository": { "type": "git", "url": "https://github.com/One-com/node-oconf.git" From ef1b1e29f29fab73b49c8019ad5191f3c36980cb Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:03:59 +0100 Subject: [PATCH 017/108] remove unused underscore dependency --- bin/oconf | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/oconf b/bin/oconf index 6186147..91696d7 100755 --- a/bin/oconf +++ b/bin/oconf @@ -3,7 +3,6 @@ var oconf = require('../lib/index'), util = require('util'), - _ = require('underscore'), argv = require('optimist') // TODO: Remove this option in v4. .option('lint', { From d2ba329499ecf84af5d5f5e1e124fe047faeba0c Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:09:44 +0100 Subject: [PATCH 018/108] bin/oconf: improve help text and cli interface --- bin/oconf | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/bin/oconf b/bin/oconf index 91696d7..ebe21dc 100755 --- a/bin/oconf +++ b/bin/oconf @@ -3,13 +3,19 @@ var oconf = require('../lib/index'), util = require('util'), - argv = require('optimist') + argp = require('optimist') // TODO: Remove this option in v4. .option('lint', { type: 'boolean' }) .option('ignore', { - type: 'string' + alias: 'i', + type: 'string', + description: 'Absolute path or glob pattern for ignoring included files.' + }) + .options('help', { + alias: 'h', + description: 'This help text.' }) // TODO: Remove this option in v4. .option('bare', { @@ -20,8 +26,15 @@ var oconf = require('../lib/index'), type: 'boolean' }) .demand(1) - .usage('Usage: $0 [--ignore ] ') - .argv; + .usage('Usage: $0 [--ignore ] '), + argv = argp.argv; + +// This is needed as optimist will not force exit when --help is +// passed on it's own, and we want it to. +if (argv.h) { + argp.showHelp(); + process.exit(0); +} // TODO: Remove this check for the lint option in v4. if (argv.lint) { From 1c9536b9c8795d89ce4139fe70fc59495a14180b Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:13:39 +0100 Subject: [PATCH 019/108] code style changes --- bin/oconf | 51 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/bin/oconf b/bin/oconf index ebe21dc..fa227bb 100755 --- a/bin/oconf +++ b/bin/oconf @@ -1,33 +1,30 @@ #!/usr/bin/env node // ex: filetype=javascript -var oconf = require('../lib/index'), - util = require('util'), - argp = require('optimist') - // TODO: Remove this option in v4. - .option('lint', { - type: 'boolean' - }) - .option('ignore', { - alias: 'i', - type: 'string', - description: 'Absolute path or glob pattern for ignoring included files.' - }) - .options('help', { - alias: 'h', - description: 'This help text.' - }) - // TODO: Remove this option in v4. - .option('bare', { - type: 'boolean' - }) - // TODO: Remove this option in v4. - .option('allowmissing', { - type: 'boolean' - }) - .demand(1) - .usage('Usage: $0 [--ignore ] '), - argv = argp.argv; +var oconf = require('../lib/index'); +var util = require('util'); +var argp = require('optimist') + .option('lint', { // TODO: Remove this option in v4. + type: 'boolean' + }) + .option('ignore', { + alias: 'i', + type: 'string', + description: 'Absolute path or glob pattern for ignoring included files.' + }) + .options('help', { + alias: 'h', + description: 'This help text.' + }) + .option('bare', { // TODO: Remove this option in v4. + type: 'boolean' + }) + .option('allowmissing', { // TODO: Remove this option in v4. + type: 'boolean' + }) + .demand(1) + .usage('Usage: $0 [--ignore ] '); +var argv = argp.argv; // This is needed as optimist will not force exit when --help is // passed on it's own, and we want it to. From 31062fb1e5ef7a8ae600f5a699db3479a4053ff3 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:17:07 +0100 Subject: [PATCH 020/108] code style changes --- bin/oconf-extract-option | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/bin/oconf-extract-option b/bin/oconf-extract-option index 9f243e2..0d0380c 100755 --- a/bin/oconf-extract-option +++ b/bin/oconf-extract-option @@ -1,27 +1,26 @@ #!/usr/bin/env node // ex: filetype=javascript -var oconf = require('../lib/index'), - util = require('util'), - optimist = require('optimist'); - +var oconf = require('../lib/index'); +var util = require('util'); +var optimist = require('optimist'); var argp = optimist - .options('j', { - alias: 'json', - default: false, - description: 'Force JSON output' - }) - .options('h', { - alias: 'help', - default: false, - }) - .option('allowmissing', { - type: 'boolean', - default: false - }) - .boolean(['j', 'h']) - .demand(1) - .usage('Usage: $0 '); + .options('j', { + alias: 'json', + default: false, + description: 'Force JSON output' + }) + .options('h', { + alias: 'help', + default: false, + }) + .option('allowmissing', { + type: 'boolean', + default: false + }) + .boolean(['j', 'h']) + .demand(1) + .usage('Usage: $0 '); var argv = argp.argv; if (argv.h) { From 6146ab1193139b0ea483c389e2cd817a5b88d6ed Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:19:22 +0100 Subject: [PATCH 021/108] oconf-extract-option: consistency changes to the cli options --- bin/oconf-extract-option | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/oconf-extract-option b/bin/oconf-extract-option index 0d0380c..d0d44ea 100755 --- a/bin/oconf-extract-option +++ b/bin/oconf-extract-option @@ -5,20 +5,20 @@ var oconf = require('../lib/index'); var util = require('util'); var optimist = require('optimist'); var argp = optimist - .options('j', { - alias: 'json', - default: false, + .option('json', { + alias: 'j', + type: 'boolean', description: 'Force JSON output' }) - .options('h', { - alias: 'help', - default: false, + .option('help', { + alias: 'h', + type: 'boolean', + description: 'This help text' }) .option('allowmissing', { type: 'boolean', - default: false + description: 'Exit silently with no output, if no value was found.' }) - .boolean(['j', 'h']) .demand(1) .usage('Usage: $0 '); var argv = argp.argv; From 22345ed75ae6d03c4833b4d2a3bf34450f269208 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:29:43 +0100 Subject: [PATCH 022/108] consistency changes --- bin/oconf | 2 +- bin/oconf-extract-option | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/oconf b/bin/oconf index fa227bb..9885d6a 100755 --- a/bin/oconf +++ b/bin/oconf @@ -28,7 +28,7 @@ var argv = argp.argv; // This is needed as optimist will not force exit when --help is // passed on it's own, and we want it to. -if (argv.h) { +if (argv.help) { argp.showHelp(); process.exit(0); } diff --git a/bin/oconf-extract-option b/bin/oconf-extract-option index d0d44ea..251bdcc 100755 --- a/bin/oconf-extract-option +++ b/bin/oconf-extract-option @@ -23,7 +23,9 @@ var argp = optimist .usage('Usage: $0 '); var argv = argp.argv; -if (argv.h) { +// This is needed as optimist will not force exit when --help is +// passed on it's own, and we want it to. +if (argv.help) { argp.showHelp(); process.exit(); } From 989a0e138925284aad1f46b5f851a89e7fb76251 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:29:52 +0100 Subject: [PATCH 023/108] oconf-lint: force exit on --help --- bin/oconf-lint | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/bin/oconf-lint b/bin/oconf-lint index 35d6eb7..f46e02f 100755 --- a/bin/oconf-lint +++ b/bin/oconf-lint @@ -1,8 +1,20 @@ #!/usr/bin/env node -var argv = require('optimist') +var argp = require('optimist') .demand(1) .usage('Usage: $0 path [..., path]') - .argv; + .option('help', { + alias: 'h', + type: 'boolean', + description: 'This help text' + }); +var argv = argp.argv; + +// This is needed as optimist will not force exit when --help is +// passed on it's own, and we want it to. +if (argv.help) { + argp.showHelp(); + process.exit(); +} var files = argv._.map(function (path) { return require('path').resolve(process.cwd(), path); From 4508e47f6e0c9105fc1f4ebcc47311be9cd6dd76 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:30:11 +0100 Subject: [PATCH 024/108] 3.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8c7d1b0..f1b51b1 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Morten Siebuhr ", "name": "oconf", "description": "Configuration", - "version": "3.0.1", + "version": "3.0.2", "repository": { "type": "git", "url": "https://github.com/One-com/node-oconf.git" From 77e531403d85e1c7eb47e7c9d68e4506f3d6c4e0 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 16:32:24 +0100 Subject: [PATCH 025/108] add contributors --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index f1b51b1..6430274 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,10 @@ "type": "git", "url": "https://github.com/One-com/node-oconf.git" }, + "contributors": [ + "Andreas Lind ", + "Gustav Nikolaj Olsen " + ], "homepage": "https://github.com/One-com/node-oconf", "main": "lib/index.js", "keywords": [ From 44a1d4dfb8c7964ba3bc7bd54ad8023f657603e6 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 23:13:27 +0100 Subject: [PATCH 026/108] add tests for bin/oconf --- test/bin/oconf.spec.js | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 test/bin/oconf.spec.js diff --git a/test/bin/oconf.spec.js b/test/bin/oconf.spec.js new file mode 100644 index 0000000..85dcc66 --- /dev/null +++ b/test/bin/oconf.spec.js @@ -0,0 +1,52 @@ +/* global describe, it */ +var exec = require('child_process').exec; +var expect = require('unexpected'); + +var pathToBin = require('path').resolve(__dirname, '../../bin/', 'oconf'); + +describe('bin/oconf', function () { + it('should print the resolved json structure to stdout', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'base.cjson'); + exec(pathToBin + ' ' + testFile, function (err, stdout, stderr) { + expect(err, 'to be null'); + expect(stdout, 'to equal', [ + '{', + ' "foo": "overwrite this",', + ' "what": "this is from default.cjson."', + '}', + '' + ].join('\n')); + expect(stderr, 'to equal', ''); + done(); + }); + }); + it('should fail when asked for nonexistant file', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'nonExistent.cjson'); + exec(pathToBin + ' ' + testFile, function (err, stdout) { + expect(err, 'to be an', Error); + expect(err, 'to satisfy', { + message: /Error: ENOENT, no such file or directory/ + }); + done(); + }); + }); + it('should fail when resolved file includes non existing file', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'includeNonExistentFile.cjson'); + exec(pathToBin + ' ' + testFile, function (err, stdout) { + expect(err, 'to be an', Error); + expect(err, 'to have property', 'message'); + expect(err.message, 'to match', /Error: ENOENT, no such file or directory/); + expect(err.message, 'not to match', /includeNonExistentFile.cjson/); + done(); + }); + }); + it('should not fail when resolved file includes non existing file when passed --ignore', function (done) { + var ignoreFile = require('path').resolve(__dirname, '..', 'files', 'nonExistentFile.cjson'); + var testFile = require('path').resolve(__dirname, '..', 'files', 'includeNonExistentFile.cjson'); + exec(pathToBin + ' --ignore ' + ignoreFile + ' ' + testFile, function (err, stdout) { + expect(err, 'to be null'); + expect(stdout, 'to equal', '{\n "foo": 123\n}\n'); + done(); + }); + }); +}); From 29cc015635dc3a83433670485f1b9c4f83721fcb Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 23:25:31 +0100 Subject: [PATCH 027/108] add tests for bin/oconf-lint --- bin/oconf-lint | 2 +- test/bin/oconf-lint.spec.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 test/bin/oconf-lint.spec.js diff --git a/bin/oconf-lint b/bin/oconf-lint index f46e02f..751d32f 100755 --- a/bin/oconf-lint +++ b/bin/oconf-lint @@ -22,7 +22,7 @@ var files = argv._.map(function (path) { require('async').eachSeries(files, require('../lib/lint'), function (err) { if (err) { - console.error(err.file, '\n'); + console.error(err.file + '\n'); console.error(err.message); process.exit(1); } else { diff --git a/test/bin/oconf-lint.spec.js b/test/bin/oconf-lint.spec.js new file mode 100644 index 0000000..65a672b --- /dev/null +++ b/test/bin/oconf-lint.spec.js @@ -0,0 +1,35 @@ +/* global describe, it */ +var exec = require('child_process').exec; +var expect = require('unexpected'); + +var pathToBin = require('path').resolve(__dirname, '../../bin/', 'oconf-lint'); + +describe('bin/oconf-lint', function () { + it('should exit with no errors if valid', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'lint', 'valid.cjson'); + exec(pathToBin + ' ' + testFile, function (err, stdout, stderr) { + expect(err, 'to be null'); + expect(stdout, 'to equal', ''); + expect(stderr, 'to equal', 'No linting errors found.\n'); + done(); + }); + }); + it('should report the errors if invalid', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'lint', 'invalid.cjson'); + exec(pathToBin + ' ' + testFile, function (err, stdout, stderr) { + expect(err, 'to be an', Error); + expect(err, 'to have property', 'code', 1); + expect(stdout, 'to equal', ''); + expect(stderr, 'to equal', [ + testFile, + '', + 'Parse error on line 2:', + '{ "foo": "bar}', + '------------^', + "Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined'", + '' + ].join('\n')); + done(); + }); + }); +}); From 8b30d1ccfd452dcc2907558062110e066c9e6a8d Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 1 Mar 2015 23:34:28 +0100 Subject: [PATCH 028/108] add tests for bin/oconf-extract-values fixes #15 --- test/bin/oconf-extract-option.spec.js | 54 +++++++++++++++++++++++++++ test/files/deep.cjson | 5 +++ 2 files changed, 59 insertions(+) create mode 100644 test/bin/oconf-extract-option.spec.js create mode 100644 test/files/deep.cjson diff --git a/test/bin/oconf-extract-option.spec.js b/test/bin/oconf-extract-option.spec.js new file mode 100644 index 0000000..49686c8 --- /dev/null +++ b/test/bin/oconf-extract-option.spec.js @@ -0,0 +1,54 @@ +/* global describe, it */ +var exec = require('child_process').exec; +var expect = require('unexpected'); + +var pathToBin = require('path').resolve(__dirname, '../../bin/', 'oconf-extract-option'); + +describe('bin/oconf-extract-option', function () { + it('should return the option value', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'base.cjson'); + exec(pathToBin + ' ' + testFile + ' foo', function (err, stdout, stderr) { + expect(err, 'to be null'); + expect(stdout, 'to equal', 'overwrite this\n'); + expect(stderr, 'to equal', ''); + done(); + }); + }); + it('should return the option value as json when passed --json', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'base.cjson'); + exec(pathToBin + ' --json ' + testFile + ' foo', function (err, stdout, stderr) { + expect(err, 'to be null'); + expect(stdout, 'to equal', '"overwrite this"\n'); + expect(stderr, 'to equal', ''); + done(); + }); + }); + it('should fail when no such option exists', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'base.cjson'); + exec(pathToBin + ' ' + testFile + ' bar', function (err, stdout, stderr) { + expect(err, 'to be an', Error); + expect(err, 'to have property', 'code', 1); + expect(stdout, 'to equal', ''); + expect(stderr, 'to match', /Key bar not found/); + done(); + }); + }); + it('should not fail when no such option exists when --allowmissing passed', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'base.cjson'); + exec(pathToBin + ' --allowmissing ' + testFile + ' bar', function (err, stdout, stderr) { + expect(err, 'to be null'); + expect(stdout, 'to equal', ''); + expect(stderr, 'to match', ''); + done(); + }); + }); + it('should support dotting out properties (foo.bar)', function (done) { + var testFile = require('path').resolve(__dirname, '..', 'files', 'deep.cjson'); + exec(pathToBin + ' ' + testFile + ' foo.bar', function (err, stdout, stderr) { + expect(err, 'to be null'); + expect(stdout, 'to equal', 'qux\n'); + expect(stderr, 'to match', ''); + done(); + }); + }); +}); diff --git a/test/files/deep.cjson b/test/files/deep.cjson new file mode 100644 index 0000000..586f3e5 --- /dev/null +++ b/test/files/deep.cjson @@ -0,0 +1,5 @@ +{ + "foo": { + "bar": "qux" + } +} From 59b35ec0c24b34c317815c9c155b54e1e5b8ca96 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 8 Mar 2015 00:00:04 +0100 Subject: [PATCH 029/108] update glob to 5.0.1 (4.4.1 was unpublished :-(((() --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6430274..84e2581 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "dependencies": { "async": "0.9.0", "cjson": "0.3.0", - "glob": "4.4.1", + "glob": "5.0.1", "minimatch": "2.0.1", "optimist": "0.6.1", "passerror": "1.1.0", From a8eb49565c0dc81acf4c5bf1aa38da88eaed0058 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Sun, 8 Mar 2015 00:00:09 +0100 Subject: [PATCH 030/108] 3.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 84e2581..78fe494 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Morten Siebuhr ", "name": "oconf", "description": "Configuration", - "version": "3.0.2", + "version": "3.0.3", "repository": { "type": "git", "url": "https://github.com/One-com/node-oconf.git" From 7033552e2ca9fba3139261f6fefd0b58281609b8 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Tue, 21 Apr 2015 19:29:15 +0200 Subject: [PATCH 031/108] update unexpected to v7.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 78fe494..d1ab1d9 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,6 @@ "jscs": "1.10.0", "jshint": "2.5.11", "mocha": "*", - "unexpected": "5.5.2" + "unexpected": "7.0.0" } } From ce40d11e95636e72ade2a9ea1af23b5c85d97883 Mon Sep 17 00:00:00 2001 From: Gustav Nikolaj Olsen Date: Tue, 21 Apr 2015 23:14:46 +0200 Subject: [PATCH 032/108] attempt to merge the functionality back into a single file --- bin/new-oconf | 127 +++++++++++++++++++++ test/bin/new-oconf.spec.js | 218 +++++++++++++++++++++++++++++++++++++ 2 files changed, 345 insertions(+) create mode 100755 bin/new-oconf create mode 100644 test/bin/new-oconf.spec.js diff --git a/bin/new-oconf b/bin/new-oconf new file mode 100755 index 0000000..284262f --- /dev/null +++ b/bin/new-oconf @@ -0,0 +1,127 @@ +#!/usr/bin/env node + +var oconf = require('../lib/index'); +var util = require('util'); + +var argp = require('optimist') + .usage('Usage: $0 [--lint|--extract-option