Compare commits

...

20 Commits

Author SHA1 Message Date
2e4745b189 update null examples 2018-07-31 16:58:36 +00:00
21098984f1 v2.1.2: update urls 2018-07-31 10:49:03 -06:00
b2fdf0aba2 check false on the right variable 2014-02-24 05:27:01 -07:00
7b459f1f87 allow namespaces to be turned off 2014-02-24 05:23:47 -07:00
3a2ada1ce0 Update README.md 2014-02-03 15:34:54 -06:00
a881915cfe Update README.md 2014-02-03 15:33:28 -06:00
5e9e9d8a41 Update README.md 2014-02-03 15:13:55 -06:00
780b7583a1 Update README.md 2014-02-03 15:13:19 -06:00
c4efbba4da Update README.md 2014-02-03 15:08:54 -06:00
6f7b83ea15 Update README.md 2014-02-03 15:06:26 -06:00
1a9a10c24e Update README.md 2014-02-03 15:05:16 -06:00
9cdcdf98d9 updated package meta data 2014-02-03 14:00:29 -07:00
a430f94fce made more browser-friendly and added stringify option 2014-01-26 14:39:47 -07:00
699f673b79 made more browser-friendly 2014-01-26 14:25:42 -07:00
4e61155c7e remove ender from keywords for pakmanager's sake 2013-03-06 16:52:51 -07:00
a704e4ad02 fixed bug where if toJSON is called before keys, it threw an error 2012-03-03 14:05:37 -07:00
16fb1c730e fixed bug with upgrading from 1.0.x 2012-03-03 13:04:34 -07:00
6dba7f09f8 fixed README typo with comma 2012-03-02 11:53:23 -07:00
dfe7ca8752 clarified README 2012-03-02 11:51:58 -07:00
3ddf2be63d documented new features 2012-03-02 11:35:53 -07:00
14 changed files with 299 additions and 877 deletions

View File

@ -1,48 +1,71 @@
jsonStorage JsonStorage
==== ====
A light abstraction for DOMStorage (such as localStorage). A light, sensible abstraction for DOMStorage (such as localStorage).
Installation Installation
=== ===
Ender.JS (Browser) Bower (Browser)
ender build json-storage ```bash
bower install json-storage
# or
wget https://git.coolaj86.com/coolaj86/json-storage.js/raw/branch/master/json-storage.js
```
Node.JS (Server) Node.JS (Server)
npm install localStorage json-storage ```bash
npm install -S localStorage json-storage
```
Usage Usage
=== ===
Made fo for Node.JS and Ender.JS (browser-side). Made for Node.js and Bower (browser-side).
var localStorage = require('localStorage') ```javascript
, JsonStorage = require('json-storage') var localStorage = require('localStorage')
, db = JsonStorage(localStorage, 'my-app-prefix') , JsonStorage = require('json-storage').JsonStorage
, store = JsonStorage.create(localStorage, 'my-widget-namespace', { stringify: true })
, myValue = { , myValue = {
foo: "bar" foo: "bar"
, baz: "quux" , baz: "quux"
} }
; ;
db.set('myKey', myValue); store.set('myKey', myValue);
myValue = db.get('myKey'); myValue = store.get('myKey');
```
NOTE: When using with Node and the `localStorage` module,
you may wish to pass the `{ stringify: false }` option to prevent double stringification.
API API
=== ===
* JsonStorage(DOMStorage, 'application-prefix') // optional prefix * `JsonStorage.create(DOMStorage, namespace, opts)`
* get(key) * `DOMStorage` should be globalStorage, sessionStorage, or localStorage. Defaults to window.localStorage if set to `null`.
* set(key, value) * `namespace` is optional string which allows multiple non-conflicting storage containers. For example you could pass two widgets different storage containers and not worry about naming conflicts:
* remove(key) * `Gizmos.create(JsonStorage.create(null, 'my-gizmos'))`
* clear() * `Gadgets.create(JsonStorage.create(null, 'my-gadgets'))`
* keys() * Namespacing can be turned off by explicitly setting `false`
* size() * `Gadgets.create(JsonStorage.create(null, false))`
* `opts`
* `stringify` set to `false` in `node` to avoid double stringifying
* `store.get(key)`
* `store.set(key, value)`
* `store.remove(key)`
* `store.clear()`
* `store.keys()`
* `store.size()`
* `store.toJSON()`
* `JSON.stringify(store)`
null vs undefined in JSON **NOTE**: You cannot omit optional parameters. Use `null` if you want accepts the defaults for some things and provide a values for others. For example: `JsonStorage.create(null, null, { stringify: false })`
JSON / DOMStorage Conversion Gotchas
=== ===
These notes do not reflect a bugs or defects in this library, These notes do not reflect a bugs or defects in this library,
@ -52,22 +75,45 @@ they're simply to inform you of a few 'gotchas' inherent in JSON / DOMStorage co
If they do, you're probably doing something wrong in the first place. If they do, you're probably doing something wrong in the first place.
It is not valid to set `undefined` in JSON. So setting a key to `undefined` will remove it from the db. ### `undefined` vs `null`
This means that `db.set('x')` is the same as `db.remove('x')`. It is not valid to set `undefined` in JSON. So setting a key to `undefined` will remove it from the store.
This means that `store.set('x')` is the same as `store.remove('x')`.
To save `undefined`, use `null` instead. To save `undefined`, use `null` instead.
Note that both values that exist as `null` and values that don't exist at all will return `null`. Note that both values that exist as `null` and values that don't exist at all will return `null`.
db.set('existing-key', null); ```javascript
null === db.get('existing-key'); store.set('existing-key', null);
null === db.get('non-existant-key'); null === store.get('existing-key');
null === store.get('non-existant-key');
```
### `null` vs `"null"`
The special case of `null` as `"null"`, aka `"\"null\""`: The special case of `null` as `"null"`, aka `"\"null\""`:
```
typeof null // object
typeof "null" // string
typeof "\"null\"" // string
```
`null`, and `"null"` both parse as `null` the "object", instead of one being the string (which would be `"\"null\""`). `null`, and `"null"` both parse as `null` the "object", instead of one being the string (which would be `"\"null\""`).
```
JSON.parse(null) // null (object)
JSON.parse("null") // null (object)
JSON.parse("\"null\"") // 'null' (string)
```
Objects containing `null`, however, parse as expected `{ "foo": null, "bar": "null" }` will parse as `foo` being `null` but `bar` being `"null"`, much unlike the value `"null"` being parsed on its own. Objects containing `null`, however, parse as expected `{ "foo": null, "bar": "null" }` will parse as `foo` being `null` but `bar` being `"null"`, much unlike the value `"null"` being parsed on its own.
```
JSON.parse('{ "foo": null }') // { foo: null }
JSON.parse('{ "foo": "null" }') // { foo: 'null' }
```

28
bower.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "json-storage",
"version": "2.0.1",
"homepage": "https://github.com/coolaj86/json-storage-js",
"authors": [
"AJ ONeal <coolaj86@gmail.com>"
],
"description": "A wrapper for storage engines which use the W3C Storage API",
"main": "json-storage.js",
"keywords": [
"dom",
"storage",
"json",
"w3c",
"localStorage",
"sessionStorage",
"globalStorage",
"Storage"
],
"license": "Apache2",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

View File

@ -1,282 +0,0 @@
(function () {
"use strict";
var localStorage = require('localStorage')
, JsonStorage = require('json-storage')
, jsonStorage = JsonStorage(localStorage)
, db = jsonStorage
, uuidgen = require('node-uuid')
, schemamap = {}
;
function create(schema) {
var models = {};
function createModel(lsmodel, prefix, submodels, uuid) {
//
// New Model
//
function LModel(obj) {
var lmodel = this;
// Add any already-appended submodels
// TODO DRY this up
submodels.forEach(function (subname) {
var sub_ids = '_' + subname + '_ids'
, subs = obj[subname]
, suuid = schemamap[subname].uuid || 'uuid';
// Just in case the object is already created
if ('function' === typeof obj.__lookupGetter__(subname)) {
return;
}
if (false === Array.isArray(subs)) {
return;
}
obj[sub_ids] = [];
lmodel[sub_ids] = obj[sub_ids];
subs.forEach(function (sub) {
if (!sub[suuid]) {
sub[suuid] = uuidgen();
}
models[subname].set(sub[suuid], sub);
lmodel[sub_ids].push(sub[suuid]);
});
obj[subname] = undefined;
delete obj[subname];
});
// Copy object to this
Object.keys(obj).forEach(function (k) {
lmodel[k] = obj[k];
});
// create uuid if it has none
if (undefined === obj[uuid]) {
obj[uuid] = uuidgen();
lmodel[uuid] = obj[uuid];
}
}
// A simple save method
LModel.prototype.save = function () {
lsmodel.set(this[uuid], this);
};
// getters for submodels
submodels.forEach(function (subname) {
var sub_ids = '_' + subname + '_ids';
LModel.prototype.__defineGetter__(subname, function () {
// not all submodels exist at "compile-time"
var submodel = models[subname]
, lmodel = this
, subs
, suuid = schemamap[subname].uuid || 'uuid';
lmodel[sub_ids] = lmodel[sub_ids] || [];
subs = submodel.some(lmodel[sub_ids]);
// modify collection, but leave as array with forEach
// XXX maybe create prototype with forEach
subs.add = function (obj) {
subs.push(obj);
if (undefined === obj[suuid]) {
submodel.add(obj);
} else {
submodel.set(obj[suuid], obj);
}
lmodel[sub_ids].push(obj[suuid]);
lmodel.save();
};
return subs;
});
});
return LModel;
}
// A database abstraction
function Model(model) {
var lsmodel = this
, prefix = model.name
, submodels = model.has_many || []
, uuid = model.uuid || 'uuid'
, LModel = createModel(lsmodel, prefix, submodels, uuid);
lsmodel.create = function (a, b, c) {
return new LModel(a, b, c)
};
// clear
lsmodel.clear = function () {
return db.set(prefix + '-lsm', []);
};
// all keys
lsmodel.keys = function () {
return db.get(prefix + '-lsm');
};
// all items
lsmodel.all = function () {
var items = [];
lsmodel.keys().forEach(function (uuid) {
var item = lsmodel.get(uuid)
// TODO this should be a useless check
if (null === item) {
lsmodel.remove(uuid);
return;
}
items.push(item);
});
return items;
};
// TODO query accepts objects
lsmodel.query = function (obj) {
//
return null;
};
// pass in your filter function
lsmodel.filter = function (test) {
var all = lsmodel.all(),
results = [];
all.forEach(function (one) {
if (!test(one)) {
return;
}
results.push(one);
});
return results;
}
lsmodel.some = function (uuids) {
var results = [];
uuids.forEach(function (uuid) {
var one = lsmodel.get(uuid);
// push null elements to keep array indices
results.push(one);
});
return results;
}
// TODO query object
lsmodel.get = function (uuid) {
var item = db.get(uuid);
if (null === item) {
return null;
}
return new LModel(item);
};
lsmodel.set = function (uuid, val) {
var keys;
if (null === val || undefined === val) {
return db.remove(uuid);
}
keys = db.get(prefix + '-lsm') || [];
// add the key if it didn't exist
if (-1 === keys.indexOf(uuid)) {
keys.push(uuid);
db.set(prefix + '-lsm', keys);
}
submodels.forEach(function (mod) {
var children = val[mod] || [];
// TODO decouple or create new objects
children.forEach(function (child) {
var e;
if (null === child) {
return;
}
if ('string' === typeof child) {
return;
}
if ('string' !== typeof child.uuid) {
return;
}
// TODO other[mod].set(uuid, child);
});
});
/*
console.log('\n\n val');
console.log(val);
console.log('\n\n');
*/
db.set(uuid, val)
};
// Remove an item from the table list and the db
lsmodel.remove = function (uuid) {
var keys = db.get(prefix + '-lsm')
, i;
keys.forEach(function (key, j) {
if (key === uuid) {
i = j;
}
});
if (undefined === i) {
return;
}
db.remove(uuid);
keys.splice(i,1);
db.set(prefix + '-lsm', keys);
};
// Remove all objects from the table list and db
lsmodel.clear = function () {
lsmodel.keys().forEach(function (uuid) {
db.remove(uuid);
});
db.set(prefix + '-lsm', []);
};
lsmodel.add = function (val) {
var obj = lsmodel.create(val);
obj.save();
return obj;
};
}
// TODO compare versions of schema
db.set('schema-lsm', schema);
schema.forEach(function (scheme) {
var table = scheme.name
, x = db.get(table + '-lsm')
;
// Pre-create the "models" tableshould always have
schemamap[scheme.name] = scheme;
if (!Array.isArray(x)) {
db.set(table + '-lsm', []);
}
models[scheme.name] = new Model(scheme);
});
return models;
}
module.exports = create;
}());

View File

@ -1,20 +0,0 @@
{
"author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.info)",
"name": "json-storage-model",
"description": "An abstraction for models to be stored in json-storage",
"keywords": ["ender", "model", "json-storage", "localStorage", "sessionStorage", "globalStorage", "Storage"],
"version": "0.9.1",
"repository": {
"type": "git",
"url": "git://github.com/coolaj86/json-storage-js.git"
},
"engines": {
"node": ">= v0.2.0"
},
"main": "index",
"dependencies": {
"json-storage": ">= 1.0.0"
, "node-uuid": ">= 0.0.0"
},
"devDependencies": {}
}

View File

@ -1,247 +0,0 @@
(function () {
"use strict";
var Model = require('json-storage-model')
, assert = require('assert')
, schema
, lsmAll = {}
, Returns
, Batches;
schema = [
{
name: "returns",
has_many: ['batches'],
uuid: "key"
},
{
name: "batches",
has_many: ['products']
},
{
name: "products"
}
];
function setup() {
lsmAll = new Model(schema);
//console.log(lsmAll);
Returns = lsmAll.returns;
Batches = lsmAll.batches;
}
function empty() {
assert.deepEqual([], Returns.keys());
assert.deepEqual([], Returns.all());
assert.deepEqual([], Returns.some([]));
assert.deepEqual([null], Returns.some(['x']));
assert.deepEqual([null, null], Returns.some(['x','y']));
assert.deepEqual(null, Returns.get('nada'));
Returns.clear();
assert.deepEqual([], Returns.keys());
assert.deepEqual([], Returns.all());
assert.deepEqual([], Returns.some([]));
assert.deepEqual([null], Returns.some(['x']));
assert.deepEqual([null, null], Returns.some(['x','y']));
assert.deepEqual(null, Returns.get('nada'));
}
function errors() {
var errcount = 0;
// TODO make throw
try {
Returns.get();
} catch(e) {
errcount += 1;
}
//assert.equal(1, errcount);
console.log('skipped `throw error on get(undefined)`');
try {
Returns.some();
} catch(e) {
errcount += 1;
}
assert.equal(1, errcount);
Returns.some([]);
}
function createWithoutKey() {
var ret = Returns.create({
memo: "031811-IHC",
})
, ret2;
assert.ok(ret.key);
assert.equal("031811-IHC", ret.memo);
ret2 = Returns.get(ret.key);
assert.equal(null, ret2);
ret.test1 = true;
ret.save();
ret2 = Returns.get(ret.key);
assert.equal("031811-IHC", ret2.memo);
}
function createWithKey() {
var ret = Returns.create({
key: "ajs-test",
memo: "031811-IHC",
})
, ret2;
ret2 = Returns.get(ret.key);
assert.ok(!ret2);
assert.equal("ajs-test", ret.key);
ret.save();
ret2 = Returns.get(ret.key);
assert.ok(ret2.memo);
}
function insertRemove() {
var keys = []
, all = []
, ids = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
, k;
Returns.clear();
// add
function populate() {
all = [];
keys = [];
ids.forEach(function (id, i) {
// this is private logic
all.push({ key: id, _batches_ids: [] });
keys.push(all[i].key);
Returns.create(all[i]).save();
});
assert.deepEqual(all, Returns.all());
assert.deepEqual(keys, Returns.keys());
}
// Remove from first
populate();
for (k = 0; k < ids.length; k += 1) {
Returns.remove(ids[k]);
}
assert.deepEqual([], Returns.all());
assert.deepEqual([], Returns.keys());
// Remove from last
populate();
for (k = ids.length - 1; k >= 0; k -= 1) {
Returns.remove(ids[k]);
}
assert.deepEqual([], Returns.all());
assert.deepEqual([], Returns.keys());
// Remove from middle
populate();
ids.sort(function () { return 0.5 - Math.random(); });
for (k = ids.length - 1; k >= 0; k -= 1) {
Returns.remove(ids[k]);
}
assert.deepEqual([], Returns.all());
assert.deepEqual([], Returns.keys());
}
// testing all, keys, some, filter
function all() {
var keys = [],
all = [],
some,
ids = [];
Returns.clear();
assert.deepEqual(all, Returns.all());
assert.deepEqual(keys, Returns.keys());
all.push({ key: "one", memo: "3131-mtn", _batches_ids: [] });
keys.push(all[0].key);
Returns.create(all[0]).save();
all.push({ key: "two", memo: "3232-hlt", _batches_ids: [] });
keys.push(all[1].key);
Returns.create(all[1]).save();
all.push({ key: "three", memo: "4123-hbc", _batches_ids: [] });
keys.push(all[2].key);
Returns.create(all[2]).save();
all.push({ key: "four", memo: "4441-dtf", _batches_ids: [] });
keys.push(all[3].key);
Returns.create(all[3]).save();
all.push({ key: "five", memo: "4412-abn", _batches_ids: [] });
keys.push(all[4].key);
Returns.create(all[4]).save();
some = Returns.filter(function (ret) {
return /^4\d/.test(ret.memo);
});
assert.equal(3, some.length);
some.forEach(function (one) {
ids.push(one.key);
});
assert.deepEqual(some, Returns.some(ids));
assert.deepEqual(all, Returns.all());
assert.deepEqual(keys, Returns.keys());
assert.deepEqual(all.slice(1,3), Returns.some(["two", "three"]));
assert.deepEqual(keys, Returns.keys());
console.log('skipping not-implemented `query`');
}
function relate() {
var batches = [
{
uuid: "a",
name: "chuck",
_products_ids: []
},
{
name: "daryl",
_products_ids: []
}
]
, ret = Returns.create({})
, batch;
// Add relation
ret.save();
ret = Returns.get(ret.key);
ret.batches.add(batches[0]);
assert.deepEqual(Batches.all()[0], batches[0]);
assert.deepEqual(ret.batches[0], batches[0]);
ret.save();
// create with an existing relation
ret = Returns.create({ batches: batches });
batches[1].uuid = ret.batches[1].uuid;
console.log('skipping assert which requires visual inspection');
//assert.deepEqual(batches, ret.batches);
//console.log(Batches.all());
}
setup();
empty();
errors();
createWithoutKey();
createWithKey();
insertRemove();
all();
relate();
console.log("All tests passed");
}());

140
json-storage.js Normal file
View File

@ -0,0 +1,140 @@
/*jshint -W054 */
;(function (exports) {
'use strict';
var proto
, delim = ':'
;
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, namespace, opts) {
var me = this
;
if (!(this instanceof JsonStorage)) {
return new JsonStorage(w3cStorage, namespace, opts);
}
if (!w3cStorage) {
w3cStorage = window.localStorage;
} else if ('function' !== typeof w3cStorage.getItem) {
throw new Error('You must supply a W3C DOM Storage mechanism such as window.localStorage or window.sessionStorage');
}
me._opts = opts || {};
if (false === me._opts.stringify) {
me._stringify = false;
} else {
me._stringify = true;
}
// if we didn't always add at least the delimeter
// then if a keyname with the delim, it would be more
// complicated to figure it out
this._namespace = delim;
this._namespace += (namespace || 'jss');
if (false === namespace) {
this._namespace = '';
}
this._store = w3cStorage;
this._keysAreDirty = true;
this._keys = [];
}
proto = JsonStorage.prototype;
proto.clear = function () {
this._keysAreDirty = true;
this.keys().forEach(function (key) {
this.remove(key);
}, this);
};
proto.remove = function (key) {
this._keysAreDirty = true;
this._store.removeItem(key + this._namespace);
};
proto.get = function (key) {
var item = this._store.getItem(key + this._namespace)
;
if ('undefined' === typeof item) {
item = null;
}
if (this._stringify) {
item = parse(item);
}
return item;
};
proto.set = function (key, val) {
this._keysAreDirty = true;
return this._store.setItem(key + this._namespace, this._stringify && stringify(val) || val);
};
proto.keys = function () {
var i
, key
, delimAt
;
if (!this._keysAreDirty) {
return this._keys.concat([]);
}
this._keys = [];
for (i = 0; i < this._store.length; i += 1) {
key = this._store.key(i) || '';
delimAt = key.lastIndexOf(this._namespace);
// test if this key belongs to this widget
if (!this._namespace || (-1 !== delimAt)) {
this._keys.push(key.substr(0, delimAt));
}
}
this._keysAreDirty = false;
return this._keys.concat([]);
};
proto.size = function () {
return this._store.length;
};
proto.toJSON = function () {
var json = {}
;
this.keys().forEach(function (key) {
json[key] = this.get(key);
}, this);
return json;
};
JsonStorage.create = JsonStorage;
exports.JsonStorage = JsonStorage;
}('undefined' !== typeof exports && exports || new Function('return this')()));

View File

@ -1,176 +0,0 @@
(function () {
"use strict";
var Future = require('future')
, __id_ = 'id'
, nameToString = function () {
return this.name;
};
function RowType(table) {
var name = table.name,
columns = table.columns,
klass;
klass = function (id, arr) {
/*
// Extending Array doesn't work very well
var self = this;
arr.forEach(function (item, i) {
self[i] = item;
});
*/
if (!(__id_ in this)) {
this[__id_] = id;
}
this.arr = arr;
};
// TODO make more directive-like
// TODO create a delegates_to directive
klass.prototype.toString = table.toString || nameToString;
columns.forEach(function (column, i) {
klass.prototype.__defineGetter__(column, function () {
return this.arr[i];
//return this[i];
});
});
return klass;
}
function createIndexes(tables) {
Object.keys(tables).forEach(function (name) {
var table = tables[name],
index,
krow;
if (!table.columns) {
console.log("missing columns");
console.log(table);
}
table.klass = RowType(table);
index = table.indexed = {};
table.rows.forEach(function (row, z) {
// TODO no need to index
var krow = new table.klass(z, row);
//krow.id = z;
index[krow[__id_]] = krow;
table.rows[z] = krow;
});
});
}
function createRelationships(tables) {
Object.keys(tables).forEach(function (name) {
var table = tables[name],
relationships,
relHandlers = {};
// TODO create a delegates_to directive
relHandlers.belongs_to = function (relname) {
// TODO abstract name mutation
var relation = tables[relname + 's'],
relname_s = relname + '_id';
table.klass.prototype.__defineGetter__(relname, function () {
var fid = this[relname_s];
return relation.indexed[fid];
});
}
//relationships = table.relationships && table.relationships.belongs_to;
//relationships = relationships || [];
relationships = table.relationships || {};
Object.keys(relationships).forEach(function (relType) {
if (!relHandlers[relType]) {
console.log('relationship type "' + relType + '" is not supported');
return;
}
relationships[relType].forEach(relHandlers[relType]);
});
});
}
function createRelate(tables) {
var future = Future()
;
createIndexes(tables);
createRelationships(tables);
//testRelationships(tables);
//console.log(Object.keys(data));
future.fulfill(null, tables);
return future.passable();
}
var Future = require('future')
, Join = require('Join')
;
function createGet(pathname, tables) {
var future = Future()
, join = Join()
, request = require('ahr2')
, db = {}
, errs = []
;
tables.forEach(function (tablename) {
var resource = pathname + '/' + tablename + ".json"
, req = request.get(resource)
;
req.when(function (err, xhr, data) {
if (err) {
console.log('error tables-get');
console.log(err);
console.log(err.message);
return;
}
if (global.Buffer && data instanceof global.Buffer) {
data = data.toString();
}
// TODO need to refactor AHR and fix JSON / text handling
try {
data = JSON.parse(data.toString());
} catch (e) {
// ignore, it was probably already parsed
}
// follow convention
tablename = tablename.replace('-','_');
db[tablename] = data;
});
join.add(req);
});
join.when(function () {
// TODO add timeout as error
if (0 == errs.length) {
errs = null;
}
future.fulfill(errs, db);
});
return future.passable();
}
module.exports = {
get: createGet
, relate: createRelate
};
}());

View File

@ -1,21 +0,0 @@
{
"author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.info)"
, "name": "json-tables"
, "description": "An abstraction for models to be stored in json-storage"
, "keywords": ["ender", "orm", "sql", "model", "json-storage", "localStorage", "sessionStorage", "globalStorage", "Storage"]
, "version": "0.7.1"
, "repository": {
"type": "git"
, "url": "git://github.com/coolaj86/json-storage-js.git"
}
, "engines": {
"node": ">= v0.2.0"
}
, "main": "index"
, "dependencies": {
"json-storage-model": ">= 0.9.0"
, "json-storage": ">= 1.0.0"
, "node-uuid": ">= 0.0.0"
}
, "devDependencies": {}
}

View File

@ -1,79 +0,0 @@
(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;
this.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.concat([]);
}
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;
}());

View File

@ -1,17 +0,0 @@
{
"author": "AJ ONeal <coolaj86@gmail.com> (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.1",
"repository": {
"type": "git",
"url": "git://github.com/coolaj86/json-storage-js.git"
},
"engines": {
"node": ">= v0.2.0"
},
"main": "index",
"dependencies": {},
"devDependencies": {}
}

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.com)",
"name": "json-storage",
"description": "A wrapper for storage engines which use the W3C Storage API",
"keywords": ["dom", "storage", "json", "w3c", "localStorage", "sessionStorage", "globalStorage", "Storage"],
"version": "2.1.2",
"repository": {
"type": "git",
"url": "git://git.coolaj86.com/coolaj86/json-storage.js.git"
},
"engines": {
"node": ">= v0.2.0"
},
"main": "json-storage",
"browserDependencies": {},
"dependencies": {},
"devDependencies": {}
}

View File

@ -2,13 +2,13 @@
"use strict"; "use strict";
var localStorage = require('localStorage') var localStorage = require('localStorage')
, JsonStorage = require('json-storage') , JsonStorage = require('../lib/').JsonStorage
, db = JsonStorage(localStorage) , db = JsonStorage.create(localStorage)
, assert = require('assert') , assert = require('assert')
; ;
assert.equal(null, db.get('x')); assert.equal(null, db.get('x'));
assert.deepEqual([], db.keys()); assert.deepEqual([], db.keys(), 'found keys in empty db: ' + JSON.stringify(db.keys()));
db.clear(); db.clear();
assert.equal(null, db.get('x')); assert.equal(null, db.get('x'));
@ -23,5 +23,9 @@
db.clear(); db.clear();
assert.deepEqual([], db.keys()); assert.deepEqual([], db.keys());
db.set('a', 'b');
assert.deepEqual(['a'], db.keys());
assert.deepEqual({ 'a': 'b' }, db.toJSON());
console.log("Done! All tests pass."); console.log("Done! All tests pass.");
}()); }());

View File

@ -3,8 +3,8 @@
var assert = require('assert') var assert = require('assert')
, localStorage = require('localStorage') , localStorage = require('localStorage')
, JsonStorage = require('json-storage') , JsonStorage = require('../lib/').JsonStorage
, db = JsonStorage(localStorage) , db = JsonStorage.create(localStorage)
; ;
assert.strictEqual(null, db.get('a')); assert.strictEqual(null, db.get('a'));

View File

@ -0,0 +1,28 @@
(function () {
"use strict";
var localStorage = require('localStorage')
, jsonStorage = require('../lib/')
, assert = require('assert')
, store0 = jsonStorage.create(localStorage, '0')
, store1 = jsonStorage.create(localStorage, '1')
;
store0.set('foo', 'bar');
store1.set('foo', 'baz');
assert.strictEqual('bar', store0.get('foo'));
assert.strictEqual('baz', store1.get('foo'));
store0.remove('foo');
assert.strictEqual(null, store0.get('foo'));
assert.strictEqual('baz', store1.get('foo'), 'after removing a value from store1, store0 lost it as well');
store0.clear();
assert.strictEqual(null, store0.get('foo'));
assert.strictEqual('baz', store1.get('foo'), 'after clearing store0, store1 lost values');
console.log('[PASS] no assertions failed');
}());