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

@labshare/data-structures

Package Overview
Dependencies
Maintainers
3
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@labshare/data-structures - npm Package Compare versions

Comparing version 2.0.0 to 3.0.0

src/string-set/string-set.spec.ts

40

CHANGELOG.md

@@ -0,1 +1,41 @@

# [3.0.0](https://github.com/LabShare/data-structures.git/compare/v2.0.0...v3.0.0) (2018-10-30)
### Bug Fixes
* assign to variable ([7f4dcdc](https://github.com/LabShare/data-structures.git/commit/7f4dcdc))
* check by id instead of content ([fa1d5db](https://github.com/LabShare/data-structures.git/commit/fa1d5db))
* improve error message for duplicated id ([2e8c314](https://github.com/LabShare/data-structures.git/commit/2e8c314))
* improve get method ([b21826d](https://github.com/LabShare/data-structures.git/commit/b21826d))
* return false when id is absent ([725c42c](https://github.com/LabShare/data-structures.git/commit/725c42c))
* return false when id is absent ([4f4397e](https://github.com/LabShare/data-structures.git/commit/4f4397e))
* update error message ([af3ab10](https://github.com/LabShare/data-structures.git/commit/af3ab10))
* update error message ([bccaab5](https://github.com/LabShare/data-structures.git/commit/bccaab5))
* update test ([2f37d8a](https://github.com/LabShare/data-structures.git/commit/2f37d8a))
* update toposort related methods ([d9276c9](https://github.com/LabShare/data-structures.git/commit/d9276c9))
* use hash related methods for performance ([a861ccd](https://github.com/LabShare/data-structures.git/commit/a861ccd))
### Features
* add findHash and findAndDifferenceHash ([4a8a1dc](https://github.com/LabShare/data-structures.git/commit/4a8a1dc))
* add findOneHash ([f8192c4](https://github.com/LabShare/data-structures.git/commit/f8192c4))
* add removeHash and removeHashes methods ([e55e055](https://github.com/LabShare/data-structures.git/commit/e55e055))
* add removeMany and orderTriples methods ([4b63925](https://github.com/LabShare/data-structures.git/commit/4b63925))
* add, update and expose hash-related methods ([6844c99](https://github.com/LabShare/data-structures.git/commit/6844c99))
* create StringSet, improve PointerMap ([4c97df1](https://github.com/LabShare/data-structures.git/commit/4c97df1))
* export UUID ([0045082](https://github.com/LabShare/data-structures.git/commit/0045082))
* expose getIndex and getMetadata methods ([dccd086](https://github.com/LabShare/data-structures.git/commit/dccd086))
* implement bulk operations ([7d31561](https://github.com/LabShare/data-structures.git/commit/7d31561))
* import StringSet, create utils functions ([e1f05d0](https://github.com/LabShare/data-structures.git/commit/e1f05d0))
* improve MultiMap with bulk methods ([69dbf99](https://github.com/LabShare/data-structures.git/commit/69dbf99))
* include hash information for iterators ([df7281c](https://github.com/LabShare/data-structures.git/commit/df7281c))
* update plugins ([3a14747](https://github.com/LabShare/data-structures.git/commit/3a14747))
### BREAKING CHANGES
* plugins now must handle onAdd and onRemove as
multi-items operations
# [2.0.0](https://github.com/LabShare/data-structures/compare/v1.1.5...v2.0.0) (2018-09-25)

@@ -2,0 +42,0 @@

2

package.json
{
"name": "@labshare/data-structures",
"main": "./src/index.ts",
"version": "2.0.0",
"version": "3.0.0",
"description": "",

@@ -6,0 +6,0 @@ "contributors": "https://github.com/LabShare/data-structures/graphs/contributors",

import {Collection} from './collection'
import { SSet } from '../sset/sset';
import {StringSet} from '../string-set/string-set';

@@ -73,2 +74,39 @@ describe('collection', () => {

})
describe('filter collection hashes', () => {
it('should create new collection from filtered hashes', () => {
let gw = {
name: 'George Washington',
year: 1732
};
let ja = {
name: 'John Adams',
year: 1735
};
let tj = {
name: 'Thomas Jefferson',
year: 1743
};
let c0 = Collection.fromArray([
gw,
ja,
tj
]);
let c;
expect(() => c = c0.filterHashes(StringSet.fromArray([
SSet.hashOf(gw),
SSet.hashOf(ja)
]))).not.toThrow();
})
it('should copy metadata from collection', () => {
})
})
})

@@ -224,2 +262,3 @@

name: 'Luna',
id: 'luna',
lastName: 'Lovegood'

@@ -236,2 +275,3 @@ })).not.toThrow();

name: 'Luna',
id: 'luna',
lastName: 'Lovegood'

@@ -591,4 +631,130 @@ })).not.toThrow()

describe('findHash', () => {
it('should find property hash', () => {
let c = Collection.fromArray([
{a: true},
{b: false}
])
let r;
expect(()=> r = c.findHash({
a: SSet.hashOf(true)
})).not.toThrow();
expect(r.toArray()).toContain(jasmine.objectContaining({a: true}))
expect(r.toArray().length).toBe(1);
expect(()=> r = c.findHash({
a: [SSet.hashOf(true)]
})).not.toThrow();
expect(r.toArray()).toContain(jasmine.objectContaining({a: true}))
expect(r.toArray().length).toBe(1);
expect(()=> r = c.findHash({
a: []
})).not.toThrow();
expect(r.toArray().length).toBe(0);
expect(()=> r = c.findHash({
b: [SSet.hashOf(true)]
})).not.toThrow();
expect(r.toArray().length).toBe(0);
expect(()=> r = c.findHash({
b: [SSet.hashOf(false)]
})).not.toThrow();
expect(r.toArray()).toContain(jasmine.objectContaining({b: false}))
expect(r.toArray().length).toBe(1);
c = Collection.fromArray([
{b: true},
{b: false}
])
expect(()=> r = c.findHash({
b: [SSet.hashOf(false), SSet.hashOf(true)]
})).not.toThrow();
expect(r.toArray()).toContain(jasmine.objectContaining({b: false}))
expect(r.toArray()).toContain(jasmine.objectContaining({b: true}))
expect(r.toArray().length).toBe(2);
c = Collection.fromArray([
{y: 45, z: 54, id: 1}
])
expect(()=> r = c.findHash({
y: SSet.hashOf(45),
z: SSet.hashOf(54)
})).not.toThrow();
expect(r.toArray()).toContain({y: 45, z: 54, id: 1})
expect(r.toArray().length).toBe(1)
c = Collection.fromArray([
{y: 45, z: 54, id: 1}
])
expect(()=> r = c.findHash({
y: SSet.hashOf(78),
z: SSet.hashOf(54)
})).not.toThrow();
expect(r.toArray().length).toBe(0)
})
})
describe('findOneHash', () => {
it('should find property hash', () => {
let c = Collection.fromArray([
{a: true, id: 3, m: 123, n: 456},
{b: false, m: 234, n: 789}
])
let r;
expect(()=> r = c.findOneHash({
a: SSet.hashOf(true),
m: SSet.hashOf(123)
})).not.toThrow();
expect(r).toEqual({a: true, id: 3, m: 123, n: 456})
})
})
describe('findOneHashOrigin', () => {
it ('should one out of many query keys', () => {
let a = Collection.fromArray([
{name: 'Harry', id: 'harry', lastName: 'Potter'},
{name: 'Lilian', lastName: 'Potter'},
{name: 'James', lastName: 'Potter'}
]);
let r;
expect(() => r = a.findOneHashOrigin({
lastName: SSet.hashOf('Potter'),
name: SSet.hashOf('Harry')
})).not.toThrow()
expect(r).toEqual(
SSet.hashOf({name: 'Harry', lastName: 'Potter', id: 'harry'})
)
})
})
describe('removeHash', () => {
it('should remove hash from collection', () => {
let c = Collection.fromArray([
{name: 'Test', id: 'test'}
]);
expect(c.size()).toEqual(1);
expect(() => c = c.removeHash(
SSet.hashOf({name: 'Test', id: 'test'}))
).not.toThrow();
expect(c.isEmpty()).toBeTruthy();
})
})
describe('getIndex', () => {
it('should return index', () => {
let c = Collection.fromArray([
{name: 'Test', id: 'test'}
]);
expect(c.getIndex()).toBeDefined();
})
})
/* TODO: ids must be added to Collection.fromArray([item]) items */
})

@@ -6,5 +6,25 @@ import {SSet} from '../sset/sset';

import {DefaultIndex} from '../default-index/default-index';
import {PointerMap} from '../pointer-map/pointer-map';
import {StringSet} from '../string-set/string-set';
import {createTriples} from './create-triples';
const performIndexLookup = (args, props) => {
return props.index.has(args[0], args[1]) ?
props.index.from(args[0], args[1]) :
StringSet.fromEmpty();
};
const orOperator = (propName, values, props) => {
const sets = values.reduce((acc, v) => {
return [
...acc,
performIndexLookup([propName, v], props),
];
}, []);
/* Perform union between StringSets */
const finalStringSet = sets[0] ?
sets[0].union(...sets.splice(1)) :
StringSet.fromEmpty();
return finalStringSet;
};
export const indexPlugin = {

@@ -44,42 +64,81 @@ onInit(state) {

return {
props: DefaultIndex.fromTriples(
triples,
),
props: {
index: DefaultIndex.fromTriples(
triples,
),
/* TODO: Use pointerMap with nested pointerMaps for inverse.
There is no need for multiple values in this case */
inverse: DefaultIndex.fromTriples(
triples.map((triple) => [triple[2], triple[0], triple[1]]),
),
},
state,
};
},
onRemove(item, itemHash, props, state) {
let defaultIndex = props;
onRemove(items, itemHashes, props, state) {
/* TODO: foreach keys */
defaultIndex = _.reduce(item, (acc, value, key) => {
return acc.remove(key, SSet.hashOf(value), itemHash);
}, defaultIndex);
return defaultIndex;
},
onBeforeAdd(item, itemHash, props: DefaultIndex, state) {
if (!item.id) {
return {
continue: true,
message: null,
value: {
...item,
id: uuid(),
},
};
}
const result = {
index: [],
inverse: [],
};
items.forEach((item, i) => {
const itemHash = itemHashes[i];
_.forEach(item, (value, key) => {
const valueHash = props.inverse.get(itemHash, key);
const indexPath = [key, valueHash, itemHash];
const inversePath = [itemHash, key, valueHash];
/* Using mutable for performance improvement */
result.index.push(indexPath);
result.inverse.push(inversePath);
});
});
return {
continue: true,
message: null,
value: item,
index: props.index.removeMany(result.index),
inverse: props.inverse.removeMany(result.inverse),
};
},
onAdd(item, itemHash, props, state) {
let defaultIndex = props;
onBeforeAdd(items, itemHashes, props: DefaultIndex, state) {
let result;
items.forEach((item) => {
if (!item.id) {
result = {
continue: true,
message: null,
value: {
...item,
id: uuid(),
},
};
} else {
result = {
continue: true,
message: null,
value: item,
};
}
});
return result;
},
onAdd(items, itemHashes, props, state) {
/* TODO: foreach keys */
defaultIndex = _.reduce(item, (acc, value, key) => {
return acc.add(key, SSet.hashOf(value), itemHash);
}, defaultIndex);
return defaultIndex;
let result = props;
items.forEach((item, i) => {
const itemHash = itemHashes[i];
result = _.reduce(item, (acc, value, key) => {
const valueHash = SSet.hashOf(value);
const newIndex = acc.index.add(key, valueHash, itemHash);
const newInverse = acc.inverse.add(itemHash, key, valueHash);
return {
index: newIndex,
inverse: newInverse,
};
}, result);
});
return result;
},
API(state, props: DefaultIndex) {
API(state, props, set, [collection]) {
return {

@@ -89,3 +148,3 @@ findOne(query) {

/* Run sub-queries for each property key */
const results: PointerMap[] = _.reduce(
const results: StringSet[] = _.reduce(
query,

@@ -96,5 +155,5 @@ (result, value, propName) => {

...result,
props.has(args[0], args[1]) ?
props.from(args[0], args[1]) :
PointerMap.fromObject({}),
props.index.has(args[0], args[1]) ?
props.index.from(args[0], args[1]) :
StringSet.fromEmpty(),
];

@@ -104,7 +163,55 @@ },

);
let firstKey: string;
if (results.length > 1) {
firstKey = results[0].intersection(...results.slice(1)).first();
} else {
firstKey = results[0].first();
}
return state[firstKey];
},
findOneHashOrigin(query) {
const results: StringSet[] = _.reduce(
query,
(result, value, propName) => {
const args = [propName, value];
return [
...result,
props.index.has(args[0], args[1]) ?
props.index.from(args[0], args[1]) :
StringSet.fromEmpty(),
];
},
[],
);
let firstKey;
if (results.length > 1) {
firstKey = results[0].intersection(...results.slice(1)).first();
} else {
firstKey = results[0].first();
}
return firstKey;
},
findOneHash(query) {
/* TODO: separate props in indexed and not-indexed */
/* Run sub-queries for each property key */
const results: StringSet[] = _.reduce(
query,
(result, value, propName) => {
const args = [propName, value];
return [
...result,
props.index.has(args[0], args[1]) ?
props.index.from(args[0], args[1]) :
StringSet.fromEmpty(),
];
},
[],
);
let firstKey;
if (results.length > 1) {
firstKey = results[0].keysIntersection(...results.slice(1)).firstKey();
firstKey = results[0].intersection(...results.slice(1)).first();
} else {
firstKey = results[0].firstKey();
firstKey = results[0].first();
}

@@ -114,6 +221,6 @@ return state[firstKey];

find(query) {
find(query): Collection {
/* TODO: refactor/simplify with findOne */
/* Run sub-queries for each property key */
const results: PointerMap[] = _.reduce(
const results: StringSet[] = _.reduce(
query,

@@ -124,5 +231,5 @@ (r, value, propName) => {

...r,
props.has(args[0], args[1]) ?
props.from(args[0], args[1]) :
PointerMap.fromObject({}),
props.index.has(args[0], args[1]) ?
props.index.from(args[0], args[1]) :
StringSet.fromEmpty(),
];

@@ -134,14 +241,51 @@ },

if (results.length > 1) {
result = results[0].keysIntersection(...results.slice(1));
result = results[0].intersection(...results.slice(1));
} else {
result = results[0];
}
result = result.toPairs().map(([k]) => state[k]);
return Collection.fromArray(result);
return collection.filterHashes(result);
},
findHash(query): Collection {
/* TODO: refactor/simplify with findOne */
/* Run sub-queries for each property key */
const results: StringSet[] = _.reduce(
query,
(r, value, propName) => {
/* arrays work as "OR" clause */
/* TODO: Add tests */
if (_.isArray(value)) {
return [
...r,
orOperator(propName, value, props),
];
} else {
const args = [propName, value];
return [
...r,
props.index.has(args[0], args[1]) ?
props.index.from(args[0], args[1]) :
StringSet.fromEmpty(),
];
}
},
[],
);
let result: StringSet;
if (results.length > 1) {
result = results[0].intersection(...results.slice(1));
} else {
result = results[0];
}
return collection.filterHashes(result);
},
getIndex() {
return props;
return props.index;
},
getMetadata() {
return props.inverse;
},
};

@@ -166,10 +310,26 @@ },

public filterHashes(hashes: StringSet): Collection {
return this.filter((item, hash) => hashes.has(hash));
}
public findOne(query) {
return this.internal.set.$('indexPlugin').findOne(query);
return this.internal.set.$('indexPlugin', [this]).findOne(query);
}
public findOneHash(query) {
return this.internal.set.$('indexPlugin', [this]).findOneHash(query);
}
public findOneHashOrigin(query) {
return this.internal.set.$('indexPlugin', [this]).findOneHashOrigin(query);
}
public find(query) {
return this.internal.set.$('indexPlugin').find(query);
return this.internal.set.$('indexPlugin', [this]).find(query);
}
public findHash(query) {
return this.internal.set.$('indexPlugin', [this]).findHash(query);
}
public add(item) {

@@ -215,3 +375,2 @@ const newSet = this.internal.set.add(item);

{
...this.internal,
set: newSet,

@@ -240,2 +399,16 @@ },

public removeHash(item) {
return this.removeHashes([item]);
}
public removeHashes(item) {
const newSet = this.internal.set.removeHashes(item);
return new Collection(
{
...this.internal,
set: newSet,
},
);
}
public getOne() {

@@ -258,8 +431,17 @@ return this.internal.set.getOne();

public forEach(fn) {
this.internal.set.forEach(fn);
/* For collection, item metadata is included by default */
this.internal.set.forEach((item, hash) => {
const metadata = this.getMetadata().get(hash);
fn(item, hash, metadata);
});
}
public filter(fn) {
/* For collection, item metadata is included by default */
return new Collection({
set: this.internal.set.filter(fn),
...this.internal,
set: this.internal.set.filter((item, hash) => {
const metadata = this.getMetadata().get(hash);
return fn(item, hash, metadata);
}),
});

@@ -286,2 +468,10 @@ }

public getIndex() {
return this.internal.set.$('indexPlugin').getIndex();
}
public getMetadata() {
return this.internal.set.$('indexPlugin').getMetadata();
}
public changesFrom(c2: Collection) {

@@ -294,9 +484,16 @@ return c2.changesTo(this);

let comparingCollection = c2;
const removeItems = [];
/* Algorithm should track items by 'id' property */
this.forEach((item) => {
this.forEach((item, hash, metadata) => {
const id = item.id;
const c2Item = comparingCollection.findOne({id});
/* TODO: Create wrapper for info */
const c2Item = comparingCollection.findOneHash({
id: metadata.getOne('id'),
});
const c2ItemHash = comparingCollection.findOneHashOrigin({
id: metadata.getOne('id'),
});
if (c2Item) {
/* TODO: Avoid rehashing to improve performance */
if (SSet.hashOf(c2Item) !== SSet.hashOf(item)) {
if (c2ItemHash !== hash) {
changesList = changesList.add({

@@ -309,3 +506,3 @@ after: c2Item,

}
comparingCollection = comparingCollection.remove(c2Item);
removeItems.push(c2ItemHash);
} else {

@@ -319,2 +516,3 @@ changesList = changesList.add({

});
comparingCollection = comparingCollection.removeHashes(removeItems);
comparingCollection.forEach((item) => {

@@ -321,0 +519,0 @@ const id = item.id;

@@ -14,5 +14,6 @@ /* TODO: Maybe add array support? */

keys.forEach((k) => {
triples = [...triples, [k, SSet.hashOf(item[k]), itemHash] ];
const valueHash = SSet.hashOf(item[k]);
triples = [...triples, [k, valueHash, itemHash] ];
});
return triples;
};

@@ -6,2 +6,14 @@ import {MultiMap} from '../multi-map/multi-map';

type orderedTriplesArray = any[];
interface IMultiMapRemoveManyQuery {
[s: string]: string[];
}
interface IDefaultIndexRemoveManyQuery {
[s: string]: IMultiMapRemoveManyQuery;
}
type separatedFirstKeys = (i: string) => [string, IMultiMapRemoveManyQuery];
/* TODO: Generalize for n dimensions */

@@ -53,3 +65,5 @@ export class DefaultIndex {

public get(propName, valueHash) {
return this.internal.get(propName).getOne(valueHash);
return (valueHash !== undefined) ?
this.internal.get(propName).getOne(valueHash) :
this.internal.get(propName);
}

@@ -93,19 +107,61 @@

public remove(k1, k2, k3) {
return this.removeMany([[k1, k2, k3]]);
}
public orderTriples(items: string[][]): IDefaultIndexRemoveManyQuery {
/* Using mutable for performance improvement */
const acc = {};
items.forEach((item: string[]) => {
acc[item[0]] = acc[item[0]] || {};
acc[item[0]][item[1]] = acc[item[0]][item[1]] || [];
acc[item[0]][item[1]].push(item[2]);
});
return acc;
}
public removeMany(items: string[][]) {
/* Separate subKeys by same first key*/
const ordered = this.orderTriples(items);
let outerMap = this.internal;
const errorMsg = `Could not remove from DefaultIndex: ` +
`path '${[k1, k2, k3].join(', ')}' does not exist`;
if (!outerMap.has(k1)) {
throw new Error(errorMsg);
}
const innerMap = outerMap.get(k1);
if (!innerMap.has(k2, k3)) {
throw new Error(errorMsg);
}
const newInnerMap = innerMap.remove(k2, k3);
outerMap = outerMap.set(k1, newInnerMap);
if (newInnerMap.size() === 0) {
outerMap = outerMap.remove(k1);
}
const keys = Object.keys(ordered);
const removeKeys = [];
const setKeys = {};
const errorMsg = (k1, k2, k3) => `Could not remove from DefaultIndex: ` +
`path '${[k1, k2, k3].join(', ')}' does not exist`;
const checkIfValid = ([k1, k2, k3]) => {
if (!outerMap.has(k1)) {
throw new Error(errorMsg(k1, k2, k3));
}
const innerMap = outerMap.get(k1);
if (!innerMap.has(k2, k3)) {
throw new Error(errorMsg(k1, k2, k3));
}
};
items.forEach(checkIfValid);
const separateFirstKeys: separatedFirstKeys = (i) => [i, ordered[i]];
const orderedArray: orderedTriplesArray = keys.map(separateFirstKeys);
/* Loop through first keys and update them respectively */
type removeInnerKeysType = (a: [string, IMultiMapRemoveManyQuery]) => void;
const removeInnerKeys: removeInnerKeysType = ([key, inner]) => {
let innerMap: MultiMap = outerMap.get(key);
innerMap = innerMap.removeMany(inner);
if (innerMap.size() === 0) {
removeKeys.push(key);
} else {
setKeys[key] = innerMap;
}
};
orderedArray.forEach(removeInnerKeys);
outerMap = outerMap.removeMany(removeKeys).setMany(setKeys);
return new DefaultIndex(outerMap);
}
}

@@ -607,2 +607,12 @@ import {Graph} from './graph'

})
it('should return false when id is undefined', () => {
let g = Graph.fromObject({
edges: [],
nodes: [{
id: 'node0'
}]
});
expect(g.nodes.hasId()).toEqual(false);
})
})

@@ -751,2 +761,108 @@

describe('edges findAndDifference', () => {
it('should find and remove edges', () => {
let g = Graph.fromObject({
nodes: [],
edges: [
{id: 1, from: 0, to: 0, color: 'red'}
]
});
expect(g.edges.size()).toBe(1)
let r;
expect(() => r = g.edges.findAndDifference({
color: 'red'
})).not.toThrow();
expect(r.edges.size()).toBe(0)
})
})
describe('edges findOne', () => {
it('should find one edge', () => {
let g = Graph.fromObject({
nodes: [],
edges: [
{id: 1, from: 0, to: 0, color: 'red'}
]
});
expect(g.edges.size()).toBe(1)
let r;
expect(() => r = g.edges.findOne({
color: 'red'
})).not.toThrow();
expect(r).toEqual(
{id: 1, from: 0, to: 0, color: 'red'}
)
})
})
describe('edges find', () => {
let g;
beforeEach(() => {
g = Graph.fromObject({
edges: [
{
id: 'n1',
from: 0,
to: 0
}, {
id: 'n2',
name: 'Node 2',
from: 0,
to: 0
}, {
id: 1,
from: 0,
to: 0
}
],
nodes: []
});
})
it('should find edge by id', () => {
expect(g.edges.find({
id: 'n1'
}).toObject().edges).toEqual([{
id: 'n1',
from:0,
to: 0
}]);
expect(g.edges.find({
id: '1'
}).toObject().edges).toEqual([])
expect(g.edges.find({
id: 1
}).toObject().edges).toEqual([{
id: 1,
from: 0,
to: 0
}])
})
it('should not fail for inexistent key', () => {
let result;
expect(() => result = g.edges.find({
anyKey: 'anyValue'
})).not.toThrow();
expect(result.toObject().edges).toEqual([]);
})
it('should not fail for keys that exist in only one object', () => {
let result;
expect(() => result = g.edges.find({
name: 'Node 2'
})).not.toThrow();
expect(result.toObject().edges).toEqual([{
id: 'n2',
name: 'Node 2',
from: 0,
to: 0
}]);
})
})
describe('nodes filter', () => {

@@ -998,2 +1114,3 @@ it('should filter the nodes', () => {

let toArray = (arr) => arr.map(l => l.toObject().nodes);
expect(toArray(g.nodes.topologicalSort())).toEqual([

@@ -1193,3 +1310,3 @@ [{id: 1}],

})).toThrowError(
`Could not add Edge to Graph: Edge already exists`
`Could not add Edge to Graph: Edge Id already exists`
)

@@ -1196,0 +1313,0 @@ })

@@ -63,3 +63,3 @@ import * as _ from 'lodash';

const {nodes, edges} = this.internal;
if (nodes.has(item)) {
if (this.nodes.hasId(item.id)) {
throw new Error (

@@ -179,2 +179,5 @@ `Could not add Node to Graph: Node already exists`,

const {nodes, edges} = this.internal;
if (id === undefined) {
return false;
}
const maybeNode = nodes.findOne({id});

@@ -248,7 +251,32 @@ return (typeof maybeNode !== 'undefined') ? true : false;

getStartingNodes: (() => {
return this.nodes.filter((i) => {
return this.edges.findOne({
to: i.id,
const nodesWithoutIncidentEdges = (i, hash, itemMetadata) => {
const nodeIdHash = itemMetadata.getOne('id');
const itemHash = this.edges.findOneHash({
to: nodeIdHash,
}) === undefined;
return itemHash;
};
return this.nodes.filter(nodesWithoutIncidentEdges);
}).bind(this),
removeEdgesFromNodes: ((graph, nodesGraph: Graph): Graph => {
/* Remove levelNodes from graph */
const graphWithoutLevelNodes = graph.nodes.difference(nodesGraph);
/* Remove edges attached to removed nodes */
/* TODO: Abstract step into custom method */
const nodesCollection = nodesGraph.nodes.getAll();
let graphWithoutEdges = graphWithoutLevelNodes;
const hashes = [];
const addToHashesQueue = (item, hash, itemMetadata) => {
hashes.push(itemMetadata.getOne('id'));
};
nodesCollection.forEach(addToHashesQueue);
graphWithoutEdges = graphWithoutEdges.edges.findAndDifferenceHash({
from: hashes,
});
return graphWithoutEdges;
}).bind(this),

@@ -267,14 +295,3 @@

const levelNodes = graph.nodes.getStartingNodes();
/* Remove levelNodes from graph */
const graphWithoutLevelNodes = graph.nodes.difference(levelNodes);
/* Remove edges attached to removed nodes */
/* TODO: Abstract step into custom method */
const nodesCollection = Collection.fromArray(levelNodes.toObject().nodes);
let graphWithoutLevelEdges = graphWithoutLevelNodes;
nodesCollection.forEach((item) => {
graphWithoutLevelEdges = graphWithoutLevelEdges.edges.findAndDifference({
from: item.id,
});
});
const graphWithoutLevelEdges = this.nodes.removeEdgesFromNodes(graph, levelNodes);
return step(

@@ -378,2 +395,10 @@ graphWithoutLevelEdges,

findHash: ((query) => {
const {nodes, edges} = this.internal;
return new Graph({
edges: edges.findHash(query),
nodes: Collection.fromArray([]),
});
}).bind(this),
/** Shortcut method for piping Edges.find() => Edges.difference */

@@ -384,2 +409,10 @@ findAndDifference: ((query) => {

/** Shortcut method for piping Edges.find() => Edges.difference */
findAndDifferenceHash: ((query) => {
const z = this.edges.findHash(query);
const d = this.edges.difference(z);
return d;
}).bind(this),
/** Returns Edges as Collection Type instead of Graph */

@@ -433,5 +466,5 @@ getAll : (() => {

const {nodes, edges} = this.internal;
if (edges.has(item)) {
if (this.edges.hasId(item.id)) {
throw new Error (
`Could not add Edge to Graph: Edge already exists`,
`Could not add Edge to Graph: Edge Id already exists`,
);

@@ -485,2 +518,5 @@ }

const {nodes, edges} = this.internal;
if (id === undefined) {
return false;
}
const maybeNode = edges.findOne({id});

@@ -512,2 +548,8 @@ return (typeof maybeNode !== 'undefined') ? true : false;

/** Finds one item in Edges that satifies the query provided */
findOneHash: ((query) => {
const {nodes, edges} = this.internal;
return edges.findOneHash(query);
}).bind(this),
/** Gets the number of Edges in the Graph */

@@ -514,0 +556,0 @@ size: (() => {

@@ -0,1 +1,3 @@

import * as UUID from 'uuid/v4';
export {SSet} from './sset/sset';

@@ -7,1 +9,2 @@ export {SMap} from './smap/smap';

export {Graph} from './graph/graph';
export {UUID};

@@ -210,3 +210,3 @@ import { MultiMap } from "./multi-map";

expect(() => result = multiMap.getOne('b')).not.toThrow();
expect(result).toEqual('c');
expect(result).toEqual('c');
})

@@ -213,0 +213,0 @@

import { PointerMap } from '../pointer-map/pointer-map';
import { StringSet } from '../string-set/string-set';

@@ -15,3 +16,3 @@ interface IStateAndProps {

if (!outerMap.has(k1)) {
outerMap = outerMap.add(k1, PointerMap.fromObject({}));
outerMap = outerMap.add(k1, StringSet.fromEmpty());
}

@@ -38,3 +39,3 @@ const innerMap = outerMap.get(k1);

* A MultiMap consists of a pointerMap with keys that point to
* other pointerMaps. This allows one-to-many relationships
* StringSets. This allows one-to-many relationships
*/

@@ -82,3 +83,3 @@ export class MultiMap {

public getOne(k1) {
return this.internal.state.get(k1).firstKey();
return this.internal.state.get(k1).first();
}

@@ -96,31 +97,57 @@

const {state: outerMap, props: {size}} = this.internal;
if (!outerMap.has(k1)) {
throw new Error(`Could not remove from MultiMap: key '${k1}' does not exist`);
}
if (typeof k2 === 'undefined') {
return new MultiMap({
props: {
size: size - outerMap.get(k1).size(),
},
state: outerMap.remove(k1),
});
return this.removeMany({[k1]: true});
}
const innerMap = outerMap.get(k1);
if (!innerMap.has(k2)) {
throw new Error(`Could not remove from MultiMap: path '${k1}' -> '${k2}' does not exist`);
}
const newInnerMap = outerMap.get(k1).remove(k2);
let newOuterMap;
if (newInnerMap.size() === 0) {
newOuterMap = outerMap.remove(k1);
} else {
newOuterMap = outerMap.set(k1, newInnerMap);
}
return this.removeMany({[k1]: [k2]});
}
public removeMany(query: {[s: string]: string[] | boolean}): MultiMap {
const outerMap = this.internal.state;
const removeOuterKeys = [];
const setOuterKeys = {};
let size = this.size();
const queryKeys = Object.keys(query);
type keyValues = [string, string[] | boolean];
const toPairs: (k: string) => keyValues = (k) => [k, query[k]];
const orderedQuery: keyValues[] = queryKeys.map(toPairs);
const removeInnerKeys = ([key, values]: keyValues) => {
if (!outerMap.has(key)) {
throw new Error(`Could not remove from MultiMap: key '${key}' does not exist`);
}
if (typeof values === "boolean") {
size -= outerMap.get(key).size(),
removeOuterKeys.push(key);
} else {
const innerMap = outerMap.get(key);
values.forEach((k2) => {
if (!innerMap.has(k2)) {
throw new Error(`Could not remove from MultiMap: path '${key}' -> '${k2}' does not exist`);
}
});
size -= values.length;
const newInnerMap = innerMap.removeMany(values);
if (newInnerMap.size() === 0) {
removeOuterKeys.push(key);
} else {
setOuterKeys[key] = newInnerMap;
}
}
};
orderedQuery.forEach(removeInnerKeys);
const newOuterMap = outerMap.removeMany(removeOuterKeys).setMany(setOuterKeys);
return new MultiMap({
props: {
size: size - 1,
size,
},
state: newOuterMap,
});
}

@@ -127,0 +154,0 @@

@@ -224,2 +224,17 @@ import { PointerMap } from "./pointer-map";

})
it('should clear values when specified', () => {
let pm = PointerMap.fromObject({
10: '10',
20: '20',
21: '21',
22: '22'
})
let result;
expect(() => result = pm.filter(i => i % 10 === 0, true)).not.toThrow()
expect(result.toObject()).toEqual({
10: true,
20: true
})
})
})

@@ -360,2 +375,82 @@

describe('keysSet', () => {
it('should return a set of keys', () => {
let pMap = PointerMap.fromObject({})
let set;
expect(() => set = pMap.keysSet()).not.toThrow();
expect(set.toArray()).toEqual([])
pMap = PointerMap.fromObject({
'a': 'b'
})
expect(() => set = pMap.keysSet()).not.toThrow();
expect(set.toArray()).toEqual(['a'])
pMap = PointerMap.fromObject({
'a': 'b',
'c': 'd'
})
expect(() => set = pMap.keysSet()).not.toThrow();
expect(set.toArray()).toEqual(['a', 'c'])
})
})
describe('keysUnion', () => {
it('should return keys union', () => {
let p = PointerMap.fromPairs([
['a', 'b'],
['c', 'd']
])
let q = PointerMap.fromPairs([
['e', 'f'],
['g', 'h'],
['i', 'j']
])
let result;
expect(() => result = p.keysUnion(q)).not.toThrow();
expect(result.toPairs()).toEqual([
['a', 'b'],
['c', 'd'],
['e', 'f'],
['g', 'h'],
['i', 'j']
])
p = PointerMap.fromPairs([
['a', 'b'],
['c', 'd']
])
q = PointerMap.fromPairs([
['a', 'b'],
['g', 'h'],
['i', 'j']
])
expect(() => result = p.keysUnion(q)).not.toThrow();
expect(result.toPairs()).toEqual([
['a', 'b'],
['c', 'd'],
['g', 'h'],
['i', 'j']
])
})
})
describe('setMany', () => {
it('should overwrite key value pair', () => {
let p = PointerMap.fromObject({
a: '1234'
});
expect(() => p = p.setMany({
a: 2345,
b: true
})).not.toThrow();
expect(p.toPairs()).toEqual([
['a', 2345],
['b', true]
])
})
})
})
import _ = require('lodash');
import { StringSet } from '../string-set/string-set';

@@ -6,3 +7,3 @@ interface IHashMadeMap {

}
type keyValuePair = [string, string];
type keyValuePair = [string, (string| boolean)];
type pairsArray = keyValuePair[];

@@ -53,2 +54,6 @@

public isEmpty() {
return this.size() === 0;
}
public has(key: string, value?: string) {

@@ -74,2 +79,17 @@ const {state} = this.internal;

public keysUnion(...pointerMaps): PointerMap {
const result = pointerMaps.reduce((acc, p) => {
let r = acc;
p.forEach((key, value) => {
/* TODO: Implement merge */
if (!r.has(key)) {
r = r.add(key, value);
}
});
return r;
}, this);
return result;
}
public set(key, value) {

@@ -88,14 +108,43 @@ const isOverwrite = this.has(key);

public remove(key) {
if (!this.has(key)) {
throw new Error(`Could not remove from PointerMap: key '${key}' does not exist`);
}
public setMany(items: {[s: string]: any}) {
const newState = {
...this.internal.state,
};
let size = this.internal.props.size;
_.forEach(items, (value, key) => {
const isOverwrite = this.has(key);
size += (isOverwrite ? 0 : 1);
newState[key] = value;
});
return new PointerMap({
props: {
size: this.internal.props.size - 1,
size,
},
state: _.omit(this.internal.state, [key]),
state: newState,
});
}
public remove(key) {
return this.removeMany([key]);
}
public removeMany(keys: string[]) {
const newState = Object.assign({}, this.internal.state);
keys.forEach((key) => {
if (!this.has(key)) {
throw new Error(`Could not remove from PointerMap: key '${key}' does not exist`);
}
delete newState[key];
});
return new PointerMap({
props: {
size: this.internal.props.size - keys.length,
},
state: newState,
});
}
public get(key) {

@@ -112,3 +161,3 @@ if (!this.has(key)) {

public keysIntersection(...pointerMaps) {
public keysIntersection(...pointerMaps: PointerMap[]): StringSet {
pointerMaps = [this, ...pointerMaps];

@@ -121,10 +170,10 @@ const smallest = pointerMaps.reduce((acc, p) => {

}, {
item: -1,
item: null,
size: Infinity,
});
return smallest.item.filter((i) => {
return smallest.item.reduce((acc, value, i) => {
/* check if every pointerMaps has key */
return PointerMap.keyInEvery(i, pointerMaps);
}, true);
return PointerMap.keyInEvery(i, pointerMaps) ? acc.add(i) : acc;
}, StringSet.fromEmpty());

@@ -136,3 +185,3 @@ }

/* TODO: Memoize object keys */
Object.keys(this.internal.state).forEach((k) => {
this.forEach((k) => {
if (fn(k) === true) {

@@ -145,3 +194,7 @@ result = result.add(k, clearValues ? true : this.internal.state[k]);

public firstKey() {
public forEach(fn) {
Object.keys(this.internal.state).forEach((key) => fn(key, this.internal.state[key]));
}
public firstKey(): string {
const {state} = this.internal;

@@ -164,2 +217,12 @@ let result;

public keysArray(): string[] {
const {state, items} = this.internal;
const keys = Object.keys(state);
return keys;
}
public keysSet(): StringSet {
return StringSet.fromArray(this.keysArray());
}
public reduce(fn: (acc, value, key) => any, acc: any) {

@@ -166,0 +229,0 @@ const {state} = this.internal;

@@ -55,3 +55,3 @@ import { SSet } from "./sset";

onDestroy?: () => void,
API: (state, props) => any
API: (state, props, set: SSet, args: any[]) => any
}

@@ -58,0 +58,0 @@

@@ -99,2 +99,3 @@ import {SSet} from './sset';

let sset = SSet.fromArray(arr);
const sset2 = sset.map(item => item * 3);

@@ -175,2 +176,26 @@ expect(sset.size()).toBe(4);

})
it('should return same objects for two iterators', () => {
let sset = SSet.fromArray([{a: true}, {b: true}, {c: true}, {d: true}]);
let jsSet = new Set();
for (let item of sset) {
jsSet.add(item)
}
for (let item of sset) {
expect(jsSet.has(item)).toBeTruthy();
}
expect(jsSet.size).toEqual(4);
let sset2 = sset.add({y: 'z'});
jsSet = new Set();
for (let item of sset2) {
jsSet.add(item)
}
for (let item of sset) {
expect(jsSet.has(item)).toBeTruthy();
jsSet.add(item)
}
expect(jsSet.size).toEqual(5);
})
})

@@ -1113,2 +1138,11 @@

})
describe('removeHashes', () => {
it('should throw error if inexistent hash', () => {
let sset = SSet.fromArray([1, 2, 3]);
expect(() => sset.removeHashes(['inexistentHash'])).toThrowError(
`Could not remove hash from SSet: hash 'inexistentHash' does not exist in the set`
);
})
})
})

@@ -22,3 +22,3 @@ import _ = require('lodash');

/* Remove any unsupported values for JSON */
array = JSON.parse(JSON.stringify(array));
JSON.parse(JSON.stringify(array));

@@ -102,20 +102,47 @@ const internalState = {

type argsType = (a: SSet, b: any, c: boolean) => SSet;
const lsDifference: [SSet, argsType] =
[ largest,
(acc: SSet, item: any, largestHasIt: boolean): SSet => largestHasIt ?
acc.remove(item) : acc,
type argsType = (a: {set: SSet, hashes?: string[]}, b: any, c: boolean, d: any, e: boolean) => {set: SSet};
const lsDifference: [{set: SSet, hashes: string[]}, argsType] =
[ {set: largest, hashes: []},
(acc: {set: SSet, hashes?: string[]}, item: any, largestHasIt: boolean, itemHash, isLast: boolean) => {
/* Using Mutable for performance gains */
if (largestHasIt) {
acc.hashes.push(itemHash);
}
if (isLast === true) {
return {
set: acc.set.removeHashes(acc.hashes),
};
}
return acc;
},
];
const slDifference: [SSet, argsType] =
[ smallest,
(acc: SSet, item: any, largestHasIt: boolean): SSet => largestHasIt ?
acc.remove(item) : acc,
const slDifference: [{set: SSet, hashes: string[]}, argsType] =
[ {set: smallest, hashes: []},
(acc: {set: SSet, hashes?: string[]}, item: any, largestHasIt: boolean, itemHash, isLast: boolean) => {
/* Using Mutable for performance gains */
if (largestHasIt) {
acc.hashes.push(itemHash);
}
if (isLast === true) {
return {
set: acc.set.removeHashes(acc.hashes),
};
}
return acc;
},
];
type reducer = (acc: SSet, item: any, c: boolean) => SSet;
const unionReducer: opReducerFn = (acc: IOpReducerFnAcc, item, largestHasIt, itemHash) => ({
set: acc.set.mergeHash(itemHash, item),
});
const reducers: {
union: [SSet, reducer],
difference: [SSet, reducer],
oppositeDifference: [SSet, reducer],
intersection: [SSet, reducer],
union: [any, opReducerFn],
difference: [any, opReducerFn],
oppositeDifference: [any, opReducerFn],
intersection: [any, opReducerFn],
} = {

@@ -127,5 +154,7 @@ /* Difference and oppositeDifference are being calculated respectively as

difference: (set1 === largest) ? lsDifference : slDifference,
intersection: [smallest, (acc, item, largestHasIt): SSet => largestHasIt ? acc : acc.remove(item)],
intersection: [{set: smallest}, (acc, item, largestHasIt, itemHash) => ({
set: largestHasIt ? acc.set : acc.set.removeHash(itemHash),
})],
oppositeDifference: set1 === largest ? slDifference : lsDifference,
union: [largest, (acc, item, largestHasIt): SSet => acc.merge(item)],
union: [{set: largest}, unionReducer],
};

@@ -137,5 +166,13 @@

type setsOps = 'union' | 'difference' | 'oppositeDifference' | 'intersection';
interface IOpReducerFnAcc {set: SSet; hashes?: string[]; }
type opReducerFn = (
acc: IOpReducerFnAcc,
item: any,
largestHasIt: boolean,
itemHash: any,
isLast: boolean,
) => SSet | IOpReducerFnAcc;
type opReducer = [
SSet,
(acc: SSet, item: any, largestHasIt: boolean) => SSet
any,
opReducerFn
];

@@ -178,5 +215,5 @@ type operationArrayItem = [string, SSet, (acc: SSet, item: any, largestHasIt: boolean) => SSet];

public add(value: JSONCapable): SSet {
/* Remove unsupported values for JSON */
value = JSON.parse(JSON.stringify(value));
const hash = SSet.hashOf(value);
value = updatePlugins('onBeforeAdd', [value], [hash], this.statePropsPlugins).value;
/* Check whether value is already contained in the set */

@@ -201,10 +238,14 @@ const hashedValue = SSet.hashOf(value);

}
/* Remove any unsupported values for JSON */
value = JSON.parse(JSON.stringify(value));
const hash = SSet.hashOf(value);
return this.mergeHash(hash, value);
}
public mergeHash(hash, value) {
const isNewItem = !(hash in this.statePropsPlugins.state);
/* trigger onBeforeAdd if defined */
value = updatePlugins('onBeforeAdd', value, hash, this.statePropsPlugins).value;
value = updatePlugins('onBeforeAdd', [value], [hash], this.statePropsPlugins).value;

@@ -227,3 +268,3 @@ let newInternalState: SSetStatePropsPlugins = {

if (isNewItem) {
newInternalState = updatePlugins('onAdd', value, hash, newInternalState);
newInternalState = updatePlugins('onAdd', [value], [hash], newInternalState);
}

@@ -249,4 +290,2 @@

public remove(value: JSONCapable): SSet {
/* Remove any unsupported values for JSON */
value = JSON.parse(JSON.stringify(value));

@@ -268,3 +307,3 @@ const hashedValue = SSet.hashOf(value);

/* trigger onRemove */
newInternalState = updatePlugins('onRemove', value, hashedValue, newInternalState);
newInternalState = updatePlugins('onRemove', [value], [hashedValue], newInternalState);

@@ -274,2 +313,38 @@ return new SSet(newInternalState);

/** Remove item given its hash */
public removeHash(hashedValue: any): SSet {
return this.removeHashes([hashedValue]);
}
public removeHashes(hashedValues: any[]): SSet {
if (hashedValues.length === 0) {
return this;
}
hashedValues.forEach((hashedValue) => {
if (!(hashedValue in this.statePropsPlugins.state)) {
throw new Error(`Could not remove hash from SSet: hash '${hashedValue}' does not exist in the set`);
}
});
let newInternalState: SSetStatePropsPlugins = {
plugins: this.statePropsPlugins.plugins,
props: {
...this.statePropsPlugins.props,
size: this.statePropsPlugins.props.size - hashedValues.length,
},
state: _.omit(this.statePropsPlugins.state, hashedValues),
};
/* trigger onRemove */
newInternalState = updatePlugins('onRemove',
hashedValues.map((h) => this.statePropsPlugins.state[h]),
hashedValues,
newInternalState,
);
return new SSet(newInternalState);
}
/** Obtain the union between two SSets.

@@ -292,7 +367,8 @@ */

public difference(set: SSet): SSet {
/* TODO: Fix plugin issue for optimization */
const result = this.internalTwoSetsOperations(['difference'], this, set).difference;
const probEquals = result.probEquals(this);
/* Performance improvement: only return new Set
if difference is not itself */
const result = this.internalTwoSetsOperations(['difference'], this, set).difference;
/* TODO: Use fastEquals here */
if (result.equals(this)) {
if (probEquals) {
return this;

@@ -340,9 +416,13 @@ }

/* TODO: Add onFilter? plugin listener(s) */
public filter(fn: (JSONCapable) => boolean): SSet {
public filter(fn: (JSONCapable, hash) => boolean): SSet {
let newSet: SSet = this;
this.forEach((item) => {
if (!fn(item)) {
newSet = newSet.remove(item);
const remove = [];
/* Using mutable for performance improvement */
this.forEach((item, hash) => {
if (!fn(item, hash)) {
remove.push(hash);
}
});
newSet = newSet.removeHashes(remove);
return newSet;

@@ -360,5 +440,5 @@ }

*/
public $(name: string): any {
public $(name: string, args: any[] = []): any {
const {state, props, plugins} = this.statePropsPlugins;
return plugins[name].API(state, props[name]);
return plugins[name].API(state, props[name], this, args);
}

@@ -460,5 +540,2 @@

public has(value: JSONCapable): boolean {
/* Remove any unsupported values for JSON */
value = JSON.parse(JSON.stringify(value));
return SSet.hashOf(value) in this.statePropsPlugins.state;

@@ -486,4 +563,7 @@ }

/** Loop through SSet items and perform a function on the item if desired */
public forEach(fn: (JSONCapable) => void): void {
this.getSortedKeysArray().forEach((key) => fn(this.statePropsPlugins.state[key]));
public forEach(fn: (JSONCapable, key?, isLast?: boolean) => void): void {
const arr = this.getSortedKeysArray();
arr.forEach((key, i) => {
fn(this.statePropsPlugins.state[key], key, i + 1 === arr.length);
});
}

@@ -578,5 +658,9 @@

public equals(set: SSet): boolean {
return this.symmetricDifference(set).isEmpty();
return (this === set) || this.symmetricDifference(set).isEmpty();
}
public probEquals(set) {
return this === set;
}
/** This method is automatically used by JSON.stringify when converting to

@@ -639,11 +723,11 @@ * JSON data

smallest.forEach((item) => {
const largestHasIt = largest.has(item);
operationsQueue.forEach((opParams: any[]) =>
opParams[1] = opParams[2](opParams[1], item, largestHasIt),
);
smallest.forEach((item, hash, isLast) => {
const largestHasIt = largest.hasHash(hash);
operationsQueue.forEach((opParams: any[] ) => {
opParams[1] = opParams[2](opParams[1], item, largestHasIt, hash, isLast);
});
});
return operationsQueue.reduce((acc, value: any) => {
acc[value[0]] = value[1];
acc[value[0]] = value[1].set;
return acc;

@@ -650,0 +734,0 @@ }, {});

@@ -6,4 +6,4 @@ import _ = require('lodash');

action: 'onBeforeAdd' | 'onAdd' | 'onRemove',
item: any,
hash: string,
items: any[],
hashes: string[],
internalState: SSetStatePropsPlugins,

@@ -17,8 +17,16 @@ ): SSetStatePropsPlugins | any => {

message: null,
value: item,
value: items,
};
return _.reduce(Object.keys(plugins), (acc, pluginName) => {
/* TODO: remove workaround */
if (Object.keys(plugins).length === 0 && items.length === 1) {
return {
continue: true,
message: null,
value: items[0],
};
}
return Object.keys(plugins).reduce((acc, pluginName) => {
let listener: (
item: any,
hash: string,
items: any[],
hashes: string[],
props: PluginDeclarationProperties,

@@ -33,3 +41,3 @@ state: any,

message: null,
value: item,
value: items,
};

@@ -39,4 +47,3 @@ };

const result = listener(item, hash, props[pluginName], state);
const result = listener(items, hashes, props[pluginName], state);
if (result.continue !== true) {

@@ -54,6 +61,6 @@ throw new Error(

return _.reduce(Object.keys(plugins), (acc, pluginName) => {
return Object.keys(plugins).reduce((acc, pluginName) => {
const listener: (
item: any,
hash: string,
items: any[],
hashes: string[],
props: PluginDeclarationProperties,

@@ -63,4 +70,3 @@ state: any,

const result = listener(item, hash, props[pluginName], state);
const result = listener(items, hashes, props[pluginName], state);
return {

@@ -67,0 +73,0 @@ plugins,

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