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

@ -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

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
@ -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": {
@ -323,4 +328,30 @@ vows.describe('nconf/multiple-stores').addBatch({
teardown: function () {
nconf.remove('env');
}
}).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,6 +47,25 @@ 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');
}
}
}

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