README
Two Key Store
Simple key-value 'store' with 2 hierarchical keys.
Under the hood it just uses plain js objects, and no external dependencies.
No effort is made to protect the types of keys passed in, but constructor() and add() will skip any non-objects.
Target Environment
This was written to be compatible with vanilla nodejs from v8 onwards.
It exposes itself via module.exports
. I will assume that if you need CommonJs, ES6 or a browser module loaded, then you already know how to convert as necessary.
Keys
Keys must be:
- strings
- numbers other than NaN
- objects other than null
- not undefined
Internally, plain objects are used for storage, so the SAME_VALUE_ZERO logic will apply when comparing keys.
Install
$ npm install --save two-key-store
Usage
Import
const TwoKeyStore = require('two-key-store');
Constructor
const twoKeyStore = new TwoKeyStore();
You can also pass an object to bootstrap the store. See the add()
method for details.
const twoKeyStore = new TwoKeyStore({...});
API
set(k1, k2, entity)
Sets the entity at nested key [k1, k2]
.
An error will be thrown if either k1
or k2
are invalid keys.
const twoKeyStore = new TwoKeyStore();
// empty
twoKeyStore.set('a', 'b', 1);
// ['a', 'b']: 1
twoKeyStore.set('a', 'c', 'anything');
// ['a', 'b']: 1
// ['a', 'c']: 'anything'
twoKeyStore.set('d', 'e', [])
// ['a', 'b']: 1
// ['a', 'c']: anything
// ['d', 'e']: []
twoKeyStore.set('a', 'b', 'not 1');
// ['a', 'b']: 'not 1'
// ['a', 'c']: 'anything'
// ['d', 'e']: []
add(object)
Adds all the data that can be found, ie entities which are values of objects which are themselves values of the passed in object.
Any keys in the passed-in object which are deemed invalid will simply be ignored.
const twoKeyStore = new TwoKeyStore();
// empty
twoKeyStore.add({
a: 1, // will be ignored
b: {
c: 2,
d: 3,
},
e: {
f: {
g: 4,
h: 5
}
}
});
// ['b', 'c']: 2
// ['b', 'd']: 3
// ['e', 'f']: {g: 4, h: 5}
twoKeyStore.add([]); // no change
twoKeyStore.add({
i: {
j: 6,
k: 7
}
});
// ['b', 'c']: 2
// ['b', 'd']: 3
// ['e', 'f']: {g: 4, h: 5}
// ['i', 'j']: 6
// ['i', 'k']: 7
twoKeyStore.add({
a: {
x: 8
},
b: 'a string', // ignored
e: undefined, // ignored,
i: {
y: 9
},
i: {
undefined: 6 // ignored
},
null: 7, // ignored
NaN: 8 // ignored
});
// ['a', 'x']: 8
// ['b', 'c']: 2
// ['b', 'd']: 3
// ['e', 'f']: {g: 4, h: 5}
// ['i', 'j']: 6
// ['i', 'k']: 7
// ['i', 'y']: 9
has(k1, [k2])
If k1
and k2
are supplied, returns true if there is an entity stored against this nested key.
If only k1
is supplied, returns true if there are any entities stored under this top-level key.
If k1
is undefined this will always return false. An error will be thrown if k1
is otherwise invalid.
const twoKeyStore = new TwoKeyStore({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 4
}
});
twoKeyStore.has('a'); // true
twoKeyStore.has('b'); // false
twoKeyStore.has('x'); // false
twoKeyStore.has('a', 'b'); // true
twoKeyStore.has('a', 'd'); // false
twoKeyStore.has('a', 'e'); // false
twoKeyStore.has('a', 'x'); // false
twoKeyStore.has(undefined, 'x'); // false
twoKeyStore.has('a', undefined); // true
get(k1, [k2])
If k1
and k2
are supplied, returns the entity stored under nested key [k1, k2]
, or undefined if there is nothing stored against this nested key.
If only k1
is supplied, returns the nested object under that top-level key, or undefined if there is nothing stored under this top-level key.
If k1
is undefined this will always return undefined. An error will be thrown if k1
is otherwise invalid.
const twoKeyStore = new TwoKeyStore({
a: {
b: 1,
c: undefined
},
d: {
e: 2,
f: 3
}
});
twoKeyStore.get('a'); // {b: 1, c: undefined}
twoKeyStore.get('a', 'b'); // 1
twoKeyStore.get('a', 'b'); // 1
twoKeyStore.get('a', 'c'); // undefined
twoKeyStore.get('a', 'y'); // undefined
twoKeyStore.get('x', 'y'); // undefined
twoKeyStore.get(undefined, 'y'); // undefined
twoKeyStore.get('a', undefined); // {b: 1, c: undefined}
keys([k1])
If k1
is supplied, returns the keys of the nested object stored under this top-level key, or an empty array if nothing is stored under this top-level key.
If no argument are supplied, returns the top-level keys, or an empty array if the store is empty.
An error will be thrown if k1
is defined and invalid.
const twoKeyStore = new TwoKeyStore({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 4
}
});
const topLevelKeys = twoKeyStore.keys(); // ['a', 'd']
const keysForA = twoKeyStore.keys('a'); // ['b', 'c']
const keysForUnknown = twoKeyStore.keys('x'); // []
(new TwoKeyStore()).keys(); // []
values([k1])
If k1
is supplied, returns all the values stored under this top-level key, or an empty array if nothing is stored under this top-level key.
If no arguments are supplied, returns all the values in the store, or an empty array if the store is empty.
If k1
is invalid it will be treated as undefined.
const twoKeyStore = new TwoKeyStore({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 1
}
});
twoKeyStore.values(); // [1, 2, 3, 1]
twoKeyStore.values('a'); // [1, 2]
twoKeyStore.values('c'); // []
(new TwoKeyStore()).values(); // []
entries([k1])
If k1
is supplied, returns all entries stored under this top-level key as triples, or an empty list if nothing is stored under this top-level key.
If no arguments are supplied, returns all the entries in the store as a triple, or an empty array if the store is empty.
An error will be thrown if k1
is defined and invalid.
const twoKeyStore = new TwoKeyStore({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 4
}
});
twoKeyStore.entries();
// [
// ['a', 'b', 1],
// ['a' ,'c', 2],
// ['d' ,'e', 3],
// ['d' ,'f', 4],
// ]
twoKeyStore.entries('a');
// [
// ['a', 'b', 1],
// ['a' ,'c', 2],
// ]
twoKeyStore.entries('x'); // []
(new TwoKeyStore()).entries(); // []
forEach(fn)
Applies the fn to each entity in the store, with the keys passed as secondary arguments.
const twoKeyStore = new TwoKeyStore({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 4
}
});
twoKeyStore.forEach((entity, k1, k2) => console.log(entity, k1, k2));
// 1 a b
// 2 a c
// 3 d e
// 4 d f
delete(k1, [k2])
If k1
and k2
are supplied, this will delete the entity stored against this nested key, if one exists.
If only k1
is supplied, this will delete all entities with k1
as the top-level key, if there are any.
An error will be thrown if k1
is invalid or if k2
is defined and invalid.
const twoKeyStore = new TwoKeyStore({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 4
}
});
// ['a', 'b']: 1
// ['a', 'c']: 2
// ['d', 'e']: 3
// ['d', 'f']: 4
twoKeyStore.delete('a', 'b');
// ['a', 'c']: 2
// ['d', 'e']: 3
// ['d', 'f']: 4
twoKeyStore.delete('d');
// ['a', 'c']: 2
clear()
Clears all entities from the store.
const twoKeyStore = new TwoKeyStore({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 4
}
});
// ['a', 'b']: 1
// ['a', 'c']: 2
// ['d', 'e']: 3
// ['d', 'f']: 4
twoKeyStore.clear();
// empty
isEmpty()
Returns true if there are no entities in the store.
const twoKeyStore = new TwoKeyStore();
twoKeyStore.isEmpty(); // true
twoKeyStore.add({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 4
}
});
twoKeyStore.isEmpty(); // false
twoKeyStore.clear();
twoKeyStore.isEmpty(); // true
twoKeyStore.set('a', 'b', 1);
twoKeyStore.isEmpty(); // false
twoKeyStore.delete('a');
twoKeyStore.isEmpty(); // true
toObject()
Returns the store as an object literal.
const twoKeyStore = new TwoKeyStore();
twoKeyStore.toObject(); // {}
twoKeyStore.add({
a: {
b: 1,
c: 2
},
d: {
e: 3,
f: 4
}
});
twoKeyStore.toObject(); // {a: {b: 1, c: 2}, d: {e: 3, f: 4}}
License
UNLICENSED © [Alastair Brayne]