Added nconf.any method (#278)

* Added nconf.any method

Fixes #126
Implemented on the Provider class
Takes an array of keys, or a variable argument list
Supports both callback and non-callback invocations

* Use an explicit search base in file store test

Fixes #224
Test file was created under process.env.HOME, but test was searching in
the current working directory. If the cwd was not on the same drive as
the home directory, the test would fail.

* Added some API documentation to README for 'any'

* Tweak `.any` documentation
master
Matt Hamann 2017-10-21 16:42:24 -04:00 committed by GitHub
parent ca10d0eaf8
commit 35088a3313
6 changed files with 1474 additions and 2 deletions

View File

@ -129,6 +129,24 @@ Adds a new store with the specified `name` and `options`. If `options.type` is n
nconf.add('global', { type: 'file', file: '/path/to/globalconf.json' });
```
### nconf.any(names, callback)
Given a set of key names, gets the value of the first key found to be truthy. The key names can be given as separate arguments
or as an array. If the last argument is a function, it will be called with the result; otherwise, the value is returned.
``` js
//
// Get one of 'NODEJS_PORT' and 'PORT' as a return value
//
var port = nconf.any('NODEJS_PORT', 'PORT');
//
// Get one of 'NODEJS_IP' and 'IPADDRESS' using a callback
//
nconf.any(['NODEJS_IP', 'IPADDRESS'], function(err, value) {
console.log('Connect to IP address ' + value);
});
```
### nconf.use(name, options)
Similar to `nconf.add`, except that it can replace an existing store if new options are provided

View File

@ -275,6 +275,63 @@ Provider.prototype.get = function (key, callback) {
});
};
//
// ### function any (keys, callback)
// #### @keys {array|string...} Array of keys to query, or a variable list of strings
// #### @callback {function} **Optional** Continuation to respond to when complete.
// Retrieves the first truthy value (if any) for the specified list of keys.
//
Provider.prototype.any = function (keys, callback) {
if (!Array.isArray(keys)) {
keys = Array.prototype.slice.call(arguments);
if (keys.length > 0 && typeof keys[keys.length - 1] === 'function') {
callback = keys.pop();
} else {
callback = null;
}
}
//
// If there is no callback, use the short-circuited "get"
// on each key in turn.
//
if (!callback) {
var val;
for (var i = 0; i < keys.length; ++i) {
val = this._execute('get', 1, keys[i], callback);
if (val) {
return val;
}
}
return null;
}
var keyIndex = 0,
result,
self = this;
async.whilst(function() {
return !result && keyIndex < keys.length;
}, function(next) {
var key = keys[keyIndex];
keyIndex++;
self.get(key, function(err, v) {
if (err) {
next(err);
} else {
result = v;
next();
}
});
}, function(err) {
return err ? callback(err) : callback(null, result);
});
};
//
// ### function set (key, value, callback)
// #### @key {string} Key to set in this instance

1326
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@ vows.describe('nconf').addBatch({
assert.isFunction(nconf.key);
assert.isFunction(nconf.path);
assert.isFunction(nconf.use);
assert.isFunction(nconf.any);
assert.isFunction(nconf.get);
assert.isFunction(nconf.set);
assert.isFunction(nconf.clear);

View File

@ -201,4 +201,73 @@ vows.describe('nconf/provider').addBatch({
}
}
}
}).addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"the any() method": {
topic: new nconf.Provider({
type: 'literal',
store: {
key: "getThisValue"
}
}),
"without a callback": {
"given an array of keys with one matching": {
"should respond with the correct value": function (provider) {
assert.equal(provider.any(["notthis", "orthis", "key"]), 'getThisValue');
}
},
"given an array of keys with no match": {
"should respond with null": function (provider) {
assert.isNull(provider.any(["notthis", "orthis"]));
}
},
"given a variable argument list of keys with one matching": {
"should respond with the correct value": function (provider) {
assert.equal(provider.any("notthis", "orthis", "key"), 'getThisValue');
}
},
"given no arguments": {
"should respond with null": function (provider) {
assert.isNull(provider.any());
}
}
},
"with a callback": {
"given an array of keys with one matching": {
topic: function(provider) {
provider.any(["notthis", "orthis", "key"], this.callback);
},
"should respond with the correct value": function (err, value) {
assert.equal(value, 'getThisValue');
}
},
"given an array of keys with no match": {
topic: function(provider) {
provider.any(["notthis", "orthis"], this.callback);
},
"should respond with an undefined value": function (err, value) {
assert.isUndefined(value);
}
},
"given a variable argument list of keys with one matching": {
topic: function(provider) {
provider.any("notthis", "orthis", "key", this.callback);
},
"should respond with the correct value": function (err, value) {
assert.equal(value, 'getThisValue');
}
},
"given no keys": {
topic: function(provider) {
provider.any(this.callback);
},
"should respond with an undefined value": function (err, value) {
assert.isUndefined(value);
}
}
}
}
}
}
}).export(module);

View File

@ -195,14 +195,15 @@ vows.describe('nconf/stores/file').addBatch({
"the search() method": {
"when the target file exists higher in the directory tree": {
topic: function () {
var filePath = this.filePath = path.join(process.env.HOME, '.nconf');
var searchBase = this.searchBase = process.env.HOME;
var filePath = this.filePath = path.join(searchBase, '.nconf');
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
return new (nconf.File)({
file: '.nconf'
})
},
"should update the file appropriately": function (store) {
store.search();
store.search(this.searchBase);
assert.equal(store.file, this.filePath);
fs.unlinkSync(this.filePath);
}