@webreflection/idb-map
v0.3.2
Published
Async IndexedDB based Map
Downloads
3,604
Readme
@webreflection/idb-map
Social Media Photo by delfi de la Rua on Unsplash
An IndexedDB based Map with an asynchronous interface.
IDBMap API
An IDBMap instance implements all Map methods or accessors except these are all asynchroonus.
An IDBMap also extends EventTarget too, so dispatchEvent
is also available, among others. Handled events are by default abort
, close
, error
and versionchange
.
The IDBMap constructor is the only main different API compared to Map:
- it accepts a database's
name
suffix as string. The DB will be called'IDBMap/${name}'
. The storage name used for this db will be entries. An empty string is also a valid name but please be aware of naming collisions - it accepts an optional
options
object, currently to either override transactions' durability, where its default value is'default'
, or to use a different database prefix name which default value is'IDBMap'
type IDBMapOptions = {
durability?: 'strict' | 'relaxed' | 'default';
prefix?: string;
}
class IDBMap extends EventTarget implements Map {
constructor(
name:string,
options:IDBMapOptions = { durability: 'default', prefix: 'IDBMap' }
):IDBMap
// the only extra method not present in Map or EventTarget
close():Promise<void>
}
Example
import IDBMap from '@webreflection/idb-map';
// create an async map with a generic storage name
const idbMap = new IDBMap('my-storage-name');
// check any Map property by awaiting it
console.log(await idbMap.size);
console.log(await idbMap.has('nope'));
// optional helpers for buffered data
const encoder = new TextEncoder;
const decoder = new TextDecoder;
// set any IDB compatible value
await idbMap.set('test.txt', 'test value');
console.log(await idbMap.has('test.txt'));
await idbMap.set('other.txt', encoder.encode('other value'));
// get any IDB stored value
console.log(await idbMap.get('test.txt'));
console.log(decoder.decode(await idbMap.get('other.txt')));
// retrieve any other async Map API method
console.log(await idbMap.keys());
console.log(await idbMap.size);
for (const entry of await idbMap.entries())
console.log(entry);
// or remove a single key
await idbMap.delete('other.txt');
console.log(await idbMap.keys());
console.log(await idbMap.size);
// or clear the whole thing
await idbMap.clear();
console.log(await idbMap.keys());
console.log(await idbMap.size);
// eventually close it
await idbMap.close();
IDBMapSync API
The idb-map/sync
export returns an instance of Map (no EventTarget) with only a sync()
extra method that is needed to be awaited on bootstrap or, if many changes are performed, before closing the thread.
Its content and methods are entirely loaded into RAM so it's less efficient in that regard but surely easier to both handle and reason about plus it's definitively faster than the fully async version.
import IDBMapSync from '@webreflection/idb-map/sync';
// create an async map with a generic storage name
const idbMap = new IDBMapSync('my-storage-name');
// await to populate it on bootstrap
await idbMap.sync();
// check any Map property by awaiting it
console.log(idbMap.size);
console.log(idbMap.has('nope'));
// optional helpers for buffered data
const encoder = new TextEncoder;
const decoder = new TextDecoder;
// set any IDB compatible value
idbMap.set('test.txt', 'test value');
console.log(idbMap.has('test.txt'));
idbMap.set('other.txt', encoder.encode('other value'));
// get any IDB stored value
console.log(idbMap.get('test.txt'));
console.log(decoder.decode(idbMap.get('other.txt')));
// retrieve any other async Map API method
console.log(idbMap.keys());
console.log(idbMap.size);
for (const entry of idbMap.entries())
console.log(entry);
// or remove a single key
idbMap.delete('other.txt');
console.log(idbMap.keys());
console.log(idbMap.size);
// or clear the whole thing
idbMap.clear();
console.log(idbMap.keys());
console.log(idbMap.size);
// eventually sync it before exiting
await idbMap.sync();
Background / Goal / Why
There are other projects with a similar goal, most popular or notable is idb-keyval, but ...
- there is no familiar API around this topic, everyone offering "easy IndexedDB" is kinda proposing a new API
- there is nothing more similar than a JS' Map to actually store key / value pairs
- the Map API is nothing new to learn, here the IDBMap is just about the same except it's inevitably asynchronous ... but ...
- it is still possible via coincident to have this transparently synchronous from a worker (if that's your cup of tea), making the Map a 1:1 familiar primitive that will persist its data in user's space
- the IDBMap also extends EventTarget, forwarding internal events when/if needed
- the IDBMap adds a
.close()
asynchronous method to ensure a db has been successfully closed
That's pretty much it; you already know this module and the only different thing is the way an IDBMap is initialized.