Enable writes env and argv stores with a flag (#285)

* added fucntionality to toggle readonly for env store

* fixed issue with using lint

* updated readme to reflect env options change

* updated tests to better test readOnly property

* added fucntionality to toggle readonly for env store

* fixed issue with using lint

* updated readme to reflect env options change

* updated tests to better test readOnly property

* updated tests to fix issues.

* updated argv to have readOnly toggle-able

* added tests for argv toggle-able readonly
master
louis-murray 2017-11-12 23:11:01 -05:00 committed by Matt Hamann
parent 6c5ba64db6
commit 391665cc38
6 changed files with 104 additions and 16 deletions

View File

@ -130,7 +130,7 @@ Adds a new store with the specified `name` and `options`. If `options.type` is n
``` ```
### nconf.any(names, callback) ### 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 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. or as an array. If the last argument is a function, it will be called with the result; otherwise, the value is returned.
``` js ``` js
@ -308,6 +308,9 @@ If the return value is falsey, the entry will be dropped from the store, otherwi
*Note: If the return value doesn't adhere to the above rules, an exception will be thrown.* *Note: If the return value doesn't adhere to the above rules, an exception will be thrown.*
#### `readOnly: {true|false}` (defaultL `true`)
Allow values in the env store to be updated in the future. The default is to not allow items in the env store to be updated.
#### Examples #### Examples
``` js ``` js
@ -324,8 +327,8 @@ If the return value is falsey, the entry will be dropped from the store, otherwi
var dbHost = nconf.get('database:host'); var dbHost = nconf.get('database:host');
// //
// Can also lowerCase keys. // Can also lowerCase keys.
// Especially handy when dealing with environment variables which are usually // Especially handy when dealing with environment variables which are usually
// uppercased while argv are lowercased. // uppercased while argv are lowercased.
// //

View File

@ -20,9 +20,17 @@ var Argv = exports.Argv = function (options, usage) {
options = options || {}; options = options || {};
this.type = 'argv'; this.type = 'argv';
this.readOnly = true; this.readOnly = options.readOnly !== undefined? options.readOnly : true;
this.options = options; this.options = options;
this.usage = usage; this.usage = usage;
if(typeof options.readOnly === 'boolean') {
this.readOnly = options.readOnly;
delete options.readOnly;
} else {
this.readOnly = true;
}
if(typeof options.parseValues === 'boolean') { if(typeof options.parseValues === 'boolean') {
this.parseValues = options.parseValues; this.parseValues = options.parseValues;
delete options.parseValues; delete options.parseValues;
@ -82,7 +90,12 @@ Argv.prototype.loadArgv = function () {
argv = common.transform(argv, this.transform); argv = common.transform(argv, this.transform);
} }
this.readOnly = false; var tempWrite = false;
if(this.readOnly) {
this.readOnly = false;
tempWrite = true;
}
Object.keys(argv).forEach(function (key) { Object.keys(argv).forEach(function (key) {
var val = argv[key]; var val = argv[key];
@ -103,7 +116,9 @@ Argv.prototype.loadArgv = function () {
this.showHelp = yargs.showHelp this.showHelp = yargs.showHelp
this.help = yargs.help this.help = yargs.help
this.readOnly = true; if (tempWrite) {
this.readOnly = true;
}
return this.store; return this.store;
}; };

View File

@ -20,7 +20,7 @@ var Env = exports.Env = function (options) {
options = options || {}; options = options || {};
this.type = 'env'; this.type = 'env';
this.readOnly = true; this.readOnly = options.readOnly !== undefined? options.readOnly : true;
this.whitelist = options.whitelist || []; this.whitelist = options.whitelist || [];
this.separator = options.separator || ''; this.separator = options.separator || '';
this.lowerCase = options.lowerCase || false; this.lowerCase = options.lowerCase || false;
@ -72,7 +72,13 @@ Env.prototype.loadEnv = function () {
env = common.transform(env, this.transform); env = common.transform(env, this.transform);
} }
this.readOnly = false; var tempWrite = false;
if(this.readOnly) {
this.readOnly = false;
tempWrite = true;
}
Object.keys(env).filter(function (key) { Object.keys(env).filter(function (key) {
if (self.match && self.whitelist.length) { if (self.match && self.whitelist.length) {
return key.match(self.match) || self.whitelist.indexOf(key) !== -1 return key.match(self.match) || self.whitelist.indexOf(key) !== -1
@ -84,7 +90,7 @@ Env.prototype.loadEnv = function () {
return !self.whitelist.length || self.whitelist.indexOf(key) !== -1 return !self.whitelist.length || self.whitelist.indexOf(key) !== -1
} }
}).forEach(function (key) { }).forEach(function (key) {
var val = env[key]; var val = env[key];
if (self.parseValues) { if (self.parseValues) {
@ -99,7 +105,9 @@ Env.prototype.loadEnv = function () {
} }
}); });
this.readOnly = true; if (tempWrite) {
this.readOnly = true;
}
return this.store; return this.store;
}; };

View File

@ -21,6 +21,7 @@ process.env.FOO = 'bar';
process.env.BAR = 'zalgo'; process.env.BAR = 'zalgo';
process.env.NODE_ENV = 'debug'; process.env.NODE_ENV = 'debug';
process.env.FOOBAR = 'should not load'; process.env.FOOBAR = 'should not load';
process.env.TES = 'TING';
process.env.json_array = JSON.stringify(['foo', 'bar', 'baz']); process.env.json_array = JSON.stringify(['foo', 'bar', 'baz']);
process.env.json_obj = JSON.stringify({foo: 'bar', baz: 'foo'}); process.env.json_obj = JSON.stringify({foo: 'bar', baz: 'foo'});
process.env.NESTED__VALUE = 'nested'; process.env.NESTED__VALUE = 'nested';
@ -34,7 +35,7 @@ vows.describe('nconf/multiple-stores').addBatch({
nconf.env({ nconf.env({
// separator: '__', // separator: '__',
match: /^NCONF_/, match: /^NCONF_/,
whitelist: ['NODE_ENV', 'FOO', 'BAR'] whitelist: ['NODE_ENV', 'FOO', 'BAR', 'TES']
}); });
nconf.file({ file: completeTest }); nconf.file({ file: completeTest });
nconf.use('argv', { type: 'literal', store: data }); nconf.use('argv', { type: 'literal', store: data });
@ -51,6 +52,10 @@ vows.describe('nconf/multiple-stores').addBatch({
['NODE_ENV', 'FOO', 'BAR', 'NCONF_foo'].forEach(function (key) { ['NODE_ENV', 'FOO', 'BAR', 'NCONF_foo'].forEach(function (key) {
assert.equal(nconf.get(key), process.env[key]); assert.equal(nconf.get(key), process.env[key]);
}); });
},
"are readOnly": function () {
nconf.set('tes', 'broken');
assert(nconf.get('tes'), 'TING');
} }
}, },
"json vars": { "json vars": {
@ -174,7 +179,7 @@ vows.describe('nconf/multiple-stores').addBatch({
"JSON keys properly parsed": function () { "JSON keys properly parsed": function () {
Object.keys(process.env).forEach(function (key) { Object.keys(process.env).forEach(function (key) {
var val = process.env[key]; var val = process.env[key];
try { try {
val = JSON.parse(val); val = JSON.parse(val);
} catch (err) {} } catch (err) {}
@ -323,4 +328,30 @@ vows.describe('nconf/multiple-stores').addBatch({
teardown: function () { teardown: function () {
nconf.remove('env'); nconf.remove('env');
} }
}).export(module); }).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with a readOnly:false": {
topic: function () {
var that = this;
helpers.cp(complete, completeTest, function () {
try {
nconf.env({ readOnly: false });
that.callback();
} catch (err) {
that.callback(null, err);
}
});
}, "env vars": {
"can be changed when readOnly is false": function() {
assert.equal(nconf.get('TES'), 'TING');
nconf.set('TES', 'changed');
assert.equal(nconf.get('TES'), 'changed');
}
}
},
teardown: function () {
nconf.remove('env');
}
}).export(module);

View File

@ -47,7 +47,26 @@ vows.describe('nconf/stores/argv').addBatch({
argv.loadSync() argv.loadSync()
assert.equal(argv.get('verbose'), 'false'); assert.equal(argv.get('verbose'), 'false');
assert.equal(argv.get('v'), 'false'); assert.equal(argv.get('v'), 'false');
},
"values cannot be altered with set when readOnly:true": function (argv) {
argv.set('verbose', 'true');
assert.equal(argv.get('verbose'), 'false');
}
},
"can be created with readOnly set to be false":{
topic: function(){
var options = {verbose: {alias: 'v', default: 'false'}, readOnly: false};
return new nconf.Argv(options);
},
"readOnly is actually false": function (argv) {
assert.equal(argv.readOnly, false);
},
"values can be changed by calling .set": function (argv) {
argv.loadSync()
assert.equal(argv.get('verbose'), 'false');
argv.set('verbose', 'true');
assert.equal(argv.get('verbose'), 'true');
} }
} }
} }
}).export(module); }).export(module);

View File

@ -9,6 +9,8 @@ var vows = require('vows'),
assert = require('assert'), assert = require('assert'),
nconf = require('../../lib/nconf'); nconf = require('../../lib/nconf');
process.env.TES = 'TING';
vows.describe('nconf/stores/env').addBatch({ vows.describe('nconf/stores/env').addBatch({
"An instance of nconf.Env": { "An instance of nconf.Env": {
topic: new nconf.Env(), topic: new nconf.Env(),
@ -19,5 +21,15 @@ vows.describe('nconf/stores/env').addBatch({
assert.lengthOf(env.whitelist, 0); assert.lengthOf(env.whitelist, 0);
assert.equal(env.separator, ''); assert.equal(env.separator, '');
} }
} },
"An instance of nconf.Env with readOnly option set to false": {
topic: new nconf.Env({readOnly: false}),
"should have it's readOnly property set to false": function (env) {
assert.isFunction(env.loadSync);
assert.isFunction(env.loadEnv);
assert.isArray(env.whitelist);
assert.lengthOf(env.whitelist, 0);
assert.ok(!env.readOnly);
}
}
}).export(module); }).export(module);