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.2.0 to 0.3.0

323

browser.js

@@ -19,25 +19,4 @@ /* hugov@runbox.com | https://github.com/hville/attostore.git | license:MIT */

/**
* 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
}
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 getKey(obj, key) {
if (isObj(obj)) return obj[key]
}

@@ -49,2 +28,9 @@

function once(key, fcn, ctx) {
var wrap = fcn.length > 2
? function(a,b,c,d,e) { this.off(key, wrap, this); fcn.call(ctx, a,b,c,d,e); }
: function(a,b) { this.off(key, wrap, this); fcn.call(ctx, a,b); };
return this.on(key, wrap, this)
}
/*

@@ -72,12 +58,60 @@ patchAsync: function(patch, ondone) {

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)
/**
* @constructor
* @param {!Object} root
* @param {!Array} keys
*/
function Ref(root, keys) {
this.store = root;
this._ks = keys;
}
function getKey(obj, key) {
if (isObj(obj)) return obj[key]
Ref.prototype = {
get parent() { return new Ref(this.store, this._ks.slice(0,-1)) },
get root() { return new Ref(this.store, []) },
keys: function(path) {
return this._ks.concat(pathKeys(path))
},
/**
* @memberof Ref
* @param {Array|string} [path]
* @return {!Object}
*/
ref: function(path) {
return new Ref(this.store, this.keys(path))
},
on: function(path, fcn, ctx) {
this.store.on(this.keys(path), fcn, ctx);
return this
},
off: function(path, fcn, ctx) {
this.store.off(this.keys(path), fcn, ctx);
return this
},
once: once,
set: function(path, val, ondone) {
return promisify(setTimeout, [storeSet, 0, this.store, this.keys(path), val], ondone)
},
del: function(path, ondone) {
return promisify(setTimeout, [storeSet, 0, this.store, this.keys(path), undefined], ondone)
},
query: function(transform) {
var query = new Trie;
query._set(transform(this.store.data));
this.store.on(this._ks, function(v) { query._set(transform(v)); });
return query
}
};
function storeSet(src, key, val, cb) {
return src.patch([val === undefined ? {k:key} : {k:key, v:val}], cb)
}

@@ -94,46 +128,60 @@

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
};
/**
* @memberof Store
* @param {Array|string|number} [path]
* @return {!Object}
*/
Trie.prototype = {
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
};
ref: function(path) {
return new Ref(this, pathKeys(path))
},
Trie.prototype.once = once;
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
},
/**
* @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);
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);
}
else {
var v = getKey(val, k),
o = getKey(old, k);
if (v !== o) kid.emit(v,o,k,val);
return this
},
once: once,
/**
* @param {*} val
* @return {void}
*/
_set: function(val) {
if (val !== this.data) {
var old = this.data,
dif = null;
// update kids first
this._ks.forEach(updateKid, val);
// update self
this.data = val;
for (var i=0, fs=this._fs; i<fs.length; ++i) {
var fcn = fs[i].f;
//compute changes only once and only if required
if (fcn.length > 2) {
if (!dif) dif = compare(val, old);
fcn.call(fs[i].c, val, old, dif[0], dif[1], dif[2]);
}
else fcn.call(fs[i].c, val, old);
}
}
});
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) {

@@ -169,98 +217,57 @@ for (var i=0, itm = root; i<keys.length; ++i) {

function filterKeys(val, old) {
var res = [],
kvs = isObj(val) ? Object.keys(val) : [],
function compare(val, old) {
var 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
if (!kvs.length || !kos.length) return [kvs, [], kos]
var dif = [[],[],[]];
for (var i=0; i<kvs.length; ++i) {
if (old[kvs[i]] === undefined) dif[0].push(kvs[i]); // added
if (val[kvs[i]] !== old[kvs[i]]) dif[1].push(kvs[i]); // changed
}
for (var j=0; j<kos.length; ++j) {
if (val[kos[j]] === undefined) dif[2].push(kos[j]); // removed
}
return dif
}
/**
* @constructor
* @param {!Object} root
* @param {!Array} keys
*/
function Ref(root, keys) {
this._db = root;
this._ks = keys;
function updateKid(kid, k) {
kid._set(getKey(this, k));
}
Ref.prototype = {
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]
* @return {!Object}
*/
ref: function(path) {
return new Ref(this._db, this.keys(path))
},
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
},
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)
}
/**
* @constructor
* @param {*} [data]
* deep Equal check on JSON-like objects
* @function
* @param {*} obj - object to check
* @param {*} ref - the reference
* @return {boolean|void} true if equal
*/
function Store(data) {
this.trie = new Trie;
this.data = data;
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
}
/**
* @memberof Store
* @param {Array|string|number} [path]
* @return {!Object}
*/
Store.prototype.ref = function(path) {
return new Ref(this, pathKeys(path))
// @ts-check
var module$1 = function (initValue) {
var root = new Trie();
root.patch = patch;
root._set(initValue);
return new Ref(root, [])
};
Store.prototype.patch = function(acts, done) {
var oldV = this.data,
newV = oldV;
function patch(acts, done) {
var newV = this.data;
for (var i=0; i<acts.length; ++i) {

@@ -273,9 +280,8 @@ newV = setPath(newV, acts[i].k, acts[i].v, 0);

}
if (newV !== oldV) {
this.data = newV;
this.trie.emit(newV, oldV);
if (newV !== this.data) {
this._set(newV);
done(null, acts);
}
else done(null, null);
};
}

@@ -338,9 +344,4 @@ /**

// @ts-check
var module$1 = function () {
return new Store()
};
return module$1;
}());

@@ -18,25 +18,4 @@ /* hugov@runbox.com | https://github.com/hville/attostore.git | license:MIT */

/**
* 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
}
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 getKey(obj, key) {
if (isObj(obj)) return obj[key]
}

@@ -48,2 +27,9 @@

function once(key, fcn, ctx) {
var wrap = fcn.length > 2
? function(a,b,c,d,e) { this.off(key, wrap, this); fcn.call(ctx, a,b,c,d,e); }
: function(a,b) { this.off(key, wrap, this); fcn.call(ctx, a,b); };
return this.on(key, wrap, this)
}
/*

@@ -71,12 +57,60 @@ patchAsync: function(patch, ondone) {

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)
/**
* @constructor
* @param {!Object} root
* @param {!Array} keys
*/
function Ref(root, keys) {
this.store = root;
this._ks = keys;
}
function getKey(obj, key) {
if (isObj(obj)) return obj[key]
Ref.prototype = {
get parent() { return new Ref(this.store, this._ks.slice(0,-1)) },
get root() { return new Ref(this.store, []) },
keys: function(path) {
return this._ks.concat(pathKeys(path))
},
/**
* @memberof Ref
* @param {Array|string} [path]
* @return {!Object}
*/
ref: function(path) {
return new Ref(this.store, this.keys(path))
},
on: function(path, fcn, ctx) {
this.store.on(this.keys(path), fcn, ctx);
return this
},
off: function(path, fcn, ctx) {
this.store.off(this.keys(path), fcn, ctx);
return this
},
once: once,
set: function(path, val, ondone) {
return promisify(setTimeout, [storeSet, 0, this.store, this.keys(path), val], ondone)
},
del: function(path, ondone) {
return promisify(setTimeout, [storeSet, 0, this.store, this.keys(path), undefined], ondone)
},
query: function(transform) {
var query = new Trie;
query._set(transform(this.store.data));
this.store.on(this._ks, function(v) { query._set(transform(v)); });
return query
}
};
function storeSet(src, key, val, cb) {
return src.patch([val === undefined ? {k:key} : {k:key, v:val}], cb)
}

@@ -93,46 +127,60 @@

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
};
/**
* @memberof Store
* @param {Array|string|number} [path]
* @return {!Object}
*/
Trie.prototype = {
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
};
ref: function(path) {
return new Ref(this, pathKeys(path))
},
Trie.prototype.once = once;
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
},
/**
* @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);
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);
}
else {
var v = getKey(val, k),
o = getKey(old, k);
if (v !== o) kid.emit(v,o,k,val);
return this
},
once: once,
/**
* @param {*} val
* @return {void}
*/
_set: function(val) {
if (val !== this.data) {
var old = this.data,
dif = null;
// update kids first
this._ks.forEach(updateKid, val);
// update self
this.data = val;
for (var i=0, fs=this._fs; i<fs.length; ++i) {
var fcn = fs[i].f;
//compute changes only once and only if required
if (fcn.length > 2) {
if (!dif) dif = compare(val, old);
fcn.call(fs[i].c, val, old, dif[0], dif[1], dif[2]);
}
else fcn.call(fs[i].c, val, old);
}
}
});
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) {

@@ -168,98 +216,57 @@ for (var i=0, itm = root; i<keys.length; ++i) {

function filterKeys(val, old) {
var res = [],
kvs = isObj(val) ? Object.keys(val) : [],
function compare(val, old) {
var 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
if (!kvs.length || !kos.length) return [kvs, [], kos]
var dif = [[],[],[]];
for (var i=0; i<kvs.length; ++i) {
if (old[kvs[i]] === undefined) dif[0].push(kvs[i]); // added
if (val[kvs[i]] !== old[kvs[i]]) dif[1].push(kvs[i]); // changed
}
for (var j=0; j<kos.length; ++j) {
if (val[kos[j]] === undefined) dif[2].push(kos[j]); // removed
}
return dif
}
/**
* @constructor
* @param {!Object} root
* @param {!Array} keys
*/
function Ref(root, keys) {
this._db = root;
this._ks = keys;
function updateKid(kid, k) {
kid._set(getKey(this, k));
}
Ref.prototype = {
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]
* @return {!Object}
*/
ref: function(path) {
return new Ref(this._db, this.keys(path))
},
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
},
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)
}
/**
* @constructor
* @param {*} [data]
* deep Equal check on JSON-like objects
* @function
* @param {*} obj - object to check
* @param {*} ref - the reference
* @return {boolean|void} true if equal
*/
function Store(data) {
this.trie = new Trie;
this.data = data;
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
}
/**
* @memberof Store
* @param {Array|string|number} [path]
* @return {!Object}
*/
Store.prototype.ref = function(path) {
return new Ref(this, pathKeys(path))
// @ts-check
var module$1 = function (initValue) {
var root = new Trie();
root.patch = patch;
root._set(initValue);
return new Ref(root, [])
};
Store.prototype.patch = function(acts, done) {
var oldV = this.data,
newV = oldV;
function patch(acts, done) {
var newV = this.data;
for (var i=0; i<acts.length; ++i) {

@@ -272,9 +279,8 @@ newV = setPath(newV, acts[i].k, acts[i].v, 0);

}
if (newV !== oldV) {
this.data = newV;
this.trie.emit(newV, oldV);
if (newV !== this.data) {
this._set(newV);
done(null, acts);
}
else done(null, null);
};
}

@@ -337,7 +343,2 @@ /**

// @ts-check
var module$1 = function () {
return new Store()
};
module.exports = module$1;
// @ts-check
import {Store} from './src/_store'
import {Trie} from './src/_trie'
import {Ref} from './src/_ref'
import {isEqual} from './src/is-eq'
import {isObj} from './src/type'
export default function () {
return new Store()
export default function (initValue) {
var root = new Trie()
root.patch = patch
root._set(initValue)
return new Ref(root, [])
}
function patch(acts, done) {
var newV = this.data
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
}
}
if (newV !== this.data) {
this._set(newV)
done(null, acts)
}
else done(null, null)
}
/**
* @param {*} obj
* @param {!Array} keys
* @param {*} val
* @param {number} idx
* @return {*}
*/
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 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 {!Array} arr
* @param {number} key
* @param {*} val
* @return {!Array|Error}
*/
function aSet(arr, key, val) {
var tgt = arr.slice()
if (val === undefined) {
if (key !== arr.length-1) return Error('only the last array item can be deleted')
tgt.length = key
return tgt
}
if (key < arr.length) {
tgt[key] = val
return tgt
}
return Error('invalid array index: ' + key)
}
/**
* @param {!Object} obj
* @param {string} key
* @param {*} val
* @return {!Object}
*/
function oSet(obj, key, val) {
for (var i=0, ks=Object.keys(obj), res={}; i<ks.length; ++i) if (ks[i] !== key) res[ks[i]] = obj[ks[i]]
if (val !== undefined) res[key] = val
return res
}
{
"name": "attostore",
"version": "0.2.0",
"version": "0.3.0",
"description": "async json data store",

@@ -5,0 +5,0 @@ "keywords": [

@@ -46,4 +46,4 @@ # attodom

* only the last item of an Array can be deleted to avoid shifting of keys
* only JSON types supported (Array, Object, string, number, boolean, null)
## API

@@ -50,0 +50,0 @@

@@ -6,3 +6,2 @@ import {pathKeys} from './path-keys'

/**

@@ -14,3 +13,3 @@ * @constructor

export function Ref(root, keys) {
this._db = root
this.store = root
this._ks = keys

@@ -20,6 +19,5 @@ }

Ref.prototype = {
constructor: Ref,
get parent() { return new Ref(this._db, this._ks.slice(0,-1)) },
get root() { return new Ref(this._db, []) },
get parent() { return new Ref(this.store, this._ks.slice(0,-1)) },
get root() { return new Ref(this.store, []) },

@@ -29,2 +27,3 @@ keys: function(path) {

},
/**

@@ -36,15 +35,7 @@ * @memberof Ref

ref: function(path) {
return new Ref(this._db, this.keys(path))
return new Ref(this.store, this.keys(path))
},
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)
this.store.on(this.keys(path), fcn, ctx)
return this

@@ -54,3 +45,3 @@ },

off: function(path, fcn, ctx) {
this._db.trie.off(this.keys(path), fcn, ctx)
this.store.off(this.keys(path), fcn, ctx)
return this

@@ -61,9 +52,14 @@ },

set: function(path, val, ondone) {
return promisify(setTimeout, [storeSet, 0, this.store, this.keys(path), val], ondone)
},
del: function(path, ondone) {
return promisify(setTimeout, [storeSet, 0, this.store, this.keys(path), undefined], ondone)
},
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)
})
var query = new Trie
query._set(transform(this.store.data))
this.store.on(this._ks, function(v) { query._set(transform(v)) })
return query

@@ -70,0 +66,0 @@ }

@@ -5,2 +5,3 @@ import {isObj} from './type'

import {once} from './once'
import {Ref} from './_ref'

@@ -16,46 +17,60 @@ /**

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
}
/**
* @memberof Store
* @param {Array|string|number} [path]
* @return {!Object}
*/
Trie.prototype = {
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
}
ref: function(path) {
return new Ref(this, pathKeys(path))
},
Trie.prototype.once = once
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
},
/**
* @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)
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)
}
else {
var v = getKey(val, k),
o = getKey(old, k)
if (v !== o) kid.emit(v,o,k,val)
return this
},
once: once,
/**
* @param {*} val
* @return {void}
*/
_set: function(val) {
if (val !== this.data) {
var old = this.data,
dif = null
// update kids first
this._ks.forEach(updateKid, val)
// update self
this.data = val
for (var i=0, fs=this._fs; i<fs.length; ++i) {
var fcn = fs[i].f
//compute changes only once and only if required
if (fcn.length > 2) {
if (!dif) dif = compare(val, old)
fcn.call(fs[i].c, val, old, dif[0], dif[1], dif[2])
}
else fcn.call(fs[i].c, val, old)
}
}
})
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) {

@@ -91,12 +106,20 @@ for (var i=0, itm = root; i<keys.length; ++i) {

function filterKeys(val, old) {
var res = [],
kvs = isObj(val) ? Object.keys(val) : [],
function compare(val, old) {
var 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
if (!kvs.length || !kos.length) return [kvs, [], kos]
var dif = [[],[],[]]
for (var i=0; i<kvs.length; ++i) {
if (old[kvs[i]] === undefined) dif[0].push(kvs[i]) // added
if (val[kvs[i]] !== old[kvs[i]]) dif[1].push(kvs[i]) // changed
}
for (var j=0; j<kos.length; ++j) {
if (val[kos[j]] === undefined) dif[2].push(kos[j]) // removed
}
return dif
}
function updateKid(kid, k) {
kid._set(getKey(this, k))
}
export 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)
var wrap = fcn.length > 2
? function(a,b,c,d,e) { this.off(key, wrap, this); fcn.call(ctx, a,b,c,d,e) }
: function(a,b) { this.off(key, wrap, this); fcn.call(ctx, a,b) }
return this.on(key, wrap, this)
}

@@ -5,6 +5,7 @@ // @ts-check

function addChangesL(v,o,k) {
t('!==', v, o, 'child event only if value changed: '+k)
//t('!==', v, o && o[k], 'child event only if v[k] changed: '+k)
this.push(k)
function compare(v,o,as,ms,ds) {
t('!==', v, o, 'child event only if value changed: ')
t('{===}', as, this[0])
t('{===}', ms, this[1])
t('{===}', ds, this[2])
}

@@ -14,14 +15,12 @@

t('db - promise', function(end) {
var root = DB(),
ref_ = root.ref(),
changed = []
ref_.on('*', addChangesL, changed)
ref_.on('aa/bb/*', addChangesL, changed)
ref_.ref('aa').on('*', addChangesL, changed)
var ref = DB()
ref_.set('', {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'}).then(function() {
t('{===}', root.data, {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})
t('{===}', changed, ['aa', 'a', 'cc', 'c', 'bb', 'b'])
ref.once('',compare, [['aa', 'a'],[],[]])
ref.ref('aa').once('bb',compare, [['cc', 'c'],[],[]])
ref.once('aa',compare, [['bb', 'b'],[],[]])
ref.set('',{aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'}).then(function() {
t('{===}', ref.store.data, {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})
end()
})
})

@@ -5,59 +5,35 @@ // @ts-check

function addChangesL(v,o,k) {
t('!==', v, o, 'child event only if value changed: '+k)
this.push(k)
function compare(v,o,as,ms,ds) {
t('!==', v, o, 'child event only if value changed: ')
t('{===}', as, this[0])
t('{===}', ms, this[1])
t('{===}', ds, this[2])
}
function addChangesU(v,o,k) {
t('!==', v, o, 'child event only if value changed')
this.push(k.toUpperCase())
}
function addChangesV(v,o,k) {
t('!==', v, o, 'child event only if value changed')
this.push(k+v)
}
t('db - callback', function(end) {
var root = DB(),
ref_ = root.ref(),
refa = root.ref('aa'),
changed = []
t('ref - added keys', function(end) {
var ref = DB()
ref_.once('aa', addChangesU, changed)
refa.on('*', addChangesL, changed)
ref_.once('aa/bb', addChangesU, changed)
ref_.on(['aa','bb','*'], addChangesL, changed)
refa.once('bb/cc', addChangesU, changed)
ref_.on('*', addChangesL, changed)
ref.ref('aa').once('',compare, [['bb','b'],[],[]])
ref.once('aa/bb', compare, [['cc','c'],[],[]])
ref.ref('aa').once('bb/cc', compare, [[],[],[]])
ref.on('',compare, [['aa','a'],[],[]])
ref_.set('', {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'}, function(err) {
ref.set('', {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'}, function(err) {
t('!', err)
t('{===}', root.data, {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})
t('{===}', changed, ['bb', 'b', 'cc', 'c', 'CC', 'BB', 'AA', 'aa', 'a'])
changed.length = 0
ref_.set('aa/bb', {}, function(e) {
t('!', e)
t('{===}', root.data, {aa: {bb:{}, b: 'b'}, a:'a'})
t('{===}', changed, ['bb', 'cc', 'c', 'aa'])
refa.off('*', addChangesL, changed)
ref_.off('*', addChangesL, changed)
refa.off(['bb','*'], addChangesL, changed)
t('===', root.trie._ks.size, 0, 'dereferencing dtree')
end()
})
t('{===}', ref.store.data, {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})
end()
})
})
t('db - wildCard', function(end) {
var root = DB(),
ref_ = root.ref(),
changed = []
t('ref - del keys', function(end) {
var ref = DB({aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})
ref_.on('*/x', addChangesV, changed)
ref.once('aa', compare, [[],[],['bb','b']])
ref.once('aa/bb', compare, [[],[],['cc','c']])
ref.ref('aa/bb/cc').once('',compare, [[],[],[]])
ref.on('',compare, [[],[],['aa','a']])
ref_.set('', {A: {a:'Aa', x:'Ax'}, B: {b:'Bb'}, C: {x:'Cx'}}, function(err) {
ref.del('',function(err) {
t('!', err)
t('{===}', root.data, {A: {a:'Aa', x:'Ax'}, B: {b:'Bb'}, C: {x:'Cx'}})
t('{===}', changed, ['xAx', 'xCx'])
t('{===}', ref.store.data, undefined)
end()

@@ -68,24 +44,12 @@ })

t('db - query', function(end) {
var src = DB(),
ref = src.ref(),
var ref = DB([1,2,3,0]),
xfo = ref.query(function(v) { return v.slice().sort() })
xfo.on('', function(v,o,k,s) {
t('===', k, undefined)
t('===', s, undefined)
t('!==', v, o, 'child event only if value changed')
t('{==}', v, [0,1,2,3])
})
xfo.on('*', function(v,o,k,s) {
t('!==', v, o, 'child event only if value changed')
t('!!', Array.isArray(s))
t('!!', typeof k, 'number')
t('{==}', s, [0,1,2,3])
})
ref.set('', [1,2,3,0], function(err) {
xfo.once('',compare, [[],[0,3],[]])
ref.set('',[1,2,3,0], function(err) {
t('!', err)
t('{===}', src.data, [1,2,3,0])
t('{===}', ref.store.data, [1,2,3,0])
t('{===}', xfo.data, [0,1,2,3])
end()
})
})
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