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
This commit is contained in:
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)
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.
``` 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.*
#### `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
``` 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');
//
// Can also lowerCase keys.
// Especially handy when dealing with environment variables which are usually
// Can also lowerCase keys.
// Especially handy when dealing with environment variables which are usually
// uppercased while argv are lowercased.
//

View file

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

View file

@ -20,7 +20,7 @@ var Env = exports.Env = function (options) {
options = options || {};
this.type = 'env';
this.readOnly = true;
this.readOnly = options.readOnly !== undefined? options.readOnly : true;
this.whitelist = options.whitelist || [];
this.separator = options.separator || '';
this.lowerCase = options.lowerCase || false;
@ -72,7 +72,13 @@ Env.prototype.loadEnv = function () {
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) {
if (self.match && self.whitelist.length) {
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
}
}).forEach(function (key) {
var val = env[key];
if (self.parseValues) {
@ -99,7 +105,9 @@ Env.prototype.loadEnv = function () {
}
});
this.readOnly = true;
if (tempWrite) {
this.readOnly = true;
}
return this.store;
};

View file

@ -21,6 +21,7 @@ process.env.FOO = 'bar';
process.env.BAR = 'zalgo';
process.env.NODE_ENV = 'debug';
process.env.FOOBAR = 'should not load';
process.env.TES = 'TING';
process.env.json_array = JSON.stringify(['foo', 'bar', 'baz']);
process.env.json_obj = JSON.stringify({foo: 'bar', baz: 'foo'});
process.env.NESTED__VALUE = 'nested';
@ -34,7 +35,7 @@ vows.describe('nconf/multiple-stores').addBatch({
nconf.env({
// separator: '__',
match: /^NCONF_/,
whitelist: ['NODE_ENV', 'FOO', 'BAR']
whitelist: ['NODE_ENV', 'FOO', 'BAR', 'TES']
});
nconf.file({ file: completeTest });
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) {
assert.equal(nconf.get(key), process.env[key]);
});
},
"are readOnly": function () {
nconf.set('tes', 'broken');
assert(nconf.get('tes'), 'TING');
}
},
"json vars": {
@ -174,7 +179,7 @@ vows.describe('nconf/multiple-stores').addBatch({
"JSON keys properly parsed": function () {
Object.keys(process.env).forEach(function (key) {
var val = process.env[key];
try {
val = JSON.parse(val);
} catch (err) {}
@ -323,4 +328,30 @@ vows.describe('nconf/multiple-stores').addBatch({
teardown: function () {
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()
assert.equal(argv.get('verbose'), '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'),
nconf = require('../../lib/nconf');
process.env.TES = 'TING';
vows.describe('nconf/stores/env').addBatch({
"An instance of nconf.Env": {
topic: new nconf.Env(),
@ -19,5 +21,15 @@ vows.describe('nconf/stores/env').addBatch({
assert.lengthOf(env.whitelist, 0);
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);