New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

attostore

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

attostore - npm Package Compare versions

Comparing version 0.0.1 to 0.2.0

CHANGELOG.md

473

browser.js

@@ -5,58 +5,174 @@ /* hugov@runbox.com | https://github.com/hville/attostore.git | license:MIT */

function on(typ, fcn, ctx) {
var evts = this._db.event,
leaf = evts.setLeaf(this.keys),
list = evts[typ].get(leaf),
evtO = {f: fcn, c:ctx||null};
if (!list) evts[typ].set(leaf, [evtO]);
else if (indexOfEvt(list, fcn, ctx) === -1) list.push(evtO);
return this
/**
* @function
* @param {*} v - object to test
* @return {*} null|undefined|Constructor
*/
function cType(v) {
//null, String, Boolean, Number, Object, Array
return v == null ? v : v.constructor || Object
}
function off(typ, fcn, ctx) {
var evts = this._db.event,
leaf = evts.getLeaf(this.keys),
list = leaf && evts[typ].get(leaf);
if (list) {
var idx = indexOfEvt(list, fcn, ctx);
if (idx !== -1) list.splice(idx, 1);
if (!list.length) {
evts[typ].delete(leaf);
evts.delLeaf(this.keys);
}
function isObj(v) {
return v && typeof v === 'object'
}
/**
* deep Equal check on JSON-like objects
* @function
* @param {*} obj - object to check
* @param {*} ref - the reference
* @return {boolean|void} true if equal
*/
function isEqual(obj, ref) {
var cO = cType(obj),
cR = cType(ref);
if (cO !== cR) return false
if (cO === Array) {
if (obj.length !== ref.length) return false
for (var i=0; i<obj.length; ++i) if (!isEqual(obj[i], ref[i])) return false
return true
}
return this
if (cO === Object) {
var ko = Object.keys(obj); //TODO type annotation obj: Object
if (ko.length !== Object.keys(ref).length) return false //TODO type annotation typeof ref: Object
for (i=0; i<ko.length; ++i) if (!isEqual(obj[ko[i]], ref[ko[i]])) return false
return true
}
else return obj === ref
}
function once(etyp, fcn, ctx) {
function wrapped(data, last, ks) {
this.off(etyp, wrapped, this);
fcn.call(ctx || this, data, last, ks);
function pathKeys(path) {
return Array.isArray(path) ? path : (path && path.split) ? path.split('/') : cType(path) === Number ? [path] : []
}
/*
patchAsync: function(patch, ondone) {
return promisify(setTimeout, [patchSync, 0, this, patch], ondone)
},
patchSync: function(patch, ondone) {
return promisify(patchSync, [this, patch], ondone)
}
return this.on(etyp, wrapped, this)
*/
function promisify(fcn, args, cb) {
// avoids promises and return void if a callback is provided
if (cb) fcn.apply(null, args.concat(cb));
// return a promise only if no callback provided
else return new Promise(function(done, fail) {
fcn.apply(null, args.concat(function(err, res) {
if (err) fail(err);
else done(res);
}));
})
}
function indexOfEvt(lst, fcn, ctx) {
for (var i=0; i<lst.length; ++i) if (lst[i].f === fcn && lst[i].c === ctx) return i
return -1
function once(key, fcn, ctx) {
function wrapped(a,b,c,d) {
this.off(key, wrapped, this);
fcn.call(ctx || this, a,b,c,d);
}
return this.on(key, wrapped, this)
}
function getKey(obj, key) {
if (isObj(obj)) return obj[key]
}
/**
* @function
* @param {*} v - object to test
* @return {*} null|undefined|Constructor
* @constructor
*/
function cType(v) {
//null, String, Boolean, Number, Object, Array
return v == null ? v : v.constructor || Object
function Trie() {
this._ks = new Map;
this._fs = [];
this.data = undefined;
}
function isObj(v) {
return typeof v === 'object'
Trie.prototype.on = function(key, fcn, ctx) {
var leaf = set(this, pathKeys(key)),
list = leaf._fs;
if (indexOf(list, fcn, ctx) === -1) list.push({f: fcn, c:ctx||null});
return this
};
Trie.prototype.off = function(key, fcn, ctx) {
var keys = pathKeys(key),
itm = get(this, keys),
arr = itm && itm._fs,
idx = indexOf(arr, fcn, ctx);
if (idx !== -1) {
arr.splice(idx, 1);
if (!arr.length && !itm._ks.size) del(this, keys, 0);
}
return this
};
Trie.prototype.once = once;
/**
* @param {*} val
* @param {*} old
* @param {string} [key]
* @param {Object|Array} [obj]
* @return {void}
*/
Trie.prototype.emit = function(val, old, key, obj) {
this._ks.forEach(function(kid, k) {
if (k === '*') {
var keys = filterKeys(val, old);
for (var i=0; i<keys.length; ++i) kid.emit(getKey(val, keys[i]), getKey(old, keys[i]), keys[i], val);
}
else {
var v = getKey(val, k),
o = getKey(old, k);
if (v !== o) kid.emit(v,o,k,val);
}
});
for (var i=0, fs=this._fs; i<fs.length; ++i) fs[i].f.call(fs[i].c, val, old, key, obj);
};
function get(root, keys) {
for (var i=0, itm = root; i<keys.length; ++i) {
if (itm !== undefined) itm = itm._ks.get(''+keys[i]);
}
return itm
}
function pathKeys(path) {
return Array.isArray(path) ? path : (path && path.split) ? path.split('/') : cType(path) === Number ? [path] : []
function set(root, keys) {
for (var i=0, itm = root; i<keys.length; ++i) {
var key = ''+keys[i];
if (!itm._ks.has(key)) itm._ks.set(key, new Trie);
itm = itm._ks.get(key);
}
return itm
}
function del(trie, keys, idx) {
var key = keys[idx++],
kid = trie._ks.get(key);
if (kid) {
if (idx !== keys.length) del(kid, keys, idx);
if (!kid._ks.size && !kid._fs.length) trie._ks.delete(key);
}
}
function indexOf(arr, fcn, ctx) {
if (arr) for (var i=0; i<arr.length; ++i) if (arr[i].f === fcn && arr[i].c === ctx) return i
return -1
}
function filterKeys(val, old) {
var res = [],
kvs = isObj(val) ? Object.keys(val) : [],
kos = isObj(old) ? Object.keys(old) : [];
if (!kvs.length) return kos
if (!kos.length) return kvs
for (var i=0; i<kvs.length; ++i) if (val[kvs[i]] !== old[kvs[i]]) res.push(kvs[i]);
for (var j=0; j<kos.length; ++j) if (val[kos[j]] === undefined) res.push(kos[j]);
return res
}
/**

@@ -69,11 +185,16 @@ * @constructor

this._db = root;
this.keys = keys;
this._ks = keys;
}
Ref.prototype = {
get path() { return this.keys.join('/') },
get parent() { return new Ref(this._db, this.keys.slice(0,-1)) },
constructor: Ref,
get parent() { return new Ref(this._db, this._ks.slice(0,-1)) },
get root() { return new Ref(this._db, []) },
keys: function(path) {
return this._ks.concat(pathKeys(path))
},
/**
* @memberof Ref
* @param {Array|string} [path]

@@ -83,139 +204,77 @@ * @return {!Object}

ref: function(path) {
return new Ref(this._db, this.keys.concat(pathKeys(path)))
return new Ref(this._db, this.keys(path))
},
set: function(val, ondone) {
this._db.set(this.keys, val, ondone);
return this
set: function(path, val, ondone) {
return promisify(setTimeout, [storeSet, 0, this._db, this.keys(path), val], ondone)
},
on: on,
off: off,
once: once
};
del: function(path, ondone) {
return promisify(setTimeout, [storeSet, 0, this._db, this.keys(path)], ondone)
},
function reducePath(keys, obj, onKid, onTip, onKin, res, ctx) { //cb(this:ctx, res, kid, key, kin)
var kin = obj,
kids = [];
for (var i=0; i<keys.length; ++i) {
if (!isObj(kin)) return Error('invalid path')
var key = keys[i];
if (onKid) res = onKid.call(ctx, res, kin[key], key, kin);
kin = kids[i] = kin[key];
}
if (onTip) res = onTip.call(ctx, res, kin);
while(i--) {
if (onKin) res = onKin.call(ctx, res, kids[i], keys[i], i ? kids[i-1] : obj);
}
return res
}
function reduceTree(obj, onKid, onTip, onKin, res, ctx) { //cb(this:ctx, res, kid, key, kin)
if (isObj(obj)) for (var i=0, ks=Object.keys(obj); i<ks.length; ++i) {
var key = ks[i],
kid = obj[key];
if (onKid) res = onKid.call(ctx, res, kid, key, obj);
res = reduceTree(kid, onKid, onTip, onKin, res, ctx);
if (onKin) res = onKin.call(ctx, res, kid, key, obj);
}
else if (onTip) res = onTip(res, obj);
return res
}
function Event() {
this.dtree = Object.create(null);
this.child = new WeakMap;
this.value = new WeakMap;
}
Event.prototype = {
setLeaf: function(keys) {
for (var i=0, leaf=this.dtree; i<keys.length; ++i) {
leaf = leaf[keys[i]] || (leaf[keys[i]] = Object.create(null));
}
return leaf
on: function(path, fcn, ctx) {
this._db.trie.on(this.keys(path), fcn, ctx);
return this
},
getLeaf: function(keys) {
for (var i=0, leaf=this.dtree; i<keys.length; ++i) {
if (!(leaf = leaf[keys[i]])) return
}
return leaf
off: function(path, fcn, ctx) {
this._db.trie.off(this.keys(path), fcn, ctx);
return this
},
delLeaf: function(keys) {
reducePath(keys, this.dtree, null, onTip, delLeaf, null, this);
once: once,
query: function(transform) {
var query = new Trie,
last;
this._db.trie.on(this._ks, function(v,k,n) {
var next = transform(v,k,n);
query.emit(next, last);
});
return query
}
};
function onTip(res, tip) {
return reduceTree(tip, null, null, delLeaf, this)
function storeSet(src, key, val, cb) {
return src.patch([val === undefined ? {k:key} : {k:key, v:val}], cb)
}
function delLeaf(res, kid, key, kin) {
var eVals = res.value.get(kid),
eKids = res.child.get(kid);
if (!Object.keys(kid).length && !(eVals && eVals.length) && !(eKids && eKids.length)) delete kin[key];
return res
/**
* @constructor
* @param {*} [data]
*/
function Store(data) {
this.trie = new Trie;
this.data = data;
}
/**
* deep Equal check on JSON-like objects
* @function
* @param {*} obj - object to check
* @param {*} ref - the reference
* @return {boolean|void} true if equal
* @memberof Store
* @param {Array|string|number} [path]
* @return {!Object}
*/
function isEqual(obj, ref) {
var cO = cType(obj),
cR = cType(ref);
if (cO !== cR) return false
if (cO === Array) {
if (obj.length !== ref.length) return false
for (var i=0; i<obj.length; ++i) if (!isEqual(obj[i], ref[i])) return false
return true
}
if (cO === Object) {
var ko = Object.keys(obj); //TODO type annotation obj: Object
if (ko.length !== Object.keys(ref).length) return false //TODO type annotation typeof ref: Object
for (i=0; i<ko.length; ++i) if (!isEqual(obj[ko[i]], ref[ko[i]])) return false
return true
}
else return obj === ref
}
//TODO g(a,b) vs o(a)?a[b]:void 0
function getKey(obj, key) {
if (isObj(obj)) return obj[key]
}
//import {reduceTree, reducePath} from './reduce'
function Store(initValue) {
this.state = initValue || {};
this.event = new Event;
}
Store.prototype.set = function(keys, val, ondone) {
setTimeout(set, 0, this, keys, val, ondone);
return this
Store.prototype.ref = function(path) {
return new Ref(this, pathKeys(path))
};
//TODO patch: set all, only fire if good
function set(root, keys, value, ondone) {
var last = root.state,
evts = root.event;
var data = setUp(evts.dtree, last, keys, value, 0, evts.child);
if (data instanceof Error) {
if (ondone) ondone(data.message);
Store.prototype.patch = function(acts, done) {
var oldV = this.data,
newV = oldV;
for (var i=0; i<acts.length; ++i) {
newV = setPath(newV, acts[i].k, acts[i].v, 0);
if (newV instanceof Error) {
done(newV);
return
}
}
else if (data !== last) {
root.state = data;
fireV(evts.dtree, data, last, evts.value); //TODO manualy fire path keys instead of all refs
if (ondone) ondone(null, data);
if (newV !== oldV) {
this.data = newV;
this.trie.emit(newV, oldV);
done(null, acts);
}
}
else done(null, null);
};
/**
* @param {Object} ref
* @param {*} obj

@@ -225,71 +284,22 @@ * @param {!Array} keys

* @param {number} idx
* @param {!WeakMap} evtC
* @return {*}
*/
function setUp(ref, obj, keys, val, idx, evtC) {
if (idx === keys.length) {
if (isEqual(obj, val)) return obj
if (ref) fireC(ref, val, obj, evtC);
return val
}
function setPath(obj, keys, val, idx) {
if (val instanceof Error) return val
// last key reached => close
if (idx === keys.length) return isEqual(obj, val) ? obj : val
// recursive calls to end of path
if (!isObj(obj)) return Error('invalid path ' + keys.join('/'))
var key = keys[idx],
oldK = obj[key],
newK = setUp(ref && ref[key], oldK, keys, val, idx+1, evtC);
if (newK === oldK) return obj
var res = Array.isArray(obj) ? aSet(obj, key, newK) : oSet(obj, key, newK); //TODO obj type annotation
if (!(res instanceof Error)) fireList(evtC.get(ref), res, obj, key);
return res
var k = keys[idx],
o = obj[k],
v = setPath(o, keys, val, idx+1);
return v === o ? obj
: Array.isArray(obj) ? aSet(obj, +k, v)
: oSet(obj, k, v)
}
/**
* @param {!Object} ref
* @param {*} val
* @param {*} old
* @param {!WeakMap} evtC
* @return {void}
*/
function fireC(ref, val, old, evtC) {
if (val !== old) {
// fire children first
for (var i=0, ks=Object.keys(ref); i<ks.length; ++i) {
var k = ks[i];
fireC(ref[k], getKey(val, k), getKey(old, k), evtC); //TODO typeDef ref[k] is an Object
}
// fire parent after
var evts = evtC.get(ref);
if (evts) {
if (isObj(val)) {
if (isObj(old)) {
fireKeys(val, '!=', evts, val, old);
fireKeys(old, '!A', evts, val, old);
}
else fireKeys(val, '', evts, val, old);
}
else if (isObj(old)) fireKeys(old, '', evts, val, old);
}
}
}
/**
* @param {!Object} ref
* @param {*} val
* @param {*} old
* @param {!WeakMap} evtV
* @return {void}
*/
function fireV(ref, val, old, evtV) {
if (val !== old) {
// fire parent first
var evts = evtV.get(ref);
if (evts) fireList(evts, val, old);
// fire children after
for (var i=0, ks=Object.keys(ref); i<ks.length; ++i) {
var k = ks[i];
fireV(ref[k], getKey(val, k), getKey(old, k), evtV);
}
}
}
/**
* @param {!Array} arr

@@ -307,3 +317,3 @@ * @param {number} key

}
if (key <= arr.length) {
if (key < arr.length) {
tgt[key] = val;

@@ -327,30 +337,9 @@ return tgt

/**
* @param {Array} list
* @param {*} data
* @param {*} last
* @param {string|number} [key]
* @return {void}
*/
function fireList(list, data, last, key) {
if (list) for (var i=0; i<list.length; ++i) list[i].f.call(list[i].c, data, last, key);
}
function fireKeys(src, tst, evts, val, old) {
for (var i=0, ks=Object.keys(src); i<ks.length; ++i) {
var k = ks[i],
cond = tst === '!=' ? val[k] !== old[k] : tst === '!A' ? val[k] === undefined : true;
if(cond) fireList(evts, val, old, k);
}
}
// @ts-check
function db(initValue) {
return new Ref(new Store(initValue), [])
}
var module$1 = function () {
return new Store()
};
return db;
return module$1;
}());
/* hugov@runbox.com | https://github.com/hville/attostore.git | license:MIT */
'use strict';
function on(typ, fcn, ctx) {
var evts = this._db.event,
leaf = evts.setLeaf(this.keys),
list = evts[typ].get(leaf),
evtO = {f: fcn, c:ctx||null};
if (!list) evts[typ].set(leaf, [evtO]);
else if (indexOfEvt(list, fcn, ctx) === -1) list.push(evtO);
return this
/**
* @function
* @param {*} v - object to test
* @return {*} null|undefined|Constructor
*/
function cType(v) {
//null, String, Boolean, Number, Object, Array
return v == null ? v : v.constructor || Object
}
function off(typ, fcn, ctx) {
var evts = this._db.event,
leaf = evts.getLeaf(this.keys),
list = leaf && evts[typ].get(leaf);
if (list) {
var idx = indexOfEvt(list, fcn, ctx);
if (idx !== -1) list.splice(idx, 1);
if (!list.length) {
evts[typ].delete(leaf);
evts.delLeaf(this.keys);
}
function isObj(v) {
return v && typeof v === 'object'
}
/**
* deep Equal check on JSON-like objects
* @function
* @param {*} obj - object to check
* @param {*} ref - the reference
* @return {boolean|void} true if equal
*/
function isEqual(obj, ref) {
var cO = cType(obj),
cR = cType(ref);
if (cO !== cR) return false
if (cO === Array) {
if (obj.length !== ref.length) return false
for (var i=0; i<obj.length; ++i) if (!isEqual(obj[i], ref[i])) return false
return true
}
return this
if (cO === Object) {
var ko = Object.keys(obj); //TODO type annotation obj: Object
if (ko.length !== Object.keys(ref).length) return false //TODO type annotation typeof ref: Object
for (i=0; i<ko.length; ++i) if (!isEqual(obj[ko[i]], ref[ko[i]])) return false
return true
}
else return obj === ref
}
function once(etyp, fcn, ctx) {
function wrapped(data, last, ks) {
this.off(etyp, wrapped, this);
fcn.call(ctx || this, data, last, ks);
function pathKeys(path) {
return Array.isArray(path) ? path : (path && path.split) ? path.split('/') : cType(path) === Number ? [path] : []
}
/*
patchAsync: function(patch, ondone) {
return promisify(setTimeout, [patchSync, 0, this, patch], ondone)
},
patchSync: function(patch, ondone) {
return promisify(patchSync, [this, patch], ondone)
}
return this.on(etyp, wrapped, this)
*/
function promisify(fcn, args, cb) {
// avoids promises and return void if a callback is provided
if (cb) fcn.apply(null, args.concat(cb));
// return a promise only if no callback provided
else return new Promise(function(done, fail) {
fcn.apply(null, args.concat(function(err, res) {
if (err) fail(err);
else done(res);
}));
})
}
function indexOfEvt(lst, fcn, ctx) {
for (var i=0; i<lst.length; ++i) if (lst[i].f === fcn && lst[i].c === ctx) return i
return -1
function once(key, fcn, ctx) {
function wrapped(a,b,c,d) {
this.off(key, wrapped, this);
fcn.call(ctx || this, a,b,c,d);
}
return this.on(key, wrapped, this)
}
function getKey(obj, key) {
if (isObj(obj)) return obj[key]
}
/**
* @function
* @param {*} v - object to test
* @return {*} null|undefined|Constructor
* @constructor
*/
function cType(v) {
//null, String, Boolean, Number, Object, Array
return v == null ? v : v.constructor || Object
function Trie() {
this._ks = new Map;
this._fs = [];
this.data = undefined;
}
function isObj(v) {
return typeof v === 'object'
Trie.prototype.on = function(key, fcn, ctx) {
var leaf = set(this, pathKeys(key)),
list = leaf._fs;
if (indexOf(list, fcn, ctx) === -1) list.push({f: fcn, c:ctx||null});
return this
};
Trie.prototype.off = function(key, fcn, ctx) {
var keys = pathKeys(key),
itm = get(this, keys),
arr = itm && itm._fs,
idx = indexOf(arr, fcn, ctx);
if (idx !== -1) {
arr.splice(idx, 1);
if (!arr.length && !itm._ks.size) del(this, keys, 0);
}
return this
};
Trie.prototype.once = once;
/**
* @param {*} val
* @param {*} old
* @param {string} [key]
* @param {Object|Array} [obj]
* @return {void}
*/
Trie.prototype.emit = function(val, old, key, obj) {
this._ks.forEach(function(kid, k) {
if (k === '*') {
var keys = filterKeys(val, old);
for (var i=0; i<keys.length; ++i) kid.emit(getKey(val, keys[i]), getKey(old, keys[i]), keys[i], val);
}
else {
var v = getKey(val, k),
o = getKey(old, k);
if (v !== o) kid.emit(v,o,k,val);
}
});
for (var i=0, fs=this._fs; i<fs.length; ++i) fs[i].f.call(fs[i].c, val, old, key, obj);
};
function get(root, keys) {
for (var i=0, itm = root; i<keys.length; ++i) {
if (itm !== undefined) itm = itm._ks.get(''+keys[i]);
}
return itm
}
function pathKeys(path) {
return Array.isArray(path) ? path : (path && path.split) ? path.split('/') : cType(path) === Number ? [path] : []
function set(root, keys) {
for (var i=0, itm = root; i<keys.length; ++i) {
var key = ''+keys[i];
if (!itm._ks.has(key)) itm._ks.set(key, new Trie);
itm = itm._ks.get(key);
}
return itm
}
function del(trie, keys, idx) {
var key = keys[idx++],
kid = trie._ks.get(key);
if (kid) {
if (idx !== keys.length) del(kid, keys, idx);
if (!kid._ks.size && !kid._fs.length) trie._ks.delete(key);
}
}
function indexOf(arr, fcn, ctx) {
if (arr) for (var i=0; i<arr.length; ++i) if (arr[i].f === fcn && arr[i].c === ctx) return i
return -1
}
function filterKeys(val, old) {
var res = [],
kvs = isObj(val) ? Object.keys(val) : [],
kos = isObj(old) ? Object.keys(old) : [];
if (!kvs.length) return kos
if (!kos.length) return kvs
for (var i=0; i<kvs.length; ++i) if (val[kvs[i]] !== old[kvs[i]]) res.push(kvs[i]);
for (var j=0; j<kos.length; ++j) if (val[kos[j]] === undefined) res.push(kos[j]);
return res
}
/**

@@ -67,11 +183,16 @@ * @constructor

this._db = root;
this.keys = keys;
this._ks = keys;
}
Ref.prototype = {
get path() { return this.keys.join('/') },
get parent() { return new Ref(this._db, this.keys.slice(0,-1)) },
constructor: Ref,
get parent() { return new Ref(this._db, this._ks.slice(0,-1)) },
get root() { return new Ref(this._db, []) },
keys: function(path) {
return this._ks.concat(pathKeys(path))
},
/**
* @memberof Ref
* @param {Array|string} [path]

@@ -81,139 +202,77 @@ * @return {!Object}

ref: function(path) {
return new Ref(this._db, this.keys.concat(pathKeys(path)))
return new Ref(this._db, this.keys(path))
},
set: function(val, ondone) {
this._db.set(this.keys, val, ondone);
return this
set: function(path, val, ondone) {
return promisify(setTimeout, [storeSet, 0, this._db, this.keys(path), val], ondone)
},
on: on,
off: off,
once: once
};
del: function(path, ondone) {
return promisify(setTimeout, [storeSet, 0, this._db, this.keys(path)], ondone)
},
function reducePath(keys, obj, onKid, onTip, onKin, res, ctx) { //cb(this:ctx, res, kid, key, kin)
var kin = obj,
kids = [];
for (var i=0; i<keys.length; ++i) {
if (!isObj(kin)) return Error('invalid path')
var key = keys[i];
if (onKid) res = onKid.call(ctx, res, kin[key], key, kin);
kin = kids[i] = kin[key];
}
if (onTip) res = onTip.call(ctx, res, kin);
while(i--) {
if (onKin) res = onKin.call(ctx, res, kids[i], keys[i], i ? kids[i-1] : obj);
}
return res
}
function reduceTree(obj, onKid, onTip, onKin, res, ctx) { //cb(this:ctx, res, kid, key, kin)
if (isObj(obj)) for (var i=0, ks=Object.keys(obj); i<ks.length; ++i) {
var key = ks[i],
kid = obj[key];
if (onKid) res = onKid.call(ctx, res, kid, key, obj);
res = reduceTree(kid, onKid, onTip, onKin, res, ctx);
if (onKin) res = onKin.call(ctx, res, kid, key, obj);
}
else if (onTip) res = onTip(res, obj);
return res
}
function Event() {
this.dtree = Object.create(null);
this.child = new WeakMap;
this.value = new WeakMap;
}
Event.prototype = {
setLeaf: function(keys) {
for (var i=0, leaf=this.dtree; i<keys.length; ++i) {
leaf = leaf[keys[i]] || (leaf[keys[i]] = Object.create(null));
}
return leaf
on: function(path, fcn, ctx) {
this._db.trie.on(this.keys(path), fcn, ctx);
return this
},
getLeaf: function(keys) {
for (var i=0, leaf=this.dtree; i<keys.length; ++i) {
if (!(leaf = leaf[keys[i]])) return
}
return leaf
off: function(path, fcn, ctx) {
this._db.trie.off(this.keys(path), fcn, ctx);
return this
},
delLeaf: function(keys) {
reducePath(keys, this.dtree, null, onTip, delLeaf, null, this);
once: once,
query: function(transform) {
var query = new Trie,
last;
this._db.trie.on(this._ks, function(v,k,n) {
var next = transform(v,k,n);
query.emit(next, last);
});
return query
}
};
function onTip(res, tip) {
return reduceTree(tip, null, null, delLeaf, this)
function storeSet(src, key, val, cb) {
return src.patch([val === undefined ? {k:key} : {k:key, v:val}], cb)
}
function delLeaf(res, kid, key, kin) {
var eVals = res.value.get(kid),
eKids = res.child.get(kid);
if (!Object.keys(kid).length && !(eVals && eVals.length) && !(eKids && eKids.length)) delete kin[key];
return res
/**
* @constructor
* @param {*} [data]
*/
function Store(data) {
this.trie = new Trie;
this.data = data;
}
/**
* deep Equal check on JSON-like objects
* @function
* @param {*} obj - object to check
* @param {*} ref - the reference
* @return {boolean|void} true if equal
* @memberof Store
* @param {Array|string|number} [path]
* @return {!Object}
*/
function isEqual(obj, ref) {
var cO = cType(obj),
cR = cType(ref);
if (cO !== cR) return false
if (cO === Array) {
if (obj.length !== ref.length) return false
for (var i=0; i<obj.length; ++i) if (!isEqual(obj[i], ref[i])) return false
return true
}
if (cO === Object) {
var ko = Object.keys(obj); //TODO type annotation obj: Object
if (ko.length !== Object.keys(ref).length) return false //TODO type annotation typeof ref: Object
for (i=0; i<ko.length; ++i) if (!isEqual(obj[ko[i]], ref[ko[i]])) return false
return true
}
else return obj === ref
}
//TODO g(a,b) vs o(a)?a[b]:void 0
function getKey(obj, key) {
if (isObj(obj)) return obj[key]
}
//import {reduceTree, reducePath} from './reduce'
function Store(initValue) {
this.state = initValue || {};
this.event = new Event;
}
Store.prototype.set = function(keys, val, ondone) {
setTimeout(set, 0, this, keys, val, ondone);
return this
Store.prototype.ref = function(path) {
return new Ref(this, pathKeys(path))
};
//TODO patch: set all, only fire if good
function set(root, keys, value, ondone) {
var last = root.state,
evts = root.event;
var data = setUp(evts.dtree, last, keys, value, 0, evts.child);
if (data instanceof Error) {
if (ondone) ondone(data.message);
Store.prototype.patch = function(acts, done) {
var oldV = this.data,
newV = oldV;
for (var i=0; i<acts.length; ++i) {
newV = setPath(newV, acts[i].k, acts[i].v, 0);
if (newV instanceof Error) {
done(newV);
return
}
}
else if (data !== last) {
root.state = data;
fireV(evts.dtree, data, last, evts.value); //TODO manualy fire path keys instead of all refs
if (ondone) ondone(null, data);
if (newV !== oldV) {
this.data = newV;
this.trie.emit(newV, oldV);
done(null, acts);
}
}
else done(null, null);
};
/**
* @param {Object} ref
* @param {*} obj

@@ -223,71 +282,22 @@ * @param {!Array} keys

* @param {number} idx
* @param {!WeakMap} evtC
* @return {*}
*/
function setUp(ref, obj, keys, val, idx, evtC) {
if (idx === keys.length) {
if (isEqual(obj, val)) return obj
if (ref) fireC(ref, val, obj, evtC);
return val
}
function setPath(obj, keys, val, idx) {
if (val instanceof Error) return val
// last key reached => close
if (idx === keys.length) return isEqual(obj, val) ? obj : val
// recursive calls to end of path
if (!isObj(obj)) return Error('invalid path ' + keys.join('/'))
var key = keys[idx],
oldK = obj[key],
newK = setUp(ref && ref[key], oldK, keys, val, idx+1, evtC);
if (newK === oldK) return obj
var res = Array.isArray(obj) ? aSet(obj, key, newK) : oSet(obj, key, newK); //TODO obj type annotation
if (!(res instanceof Error)) fireList(evtC.get(ref), res, obj, key);
return res
var k = keys[idx],
o = obj[k],
v = setPath(o, keys, val, idx+1);
return v === o ? obj
: Array.isArray(obj) ? aSet(obj, +k, v)
: oSet(obj, k, v)
}
/**
* @param {!Object} ref
* @param {*} val
* @param {*} old
* @param {!WeakMap} evtC
* @return {void}
*/
function fireC(ref, val, old, evtC) {
if (val !== old) {
// fire children first
for (var i=0, ks=Object.keys(ref); i<ks.length; ++i) {
var k = ks[i];
fireC(ref[k], getKey(val, k), getKey(old, k), evtC); //TODO typeDef ref[k] is an Object
}
// fire parent after
var evts = evtC.get(ref);
if (evts) {
if (isObj(val)) {
if (isObj(old)) {
fireKeys(val, '!=', evts, val, old);
fireKeys(old, '!A', evts, val, old);
}
else fireKeys(val, '', evts, val, old);
}
else if (isObj(old)) fireKeys(old, '', evts, val, old);
}
}
}
/**
* @param {!Object} ref
* @param {*} val
* @param {*} old
* @param {!WeakMap} evtV
* @return {void}
*/
function fireV(ref, val, old, evtV) {
if (val !== old) {
// fire parent first
var evts = evtV.get(ref);
if (evts) fireList(evts, val, old);
// fire children after
for (var i=0, ks=Object.keys(ref); i<ks.length; ++i) {
var k = ks[i];
fireV(ref[k], getKey(val, k), getKey(old, k), evtV);
}
}
}
/**
* @param {!Array} arr

@@ -305,3 +315,3 @@ * @param {number} key

}
if (key <= arr.length) {
if (key < arr.length) {
tgt[key] = val;

@@ -325,28 +335,7 @@ return tgt

/**
* @param {Array} list
* @param {*} data
* @param {*} last
* @param {string|number} [key]
* @return {void}
*/
function fireList(list, data, last, key) {
if (list) for (var i=0; i<list.length; ++i) list[i].f.call(list[i].c, data, last, key);
}
function fireKeys(src, tst, evts, val, old) {
for (var i=0, ks=Object.keys(src); i<ks.length; ++i) {
var k = ks[i],
cond = tst === '!=' ? val[k] !== old[k] : tst === '!A' ? val[k] === undefined : true;
if(cond) fireList(evts, val, old, k);
}
}
// @ts-check
function db(initValue) {
return new Ref(new Store(initValue), [])
}
var module$1 = function () {
return new Store()
};
module.exports = db;
module.exports = module$1;
// @ts-check
import {Ref} from './src/_ref'
import {Store} from './src/_store'
export default function db(initValue) {
return new Ref(new Store(initValue), [])
export default function () {
return new Store()
}
{
"name": "attostore",
"version": "0.0.1",
"version": "0.2.0",
"description": "async json data store",

@@ -9,3 +9,4 @@ "keywords": [

"async",
"cursor"
"cursor",
"in-memory"
],

@@ -12,0 +13,0 @@ "author": "Hugo Villeneuve",

@@ -1,4 +0,7 @@

import {on, off, once} from './_ref-event'
import {pathKeys} from './path-keys'
import {promisify} from './promisify'
import {once} from './once'
import {Trie} from './_trie'
/**

@@ -11,11 +14,16 @@ * @constructor

this._db = root
this.keys = keys
this._ks = keys
}
Ref.prototype = {
get path() { return this.keys.join('/') },
get parent() { return new Ref(this._db, this.keys.slice(0,-1)) },
constructor: Ref,
get parent() { return new Ref(this._db, this._ks.slice(0,-1)) },
get root() { return new Ref(this._db, []) },
keys: function(path) {
return this._ks.concat(pathKeys(path))
},
/**
* @memberof Ref
* @param {Array|string} [path]

@@ -25,13 +33,38 @@ * @return {!Object}

ref: function(path) {
return new Ref(this._db, this.keys.concat(pathKeys(path)))
return new Ref(this._db, this.keys(path))
},
set: function(val, ondone) {
this._db.set(this.keys, val, ondone)
set: function(path, val, ondone) {
return promisify(setTimeout, [storeSet, 0, this._db, this.keys(path), val], ondone)
},
del: function(path, ondone) {
return promisify(setTimeout, [storeSet, 0, this._db, this.keys(path)], ondone)
},
on: function(path, fcn, ctx) {
this._db.trie.on(this.keys(path), fcn, ctx)
return this
},
on: on,
off: off,
once: once
off: function(path, fcn, ctx) {
this._db.trie.off(this.keys(path), fcn, ctx)
return this
},
once: once,
query: function(transform) {
var query = new Trie,
last
this._db.trie.on(this._ks, function(v,k,n) {
var next = transform(v,k,n)
query.emit(next, last)
})
return query
}
}
function storeSet(src, key, val, cb) {
return src.patch([val === undefined ? {k:key} : {k:key, v:val}], cb)
}

@@ -1,35 +0,43 @@

import {Event} from './_event'
//import {reduceTree, reducePath} from './reduce'
import {isEqual} from './is-eq'
import {getKey} from './get'
import {isObj} from './type'
export function Store(initValue) {
this.state = initValue || {}
this.event = new Event
import {pathKeys} from './path-keys'
import {Ref} from './_ref'
import {Trie} from './_trie'
/**
* @constructor
* @param {*} [data]
*/
export function Store(data) {
this.trie = new Trie
this.data = data
}
Store.prototype.set = function(keys, val, ondone) {
setTimeout(set, 0, this, keys, val, ondone)
return this
/**
* @memberof Store
* @param {Array|string|number} [path]
* @return {!Object}
*/
Store.prototype.ref = function(path) {
return new Ref(this, pathKeys(path))
}
//TODO patch: set all, only fire if good
function set(root, keys, value, ondone) {
var last = root.state,
evts = root.event
var data = setUp(evts.dtree, last, keys, value, 0, evts.child)
if (data instanceof Error) {
if (ondone) ondone(data.message)
Store.prototype.patch = function(acts, done) {
var oldV = this.data,
newV = oldV
for (var i=0; i<acts.length; ++i) {
newV = setPath(newV, acts[i].k, acts[i].v, 0)
if (newV instanceof Error) {
done(newV)
return
}
}
else if (data !== last) {
root.state = data
fireV(evts.dtree, data, last, evts.value) //TODO manualy fire path keys instead of all refs
if (ondone) ondone(null, data)
if (newV !== oldV) {
this.data = newV
this.trie.emit(newV, oldV)
done(null, acts)
}
else done(null, null)
}
/**
* @param {Object} ref
* @param {*} obj

@@ -39,71 +47,22 @@ * @param {!Array} keys

* @param {number} idx
* @param {!WeakMap} evtC
* @return {*}
*/
function setUp(ref, obj, keys, val, idx, evtC) {
if (idx === keys.length) {
if (isEqual(obj, val)) return obj
if (ref) fireC(ref, val, obj, evtC)
return val
}
function setPath(obj, keys, val, idx) {
if (val instanceof Error) return val
// last key reached => close
if (idx === keys.length) return isEqual(obj, val) ? obj : val
// recursive calls to end of path
if (!isObj(obj)) return Error('invalid path ' + keys.join('/'))
var key = keys[idx],
oldK = obj[key],
newK = setUp(ref && ref[key], oldK, keys, val, idx+1, evtC)
if (newK === oldK) return obj
var res = Array.isArray(obj) ? aSet(obj, key, newK) : oSet(obj, key, newK) //TODO obj type annotation
if (!(res instanceof Error)) fireList(evtC.get(ref), res, obj, key)
return res
var k = keys[idx],
o = obj[k],
v = setPath(o, keys, val, idx+1)
return v === o ? obj
: Array.isArray(obj) ? aSet(obj, +k, v)
: oSet(obj, k, v)
}
/**
* @param {!Object} ref
* @param {*} val
* @param {*} old
* @param {!WeakMap} evtC
* @return {void}
*/
function fireC(ref, val, old, evtC) {
if (val !== old) {
// fire children first
for (var i=0, ks=Object.keys(ref); i<ks.length; ++i) {
var k = ks[i]
fireC(ref[k], getKey(val, k), getKey(old, k), evtC) //TODO typeDef ref[k] is an Object
}
// fire parent after
var evts = evtC.get(ref)
if (evts) {
if (isObj(val)) {
if (isObj(old)) {
fireKeys(val, '!=', evts, val, old)
fireKeys(old, '!A', evts, val, old)
}
else fireKeys(val, '', evts, val, old)
}
else if (isObj(old)) fireKeys(old, '', evts, val, old)
}
}
}
/**
* @param {!Object} ref
* @param {*} val
* @param {*} old
* @param {!WeakMap} evtV
* @return {void}
*/
function fireV(ref, val, old, evtV) {
if (val !== old) {
// fire parent first
var evts = evtV.get(ref)
if (evts) fireList(evts, val, old)
// fire children after
for (var i=0, ks=Object.keys(ref); i<ks.length; ++i) {
var k = ks[i]
fireV(ref[k], getKey(val, k), getKey(old, k), evtV)
}
}
}
/**
* @param {!Array} arr

@@ -121,3 +80,3 @@ * @param {number} key

}
if (key <= arr.length) {
if (key < arr.length) {
tgt[key] = val

@@ -140,22 +99,1 @@ return tgt

}
/**
* @param {Array} list
* @param {*} data
* @param {*} last
* @param {string|number} [key]
* @return {void}
*/
function fireList(list, data, last, key) {
if (list) for (var i=0; i<list.length; ++i) list[i].f.call(list[i].c, data, last, key)
}
function fireKeys(src, tst, evts, val, old) {
for (var i=0, ks=Object.keys(src); i<ks.length; ++i) {
var k = ks[i],
cond = tst === '!=' ? val[k] !== old[k] : tst === '!A' ? val[k] === undefined : true
if(cond) fireList(evts, val, old, k)
}
}
import {isObj} from './type'
//TODO g(a,b) vs o(a)?a[b]:void 0
export function getKey(obj, key) {
if (isObj(obj)) return obj[key]
}

@@ -12,3 +12,3 @@ /**

export function isObj(v) {
return typeof v === 'object'
return v && typeof v === 'object'
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc