Socket
Socket
Sign inDemoInstall

nconf

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nconf - npm Package Compare versions

Comparing version 0.3.1 to 0.4.3

docs/nconf/stores/system.html

35

lib/nconf.js

@@ -12,10 +12,5 @@ /*

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`.

@@ -26,24 +21,10 @@ //

//
// ### 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
//
nconf.loadFiles = common.loadFiles;
nconf.formats = require('./nconf/formats');
nconf.stores = require('./nconf/stores');
nconf.Provider = Provider;
nconf.key = common.key;
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;

@@ -11,3 +11,3 @@ /*

formats = require('./formats'),
stores = require('./stores');
Memory = require('./stores/memory').Memory;

@@ -17,3 +17,20 @@ 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.

@@ -28,4 +45,3 @@ // #### @callback {function} Continuation to respond to when complete.

var options = Array.isArray(files) ? { files: files } : files,
store = new stores.Memory();
var options = Array.isArray(files) ? { files: files } : files;

@@ -38,20 +54,62 @@ //

function loadFile (file, next) {
function parseFile (file, next) {
fs.readFile(file, function (err, data) {
if (err) {
return next(err);
}
return !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]);
});
async.map(files, parseFile, function (err, objs) {
return err ? callback(err) : callback(null, common.merge(objs));
});
};
next();
});
//
// ### 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;
}
async.forEach(files, loadFile, function (err) {
return err ? callback(err) : callback(null, store.store);
//
// 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);
};

@@ -12,2 +12,4 @@ /*

//

@@ -20,29 +22,91 @@ // ### function Provider (options)

var Provider = exports.Provider = function (options) {
options = options || {};
this.overrides = options.overrides || null
this.useArgv = options.useArgv || false;
this.store = stores.create(options.type || 'memory', options);
var self = this;
//
// Setup default options for working with `stores`,
// `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 = [];
this.sources = [];
//
// Add the default `system` store for working with
// `overrides`, `process.env`, `process.argv` and
// a simple in-memory objects.
//
this.add('system', 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));
});
}
};
//
// ### function use (type, options)
// ### function use (name, options)
// #### @type {string} Type of the nconf store to use.
// #### @options {Object} Options for the store instance.
// Sets the active `this.store` to a new instance of the
// specified `type`.
// Adds (or replaces) a new store with the specified `name`
// and `options`. If `options.type` is not set, then `name`
// will be used instead:
//
Provider.prototype.use = function (type, options) {
var self = this;
options = options || {};
// provider.use('file');
// provider.use('file', { type: 'file', filename: '/path/to/userconf' })
//
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 || {};
var type = options.type || name;
function sameOptions () {
function sameOptions (store) {
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
|| !sameOptions()) {
this.store = stores.create(type, options);
var store = this[name],
update = store && !sameOptions(store);
if (!store || update) {
if (update) {
this.remove(name);
}
this.add(name, options);
}

@@ -54,2 +118,65 @@

//
// ### 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 || {};
var type = options.type || name;
if (Object.keys(stores).indexOf(common.capitalize(type)) === -1) {
throw new Error('Cannot add store with unknown type: ' + type);
}
this[name] = this.create(type, options);
this._stores.push(name);
if (this[name].loadSync) {
this[name].loadSync();
}
return this;
};
//
// ### 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);
return this;
};
//
// ### 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)

@@ -61,11 +188,41 @@ // #### @key {string} Key to retrieve for this instance.

Provider.prototype.get = function (key, callback) {
if (this.overrides && Object.prototype.hasOwnProperty.call(this.overrides, key)) {
if (callback) {
callback(null, this.overrides[key]);
//
// If there is no callback we can short-circuit into the default
// logic for traversing stores.
//
if (!callback) {
return this._execute('get', 1, key, callback);
}
//
// Otherwise the asynchronous, hierarchical `get` is
// slightly more complicated because we do not need to traverse
// the entire set of stores, but up until there is a defined value.
//
var current = 0,
self = this,
response;
async.whilst(function () {
return typeof response === 'undefined' && current < self._stores.length;
}, function (next) {
var store = self[self._stores[current]];
current++;
if (store.get.length >= 2) {
return store.get(key, function (err, value) {
if (err) {
return next(err);
}
response = value;
next();
});
}
return this.overrides[key];
}
return this._execute('get', 1, key, callback);
response = store.get(key);
next();
}, function (err) {
return err ? callback(err) : callback(null, response);
});
};

@@ -85,2 +242,21 @@

//
// ### 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])

@@ -118,29 +294,2 @@ // #### @key {string} Key to merge the value into

//
// ### 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)

@@ -151,14 +300,69 @@ // #### @callback {function} Continuation to respond to when complete.

Provider.prototype.load = function (callback) {
//
// If we don't have a callback and the current
// store is capable of loading synchronously
// then do so.
//
if (!callback && this.store.loadSync) {
return this.store.loadSync();
var self = this,
stores = this._stores.map(function (name) { return self[name] });
function loadStoreSync(store) {
if (!store.loadSync) {
throw new Error('nconf store ' + store.type + ' has no loadSync() method');
}
return store.loadSync();
}
return !this.store.load
? onError(new Error('nconf store ' + this.store.type + ' has no load() method'), callback)
: this.store.load(callback);
function loadStore(store, next) {
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);
}
function loadBatch (targets, done) {
if (!done) {
return common.merge(targets.map(loadStoreSync));
}
async.map(targets, loadStore, function (err, objs) {
return err ? done(err) : done(null, common.merge(objs));
});
}
function mergeSources (data) {
//
// If `data` was returned then merge it into
// the system store.
//
if (data && typeof data === 'object') {
Object.keys(data).forEach(function (key) {
self.system.merge(key, data[key]);
});
}
}
function loadSources () {
//
// If we don't have a callback and the current
// store is capable of loading synchronously
// then do so.
//
if (!callback) {
mergeSources(loadBatch(self.sources));
return loadBatch(stores);
}
loadBatch(self.sources, function (err, data) {
if (err) {
return callback(err);
}
mergeSources(data);
return loadBatch(stores, callback);
});
}
return self.sources.length
? loadSources()
: loadBatch(stores, callback);
};

@@ -174,31 +378,46 @@

Provider.prototype.save = function (value, callback) {
if (!callback) {
if (!callback && typeof value === 'function') {
callback = value;
value = null;
}
var self = this;
function saveStoreSync(name) {
var store = self[name];
//
// 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();
if (!store.saveSync) {
throw new Error('nconf store ' + store.type + ' has no saveSync() method');
}
return store.saveSync();
}
return !this.store.save
? onError(new Error('nconf store ' + this.store.type + ' has no save() method'), callback)
: this.store.save(value, callback);
function saveStore(name, next) {
var store = self[name];
if (!store.save && !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();
});
};
//
// ### 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);
};
//
// ### @private function _execute (action, syncLength, [arguments])

@@ -208,3 +427,3 @@ // #### @action {string} Action to execute on `this.store`.

// #### @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.

@@ -214,16 +433,25 @@ //

var args = Array.prototype.slice.call(arguments, 2),
callback,
callback = typeof args[args.length - 1] === 'function' && args.pop(),
self = this,
response;
if (this.store[action].length > syncLength) {
return this.store[action].apply(this.store, args);
function runAction (name, next) {
var store = self[name]
return store[action].length > syncLength
? store[action].apply(store, args.concat(next))
: next(null, store[action].apply(store, args));
}
callback = typeof args[args.length - 1] === 'function' && args.pop();
response = this.store[action].apply(this.store, args);
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;

@@ -233,25 +461,28 @@ }

//
// ### getter @useArgv {boolean}
// Gets a property indicating if we should wrap calls to `.get`
// by checking `optimist.argv`.
// ### @argv {boolean}
// Gets or sets a property representing overrides which supercede all
// other values for this instance.
//
Provider.prototype.__defineGetter__('useArgv', function () {
return this._useArgv;
});
Provider.prototype.__defineSetter__('overrides', function (val) { updateSystem.call(this, 'overrides', val) });
Provider.prototype.__defineGetter__('overrides', function () { return this._argv });
//
// ### setter @useArgv {boolean}
// Sets a property indicating if we should wrap calls to `.get`
// by checking `optimist.argv`.
// ### @argv {boolean}
// Gets or sets a property indicating if we should wrap calls to `.get`
// by checking `optimist.argv`. Can be a boolean or the pass-thru
// options for `optimist`.
//
Provider.prototype.__defineSetter__('useArgv', function (val) {
this._useArgv = val || false;
if (this._useArgv) {
this._argv = this._argv || require('optimist').argv;
this.overrides = this.overrides || this._argv;
}
});
Provider.prototype.__defineSetter__('argv', function (val) { updateSystem.call(this, 'argv', val) });
Provider.prototype.__defineGetter__('argv', function () { return 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', function (val) { updateSystem.call(this, 'env', val) });
Provider.prototype.__defineGetter__('env', function () { return this._env });
//
// Throw the `err` if a callback is not supplied

@@ -265,2 +496,19 @@ //

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();
}

@@ -9,8 +9,5 @@ /*

var fs = require('fs'),
common = require('./common'),
stores = exports;
function capitalize (str) {
return str && str[0].toUpperCase() + str.slice(1);
};
//

@@ -21,3 +18,3 @@ // Setup all stores as lazy-loaded getters.

var store = file.replace('.js', ''),
name = capitalize(store);
name = common.capitalize(store);

@@ -27,13 +24,2 @@ stores.__defineGetter__(name, function () {

});
});
//
// ### 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);
};
});

@@ -21,5 +21,5 @@ /*

var File = exports.File = function (options) {
if (!options.file) {
if (!options || !options.file) {
throw new Error ('Missing required option `files`');
}
}

@@ -132,4 +132,4 @@ Memory.call(this, options);

try {
data = fs.readFileSync(this.file, 'utf8');
this.store = this.format.parse(data);
data = this.format.parse(fs.readFileSync(this.file, 'utf8'));
this.store = data;
}

@@ -136,0 +136,0 @@ catch (ex) {

@@ -8,3 +8,3 @@ /*

var nconf = require('../../nconf');
var common = require('../common');

@@ -20,6 +20,12 @@ //

var Memory = exports.Memory = function (options) {
options = options || {};
this.type = 'memory';
this.store = {};
this.mtimes = {};
options = options || {};
this.type = 'memory';
this.store = {};
this.mtimes = {};
this.readOnly = false;
this.loadFrom = options.loadFrom || null;
if (this.loadFrom) {
this.store = common.loadFilesSync(this.loadFrom);
}
};

@@ -34,3 +40,3 @@

var target = this.store,
path = nconf.path(key);
path = common.path(key);

@@ -60,4 +66,8 @@ //

Memory.prototype.set = function (key, value) {
if (this.readOnly) {
return false;
}
var target = this.store,
path = nconf.path(key);
path = common.path(key);

@@ -93,4 +103,8 @@ //

Memory.prototype.clear = function (key) {
if (this.readOnly) {
return false;
}
var target = this.store,
path = nconf.path(key);
path = common.path(key);

@@ -129,2 +143,6 @@ //

Memory.prototype.merge = function (key, value) {
if (this.readOnly) {
return false;
}
//

@@ -140,3 +158,3 @@ // If the key is not an `Object` or is an `Array`,

target = this.store,
path = nconf.path(key),
path = common.path(key),
fullKey = key;

@@ -184,2 +202,6 @@

Memory.prototype.reset = function () {
if (this.readOnly) {
return false;
}
this.mtimes = {};

@@ -186,0 +208,0 @@ this.store = {};

{
"name": "nconf",
"description": "A hybrid local / remote configuration storage library for node.js.",
"version": "0.3.1",
"description": "Hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging.",
"version": "0.4.3",
"author": "Charlie Robbins <charlie.robbins@gmail.com>",

@@ -6,0 +6,0 @@ "repository": {

# nconf
A hybrid local / remote configuration storage library for node.js.
Hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging.

@@ -17,3 +17,3 @@ ## Installation

## Usage
## Getting started
Using nconf is easy; it is designed to be a simple key-value store with support for both local and remote storage. Keys are namespaced and delimited by `:`. Lets dive right into sample usage:

@@ -28,3 +28,3 @@

//
nconf.use('file', { file: 'path/to/your/config.json' });
nconf.add('file', { file: 'path/to/your/config.json' });
nconf.set('database:host', '127.0.0.1');

@@ -34,5 +34,6 @@ nconf.set('database:port', 5984);

//
// Get the entire database object from nconf
// Get the entire database object from nconf. This will output
// { host: '127.0.0.1', port: 5984 }
//
var database = nconf.get('database');
console.dir(nconf.get('database'));

@@ -49,2 +50,67 @@ //

## Hierarchical configuration
Configuration management can get complicated very quickly for even trivial applications running in production. `nconf` addresses this problem by enabling you to setup a hierarchy for different sources of configuration with some sane defaults (in-order):
1. Manually set overrides
2. Command-line arguments
3. Environment variables
4. Any additional user stores (in the order they were added)
The top-level of `nconf` is an instance of the `nconf.Provider` abstracts this all for you into a simple API.
### nconf.add(name, options)
Adds a new store with the specified `name` and `options`. If `options.type` is not set, then `name` will be used instead:
``` js
nconf.add('global', { type: 'file', filename: '/path/to/globalconf.json' });
nconf.add('userconf', { type: 'file', filename: '/path/to/userconf.json' });
```
### nconf.use(name, options)
Similar to `nconf.add`, except that it can replace an existing store if new options are provided
``` js
//
// Load a file store onto nconf with the specified settings
//
nconf.use('file', { filename: '/path/to/some/config-file.json' });
//
// Replace the file store with new settings
//
nconf.use('file', { filename: 'path/to/a-new/config-file.json' });
```
### nconf.remove(name)
Removes the store with the specified `name.` The configuration stored at that level will no longer be used for lookup(s).
``` js
nconf.remove('file');
```
## Working with Configuration
`nconf` will traverse the set of stores that you have setup in-order to ensure that the value in the store of the highest priority is used. For example to setup following sample configuration:
1. Command-line arguments
2. Environment variables
3. User configuration
3. Global configuration
``` js
var nconf = require('nconf');
//
// Read in command-line arugments and environment variables
//
nconf.argv = nconf.env = true;
//
// Setup the `user` store followed by the `global` store. Note that
// order is significant in these operations.
//
nconf.add('user', { file: 'path/to/user-config.json' });
nconf.add('global', { file: 'path/to/global-config.json' })
```
## Storage Engines

@@ -59,2 +125,23 @@

### System
Based on the Memory store, but exposes hooks into manual overrides, command-line arguments, and environment variables (in that order of priority). Every instance of `nconf.Provider`, including the top-level `nconf` object itself already has a `System` store at the top-level, so configuring it only requires setting properties
``` js
//
// `nconf.get(awesome)` will always return true regardless of
// command-line arguments or environment variables.
//
nconf.overrides = { awesome: true };
//
// Can also be an object literal to pass to `optimist`.
//
nconf.argv = true;
//
// Can also be an array of variable names to restrict loading to.
//
nconf.env = true;
```
### File

@@ -101,5 +188,5 @@ Based on the Memory store, but provides additional methods `.save()` and `.load()` which allow you to read your configuration to and from file. As with the Memory store, all method calls are synchronous with the exception of `.save()` and `.load()` which take callback functions. It is important to note that setting keys in the File engine will not be persisted to disk until a call to `.save()` is made.

``` bash
$ npm test
```
vows test/*-test.js --spec
```

@@ -106,0 +193,0 @@ #### Author: [Charlie Robbins](http://nodejitsu.com)

@@ -31,3 +31,3 @@ /*

nconf.use('memory');
assert.instanceOf(nconf.store, nconf.stores.Memory);
assert.instanceOf(nconf.memory, nconf.stores.Memory);
}

@@ -55,6 +55,21 @@ },

"the get() method": {
"should respond with the correct value": function () {
assert.equal(nconf.get('foo:bar:bazz'), 'buzz');
"without a callback": {
"should respond with the correct value": function () {
assert.equal(nconf.get('foo:bar:bazz'), 'buzz');
}
},
"with a callback": {
topic: function () {
nconf.get('foo:bar:bazz', this.callback);
},
"should respond with the correct value": function (err, value) {
assert.equal(value, 'buzz');
}
}
},
}
}
}
}).addBatch({
"When using nconf": {
"with the memory store": {
"the clear() method": {

@@ -70,5 +85,3 @@ "should respond with the true": function () {

"should throw an exception": function () {
assert.throws(function () {
nconf.load();
})
assert.throws(function () { nconf.load() });
}

@@ -88,5 +101,3 @@ },

"should throw an exception": function () {
assert.throws(function () {
nconf.save();
})
assert.throws(function () { nconf.save() });
}

@@ -93,0 +104,0 @@ },

@@ -13,34 +13,10 @@ /*

vows = require('vows'),
helpers = require('./helpers'),
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')],
override = JSON.parse(fs.readFileSync(files[0]), 'utf8'),
first = '/path/to/file1',
second = '/path/to/file2';
override = JSON.parse(fs.readFileSync(files[0]), 'utf8');
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({

@@ -50,17 +26,32 @@ "When using nconf": {

"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: files[0] }),
"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);
provider.use('file', { file: second });
assert.equal(provider.file.file, files[0]);
provider.use('file', { file: files[1] });
assert.notStrictEqual(old, provider.store);
assert.equal(provider.store.file, second);
assert.notStrictEqual(old, provider.file);
assert.equal(provider.file.file, files[1]);
}
},
"when 'useArgv' is true": assertDefaults(path.join(__dirname, 'fixtures', 'scripts', 'nconf-override.js'))
"when 'argv' is true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'provider-argv.js'),
argv: ['--something', 'foobar']
}),
"when 'env' is true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'provider-env.js'),
env: { SOMETHING: 'foobar' }
}),
},
"the default nconf provider": {
"when 'useArgv' is true": assertDefaults(path.join(__dirname, 'fixtures', 'scripts', 'default-override.js'))
"when 'argv' is set to true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-argv.js'),
argv: ['--something', 'foobar'],
env: { SOMETHING: true }
}),
"when 'env' is set to true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-env.js'),
env: { SOMETHING: 'foobar' }
})
}

@@ -76,12 +67,20 @@ }

provider.merge(override);
assertMerged(provider);
helpers.assertMerged(null, provider.file.store);
}
},
"the mergeFiles() method": {
topic: function () {
var provider = new nconf.Provider().use('memory');
provider.mergeFiles(files, this.callback.bind(this, null, provider))
},
"should have the result merged in": function (_, provider) {
assertMerged(provider);
"when sources are passed in": {
topic: new nconf.Provider({
sources: {
user: {
type: 'file',
file: files[0]
},
global: {
type: 'file',
file: files[1]
}
}
}),
"should have the result merged in": function (provider) {
helpers.assertMerged(null, provider.load());
}

@@ -88,0 +87,0 @@ }

@@ -6,2 +6,27 @@ var fs = require('fs'),

//
// Configure the provider with a single store and
// support for command-line arguments and environment
// variables.
//
var single = new nconf.Provider({
env: true,
argv: true,
store: {
type: 'file',
file: path.join(__dirname, 'config.json')
}
});
//
// Configure the provider with multiple hierarchical stores
// representing `user` and `global` configuration values.
//
var multiple = new nconf.Provider({
stores: [
{ name: 'user', type: 'file', file: path.join(__dirname, 'user-config.json') },
{ name: 'global', type: 'global', file: path.join(__dirname, 'global-config.json') }
]
});
//
// Setup nconf to use the 'file' store and set a couple of values;

@@ -8,0 +33,0 @@ //

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc