From 16a18bffe697406e9862d7748652af88555babf8 Mon Sep 17 00:00:00 2001 From: indexzero Date: Tue, 22 Nov 2011 21:22:09 -0500 Subject: [PATCH] [refactor] Expose all store prototypes on `nconf.*`. Expose store instances on Provider.stores and Provider.sources --- lib/nconf.js | 15 ++- lib/nconf/provider.js | 112 ++++++++++----------- lib/nconf/stores.js | 22 ---- lib/nconf/stores/argv.js | 5 +- test/fixtures/scripts/nconf-change-argv.js | 2 +- test/nconf-test.js | 2 +- test/provider-test.js | 10 +- test/stores/argv-test.js | 4 +- test/stores/env-test.js | 4 +- test/stores/file-store-test.js | 10 +- test/stores/literal-test.js | 4 +- test/stores/memory-store-test.js | 2 +- 12 files changed, 90 insertions(+), 102 deletions(-) delete mode 100644 lib/nconf/stores.js diff --git a/lib/nconf.js b/lib/nconf.js index bc9646c..299a0b2 100644 --- a/lib/nconf.js +++ b/lib/nconf.js @@ -16,6 +16,18 @@ var fs = require('fs'), // require('pkginfo')(module, 'version'); +// +// Setup all stores as lazy-loaded getters. +// +fs.readdirSync(__dirname + '/nconf/stores').forEach(function (file) { + var store = file.replace('.js', ''), + name = common.capitalize(store); + + nconf.__defineGetter__(name, function () { + return require('./nconf/stores/' + store)[name]; + }); +}); + // // Expose the various components included with nconf // @@ -24,5 +36,4 @@ nconf.path = common.path; nconf.loadFiles = common.loadFiles; nconf.loadFilesSync = common.loadFilesSync; nconf.formats = require('./nconf/formats'); -nconf.stores = require('./nconf/stores'); -nconf.Provider = Provider; \ No newline at end of file +nconf.Provider = Provider; diff --git a/lib/nconf/provider.js b/lib/nconf/provider.js index b0ec3f3..b830b0e 100644 --- a/lib/nconf/provider.js +++ b/lib/nconf/provider.js @@ -6,10 +6,7 @@ */ var async = require('async'), - common = require('./common'), - stores = require('./stores'); - - + common = require('./common'); // // ### function Provider (options) @@ -25,38 +22,9 @@ var Provider = exports.Provider = function (options) { // `overrides`, `process.env` and `process.argv`. // options = options || {}; - this._stores = {}; - this._sources = []; - - // - // Add any stores passed in through the options - // to this instance. - // - if (options.type) { - this.add(options.type, options); - } - else if (options.store) { - this.add(options.store.name || options.store.type, options.store); - } - else if (options.stores) { - Object.keys(options.stores).forEach(function (name) { - var store = options.stores[name]; - self.add(store.name || name || store.type, store); - }); - } - - // - // Add any read-only sources to this instance - // - if (options.source) { - this._sources.push(this.create(options.source.type || options.source.name, options.source)); - } - else if (options.sources) { - Object.keys(options.sources).forEach(function (name) { - var source = options.sources[name]; - self._sources.push(self.create(source.type || source.name || name, source)); - }); - } + this.stores = {}; + this.sources = []; + this.init(options); }; // @@ -100,7 +68,7 @@ Provider.prototype.use = function (name, options) { }); } - var store = this._stores[name], + var store = this.stores[name], update = store && !sameOptions(store); if (!store || update) { @@ -128,14 +96,14 @@ Provider.prototype.add = function (name, options) { options = options || {}; var type = options.type || name; - if (Object.keys(stores).indexOf(common.capitalize(type)) === -1) { + if (!require('../nconf')[common.capitalize(type)]) { throw new Error('Cannot add store with unknown type: ' + type); } - this._stores[name] = this.create(type, options); + this.stores[name] = this.create(type, options); - if (this._stores[name].loadSync) { - this._stores[name].loadSync(); + if (this.stores[name].loadSync) { + this.stores[name].loadSync(); } return this; @@ -149,7 +117,7 @@ Provider.prototype.add = function (name, options) { // this was used in the call to `.add()`. // Provider.prototype.remove = function (name) { - delete this._stores[name]; + delete this.stores[name]; return this; }; @@ -161,7 +129,39 @@ Provider.prototype.remove = function (name) { // specified `options`. // Provider.prototype.create = function (type, options) { - return new stores[common.capitalize(type.toLowerCase())](options); + return new (require('../nconf')[common.capitalize(type.toLowerCase())])(options); +}; + +Provider.prototype.init = function (options) { + // + // Add any stores passed in through the options + // to this instance. + // + if (options.type) { + this.add(options.type, options); + } + else if (options.store) { + this.add(options.store.name || options.store.type, options.store); + } + else if (options.stores) { + Object.keys(options.stores).forEach(function (name) { + var store = options.stores[name]; + self.add(store.name || name || store.type, store); + }); + } + + // + // Add any read-only sources to this instance + // + if (options.source) { + this.sources.push(this.create(options.source.type || options.source.name, options.source)); + } + else if (options.sources) { + Object.keys(options.sources).forEach(function (name) { + var source = options.sources[name]; + self.sources.push(self.create(source.type || source.name || name, source)); + }); + } }; // @@ -185,14 +185,14 @@ Provider.prototype.get = function (key, callback) { // the entire set of stores, but up until there is a defined value. // var current = 0, - names = Object.keys(this._stores), + names = Object.keys(this.stores), self = this, response; async.whilst(function () { return typeof response === 'undefined' && current < names.length; }, function (next) { - var store = self._stores[names[current]]; + var store = self.stores[names[current]]; current++; if (store.get.length >= 2) { @@ -282,7 +282,7 @@ Provider.prototype.merge = function () { // Provider.prototype.load = function (callback) { var self = this, - stores = Object.keys(this._stores).map(function (name) { return self._stores[name] }); + stores = Object.keys(this.stores).map(function (name) { return self.stores[name] }); function loadStoreSync(store) { if (!store.loadSync) { @@ -331,11 +331,11 @@ Provider.prototype.load = function (callback) { // then do so. // if (!callback) { - mergeSources(loadBatch(self._sources)); + mergeSources(loadBatch(self.sources)); return loadBatch(stores); } - loadBatch(self._sources, function (err, data) { + loadBatch(self.sources, function (err, data) { if (err) { return callback(err); } @@ -345,7 +345,7 @@ Provider.prototype.load = function (callback) { }); } - return self._sources.length + return self.sources.length ? loadSources() : loadBatch(stores, callback); }; @@ -364,10 +364,10 @@ Provider.prototype.save = function (value, callback) { } var self = this, - names = Object.keys(this._stores); + names = Object.keys(this.stores); function saveStoreSync(name) { - var store = self._stores[name]; + var store = self.stores[name]; if (!store.saveSync) { throw new Error('nconf store ' + store.type + ' has no saveSync() method'); @@ -377,7 +377,7 @@ Provider.prototype.save = function (value, callback) { } function saveStore(name, next) { - var store = self._stores[name]; + var store = self.stores[name]; if (!store.save && !store.saveSync) { return next(new Error('nconf store ' + store.type + ' has no save() method')); @@ -418,7 +418,7 @@ Provider.prototype._execute = function (action, syncLength /* [arguments] */) { response; function runAction (name, next) { - var store = self._stores[name]; + var store = self.stores[name]; if (destructive && store.readOnly) { return next(); @@ -430,15 +430,15 @@ Provider.prototype._execute = function (action, syncLength /* [arguments] */) { } if (callback) { - return async.forEach(Object.keys(this._stores), runAction, function (err) { + return async.forEach(Object.keys(this.stores), runAction, function (err) { return err ? callback(err) : callback(); }); } - Object.keys(this._stores).forEach(function (name) { + Object.keys(this.stores).forEach(function (name) { if (typeof response === 'undefined') { - var store = self._stores[name]; + var store = self.stores[name]; if (destructive && store.readOnly) { return; diff --git a/lib/nconf/stores.js b/lib/nconf/stores.js deleted file mode 100644 index b44b3b6..0000000 --- a/lib/nconf/stores.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * stores.js: Top-level include for all nconf stores - * - * (C) 2011, Charlie Robbins - * - */ - -var fs = require('fs'), - common = require('./common'), - stores = exports; - -// -// Setup all stores as lazy-loaded getters. -// -fs.readdirSync(__dirname + '/stores').forEach(function (file) { - var store = file.replace('.js', ''), - name = common.capitalize(store); - - stores.__defineGetter__(name, function () { - return require('./stores/' + store)[name]; - }); -}); \ No newline at end of file diff --git a/lib/nconf/stores/argv.js b/lib/nconf/stores/argv.js index 1e2d4a0..3e7124b 100644 --- a/lib/nconf/stores/argv.js +++ b/lib/nconf/stores/argv.js @@ -6,7 +6,6 @@ */ var util = require('util'), - optimist = require('optimist'), Memory = require('./memory').Memory; // @@ -45,8 +44,8 @@ Argv.prototype.loadArgv = function () { argv; argv = typeof this.options === 'object' - ? optimist(process.argv.slice(2)).options(this.options).argv - : optimist(process.argv.slice(2)).argv; + ? require('optimist')(process.argv.slice(2)).options(this.options).argv + : require('optimist')(process.argv.slice(2)).argv; if (!argv) { return; diff --git a/test/fixtures/scripts/nconf-change-argv.js b/test/fixtures/scripts/nconf-change-argv.js index 1aaed1a..032274b 100644 --- a/test/fixtures/scripts/nconf-change-argv.js +++ b/test/fixtures/scripts/nconf-change-argv.js @@ -11,6 +11,6 @@ var nconf = require('../../../lib/nconf').argv(); // Remove 'badValue', 'evenWorse' and 'OHNOEZ' // process.argv.splice(3, 3); -nconf._stores['argv'].loadArgv(); +nconf.stores['argv'].loadArgv(); process.stdout.write(nconf.get('something')); diff --git a/test/nconf-test.js b/test/nconf-test.js index 2cb8a39..44f613e 100644 --- a/test/nconf-test.js +++ b/test/nconf-test.js @@ -28,7 +28,7 @@ vows.describe('nconf').addBatch({ "the use() method": { "should instaniate the correct store": function () { nconf.use('memory'); - assert.instanceOf(nconf._stores['memory'], nconf.stores.Memory); + assert.instanceOf(nconf.stores['memory'], nconf.Memory); } }, "it should": { diff --git a/test/provider-test.js b/test/provider-test.js index f2440da..e3d7286 100644 --- a/test/provider-test.js +++ b/test/provider-test.js @@ -24,13 +24,13 @@ vows.describe('nconf/provider').addBatch({ "calling the use() method with the same store type and different options": { topic: new nconf.Provider().use('file', { file: files[0] }), "should use a new instance of the store type": function (provider) { - var old = provider._stores['file']; + var old = provider.stores['file']; - assert.equal(provider._stores.file.file, files[0]); + assert.equal(provider.stores.file.file, files[0]); provider.use('file', { file: files[1] }); - assert.notStrictEqual(old, provider._stores.file); - assert.equal(provider._stores.file.file, files[1]); + assert.notStrictEqual(old, provider.stores.file); + assert.equal(provider.stores.file.file, files[1]); } }, "when 'argv' is true": helpers.assertSystemConf({ @@ -71,7 +71,7 @@ vows.describe('nconf/provider').addBatch({ "should have the result merged in": function (provider) { provider.load(); provider.merge(override); - helpers.assertMerged(null, provider._stores.file.store); + helpers.assertMerged(null, provider.stores.file.store); } } } diff --git a/test/stores/argv-test.js b/test/stores/argv-test.js index 33014d1..764daab 100644 --- a/test/stores/argv-test.js +++ b/test/stores/argv-test.js @@ -11,8 +11,8 @@ var vows = require('vows'), nconf = require('../../lib/nconf'); vows.describe('nconf/stores/argv').addBatch({ - "An instance of nconf.stores.Argv": { - topic: new nconf.stores.Argv(), + "An instance of nconf.Argv": { + topic: new nconf.Argv(), "should have the correct methods defined": function (argv) { assert.isFunction(argv.loadSync); assert.isFunction(argv.loadArgv); diff --git a/test/stores/env-test.js b/test/stores/env-test.js index f9ce5d8..e3c2bca 100644 --- a/test/stores/env-test.js +++ b/test/stores/env-test.js @@ -11,8 +11,8 @@ var vows = require('vows'), nconf = require('../../lib/nconf'); vows.describe('nconf/stores/env').addBatch({ - "An instance of nconf.stores.Env": { - topic: new nconf.stores.Env(), + "An instance of nconf.Env": { + topic: new nconf.Env(), "should have the correct methods defined": function (env) { assert.isFunction(env.loadSync); assert.isFunction(env.loadEnv); diff --git a/test/stores/file-store-test.js b/test/stores/file-store-test.js index e4481bb..3149d02 100644 --- a/test/stores/file-store-test.js +++ b/test/stores/file-store-test.js @@ -18,7 +18,7 @@ vows.describe('nconf/stores/file').addBatch({ topic: function () { var filePath = path.join(__dirname, '..', 'fixtures', 'store.json'); fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); - store = new nconf.stores.File({ file: filePath }); + store = new nconf.File({ file: filePath }); return null; }, "the load() method": { @@ -34,7 +34,7 @@ vows.describe('nconf/stores/file').addBatch({ "When using the nconf file store": { topic: function () { var filePath = path.join(__dirname, '..', 'fixtures', 'malformed.json'); - store = new nconf.stores.File({ file: filePath }); + store = new nconf.File({ file: filePath }); return null; }, "the load() method with a malformed JSON config file": { @@ -50,7 +50,7 @@ vows.describe('nconf/stores/file').addBatch({ "When using the nconf file store": { topic: function () { var tmpPath = path.join(__dirname, '..', 'fixtures', 'tmp.json'), - tmpStore = new nconf.stores.File({ file: tmpPath }); + tmpStore = new nconf.File({ file: tmpPath }); return tmpStore; }, "the save() method": { @@ -108,7 +108,7 @@ vows.describe('nconf/stores/file').addBatch({ topic: function () { var filePath = this.filePath = path.join(process.env.HOME, '.nconf'); fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); - return new (nconf.stores.File)({ + return new (nconf.File)({ file: '.nconf' }) }, @@ -121,7 +121,7 @@ vows.describe('nconf/stores/file').addBatch({ "when the target file doesn't exist higher in the directory tree": { topic: function () { var filePath = this.filePath = path.join(__dirname, '..', 'fixtures', 'search-store.json'); - return new (nconf.stores.File)({ + return new (nconf.File)({ dir: path.dirname(filePath), file: 'search-store.json' }) diff --git a/test/stores/literal-test.js b/test/stores/literal-test.js index 3944bab..9876c3d 100644 --- a/test/stores/literal-test.js +++ b/test/stores/literal-test.js @@ -11,8 +11,8 @@ var vows = require('vows'), nconf = require('../../lib/nconf'); vows.describe('nconf/stores/literal').addBatch({ - "An instance of nconf.stores.Literal": { - topic: new nconf.stores.Literal({ + "An instance of nconf.Literal": { + topic: new nconf.Literal({ foo: 'bar', one: 2 }), diff --git a/test/stores/memory-store-test.js b/test/stores/memory-store-test.js index 1512262..aa3f095 100644 --- a/test/stores/memory-store-test.js +++ b/test/stores/memory-store-test.js @@ -12,7 +12,7 @@ var vows = require('vows'), vows.describe('nconf/stores/memory').addBatch({ "When using the nconf memory store": { - topic: new nconf.stores.Memory(), + topic: new nconf.Memory(), "the set() method": { "should respond with true": function (store) { assert.isTrue(store.set('foo:bar:bazz', 'buzz'));