diff --git a/lib/nconf/common.js b/lib/nconf/common.js index b6e16d9..2c092e3 100644 --- a/lib/nconf/common.js +++ b/lib/nconf/common.js @@ -16,9 +16,11 @@ var common = exports; // ### function path (key) // #### @key {string} The ':' delimited key to split // Returns a fully-qualified path to a nested nconf key. +// If given null or undefined it should return an empty path. +// '' should still be respected as a path. // common.path = function (key) { - return key.split(':'); + return key == null ? [] : key.split(':'); }; // diff --git a/lib/nconf/stores/memory.js b/lib/nconf/stores/memory.js index fbab7af..b53ac12 100644 --- a/lib/nconf/stores/memory.js +++ b/lib/nconf/stores/memory.js @@ -42,15 +42,14 @@ Memory.prototype.get = function (key) { // while (path.length > 0) { key = path.shift(); - if (!(target && key in target)) { - return; - } - - target = target[key]; - if (path.length === 0) { - return target; + if (target && key in target) { + target = target[key]; + continue; } + return undefined; } + + return target; }; // @@ -67,6 +66,20 @@ Memory.prototype.set = function (key, value) { var target = this.store, path = common.path(key); + if (path.length === 0) { + // + // Root must be an object + // + if (!value || typeof value !== 'object') { + return false; + } + else { + this.reset(); + this.store = value; + return true; + } + } + // // Update the `mtime` (modified time) of the key // @@ -101,6 +114,7 @@ Memory.prototype.clear = function (key) { } var target = this.store, + value = target, path = common.path(key); // @@ -111,17 +125,17 @@ Memory.prototype.clear = function (key) { // // Scope into the object to get the appropriate nested context // - while (path.length > 1) { - key = path.shift(); - if (!target[key]) { - return; + for (var i = 0; i < path.length - 1; i++) { + key = path[i]; + value = target[key]; + if (typeof value !== 'function' && typeof value !== 'object') { + return false; } - - target = target[key]; + target = value; } // Delete the key from the nested JSON structure - key = path.shift(); + key = path[i]; delete target[key]; return true; }; diff --git a/test/nconf-test.js b/test/nconf-test.js index 111a4f0..95a3904 100644 --- a/test/nconf-test.js +++ b/test/nconf-test.js @@ -68,6 +68,31 @@ vows.describe('nconf').addBatch({ } } } +}).addBatch({ + "When using the nconf": { + "with the memory store": { + "the get() method": { + "should respond allow access to the root": function () { + assert(nconf.get(null)); + assert(nconf.get(undefined)); + assert(nconf.get()); + } + }, + "the set() method": { + "should respond allow access to the root and complain about non-objects": function () { + assert(!nconf.set(null, null)); + assert(!nconf.set(null, undefined)); + assert(!nconf.set(null)); + assert(!nconf.set(null, '')); + assert(!nconf.set(null, 1)); + var original = nconf.get(); + assert(nconf.set(null, nconf.get())); + assert.notEqual(nconf.get(), original); + assert.deepEqual(nconf.get(), original) + } + } + } + } }).addBatch({ "When using nconf": { "with the memory store": { diff --git a/test/provider-test.js b/test/provider-test.js index 7d87972..78ee97d 100644 --- a/test/provider-test.js +++ b/test/provider-test.js @@ -141,7 +141,7 @@ vows.describe('nconf/provider').addBatch({ }), "with a single object": assertProvider(function (provider) { provider.file({ - dir: helpers.fixture('hierarchy'), + dir: helpers.fixture(''), file: 'store.json', search: true }); @@ -151,7 +151,7 @@ vows.describe('nconf/provider').addBatch({ }), "with a name and an object": assertProvider(function (provider) { provider.file('custom', { - dir: helpers.fixture('hierarchy'), + dir: helpers.fixture(''), file: 'store.json', search: true });