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.7.0 to 0.8.0

src/_state.js

350

browser.js

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

function pathKeys(path) {
var ct = cType(path);
return ct === Array ? path : ct === Number ? [path] : !path ? [] : path.split('/')
}
/**
* 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) {

@@ -54,131 +24,8 @@ if (isObj(obj)) return obj[key]

/**
* @param {Object|Array<Object>} ops
* @return {Error|void}
*/
function patch(ops) {
var data = Array.isArray(ops) ? ops.reduce(setRed, this.data) : setRed(this.data, ops);
return data instanceof Error ? data : update(this, data, '')
function pathKeys(path) {
var ct = cType(path);
return ct === Array ? path : ct === Number ? [path] : !path ? [] : path.split('/')
}
/**
* @param {*} res
* @param {Object} op
* @returns {*}
*/
function setRed(res, op) {
return res instanceof Error ? res : setKeys(res, pathKeys(op.p), op.v, 0)
}
/**
* @param {!Object} store
* @param {*} val
* @param {string} key
* @return {void|Error}
*/
function update(store, val, key) {
if (val instanceof Error) return val
if (val !== store.data) {
var old = store.data;
store.data = val;
// fire kids first...
store._ks.forEach(updateKid, val);
// ...then self
for (var i=0, fs=store._fs; i<fs.length; ++i) {
fs[i].f.call(fs[i].c === undefined ? store : fs[i].c, val, key, old);
}
}
}
function updateKid(kid, k) {
update(kid, getKey(this, k), k);
}
/**
* @param {*} obj
* @param {!Array} keys
* @param {*} val
* @param {number} idx
* @return {*}
*/
function setKeys(obj, keys, val, idx) {
// 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 = setKeys(o, keys, val, idx+1);
return v instanceof Error ? v : 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
}
/**
* @param {null|string|Array} path
* @param {*} [data]
* @return {Object}
*/
function setOperation(path, data) {
if (path === undefined || data === undefined) throw Error('undefined argument')
return {p: path, v: data}
}
/**
* @param {null|string|Array} path
* @return {Object}
*/
function delOperation(path) {
if (path === undefined) throw Error('undefined argument')
return {p: path == null ? '' : path}
}
/**
* @param {string} name
* @param {*} [data]
* @return {Error|void}
*/
function run(name, data) {
var ops = this._cs[name] && this._cs[name](data);
if (!ops) return Error('invalid command ' + name)
return this.run(ops)
}
/**
* @constructor

@@ -193,2 +40,3 @@ * @param {*} [data]

/**

@@ -200,3 +48,3 @@ * @param {Array|string|number} key

*/
function on(key, fcn, ctx) {
Trie.prototype.on = function(key, fcn, ctx) {
var leaf = setLeaf(this, pathKeys(key)),

@@ -206,3 +54,3 @@ list = leaf._fs;

return this
}
};

@@ -215,3 +63,3 @@ /**

*/
function off(key, fcn, ctx) {
Trie.prototype.off = function(key, fcn, ctx) {
var keys = pathKeys(key),

@@ -226,3 +74,3 @@ itm = getLeaf(this, keys),

return this
}
};

@@ -235,3 +83,3 @@ /**

*/
function once(key, fcn, ctx) {
Trie.prototype.once = function(key, fcn, ctx) {
var store = this;

@@ -243,4 +91,5 @@ function wrap(v,k,o) {

return this.on(key, wrap, ctx)
}
};
/**

@@ -299,2 +148,27 @@ * @param {Trie} root

/**
* 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
}
/**
* @constructor

@@ -304,17 +178,7 @@ * @param {*} [data]

*/
function Store(data, commands) {
this._ks = new Map;
this._fs = [];
this._cs = commands || {};
function State(data) {
this.data = data;
}
Store.prototype.on = on;
Store.prototype.off = off;
Store.prototype.once = once;
Store.prototype.patch = patch;
Store.prototype.run = run;
Store.prototype.get = function(path) {
State.prototype.get = function(path) {
var keys = pathKeys(path);

@@ -328,2 +192,130 @@ for (var i=0, itm = this.data; i<keys.length; ++i) {

/**
* @param {null|string|Array} path
* @param {*} data
* @return {Object}
*/
State.prototype.set = function(path, data) {
if (!(this.data instanceof Error)) this.data = setKeys(this.data, pathKeys(path), data, 0);
return this
};
/**
* @param {null|string|Array} path
* @return {Object}
*/
State.prototype.delete = function(path) {
return this.set(path, undefined)
};
/**
* @param {*} obj
* @param {!Array} keys
* @param {*} val
* @param {number} idx
* @return {*}
*/
function setKeys(obj, keys, val, idx) {
// 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 = setKeys(o, keys, val, idx+1);
return v instanceof Error ? v : 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
}
/**
* @constructor
* @param {*} initValue
* @param {Object} commands
*/
function Store(initValue, commands) {
this._ks = new Map;
this._fs = [];
this._cs = commands || {};
this.data = initValue;
}
Store.prototype.on = Trie.prototype.on;
Store.prototype.off = Trie.prototype.off;
Store.prototype.once = Trie.prototype.once;
Store.prototype.get = State.prototype.get;
/**
* @param {string} name
* @param {...*} [param]
* @return {Error|void}
*/
Store.prototype.run = function(name, param) { //eslint-disable-line no-unused-vars
var state = new State(this.data),
cmd = this._cs[name];
if (!cmd) return Error('invalid command ' + name)
for (var i=1, args=[]; i<arguments.length; ++i) args[i-1] = arguments[i];
cmd.apply(state, args);
return state.data instanceof Error ? state.data : update(this, state.data, null)
};
/**
* @param {!Object} trie
* @param {*} val
* @param {string} key
* @return {void|Error}
*/
function update(trie, val, key) {
if (val instanceof Error) return val
if (val !== trie.data) {
var old = trie.data;
trie.data = val;
// fire kids first...
trie._ks.forEach(updateKid, val);
// ...then self
for (var i=0, fs=trie._fs; i<fs.length; ++i) {
fs[i].f.call(fs[i].c, val, key, old);
}
}
}
function updateKid(kid, k) {
update(kid, getKey(this, k), k);
}
function missingKeys(reference, value) {

@@ -351,8 +343,8 @@ var keys = isObj(reference) ? Object.keys(reference) : [];

/**
* @param {*} [initialValue]
* @param {Object} [commands]
* @param {*} initValue
* @param {Object} commands
* @return {Store}
*/
function createStore(initialValue, commands) {
return new Store(initialValue, commands)
function createStore(initValue, commands) {
return new Store(initValue, commands)
}

@@ -364,5 +356,3 @@

exports.Store = Store;
exports.setOperation = setOperation;
exports.delOperation = delOperation;
}((this.attostore = this.attostore || {})));

@@ -20,32 +20,2 @@ /* hugov@runbox.com | https://github.com/hville/attostore.git | license:MIT */

function pathKeys(path) {
var ct = cType(path);
return ct === Array ? path : ct === Number ? [path] : !path ? [] : path.split('/')
}
/**
* 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) {

@@ -55,131 +25,8 @@ if (isObj(obj)) return obj[key]

/**
* @param {Object|Array<Object>} ops
* @return {Error|void}
*/
function patch(ops) {
var data = Array.isArray(ops) ? ops.reduce(setRed, this.data) : setRed(this.data, ops);
return data instanceof Error ? data : update(this, data, '')
function pathKeys(path) {
var ct = cType(path);
return ct === Array ? path : ct === Number ? [path] : !path ? [] : path.split('/')
}
/**
* @param {*} res
* @param {Object} op
* @returns {*}
*/
function setRed(res, op) {
return res instanceof Error ? res : setKeys(res, pathKeys(op.p), op.v, 0)
}
/**
* @param {!Object} store
* @param {*} val
* @param {string} key
* @return {void|Error}
*/
function update(store, val, key) {
if (val instanceof Error) return val
if (val !== store.data) {
var old = store.data;
store.data = val;
// fire kids first...
store._ks.forEach(updateKid, val);
// ...then self
for (var i=0, fs=store._fs; i<fs.length; ++i) {
fs[i].f.call(fs[i].c === undefined ? store : fs[i].c, val, key, old);
}
}
}
function updateKid(kid, k) {
update(kid, getKey(this, k), k);
}
/**
* @param {*} obj
* @param {!Array} keys
* @param {*} val
* @param {number} idx
* @return {*}
*/
function setKeys(obj, keys, val, idx) {
// 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 = setKeys(o, keys, val, idx+1);
return v instanceof Error ? v : 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
}
/**
* @param {null|string|Array} path
* @param {*} [data]
* @return {Object}
*/
function setOperation(path, data) {
if (path === undefined || data === undefined) throw Error('undefined argument')
return {p: path, v: data}
}
/**
* @param {null|string|Array} path
* @return {Object}
*/
function delOperation(path) {
if (path === undefined) throw Error('undefined argument')
return {p: path == null ? '' : path}
}
/**
* @param {string} name
* @param {*} [data]
* @return {Error|void}
*/
function run(name, data) {
var ops = this._cs[name] && this._cs[name](data);
if (!ops) return Error('invalid command ' + name)
return this.run(ops)
}
/**
* @constructor

@@ -194,2 +41,3 @@ * @param {*} [data]

/**

@@ -201,3 +49,3 @@ * @param {Array|string|number} key

*/
function on(key, fcn, ctx) {
Trie.prototype.on = function(key, fcn, ctx) {
var leaf = setLeaf(this, pathKeys(key)),

@@ -207,3 +55,3 @@ list = leaf._fs;

return this
}
};

@@ -216,3 +64,3 @@ /**

*/
function off(key, fcn, ctx) {
Trie.prototype.off = function(key, fcn, ctx) {
var keys = pathKeys(key),

@@ -227,3 +75,3 @@ itm = getLeaf(this, keys),

return this
}
};

@@ -236,3 +84,3 @@ /**

*/
function once(key, fcn, ctx) {
Trie.prototype.once = function(key, fcn, ctx) {
var store = this;

@@ -244,4 +92,5 @@ function wrap(v,k,o) {

return this.on(key, wrap, ctx)
}
};
/**

@@ -300,2 +149,27 @@ * @param {Trie} root

/**
* 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
}
/**
* @constructor

@@ -305,17 +179,7 @@ * @param {*} [data]

*/
function Store(data, commands) {
this._ks = new Map;
this._fs = [];
this._cs = commands || {};
function State(data) {
this.data = data;
}
Store.prototype.on = on;
Store.prototype.off = off;
Store.prototype.once = once;
Store.prototype.patch = patch;
Store.prototype.run = run;
Store.prototype.get = function(path) {
State.prototype.get = function(path) {
var keys = pathKeys(path);

@@ -329,2 +193,130 @@ for (var i=0, itm = this.data; i<keys.length; ++i) {

/**
* @param {null|string|Array} path
* @param {*} data
* @return {Object}
*/
State.prototype.set = function(path, data) {
if (!(this.data instanceof Error)) this.data = setKeys(this.data, pathKeys(path), data, 0);
return this
};
/**
* @param {null|string|Array} path
* @return {Object}
*/
State.prototype.delete = function(path) {
return this.set(path, undefined)
};
/**
* @param {*} obj
* @param {!Array} keys
* @param {*} val
* @param {number} idx
* @return {*}
*/
function setKeys(obj, keys, val, idx) {
// 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 = setKeys(o, keys, val, idx+1);
return v instanceof Error ? v : 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
}
/**
* @constructor
* @param {*} initValue
* @param {Object} commands
*/
function Store(initValue, commands) {
this._ks = new Map;
this._fs = [];
this._cs = commands || {};
this.data = initValue;
}
Store.prototype.on = Trie.prototype.on;
Store.prototype.off = Trie.prototype.off;
Store.prototype.once = Trie.prototype.once;
Store.prototype.get = State.prototype.get;
/**
* @param {string} name
* @param {...*} [param]
* @return {Error|void}
*/
Store.prototype.run = function(name, param) { //eslint-disable-line no-unused-vars
var state = new State(this.data),
cmd = this._cs[name];
if (!cmd) return Error('invalid command ' + name)
for (var i=1, args=[]; i<arguments.length; ++i) args[i-1] = arguments[i];
cmd.apply(state, args);
return state.data instanceof Error ? state.data : update(this, state.data, null)
};
/**
* @param {!Object} trie
* @param {*} val
* @param {string} key
* @return {void|Error}
*/
function update(trie, val, key) {
if (val instanceof Error) return val
if (val !== trie.data) {
var old = trie.data;
trie.data = val;
// fire kids first...
trie._ks.forEach(updateKid, val);
// ...then self
for (var i=0, fs=trie._fs; i<fs.length; ++i) {
fs[i].f.call(fs[i].c, val, key, old);
}
}
}
function updateKid(kid, k) {
update(kid, getKey(this, k), k);
}
function missingKeys(reference, value) {

@@ -352,8 +344,8 @@ var keys = isObj(reference) ? Object.keys(reference) : [];

/**
* @param {*} [initialValue]
* @param {Object} [commands]
* @param {*} initValue
* @param {Object} commands
* @return {Store}
*/
function createStore(initialValue, commands) {
return new Store(initialValue, commands)
function createStore(initValue, commands) {
return new Store(initValue, commands)
}

@@ -365,3 +357,1 @@

exports.Store = Store;
exports.setOperation = setOperation;
exports.delOperation = delOperation;

@@ -5,8 +5,8 @@ // @ts-check

/**
* @param {*} [initialValue]
* @param {Object} [commands]
* @param {*} initValue
* @param {Object} commands
* @return {Store}
*/
export function createStore(initialValue, commands) {
return new Store(initialValue, commands)
export function createStore(initValue, commands) {
return new Store(initValue, commands)
}

@@ -16,2 +16,1 @@

export {Store} from './src/_store'
export {setOperation, delOperation} from './src/_store-ops'
{
"name": "attostore",
"version": "0.7.0",
"version": "0.8.0",
"description": "json data store",

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

@@ -13,5 +13,5 @@ # attodom

var store = create({}, {
yell: function(name) { return setOperation('yell', name) },
sing: function(name) { return setOperation('sing', name) },
stop: function() { return [delOperation('yell'), delOperation('sing')] },
yell: function(name) { this.set('yell', name) },
sing: function(name) { this.set('sing', name) },
stop: function() { this.delete('yell').delete('sing')] },
})

@@ -44,14 +44,10 @@

createStore(initValue: `any`, commands: `{cmdName: Command}`): `Store`
setOperation(path, data): `Operation`
delOperation(path): `Operation`
createStore(initValue: `any`, commands: `{commandName: Command}`): `Store`
### Store
.patch(`Operation|Operations`): `Error|void`
.on(path: `Path`, handler: `(val, key, old, key)=>void`, [, context: `any`]): `Ref`
.once(path: `Path`, handler: `(val, key, old, key)=>void`, [, context: `any`]): `Ref`
.off(path: `Path`, handler: `(val, key, old, key)=>void`, [, context: `any`]): `Ref`
.run(commandName: `string`, ...args: `any`): `Error|void`

@@ -61,3 +57,3 @@

`any => Operation|Operations`
`(this:{set, delete, get}, any) => void`

@@ -64,0 +60,0 @@

@@ -1,33 +0,60 @@

import {pathKeys} from './path-keys'
import {isObj} from './type'
import {patch} from './_store-edits'
import {run} from './_store-ops'
import {on, off, once} from './_store-events'
import {Trie} from './_trie'
import {State} from './_state'
import {getKey} from './get-key'
/**
* @constructor
* @param {*} [data]
* @param {Object} [commands]
* @param {*} initValue
* @param {Object} commands
*/
export function Store(data, commands) {
export function Store(initValue, commands) {
this._ks = new Map
this._fs = []
this._cs = commands || {}
this.data = data
this.data = initValue
}
Store.prototype.on = on
Store.prototype.off = off
Store.prototype.once = once
Store.prototype.on = Trie.prototype.on
Store.prototype.off = Trie.prototype.off
Store.prototype.once = Trie.prototype.once
Store.prototype.patch = patch
Store.prototype.run = run
Store.prototype.get = State.prototype.get
Store.prototype.get = function(path) {
var keys = pathKeys(path)
for (var i=0, itm = this.data; i<keys.length; ++i) {
if (isObj(itm)) itm = itm[keys[i]]
else return
/**
* @param {string} name
* @param {...*} [param]
* @return {Error|void}
*/
Store.prototype.run = function(name, param) { //eslint-disable-line no-unused-vars
var state = new State(this.data),
cmd = this._cs[name]
if (!cmd) return Error('invalid command ' + name)
for (var i=1, args=[]; i<arguments.length; ++i) args[i-1] = arguments[i]
cmd.apply(state, args)
return state.data instanceof Error ? state.data : update(this, state.data, null)
}
/**
* @param {!Object} trie
* @param {*} val
* @param {string} key
* @return {void|Error}
*/
function update(trie, val, key) {
if (val instanceof Error) return val
if (val !== trie.data) {
var old = trie.data
trie.data = val
// fire kids first...
trie._ks.forEach(updateKid, val)
// ...then self
for (var i=0, fs=trie._fs; i<fs.length; ++i) {
fs[i].f.call(fs[i].c, val, key, old)
}
}
return itm
}
function updateKid(kid, k) {
update(kid, getKey(this, k), k)
}

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

import {getKey} from './get-key'
import {pathKeys} from './path-keys'
/**

@@ -10,1 +13,101 @@ * @constructor

}
/**
* @param {Array|string|number} key
* @param {Function} fcn
* @param {*} [ctx]
* @return {!Object}
*/
Trie.prototype.on = function(key, fcn, ctx) {
var leaf = setLeaf(this, pathKeys(key)),
list = leaf._fs
if (indexOf(list, fcn, ctx) === -1) list.push({f: fcn, c:ctx})
return this
}
/**
* @param {Array|string|number} key
* @param {Function} fcn
* @param {*} [ctx]
* @return {!Object}
*/
Trie.prototype.off = function(key, fcn, ctx) {
var keys = pathKeys(key),
itm = getLeaf(this, keys),
arr = itm && itm._fs,
idx = indexOf(arr, fcn, ctx)
if (idx !== -1) {
arr.splice(idx, 1)
if (!arr.length && !itm._ks.size) delLeaf(this, keys, 0)
}
return this
}
/**
* @param {Array|string|number} key
* @param {Function} fcn
* @param {*} [ctx]
* @return {!Object}
*/
Trie.prototype.once = function(key, fcn, ctx) {
var store = this
function wrap(v,k,o) {
store.off(key, wrap, ctx);
fcn.call(this, v,k,o)
}
return this.on(key, wrap, ctx)
}
/**
* @param {Trie} root
* @param {Array<string>} keys
* @return {Trie}
*/
function getLeaf(root, keys) {
for (var i=0, itm = root; i<keys.length; ++i) {
if (itm !== undefined) itm = itm._ks.get(''+keys[i])
}
return itm
}
/**
* @param {Trie} root
* @param {Array<string>} keys
* @return {Trie}
*/
function setLeaf(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(getKey(itm.data, key)))
itm = itm._ks.get(key)
}
return itm
}
/**
* @param {Trie} trie
* @param {Array<string>} keys
* @param {number} idx
* @return {void}
*/
function delLeaf(trie, keys, idx) {
var key = keys[idx++],
kid = trie._ks.get(key)
if (kid instanceof Trie) {
if (idx !== keys.length) delLeaf(kid, keys, idx)
if (!kid._ks.size && !kid._fs.length) trie._ks.delete(key)
}
}
/**
* @param {Array} arr
* @param {Function} fcn
* @param {*} ctx
* @return {number}
*/
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
}

@@ -6,9 +6,7 @@ var S = require( '../index' ),

changed = S.changedKeys,
missing = S.missingKeys,
setOp = S.setOperation,
delOp = S.delOperation
missing = S.missingKeys
function compare(v,k,o) {
t('!==', v, o, 'child event only if value changed: ')
t('===', k === null || typeof k === 'string', true, 'child event only if value changed: ')
t('===', k === null || typeof k === 'string', true, 'child event only if value changed: '+k)
if (this) {

@@ -22,3 +20,5 @@ t('{==}', missing(v,o), this[0], 'added keys')

t('ref - added keys', function() {
var store = create()
var store = create({}, {
init: function(v) { this.set('', v) }
})

@@ -30,3 +30,3 @@ store.once('aa',compare, [['bb','b'],[],[]])

t('!', store.patch(setOp(null, {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})), 'no errors')
t('!', store.run('init', {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'}), 'no errors')
t('{===}', store.data, {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})

@@ -37,3 +37,7 @@ })

t('ref - del keys', function() {
var store = create({aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})
var store = create(null, {
init: function(v) { this.set([], v) },
clear: function() { this.delete() }
})
store.run('init', {aa: {bb:{cc:{}, c: 'c'}, b: 'b'}, a:'a'})

@@ -45,3 +49,3 @@ store.once('aa', compare, [[],[],['bb','b']])

t('!', store.patch(delOp('')))
t('!', store.run('clear'))
t('{===}', store.data, undefined)

@@ -51,3 +55,7 @@ })

t('auto purge trie', function() {
var store = create()
var store = create(null, {
init: function(v) { this.set(null, v) },
set: function(p,v) { this.set(p,v) },
clear: function() { this.delete() }
})
function noop(){}

@@ -64,9 +72,14 @@ t('===', store._ks.size, 0)

t('db - query', function() {
var store = create({data: {list: [1,0]}, view:{}, acts:{}, done:[]})
var store = create(null, {
init: function(v) { this.set(null, v) },
set: function(p,v) { this.set(p,v) },
clear: function() { this.delete() }
})
store.run('init', {data: {list: [1,0]}, view:{}, acts:{}, done:[]})
store.on('data/list', function(v) {
store.patch(setOp('view/sort', v.slice().sort()))
store.run('set', 'view/sort', v.slice().sort())
})
store.on('acts/push', function(v) {
store.patch(setOp('data/list', store.get('data/list').concat(v)))
store.run('set', 'data/list', store.get('data/list').concat(v))
})

@@ -78,3 +91,3 @@

t('!', store.patch(setOp('acts/push', 9)))
t('!', store.run('set', 'acts/push', 9))
t('{===}', store.data.data.list, [1,0,9])//[1,0]

@@ -88,6 +101,6 @@ t('{===}', store.data.view.sort, [0,1,9])//undefined

var commands = {
init: function() { return setOp('', {}) },
yell: function(x) { return setOp('yell', !!x) },
sing: function(x) { return setOp('sing', !!x) },
stop: function() { return [delOp('yell'), delOp('sing')] }
init: function() { this.set('', {}) },
yell: function(x) { this.set('yell', !!x) },
sing: function(x) { this.set('sing', !!x) },
stop: function() { this.delete('yell').delete('sing') }
},

@@ -103,3 +116,3 @@ store = create(null, commands),

t('{===}', store.data, expected.newVal)
})
}, store)
store.run('init')

@@ -110,3 +123,3 @@ expected = {newVal:{yell:true}, oldVal:{}}

store.run('sing', 2)
expected = {newVal:{yell:false, sing:false}, oldVal:{yell:true, sing:true}}
expected = {newVal:{}, oldVal:{yell:true, sing:true}}
store.run('stop')

@@ -117,4 +130,6 @@ })

t('store - errors', function() {
var initVal = {},
store = create(initVal)
var store = create(null, {
set: function(p,v) { this.set(p,v) },
del: function(p) { this.delete(p) }
})

@@ -125,4 +140,6 @@ store.on('', function() {

t('===', store.patch(setOp('a/b', 9)) instanceof Error, true)
t('===', store.patch(delOp('a/b')) instanceof Error, true)
t('===', store.run('set', 'a/b', 9) instanceof Error, true)
t('===', store.run('del', 'a/b') instanceof Error, true)
var res = store.run('set', 'a/b', 9)
t('===', res instanceof Error && res.message, 'invalid path: a/b')
})
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