commit bf858f60731aed459954ac61688c04a1171827a9 Author: AJ ONeal Date: Fri Jul 22 19:22:57 2011 -0600 lightweight json wrapper for w3c Storage engines diff --git a/README.md b/README.md new file mode 100644 index 0000000..8010727 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +jsonStorage +==== + +A light abstraction for DOMStorage (such as localStorage). + +Made fo for Node.JS and Ender.JS (browser-side). + + var localStorage = require('localStorage') + , JsonStorage = require('json-storage') + , db = JsonStorage(localStorage) + , myValue = { + foo: "bar" + , baz: "quux" + } + ; + + db.set('myKey', myValue); + myValue = db.get('myKey'); + +API +=== + + * get(key) + * set(key, value) + * remove(key) + * clear() + * keys() + * size() + +null vs undefined in JSON +=== + +Since it is not valid to set `undefined` in JSON, calling `db.set('x')` is the same as `db.remove('x')`. + +However, `null`, and `"null"` both parse as `null` the "object", but the string (which would be `"\"null\""`). + +Therefore, setting a key to `undefined` will remove it from the db, but setting it to `null` will save it. + +Yet both values that exist as `null` and values that don't exist will return `null`. + +Also `{ "foo": null, "bar": "null" }` will parse as `foo` being `null` but `bar` being `"null"`, much unlike the value `"null"` being parsed on its own. diff --git a/lib/json-storage.js b/lib/json-storage.js new file mode 100644 index 0000000..29c414c --- /dev/null +++ b/lib/json-storage.js @@ -0,0 +1,77 @@ +(function () { + "use strict"; + + var db; + + function Stringify(obj) { + var str; + try { + str = JSON.stringify(obj); + } catch(e) { + str = ""; + } + + return str; + } + + function Parse(str) { + var obj = null; + try { + obj = JSON.parse(str); + } catch(e) {} + + return obj; + } + + function JsonStorage(w3cStorage) { + this.db = w3cStorage; + this.keysAreDirty = true; + } + db = JsonStorage; + + db.prototype.clear = function () { + this.keysAreDirty = true; + self.keys().forEach(function (uuid) { + this.remove(uuid); + }, this); + }; + + db.prototype.remove = function (uuid) { + this.keysAreDirty = true; + this.db.removeItem(uuid); + }; + + db.prototype.get = function (uuid) { + return Parse(this.db.getItem(uuid)); + }; + + db.prototype.set = function (uuid, val) { + this.keysAreDirty = true; + return this.db.setItem(uuid, Stringify(val)); + }; + + db.prototype.keys = function () { + var i; + + if (!this.keysAreDirty) { + return this.keys; + } + + this.keys = []; + for (i = 0; i < this.db.length; i += 1) { + this.keys.push(this.db.key(i)); + } + this.keysAreDirty = false; + return this.keys.concat([]); + }; + + db.prototype.size = function () { + return this.db.length; + }; + + function create(w3cStorage) { + return new JsonStorage(w3cStorage); + } + + module.exports = create; +}()); diff --git a/lib/package.json b/lib/package.json new file mode 100644 index 0000000..fe90600 --- /dev/null +++ b/lib/package.json @@ -0,0 +1,17 @@ +{ + "author": "AJ ONeal (http://coolaj86.info)", + "name": "json-storage", + "description": "A wrapper for storage engines which use the W3C Storage API", + "keywords": ["ender", "localStorage", "sessionStorage", "globalStorage", "Storage"], + "version": "1.0.0", + "repository": { + "type": "git", + "url": "git://github.com/coolaj86/json-storage-js.git" + }, + "engines": { + "node": ">= v0.2.0" + }, + "main": "json-storage.js", + "dependencies": {}, + "devDependencies": {} +} diff --git a/tests/node_modules/json-storage/json-storage.js b/tests/node_modules/json-storage/json-storage.js new file mode 100644 index 0000000..29c414c --- /dev/null +++ b/tests/node_modules/json-storage/json-storage.js @@ -0,0 +1,77 @@ +(function () { + "use strict"; + + var db; + + function Stringify(obj) { + var str; + try { + str = JSON.stringify(obj); + } catch(e) { + str = ""; + } + + return str; + } + + function Parse(str) { + var obj = null; + try { + obj = JSON.parse(str); + } catch(e) {} + + return obj; + } + + function JsonStorage(w3cStorage) { + this.db = w3cStorage; + this.keysAreDirty = true; + } + db = JsonStorage; + + db.prototype.clear = function () { + this.keysAreDirty = true; + self.keys().forEach(function (uuid) { + this.remove(uuid); + }, this); + }; + + db.prototype.remove = function (uuid) { + this.keysAreDirty = true; + this.db.removeItem(uuid); + }; + + db.prototype.get = function (uuid) { + return Parse(this.db.getItem(uuid)); + }; + + db.prototype.set = function (uuid, val) { + this.keysAreDirty = true; + return this.db.setItem(uuid, Stringify(val)); + }; + + db.prototype.keys = function () { + var i; + + if (!this.keysAreDirty) { + return this.keys; + } + + this.keys = []; + for (i = 0; i < this.db.length; i += 1) { + this.keys.push(this.db.key(i)); + } + this.keysAreDirty = false; + return this.keys.concat([]); + }; + + db.prototype.size = function () { + return this.db.length; + }; + + function create(w3cStorage) { + return new JsonStorage(w3cStorage); + } + + module.exports = create; +}()); diff --git a/tests/node_modules/json-storage/package.json b/tests/node_modules/json-storage/package.json new file mode 100644 index 0000000..fe90600 --- /dev/null +++ b/tests/node_modules/json-storage/package.json @@ -0,0 +1,17 @@ +{ + "author": "AJ ONeal (http://coolaj86.info)", + "name": "json-storage", + "description": "A wrapper for storage engines which use the W3C Storage API", + "keywords": ["ender", "localStorage", "sessionStorage", "globalStorage", "Storage"], + "version": "1.0.0", + "repository": { + "type": "git", + "url": "git://github.com/coolaj86/json-storage-js.git" + }, + "engines": { + "node": ">= v0.2.0" + }, + "main": "json-storage.js", + "dependencies": {}, + "devDependencies": {} +} diff --git a/tests/node_modules/localStorage/localStorage.js b/tests/node_modules/localStorage/localStorage.js new file mode 100644 index 0000000..4a74dff --- /dev/null +++ b/tests/node_modules/localStorage/localStorage.js @@ -0,0 +1,54 @@ +// http://www.rajdeepd.com/articles/chrome/localstrg/LocalStorageSample.htm + +// NOTE: +// this varies from actual localStorage in some subtle ways + +// also, there is no persistence +// TODO persist +(function () { + "use strict"; + + var db; + + function LocalStorage() { + } + db = LocalStorage; + + db.prototype.getItem = function (key) { + if (key in this) { + return String(this[key]); + } + return null; + }; + + db.prototype.setItem = function (key, val) { + this[key] = String(val); + }; + + db.prototype.removeItem = function (key) { + delete this[key]; + }; + + db.prototype.clear = function () { + var self = this; + Object.keys(self).forEach(function (key) { + self[key] = undefined; + delete self[key]; + }); + }; + + db.prototype.key = function (i) { + i = i || 0; + return Object.keys(this)[i]; + }; + + db.prototype.__defineGetter__('length', function () { + return Object.keys(this).length; + }); + + if (global.localStorage) { + module.exports = localStorage; + } else { + module.exports = new LocalStorage(); + } +}()); diff --git a/tests/node_modules/localStorage/package.json b/tests/node_modules/localStorage/package.json new file mode 100644 index 0000000..2d96f56 --- /dev/null +++ b/tests/node_modules/localStorage/package.json @@ -0,0 +1,16 @@ +{ + "author": "AJ ONeal (http://coolaj86.info)", + "name": "localStorage", + "description": "W3C localStorage for Node.JS", + "version": "1.0.0", + "repository": { + "type": "git", + "url": "git://github.com/coolaj86/node-localStorage.git" + }, + "engines": { + "node": ">= v0.2.0" + }, + "main": "localStorage.js", + "dependencies": {}, + "devDependencies": {} +} diff --git a/tests/test.js b/tests/test.js new file mode 100644 index 0000000..9184908 --- /dev/null +++ b/tests/test.js @@ -0,0 +1,28 @@ +(function () { + "use strict"; + + var assert = require('assert') + , localStorage = require('localStorage') + , JsonStorage = require('json-storage') + , db = JsonStorage(localStorage) + ; + + assert.strictEqual(null, db.get('a')); + + // you can't really save undefined as JSON, it's not valid + // the attempt to do so will delete the underlying key + db.set('a'); + assert.strictEqual(null, db.get('a')); + + db.set('a', 1); + assert.strictEqual(1, db.get('a')); + + db.set('a', '1'); + assert.strictEqual('1', db.get('a')); + + db.set('a', [1]); + assert.deepEqual([1], db.get('a')); + + db.set('a', { 'a': [1] }); + assert.deepEqual({'a': [1] }, db.get('a')); +}());