npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@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.