[api test breaking refactor] Significant refactor to how nconf works. Now a fully hierarchical configuration storage mechanism capable of multiple levels of stores of the same type.
This commit is contained in:
parent
2bda7b6216
commit
da2da7aea8
11 changed files with 550 additions and 234 deletions
35
lib/nconf.js
35
lib/nconf.js
|
@ -9,39 +9,20 @@ var fs = require('fs'),
|
||||||
async = require('async'),
|
async = require('async'),
|
||||||
common = require('./nconf/common'),
|
common = require('./nconf/common'),
|
||||||
Provider = require('./nconf/provider').Provider,
|
Provider = require('./nconf/provider').Provider,
|
||||||
nconf = module.exports = Object.create(Provider.prototype);
|
nconf = module.exports = new Provider();
|
||||||
|
|
||||||
//
|
|
||||||
// Use the memory engine by default.
|
|
||||||
//
|
|
||||||
nconf.use('memory');
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Expose the version from the package.json using `pkginfo`.
|
// Expose the version from the package.json using `pkginfo`.
|
||||||
//
|
//
|
||||||
require('pkginfo')(module, 'version');
|
require('pkginfo')(module, 'version');
|
||||||
|
|
||||||
//
|
|
||||||
// ### function path (key)
|
|
||||||
// #### @key {string} The ':' delimited key to split
|
|
||||||
// Returns a fully-qualified path to a nested nconf key.
|
|
||||||
//
|
|
||||||
nconf.path = function (key) {
|
|
||||||
return key.split(':');
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function key (arguments)
|
|
||||||
// Returns a `:` joined string from the `arguments`.
|
|
||||||
//
|
|
||||||
nconf.key = function () {
|
|
||||||
return Array.prototype.slice.call(arguments).join(':');
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Expose the various components included with nconf
|
// Expose the various components included with nconf
|
||||||
//
|
//
|
||||||
nconf.loadFiles = common.loadFiles;
|
nconf.key = common.key;
|
||||||
nconf.formats = require('./nconf/formats');
|
nconf.path = common.path;
|
||||||
nconf.stores = require('./nconf/stores');
|
nconf.loadFiles = common.loadFiles;
|
||||||
nconf.Provider = Provider;
|
nconf.loadFilesSync = common.loadFilesSync;
|
||||||
|
nconf.formats = require('./nconf/formats');
|
||||||
|
nconf.stores = require('./nconf/stores');
|
||||||
|
nconf.Provider = Provider;
|
|
@ -8,12 +8,29 @@
|
||||||
var fs = require('fs'),
|
var fs = require('fs'),
|
||||||
async = require('async'),
|
async = require('async'),
|
||||||
formats = require('./formats'),
|
formats = require('./formats'),
|
||||||
stores = require('./stores');
|
Memory = require('./stores/Memory').Memory;
|
||||||
|
|
||||||
var common = exports;
|
var common = exports;
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function loadFiles (files)
|
// ### function path (key)
|
||||||
|
// #### @key {string} The ':' delimited key to split
|
||||||
|
// Returns a fully-qualified path to a nested nconf key.
|
||||||
|
//
|
||||||
|
common.path = function (key) {
|
||||||
|
return key.split(':');
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function key (arguments)
|
||||||
|
// Returns a `:` joined string from the `arguments`.
|
||||||
|
//
|
||||||
|
common.key = function () {
|
||||||
|
return Array.prototype.slice.call(arguments).join(':');
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function loadFiles (files, callback)
|
||||||
// #### @files {Object|Array} List of files (or settings object) to load.
|
// #### @files {Object|Array} List of files (or settings object) to load.
|
||||||
// #### @callback {function} Continuation to respond to when complete.
|
// #### @callback {function} Continuation to respond to when complete.
|
||||||
// Loads all the data in the specified `files`.
|
// Loads all the data in the specified `files`.
|
||||||
|
@ -23,8 +40,7 @@ common.loadFiles = function (files, callback) {
|
||||||
return callback(null, {});
|
return callback(null, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = Array.isArray(files) ? { files: files } : files,
|
var options = Array.isArray(files) ? { files: files } : files;
|
||||||
store = new stores.Memory();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the default JSON format if not already
|
// Set the default JSON format if not already
|
||||||
|
@ -32,22 +48,64 @@ common.loadFiles = function (files, callback) {
|
||||||
//
|
//
|
||||||
options.format = options.format || formats.json;
|
options.format = options.format || formats.json;
|
||||||
|
|
||||||
function loadFile (file, next) {
|
function parseFile (file, next) {
|
||||||
fs.readFile(file, function (err, data) {
|
fs.readFile(file, function (err, data) {
|
||||||
if (err) {
|
return !err
|
||||||
return next(err);
|
? next(null, options.format.parse(data.toString()))
|
||||||
}
|
: next(err);
|
||||||
|
|
||||||
data = options.format.parse(data.toString());
|
|
||||||
Object.keys(data).forEach(function (key) {
|
|
||||||
store.merge(key, data[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async.forEach(files, loadFile, function (err) {
|
async.map(files, parseFile, function (err, objs) {
|
||||||
return err ? callback(err) : callback(null, store.store);
|
return err ? callback(err) : callback(null, common.merge(objs));
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function loadFilesSync (files)
|
||||||
|
// #### @files {Object|Array} List of files (or settings object) to load.
|
||||||
|
// Loads all the data in the specified `files` synchronously.
|
||||||
|
//
|
||||||
|
common.loadFilesSync = function (files) {
|
||||||
|
if (!files) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set the default JSON format if not already
|
||||||
|
// specified
|
||||||
|
//
|
||||||
|
var options = Array.isArray(files) ? { files: files } : files;
|
||||||
|
options.format = options.format || formats.json;
|
||||||
|
|
||||||
|
return common.merge(files.map(function (file) {
|
||||||
|
return options.format.parse(fs.readFileSync(file, 'utf8'));
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function merge (objs)
|
||||||
|
// #### @objs {Array} Array of object literals to merge
|
||||||
|
// Merges the specified `objs` using a temporary instance
|
||||||
|
// of `stores.Memory`.
|
||||||
|
//
|
||||||
|
common.merge = function (objs) {
|
||||||
|
var store = new Memory();
|
||||||
|
|
||||||
|
objs.forEach(function (obj) {
|
||||||
|
Object.keys(obj).forEach(function (key) {
|
||||||
|
store.merge(key, obj[key]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return store.store;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function capitalize (str)
|
||||||
|
// #### @str {string} String to capitalize
|
||||||
|
// Capitalizes the specified `str`.
|
||||||
|
//
|
||||||
|
common.capitalize = function (str) {
|
||||||
|
return str && str[0].toUpperCase() + str.slice(1);
|
||||||
};
|
};
|
|
@ -9,6 +9,8 @@ var async = require('async'),
|
||||||
common = require('./common'),
|
common = require('./common'),
|
||||||
stores = require('./stores');
|
stores = require('./stores');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function Provider (options)
|
// ### function Provider (options)
|
||||||
// #### @options {Object} Options for this instance.
|
// #### @options {Object} Options for this instance.
|
||||||
|
@ -16,38 +18,137 @@ var async = require('async'),
|
||||||
// for exposing the pluggable storage features of `nconf`.
|
// for exposing the pluggable storage features of `nconf`.
|
||||||
//
|
//
|
||||||
var Provider = exports.Provider = function (options) {
|
var Provider = exports.Provider = function (options) {
|
||||||
options = options || {};
|
var self = this;
|
||||||
this.overrides = options.overrides || null;
|
|
||||||
this.useArgv = options.useArgv || false;
|
//
|
||||||
this.useEnv = options.useEnv || false;
|
// Setup default options for working with `stores`,
|
||||||
this.store = stores.create(options.type || 'memory', options);
|
// `overrides`, `process.env` and `process.argv`.
|
||||||
|
//
|
||||||
|
options = options || {};
|
||||||
|
this._overrides = options.overrides || null;
|
||||||
|
this._argv = options.argv || false;
|
||||||
|
this._env = options.env || false;
|
||||||
|
this._reserved = Object.keys(Provider.prototype);
|
||||||
|
this._stores = [];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add the default `system` store for working with
|
||||||
|
// `overrides`, `process.env`, `process.argv` and
|
||||||
|
// a simple in-memory objects.
|
||||||
|
//
|
||||||
|
this.add('system', options);
|
||||||
|
|
||||||
|
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 (store) {
|
||||||
|
self.add(store.name || store.type, store);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function use (type, options)
|
// ### function use (name, options)
|
||||||
// #### @type {string} Type of the nconf store to use.
|
// #### @type {string} Type of the nconf store to use.
|
||||||
// #### @options {Object} Options for the store instance.
|
// #### @options {Object} Options for the store instance.
|
||||||
// Sets the active `this.store` to a new instance of the
|
// Adds (or replaces) a new store with the specified `name`
|
||||||
// specified `type`.
|
// and `options`. If `options.type` is not set, then `name`
|
||||||
|
// will be used instead:
|
||||||
//
|
//
|
||||||
Provider.prototype.use = function (type, options) {
|
// provider.use('file');
|
||||||
var self = this;
|
// provider.use('file', { type: 'file', filename: '/path/to/userconf' })
|
||||||
options = options || {};
|
//
|
||||||
|
Provider.prototype.use = function (name, options) {
|
||||||
|
if (name === 'system') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (this._reserved.indexOf(name) !== -1) {
|
||||||
|
throw new Error('Cannot use reserved name: ' + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
options.type = options.type || name;
|
||||||
|
|
||||||
function sameOptions () {
|
function sameOptions (store) {
|
||||||
return Object.keys(options).every(function (key) {
|
return Object.keys(options).every(function (key) {
|
||||||
return options[key] === self.store[key];
|
return options[key] === store[key];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.store || type.toLowerCase() !== this.store.type
|
var store = this[name],
|
||||||
|| !sameOptions()) {
|
update = store && !sameOptions(store);
|
||||||
this.store = stores.create(type, options);
|
|
||||||
|
if (!store || update) {
|
||||||
|
if (update) {
|
||||||
|
this.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.add(name, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function add (name, options)
|
||||||
|
// #### @name {string} Name of the store to add to this instance
|
||||||
|
// #### @options {Object} Options for the store to create
|
||||||
|
// Adds a new store with the specified `name` and `options`. If `options.type`
|
||||||
|
// is not set, then `name` will be used instead:
|
||||||
|
//
|
||||||
|
// provider.add('memory');
|
||||||
|
// provider.add('userconf', { type: 'file', filename: '/path/to/userconf' })
|
||||||
|
//
|
||||||
|
Provider.prototype.add = function (name, options) {
|
||||||
|
if (this._reserved.indexOf(name) !== -1) {
|
||||||
|
throw new Error('Cannot use reserved name: ' + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
options.type = options.type || name;
|
||||||
|
|
||||||
|
if (Object.keys(stores).indexOf(common.capitalize(options.type)) === -1) {
|
||||||
|
throw new Error('Cannot add store with unknown type: ' + options.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
this[name] = this.create(options.type, options);
|
||||||
|
this._stores.push(name);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function remove (name)
|
||||||
|
// #### @name {string} Name of the store to remove from this instance
|
||||||
|
// Removes a store with the specified `name` from this instance. Users
|
||||||
|
// are allowed to pass in a type argument (e.g. `memory`) as name if
|
||||||
|
// this was used in the call to `.add()`.
|
||||||
|
//
|
||||||
|
Provider.prototype.remove = function (name) {
|
||||||
|
if (this._reserved.indexOf(name) !== -1) {
|
||||||
|
throw new Error('Cannot use reserved name: ' + name);
|
||||||
|
}
|
||||||
|
else if (!this[name]) {
|
||||||
|
throw new Error('Cannot remove store that does not exist: ' + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete this[name];
|
||||||
|
this._stores.splice(this._stores.indexOf(name), 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function create (type, options)
|
||||||
|
// #### @type {string} Type of the nconf store to use.
|
||||||
|
// #### @options {Object} Options for the store instance.
|
||||||
|
// Creates a store of the specified `type` using the
|
||||||
|
// specified `options`.
|
||||||
|
//
|
||||||
|
Provider.prototype.create = function (type, options) {
|
||||||
|
return new stores[common.capitalize(type.toLowerCase())](options);
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function get (key, callback)
|
// ### function get (key, callback)
|
||||||
// #### @key {string} Key to retrieve for this instance.
|
// #### @key {string} Key to retrieve for this instance.
|
||||||
|
@ -55,14 +156,6 @@ Provider.prototype.use = function (type, options) {
|
||||||
// Retrieves the value for the specified key (if any).
|
// Retrieves the value for the specified key (if any).
|
||||||
//
|
//
|
||||||
Provider.prototype.get = function (key, callback) {
|
Provider.prototype.get = function (key, callback) {
|
||||||
if (this.overrides && Object.prototype.hasOwnProperty.call(this.overrides, key)) {
|
|
||||||
if (callback) {
|
|
||||||
callback(null, this.overrides[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.overrides[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._execute('get', 1, key, callback);
|
return this._execute('get', 1, key, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,6 +170,25 @@ Provider.prototype.set = function (key, value, callback) {
|
||||||
return this._execute('set', 2, key, value, callback);
|
return this._execute('set', 2, key, value, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function reset (callback)
|
||||||
|
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
||||||
|
// Clears all keys associated with this instance.
|
||||||
|
//
|
||||||
|
Provider.prototype.reset = function (callback) {
|
||||||
|
return this._execute('reset', 0, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function clear (key, callback)
|
||||||
|
// #### @key {string} Key to remove from this instance
|
||||||
|
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
||||||
|
// Removes the value for the specified `key` from this instance.
|
||||||
|
//
|
||||||
|
Provider.prototype.clear = function (key, callback) {
|
||||||
|
return this._execute('clear', 1, key, callback);
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function merge ([key,] value [, callback])
|
// ### function merge ([key,] value [, callback])
|
||||||
// #### @key {string} Key to merge the value into
|
// #### @key {string} Key to merge the value into
|
||||||
|
@ -109,51 +221,48 @@ Provider.prototype.merge = function () {
|
||||||
return this._execute('merge', 2, key, value, callback);
|
return this._execute('merge', 2, key, value, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
|
||||||
// ### function mergeFiles (files, callback)
|
|
||||||
// #### @files {Object|Array} List of files (or settings object) to load.
|
|
||||||
// #### @callback {function} Continuation to respond to when complete.
|
|
||||||
// Merges all `key:value` pairs in the `files` supplied into the
|
|
||||||
// store that is managed by this provider instance.
|
|
||||||
//
|
|
||||||
Provider.prototype.mergeFiles = function (files, callback) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
common.loadFiles(files, function (err, merged) {
|
|
||||||
return !err
|
|
||||||
? self.merge(merged, callback)
|
|
||||||
: onError(err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function clear (key, callback)
|
|
||||||
// #### @key {string} Key to remove from this instance
|
|
||||||
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
|
||||||
// Removes the value for the specified `key` from this instance.
|
|
||||||
//
|
|
||||||
Provider.prototype.clear = function (key, callback) {
|
|
||||||
return this._execute('clear', 1, key, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function load (callback)
|
// ### function load (callback)
|
||||||
// #### @callback {function} Continuation to respond to when complete.
|
// #### @callback {function} Continuation to respond to when complete.
|
||||||
// Responds with an Object representing all keys associated in this instance.
|
// Responds with an Object representing all keys associated in this instance.
|
||||||
//
|
//
|
||||||
Provider.prototype.load = function (callback) {
|
Provider.prototype.load = function (callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
function loadStoreSync(name) {
|
||||||
|
var store = self[name];
|
||||||
|
|
||||||
|
if (!store.loadSync) {
|
||||||
|
throw new Error('nconf store ' + store.type + ' has no loadSync() method');
|
||||||
|
}
|
||||||
|
|
||||||
|
return store.loadSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadStore(name, next) {
|
||||||
|
var store = self[name];
|
||||||
|
|
||||||
|
if (!store.load && !store.loadSync) {
|
||||||
|
return next(new Error('nconf store ' + store.type + ' has no load() method'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return store.loadSync
|
||||||
|
? next(null, store.loadSync())
|
||||||
|
: store.load(next);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we don't have a callback and the current
|
// If we don't have a callback and the current
|
||||||
// store is capable of loading synchronously
|
// store is capable of loading synchronously
|
||||||
// then do so.
|
// then do so.
|
||||||
//
|
//
|
||||||
if (!callback && this.store.loadSync) {
|
if (!callback) {
|
||||||
return this.store.loadSync();
|
return common.merge(this._stores.map(loadStoreSync));
|
||||||
}
|
}
|
||||||
|
|
||||||
return !this.store.load
|
async.map(this._stores, loadStore, function (err, objs) {
|
||||||
? onError(new Error('nconf store ' + this.store.type + ' has no load() method'), callback)
|
return err ? callback(err) : callback(null, common.merge(objs));
|
||||||
: this.store.load(callback);
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -164,32 +273,47 @@ Provider.prototype.load = function (callback) {
|
||||||
// instance and then adds all key-value pairs in `value`.
|
// instance and then adds all key-value pairs in `value`.
|
||||||
//
|
//
|
||||||
Provider.prototype.save = function (value, callback) {
|
Provider.prototype.save = function (value, callback) {
|
||||||
if (!callback) {
|
if (!callback && typeof value === 'function') {
|
||||||
callback = value;
|
callback = value;
|
||||||
value = null;
|
value = null;
|
||||||
|
|
||||||
//
|
|
||||||
// If we still don't have a callback and the
|
|
||||||
// current store is capable of saving synchronously
|
|
||||||
// then do so.
|
|
||||||
//
|
|
||||||
if (!callback && this.store.saveSync) {
|
|
||||||
return this.store.saveSync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !this.store.save
|
var self = this;
|
||||||
? onError(new Error('nconf store ' + this.store.type + ' has no save() method'), callback)
|
|
||||||
: this.store.save(value, callback);
|
function saveStoreSync(name) {
|
||||||
};
|
var store = self[name];
|
||||||
|
|
||||||
//
|
if (!store.saveSync) {
|
||||||
// ### function reset (callback)
|
throw new Error('nconf store ' + store.type + ' has no saveSync() method');
|
||||||
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
}
|
||||||
// Clears all keys associated with this instance.
|
|
||||||
//
|
return store.saveSync();
|
||||||
Provider.prototype.reset = function (callback) {
|
}
|
||||||
return this._execute('reset', 0, callback);
|
|
||||||
|
function saveStore(name, next) {
|
||||||
|
var store = self[name];
|
||||||
|
|
||||||
|
if (!store.load && !store.saveSync) {
|
||||||
|
return next(new Error('nconf store ' + store.type + ' has no save() method'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return store.saveSync
|
||||||
|
? next(null, store.saveSync())
|
||||||
|
: store.save(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If we don't have a callback and the current
|
||||||
|
// store is capable of saving synchronously
|
||||||
|
// then do so.
|
||||||
|
//
|
||||||
|
if (!callback) {
|
||||||
|
return common.merge(this._stores.map(saveStoreSync));
|
||||||
|
}
|
||||||
|
|
||||||
|
async.map(this._stores, saveStore, function (err, objs) {
|
||||||
|
return err ? callback(err) : callback();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -197,49 +321,67 @@ Provider.prototype.reset = function (callback) {
|
||||||
// #### @action {string} Action to execute on `this.store`.
|
// #### @action {string} Action to execute on `this.store`.
|
||||||
// #### @syncLength {number} Function length of the sync version.
|
// #### @syncLength {number} Function length of the sync version.
|
||||||
// #### @arguments {Array} Arguments array to apply to the action
|
// #### @arguments {Array} Arguments array to apply to the action
|
||||||
// Executes the specified `action` on `this.store`, ensuring a callback supplied
|
// Executes the specified `action` on all stores for this instance, ensuring a callback supplied
|
||||||
// to a synchronous store function is still invoked.
|
// to a synchronous store function is still invoked.
|
||||||
//
|
//
|
||||||
Provider.prototype._execute = function (action, syncLength /* [arguments] */) {
|
Provider.prototype._execute = function (action, syncLength /* [arguments] */) {
|
||||||
var args = Array.prototype.slice.call(arguments, 2),
|
var args = Array.prototype.slice.call(arguments, 2),
|
||||||
callback,
|
callback = typeof args[args.length - 1] === 'function' && args.pop(),
|
||||||
|
self = this,
|
||||||
response;
|
response;
|
||||||
|
|
||||||
if (this.store[action].length > syncLength) {
|
|
||||||
return this.store[action].apply(this.store, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
callback = typeof args[args.length - 1] === 'function' && args.pop();
|
function runAction (name, next) {
|
||||||
response = this.store[action].apply(this.store, args);
|
var store = self[name]
|
||||||
|
|
||||||
|
return store[action].length > syncLength
|
||||||
|
? store[action].apply(store, args.concat(next))
|
||||||
|
: next(null, store[action].apply(store, args));
|
||||||
|
}
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(null, response);
|
return async.forEach(self._stores, runAction, function (err) {
|
||||||
|
return err ? callback(err) : callback();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._stores.forEach(function (name) {
|
||||||
|
var store = self[name];
|
||||||
|
response = store[action].apply(store, args);
|
||||||
|
});
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### getter @useArgv {boolean}
|
// ### @argv {boolean}
|
||||||
// Gets a property indicating if we should wrap calls to `.get`
|
// Gets or sets a property representing overrides which supercede all
|
||||||
// by checking `optimist.argv`.
|
// other values for this instance.
|
||||||
//
|
//
|
||||||
Provider.prototype.__defineGetter__('useArgv', function () {
|
Provider.prototype.__defineSetter__('overrides', updateSystem.bind(this, 'overrides'));
|
||||||
return this._useArgv;
|
Provider.prototype.__defineGetter__('overrides', function () {
|
||||||
|
return this._argv;
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### setter @useArgv {boolean}
|
// ### @argv {boolean}
|
||||||
// Sets a property indicating if we should wrap calls to `.get`
|
// Gets or sets a property indicating if we should wrap calls to `.get`
|
||||||
// by checking `optimist.argv`.
|
// by checking `optimist.argv`. Can be a boolean or the pass-thru
|
||||||
|
// options for `optimist`.
|
||||||
//
|
//
|
||||||
Provider.prototype.__defineSetter__('useArgv', function (val) {
|
Provider.prototype.__defineSetter__('argv', updateSystem.bind(this, 'argv'));
|
||||||
this._useArgv = val || false;
|
Provider.prototype.__defineGetter__('argv', function () {
|
||||||
|
return this._argv;
|
||||||
if (this._useArgv) {
|
});
|
||||||
this._argv = this._argv || require('optimist').argv;
|
|
||||||
this.overrides = this.overrides || this._argv;
|
//
|
||||||
}
|
// ### @env {boolean}
|
||||||
|
// Gets or sets a property indicating if we should wrap calls to `.get`
|
||||||
|
// by checking `process.env`. Can be a boolean or an Array of
|
||||||
|
// environment variables to extract.
|
||||||
|
//
|
||||||
|
Provider.prototype.__defineSetter__('env', updateSystem.bind(this, 'env'));
|
||||||
|
Provider.prototype.__defineGetter__('env', function () {
|
||||||
|
return this._env;
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -251,4 +393,21 @@ function onError(err, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
throw err;
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper function for working with the
|
||||||
|
// default `system` store for providers.
|
||||||
|
//
|
||||||
|
function updateSystem(prop, value) {
|
||||||
|
var system = this['system'];
|
||||||
|
|
||||||
|
if (system[prop] === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value || false;
|
||||||
|
this['_' + prop] = value;
|
||||||
|
system[prop] = value;
|
||||||
|
system.loadSync();
|
||||||
}
|
}
|
|
@ -6,31 +6,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var fs = require('fs'),
|
var fs = require('fs'),
|
||||||
|
common = require('./common'),
|
||||||
stores = exports;
|
stores = exports;
|
||||||
|
|
||||||
function capitalize (str) {
|
|
||||||
return str && str[0].toUpperCase() + str.slice(1);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup all stores as lazy-loaded getters.
|
// Setup all stores as lazy-loaded getters.
|
||||||
//
|
//
|
||||||
fs.readdirSync(__dirname + '/stores').forEach(function (file) {
|
fs.readdirSync(__dirname + '/stores').forEach(function (file) {
|
||||||
var store = file.replace('.js', ''),
|
var store = file.replace('.js', ''),
|
||||||
name = capitalize(store);
|
name = common.capitalize(store);
|
||||||
|
|
||||||
stores.__defineGetter__(name, function () {
|
stores.__defineGetter__(name, function () {
|
||||||
return require('./stores/' + store)[name];
|
return require('./stores/' + store)[name];
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
|
||||||
// ### function create (type, options)
|
|
||||||
// #### @type {string} Type of the nconf store to use.
|
|
||||||
// #### @options {Object} Options for the store instance.
|
|
||||||
// Creates a store of the specified `type` using the
|
|
||||||
// specified `options`.
|
|
||||||
//
|
|
||||||
stores.create = function (type, options) {
|
|
||||||
return new stores[capitalize(type.toLowerCase())](options);
|
|
||||||
};
|
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var nconf = require('../../nconf');
|
var common = require('../common');
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function Memory (options)
|
// ### function Memory (options)
|
||||||
|
@ -16,10 +16,16 @@ var nconf = require('../../nconf');
|
||||||
// e.g. `my:nested:key` ==> `{ my: { nested: { key: } } }`
|
// e.g. `my:nested:key` ==> `{ my: { nested: { key: } } }`
|
||||||
//
|
//
|
||||||
var Memory = exports.Memory = function (options) {
|
var Memory = exports.Memory = function (options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
this.type = 'memory';
|
this.type = 'memory';
|
||||||
this.store = {};
|
this.store = {};
|
||||||
this.mtimes = {};
|
this.mtimes = {};
|
||||||
|
this.readOnly = false;
|
||||||
|
this.loadFrom = options.loadFrom || null;
|
||||||
|
|
||||||
|
if (this.loadFrom) {
|
||||||
|
this.store = common.loadFilesSync(this.loadFrom);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -29,7 +35,7 @@ var Memory = exports.Memory = function (options) {
|
||||||
//
|
//
|
||||||
Memory.prototype.get = function (key) {
|
Memory.prototype.get = function (key) {
|
||||||
var target = this.store,
|
var target = this.store,
|
||||||
path = nconf.path(key);
|
path = common.path(key);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Scope into the object to get the appropriate nested context
|
// Scope into the object to get the appropriate nested context
|
||||||
|
@ -54,8 +60,12 @@ Memory.prototype.get = function (key) {
|
||||||
// Sets the `value` for the specified `key` in this instance.
|
// Sets the `value` for the specified `key` in this instance.
|
||||||
//
|
//
|
||||||
Memory.prototype.set = function (key, value) {
|
Memory.prototype.set = function (key, value) {
|
||||||
|
if (this.readOnly) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var target = this.store,
|
var target = this.store,
|
||||||
path = nconf.path(key);
|
path = common.path(key);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update the `mtime` (modified time) of the key
|
// Update the `mtime` (modified time) of the key
|
||||||
|
@ -86,8 +96,12 @@ Memory.prototype.set = function (key, value) {
|
||||||
// Removes the value for the specified `key` from this instance.
|
// Removes the value for the specified `key` from this instance.
|
||||||
//
|
//
|
||||||
Memory.prototype.clear = function (key) {
|
Memory.prototype.clear = function (key) {
|
||||||
|
if (this.readOnly) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var target = this.store,
|
var target = this.store,
|
||||||
path = nconf.path(key);
|
path = common.path(key);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Remove the key from the set of `mtimes` (modified times)
|
// Remove the key from the set of `mtimes` (modified times)
|
||||||
|
@ -121,6 +135,10 @@ Memory.prototype.clear = function (key) {
|
||||||
// completely overwritten.
|
// completely overwritten.
|
||||||
//
|
//
|
||||||
Memory.prototype.merge = function (key, value) {
|
Memory.prototype.merge = function (key, value) {
|
||||||
|
if (this.readOnly) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If the key is not an `Object` or is an `Array`,
|
// If the key is not an `Object` or is an `Array`,
|
||||||
// then simply set it. Merging is for Objects.
|
// then simply set it. Merging is for Objects.
|
||||||
|
@ -131,7 +149,7 @@ Memory.prototype.merge = function (key, value) {
|
||||||
|
|
||||||
var self = this,
|
var self = this,
|
||||||
target = this.store,
|
target = this.store,
|
||||||
path = nconf.path(key),
|
path = common.path(key),
|
||||||
fullKey = key;
|
fullKey = key;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -174,6 +192,10 @@ Memory.prototype.merge = function (key, value) {
|
||||||
// Clears all keys associated with this instance.
|
// Clears all keys associated with this instance.
|
||||||
//
|
//
|
||||||
Memory.prototype.reset = function () {
|
Memory.prototype.reset = function () {
|
||||||
|
if (this.readOnly) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this.mtimes = {};
|
this.mtimes = {};
|
||||||
this.store = {};
|
this.store = {};
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -19,9 +19,11 @@ var util = require('util'),
|
||||||
var System = exports.System = function (options) {
|
var System = exports.System = function (options) {
|
||||||
Memory.call(this, options);
|
Memory.call(this, options);
|
||||||
|
|
||||||
this.type = 'system';
|
this.type = 'system';
|
||||||
this.only = options.only || [];
|
this.readOnly = true;
|
||||||
this.argv = options.argv || {};
|
this.overrides = options.overrides || null;
|
||||||
|
this.env = options.env || false;
|
||||||
|
this.argv = options.argv || false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inherit from the Memory store
|
// Inherit from the Memory store
|
||||||
|
@ -32,9 +34,65 @@ util.inherits(System, Memory);
|
||||||
// Loads the data passed in from `process.env` into this instance.
|
// Loads the data passed in from `process.env` into this instance.
|
||||||
//
|
//
|
||||||
System.prototype.loadSync = function () {
|
System.prototype.loadSync = function () {
|
||||||
this.loadEnv();
|
if (this.env) {
|
||||||
this.loadArgv();
|
this.loadEnv();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.argv) {
|
||||||
|
this.loadArgv();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.overrides) {
|
||||||
|
this.loadOverrides();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.store;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function loadOverrides ()
|
||||||
|
// Loads any overrides set on this instance into
|
||||||
|
// the underlying managed `Memory` store.
|
||||||
|
//
|
||||||
|
System.prototype.loadOverrides = function () {
|
||||||
|
if (!this.overrides) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this,
|
||||||
|
keys = Object.keys(this.overrides);
|
||||||
|
|
||||||
|
keys.forEach(function (key) {
|
||||||
|
self.set(key, self.overrides[key]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.store;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### function loadArgv ()
|
||||||
|
// Loads the data passed in from the command-line arguments
|
||||||
|
// into this instance.
|
||||||
|
//
|
||||||
|
System.prototype.loadArgv = function () {
|
||||||
|
var self = this,
|
||||||
|
argv;
|
||||||
|
|
||||||
|
if (typeof this.argv === 'object') {
|
||||||
|
argv = require('optimist').options(this.argv).argv;
|
||||||
|
}
|
||||||
|
else if (this.argv) {
|
||||||
|
argv = require('optimist').argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!argv) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(argv).forEach(function (key) {
|
||||||
|
self.set(key, argv[key]);
|
||||||
|
});
|
||||||
|
|
||||||
return this.store;
|
return this.store;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,28 +103,15 @@ System.prototype.loadSync = function () {
|
||||||
System.prototype.loadEnv = function () {
|
System.prototype.loadEnv = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
if (!this.env) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Object.keys(process.env).filter(function (key) {
|
Object.keys(process.env).filter(function (key) {
|
||||||
return !self.only.length || self.only.indexOf(key) !== -1;
|
return !self.env.length || self.env.indexOf(key) !== -1;
|
||||||
}).forEach(function (key) {
|
}).forEach(function (key) {
|
||||||
self.set(key, process.env[key]);
|
self.set(key, process.env[key]);
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.store;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function loadSync ()
|
|
||||||
// Loads the data passed in from the command-line arguments
|
|
||||||
// into this instance.
|
|
||||||
//
|
|
||||||
Argv.prototype.loadArgv = function () {
|
|
||||||
var self = this, argv = Object.keys(this.argv) > 0
|
|
||||||
? require('optimist').options(this.argv).argv
|
|
||||||
: require('optimist').argv;
|
|
||||||
|
|
||||||
Object.keys(argv).forEach(function (key) {
|
|
||||||
self.set(key, argv[key])
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.store;
|
return this.store;
|
||||||
};
|
};
|
32
test/common-test.js
Normal file
32
test/common-test.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* common.js: Tests for common utility function in nconf.
|
||||||
|
*
|
||||||
|
* (C) 2011, Charlie Robbins
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var fs = require('fs'),
|
||||||
|
path = require('path'),
|
||||||
|
vows = require('vows'),
|
||||||
|
assert = require('assert'),
|
||||||
|
helpers = require('./helpers'),
|
||||||
|
nconf = require('../lib/nconf');
|
||||||
|
|
||||||
|
var mergeDir = path.join(__dirname, 'fixtures', 'merge'),
|
||||||
|
files = fs.readdirSync(mergeDir).map(function (f) { return path.join(mergeDir, f) });
|
||||||
|
|
||||||
|
vows.describe('nconf/common').addBatch({
|
||||||
|
"Using nconf.common module": {
|
||||||
|
"the loadFiles() method": {
|
||||||
|
topic: function () {
|
||||||
|
nconf.loadFiles(files, this.callback);
|
||||||
|
},
|
||||||
|
"should merge the files correctly": helpers.assertMerged
|
||||||
|
},
|
||||||
|
"the loadFilesSync() method": {
|
||||||
|
"should merge the files correctly": function () {
|
||||||
|
helpers.assertMerged(null, nconf.loadFilesSync(files));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).export(module);
|
40
test/helpers.js
Normal file
40
test/helpers.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* helpers.js: Test helpers for nconf.
|
||||||
|
*
|
||||||
|
* (C) 2011, Charlie Robbins
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var assert = require('assert'),
|
||||||
|
spawn = require('child_process').spawn,
|
||||||
|
nconf = require('../lib/nconf');
|
||||||
|
|
||||||
|
exports.assertMerged = function (err, merged) {
|
||||||
|
merged = merged instanceof nconf.Provider
|
||||||
|
? merged.store.store
|
||||||
|
: merged;
|
||||||
|
|
||||||
|
assert.isNull(err);
|
||||||
|
assert.isObject(merged);
|
||||||
|
assert.isTrue(merged.apples);
|
||||||
|
assert.isTrue(merged.bananas);
|
||||||
|
assert.isObject(merged.candy);
|
||||||
|
assert.isTrue(merged.candy.something1);
|
||||||
|
assert.isTrue(merged.candy.something2);
|
||||||
|
assert.isTrue(merged.candy.something3);
|
||||||
|
assert.isTrue(merged.candy.something4);
|
||||||
|
assert.isTrue(merged.dates);
|
||||||
|
assert.isTrue(merged.elderberries);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.assertDefaults = function (script) {
|
||||||
|
return {
|
||||||
|
topic: function () {
|
||||||
|
spawn('node', [script, '--something', 'foobar'])
|
||||||
|
.stdout.once('data', this.callback.bind(this, null));
|
||||||
|
},
|
||||||
|
"should respond with the value passed into the script": function (_, data) {
|
||||||
|
assert.equal(data.toString(), 'foobar');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ vows.describe('nconf').addBatch({
|
||||||
"the use() method": {
|
"the use() method": {
|
||||||
"should instaniate the correct store": function () {
|
"should instaniate the correct store": function () {
|
||||||
nconf.use('memory');
|
nconf.use('memory');
|
||||||
assert.instanceOf(nconf.store, nconf.stores.Memory);
|
assert.instanceOf(nconf.memory, nconf.stores.Memory);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"it should": {
|
"it should": {
|
||||||
|
|
|
@ -10,60 +10,38 @@ var assert = require('assert'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
spawn = require('child_process').spawn,
|
spawn = require('child_process').spawn,
|
||||||
vows = require('vows'),
|
vows = require('vows'),
|
||||||
|
helpers = require('./helpers'),
|
||||||
nconf = require('../lib/nconf');
|
nconf = require('../lib/nconf');
|
||||||
|
|
||||||
var mergeFixtures = path.join(__dirname, 'fixtures', 'merge'),
|
var fixturesDir = path.join(__dirname, 'fixtures'),
|
||||||
|
mergeFixtures = path.join(fixturesDir, 'merge'),
|
||||||
files = [path.join(mergeFixtures, 'file1.json'), path.join(mergeFixtures, 'file2.json')],
|
files = [path.join(mergeFixtures, 'file1.json'), path.join(mergeFixtures, 'file2.json')],
|
||||||
override = JSON.parse(fs.readFileSync(files[0]), 'utf8'),
|
override = JSON.parse(fs.readFileSync(files[0]), 'utf8'),
|
||||||
first = '/path/to/file1',
|
first = '/path/to/file1',
|
||||||
second = '/path/to/file2';
|
second = '/path/to/file2';
|
||||||
|
|
||||||
function assertDefaults (script) {
|
|
||||||
return {
|
|
||||||
topic: function () {
|
|
||||||
spawn('node', [script, '--something', 'foobar'])
|
|
||||||
.stdout.once('data', this.callback.bind(this, null));
|
|
||||||
},
|
|
||||||
"should respond with the value passed into the script": function (_, data) {
|
|
||||||
assert.equal(data.toString(), 'foobar');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertMerged (provider) {
|
|
||||||
var store = provider.store.store;
|
|
||||||
assert.isTrue(store.apples);
|
|
||||||
assert.isTrue(store.bananas);
|
|
||||||
assert.isTrue(store.candy.something1);
|
|
||||||
assert.isTrue(store.candy.something2);
|
|
||||||
assert.isTrue(store.candy.something3);
|
|
||||||
assert.isTrue(store.candy.something4);
|
|
||||||
assert.isTrue(store.dates);
|
|
||||||
assert.isTrue(store.elderberries);
|
|
||||||
}
|
|
||||||
|
|
||||||
vows.describe('nconf/provider').addBatch({
|
vows.describe('nconf/provider').addBatch({
|
||||||
"When using nconf": {
|
"When using nconf": {
|
||||||
"an instance of 'nconf.Provider'": {
|
"an instance of 'nconf.Provider'": {
|
||||||
"calling the use() method with the same store type and different options": {
|
"calling the use() method with the same store type and different options": {
|
||||||
topic: new nconf.Provider().use('file', { file: first }),
|
topic: new nconf.Provider().use('file', { file: first }),
|
||||||
"should use a new instance of the store type": function (provider) {
|
"should use a new instance of the store type": function (provider) {
|
||||||
var old = provider.store;
|
var old = provider.file;
|
||||||
|
|
||||||
assert.equal(provider.store.file, first);
|
assert.equal(provider.file.file, first);
|
||||||
provider.use('file', { file: second });
|
provider.use('file', { file: second });
|
||||||
|
|
||||||
assert.notStrictEqual(old, provider.store);
|
assert.notStrictEqual(old, provider.file);
|
||||||
assert.equal(provider.store.file, second);
|
assert.equal(provider.file.file, second);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"when 'useArgv' is true": assertDefaults(path.join(__dirname, 'fixtures', 'scripts', 'nconf-override.js'))
|
//"when 'useArgv' is true": helpers.assertDefaults(path.join(fixturesDir, 'scripts', 'nconf-override.js'))
|
||||||
},
|
},
|
||||||
"the default nconf provider": {
|
/*"the default nconf provider": {
|
||||||
"when 'useArgv' is true": assertDefaults(path.join(__dirname, 'fixtures', 'scripts', 'default-override.js'))
|
"when 'useArgv' is true": helpers.assertDefaults(path.join(fixturesDir, 'scripts', 'default-override.js'))
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}).addBatch({
|
})/*.addBatch({
|
||||||
"When using nconf": {
|
"When using nconf": {
|
||||||
"an instance of 'nconf.Provider'": {
|
"an instance of 'nconf.Provider'": {
|
||||||
"the merge() method": {
|
"the merge() method": {
|
||||||
|
@ -71,7 +49,7 @@ vows.describe('nconf/provider').addBatch({
|
||||||
"should have the result merged in": function (provider) {
|
"should have the result merged in": function (provider) {
|
||||||
provider.load();
|
provider.load();
|
||||||
provider.merge(override);
|
provider.merge(override);
|
||||||
assertMerged(provider);
|
helpers.assertMerged(null, provider);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"the mergeFiles() method": {
|
"the mergeFiles() method": {
|
||||||
|
@ -80,9 +58,9 @@ vows.describe('nconf/provider').addBatch({
|
||||||
provider.mergeFiles(files, this.callback.bind(this, null, provider))
|
provider.mergeFiles(files, this.callback.bind(this, null, provider))
|
||||||
},
|
},
|
||||||
"should have the result merged in": function (_, provider) {
|
"should have the result merged in": function (_, provider) {
|
||||||
assertMerged(provider);
|
helpers.assertMerged(null, provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).export(module);
|
})*/.export(module);
|
15
usage.js
15
usage.js
|
@ -2,6 +2,21 @@ var fs = require('fs'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
nconf = require('./lib/nconf');
|
nconf = require('./lib/nconf');
|
||||||
|
|
||||||
|
var single = new nconf.Provider({
|
||||||
|
useEnv: true,
|
||||||
|
useArgv: true,
|
||||||
|
store: {
|
||||||
|
type: 'file',
|
||||||
|
file: path.join(__dirname, 'config.json')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var multiple = new nconf.Provider({
|
||||||
|
stores: [
|
||||||
|
{ type: 'file', }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup nconf to use the 'file' store and set a couple of values;
|
// Setup nconf to use the 'file' store and set a couple of values;
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue