From 67b5c8ab2a0519a54b7e6b1aaf0578dbe5d30992 Mon Sep 17 00:00:00 2001 From: indexzero Date: Thu, 31 Mar 2011 02:32:47 -0400 Subject: [PATCH] [api test] First pass at implementation --- lib/nconf.js | 55 +++++++++++++++++++++++++++++++ lib/nconf/stores.js | 12 +++++++ lib/nconf/stores/file.js | 41 +++++++++++++++++++++++ lib/nconf/stores/memory.js | 66 ++++++++++++++++++++++++++++++++++++++ lib/nconf/stores/redis.js | 48 +++++++++++++++++++++++++++ lib/nconf/utils.js | 16 +++++++++ test/stores/memory-test.js | 35 ++++++++++++++++++++ 7 files changed, 273 insertions(+) create mode 100644 lib/nconf.js create mode 100644 lib/nconf/stores.js create mode 100644 lib/nconf/stores/file.js create mode 100644 lib/nconf/stores/memory.js create mode 100644 lib/nconf/stores/redis.js create mode 100644 lib/nconf/utils.js create mode 100644 test/stores/memory-test.js diff --git a/lib/nconf.js b/lib/nconf.js new file mode 100644 index 0000000..a05ff87 --- /dev/null +++ b/lib/nconf.js @@ -0,0 +1,55 @@ +/* + * nconf.js: Top-level include for the nconf module + * + * (C) 2011, Charlie Robbins + * + */ + +require.paths.unshift(__dirname); + +var nconf = exports; + +nconf.utils = require('nconf/utils'); +nconf.stores = require('nconf/stores'); + +nconf.use = function (type, options) { + nconf.store = new nconf.stores[type](options); +}; + +nconf.get = function (key, callback) { + return nconf.store.get(key, callback); +}; + +nconf.set = function (key, value, callback) { + return nconf.store.set(key, value, callback); +}; + +nconf.clear = function (key, callback) { + return nconf.store.clear(key, callback); +}; + +nconf.load = function (callback) { + if (!nconf.store.load) { + var error = new Error('nconf store ' + nconf.store.type + ' has no load() method'); + if (callback) { + return callback (err); + } + + throw error; + } + + return nconf.store.load(callback); +}; + +nconf.save = function (callback) { + if (!nconf.store.save) { + var error = new Error('nconf store ' + nconf.store.type + ' has no save() method'); + if (callback) { + return callback (err); + } + + throw error; + } + + return nconf.store.save(callback); +}; \ No newline at end of file diff --git a/lib/nconf/stores.js b/lib/nconf/stores.js new file mode 100644 index 0000000..6fd277c --- /dev/null +++ b/lib/nconf/stores.js @@ -0,0 +1,12 @@ +/* + * stores.js: Top-level include for all nconf stores + * + * (C) 2011, Charlie Robbins + * + */ + +var stores = exports; + +stores.Memory = require('nconf/stores/memory').Memory; +stores.File = require('nconf/stores/file').File; +stores.Redis = require('nconf/stores/redis').Redis; \ No newline at end of file diff --git a/lib/nconf/stores/file.js b/lib/nconf/stores/file.js new file mode 100644 index 0000000..cdaa797 --- /dev/null +++ b/lib/nconf/stores/file.js @@ -0,0 +1,41 @@ +/* + * file.js: Simple file storage engine for nconf files + * + * (C) 2011, Charlie Robbins + * + */ + +var fs = require('fs'), + util = require('util'), + Memory = require('./memory').Memory; + +var File = exports.File = function (options) { + if (!options.file) { + throw new Error ('Missing required option `files`'); + } + + nconf.stores.Memory.call(this, options); + + this.file = options.file; + this.format = options.format || JSON; +}; + +util.inherits(File, Memory); + +File.prototype.save = function (callback) { + fs.save(this.file, this.format.stringify(this.store), function (err) { + return err ? callback(err) : callback(); + }); +}; + +File.prototype.load = function (callback) { + var self = this; + fs.load(this.file, function (err, data) { + if (err) { + return callback(err); + } + + self.store = self.format.parse(data.toString()); + callback(null, self.store); + }); +}; \ No newline at end of file diff --git a/lib/nconf/stores/memory.js b/lib/nconf/stores/memory.js new file mode 100644 index 0000000..41e843e --- /dev/null +++ b/lib/nconf/stores/memory.js @@ -0,0 +1,66 @@ +/* + * memory.js: Simple memory storage engine for nconf configuration(s) + * + * (C) 2011, Charlie Robbins + * + */ + +var nconf = require('nconf'); + +var Memory = exports.Memory = function (options) { + options = options || {}; + this.store = {}; +}; + +Memory.prototype.get = function (key) { + var target = this.store, + path = nconf.utils.path(key); + + while (path.length > 0) { + key = path.shift(); + if (!target[key]) { + return; + } + + target = target[key]; + if (path.length === 0) { + return target; + } + } +}; + +Memory.prototype.set = function (key, value) { + var target = this.store, + path = nconf.utils.path(key); + + while (path.length > 1) { + key = path.shift(); + if (!target[key]) { + target[key] = {}; + } + + target = target[key]; + } + + key = path.shift(); + target[key] = value; + return true; +}; + +Memory.prototype.clear = function (key) { + var target = this.store, + path = nconf.utils.path(key); + + while (path.length > 1) { + key = path.shift(); + if (!target[key]) { + return; + } + + target = target[key]; + } + + key = path.shift(); + delete target[key]; + return true; +}; \ No newline at end of file diff --git a/lib/nconf/stores/redis.js b/lib/nconf/stores/redis.js new file mode 100644 index 0000000..af77f77 --- /dev/null +++ b/lib/nconf/stores/redis.js @@ -0,0 +1,48 @@ +/* + * redis.js: Redis storage engine for nconf configuration(s) + * + * (C) 2011, Charlie Robbins + * + */ + +var async = require('async'), + redis = require('redis'), + nconf = require('nconf'), + Memory = require('./Memory').Memory; + +var Redis = exports.Redis = function (options) { + this.namespace = options.namespace || 'nconf'; + this.host = options.host || 'localhost'; + this.port = options.port || 6379; + this.cache = new Memory(); + this.redis = redis.createClient(options.port, options.host); +}; + +Redis.prototype.get = function (key, callback) { + +}; + +Redis.prototype.set = function (key, value, callback) { + var self = this, + path = nconf.utils.path(key); + + function addKey (partial, next) { + var index = path.indexOf(partial), + base = [self.namespace].concat(path.slice(0, index)), + parent = nconf.utils.key(base.concat('keys')); + + self.redis.rpush(parent, partial, next); + }; + + async.forEach(path, addKey, function (err) { + if (err) { + return callback(err); + } + + + }); +}; + +Redis.prototype.clear = function (key, callback) { + +}; diff --git a/lib/nconf/utils.js b/lib/nconf/utils.js new file mode 100644 index 0000000..969a6ee --- /dev/null +++ b/lib/nconf/utils.js @@ -0,0 +1,16 @@ +/* + * utils.js: Utils for the nconf module. + * + * (C) 2011, Charlie Robbins + * + */ + +var utils = exports; + +utils.key = function () { + return Array.prototype.slice.call(arguments).join(':'); +}; + +utils.path = function (key) { + return key.split(':'); +}; \ No newline at end of file diff --git a/test/stores/memory-test.js b/test/stores/memory-test.js new file mode 100644 index 0000000..5e43f17 --- /dev/null +++ b/test/stores/memory-test.js @@ -0,0 +1,35 @@ +/* + * memory.js: Simple memory storage engine for nconf configuration(s) + * + * (C) 2011, Charlie Robbins + * + */ + +require.paths.unshift(require('path').join(__dirname, '..', '..', 'lib')); + +var vows = require('vows'), + assert = require('assert'), + nconf = require('nconf'); + +vows.describe('nconf/stores/memory').addBatch({ + "When using the nconf memory store": { + topic: new nconf.stores.Memory(), + "the set() method": { + "should respond with true": function (store) { + assert.isTrue(store.set('foo:bar:bazz', 'buzz')); + } + }, + "the get() method": { + "should respond with the correct value": function (store) { + assert.equal(store.get('foo:bar:bazz'), 'buzz'); + } + }, + "the clear() method": { + "should respond with the true": function (store) { + assert.equal(store.get('foo:bar:bazz'), 'buzz'); + assert.isTrue(store.clear('foo:bar:bazz')); + assert.isTrue(typeof store.get('foo:bar:bazz') === 'undefined'); + } + } + } +}).export(module); \ No newline at end of file