Skip to content

fullmooner-stack/eventloop_idb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EventLoop_idb

The Fastest IndexedDB wrapper out there.

A fast, simple, single file, zero-dependency wrapper driven by an asynchronous micro-task event loop. Groups reads, writes, and deletes into controlled transactional batches — eliminating write-amplification, context switching, and transaction thrashing.

npm version license

npm i eventloop_idb

or copy/paste the single file at src/index.ts

Performance

Benchmark

Compare against other IndexedDB wrappers at idbwrappersbenchmark.vercel.app


Usage

Instantiation

import { EventLoop_idb } from 'eventloop_idb';
const db = new EventLoop_idb('my_store');

Write

const item = { id: "123_string", name: "john doe", age: 31 }
db.write(item.id, () => item, (success) => { if (success) console.log('saved'); });

Read

db.read("123_string", (item) => console.log(item)); // { id: "123_string", name: "john doe", age: 31 }

Delete

db.delete("123_string", (success) => success && console.log("successfully deleted item 123_string"));

Read all keys

db.getAllKeys((allKeys) => console.log(allKeys)); // reads all keys
db.getAllKeys((allKeys) => console.log(allKeys), null, 10); // reads the first 10 keys
const idbKeyRange = [10, 100];
db.getAllKeys((allKeys) => console.log(allKeys), idbKeyRange); // reads all keys within an idb key range

Read all items

db.getAll((allItems) => console.log(allItems)); // reads all items
db.getAll((allItems) => console.log(allItems), null, 10); // reads the first 10 items
const idbKeyRange = [10, 100];
db.getAll((allItems) => console.log(allItems), idbKeyRange); // reads all items within an idb key range

Clear all items from database

db.clear((success) => success && console.log(`${db.name} was successfully cleared`));

Reactive State

EventLoop_idb exposes raw Set-based callback collections. Sets do not self-execute on subscription, so always sync the current value before subscribing.

Subscribe to connection state

let connectionState = false;
const trackConnection = (connected) => (connectionState = connected);
connectionState = db.readyFlag;
db.onReadyStateChangeClbs.add(trackConnection);

Unsubscribe from connection state

db.onReadyStateChangeClbs.delete(trackConnection); // unsubscribe single subscriber
db.onReadyStateChangeClbs.clear(); // unsubscribe all subscribers

Subscribe to on-idle

Fires when all pending operations are exhausted and the instance goes idle.

const isIdle = () => console.log(db.name, "is idling");
db.onIdleClbs.add(isIdle);

Unsubscribe from on-idle

db.onIdleClbs.delete(isIdle); // unsubscribe single subscriber
db.onIdleClbs.clear(); // unsubscribe all subscribers

Examples

React

import { useState, useEffect } from 'react';
import { EventLoop_idb } from 'eventloop_idb';

const db = new EventLoop_idb('my-store');

export function App() {
  const [ready, setReady] = useState(db.readyFlag);
  const [data, setData] = useState(null);

  useEffect(() => {
    setReady(db.readyFlag);
    const onState = (r) => setReady(r);
    db.onReadyStateChangeClbs.add(onState);
    return () => db.onReadyStateChangeClbs.delete(onState);
  }, []);

  const handleWrite = (item) => {
    db.write(item.id, () => item, (success) => {
      if (success) toast("success");
      else toast("fail");
    });
  };

  return (
    <div>
      <p>{ready ? '🟢 Connected' : '⚪ Connecting...'}</p>
      {data && <pre>{JSON.stringify(data, null, 2)}</pre>}
      <button onClick={() => handleWrite({ id: "1", name: "john" })}>save</button>
    </div>
  );
}

SolidJS

import { createSignal, onCleanup } from 'solid-js';
import { EventLoop_idb } from 'eventloop_idb';

const db = new EventLoop_idb('my-store');

export function App() {
  const [ready, setReady] = createSignal(db.readyFlag);
  const [items, setItems] = createSignal([]);

  setReady(db.readyFlag);
  db.onReadyStateChangeClbs.add(setReady);

  onCleanup(() => db.onReadyStateChangeClbs.delete(setReady));

  return <p>{ready() ? '🟢 Connected' : '⚪ Connecting...'}{items().length} records</p>;
}

API

Constructor

new EventLoop_idb(name: string)

Properties

Property Type Description
name string The name of the DB
db IDBDatabase Direct access to the raw native IDB instance
readyFlag boolean true when open and ready
readyState string Detailed connection state: 'done' · 'blocked' · 'closed' · 'unexpectedly closed' · 'close'
onReadyStateChangeClbs Set<(readyFlag: boolean) => void> Fires on every connection state transition
onIdleClbs Set<() => void> Fires when all pending operations are exhausted and the instance goes idle

Methods

Read.

read(id: string, clb: (res: any) => void): void

Read all keys, or only matching keys if either or both range or count are provided (skip range with null).

getAllKeys(clb: (keys: string[]) => void, range?: IDBKeyRange, count?: number): void

Read all items, or only matching items if either or both range or count are provided (skip range with null).

getAll(clb: (items: any[]) => void, range?: IDBKeyRange, count?: number): void

Write (takes an accessor () => item, not a direct value).

write(id: string, data: (id: string) => any, clb?: (ok: boolean) => void): void

Delete a single record.

delete(id: string, clb?: (ok: boolean) => void): void

Delete all records.

clear(clb?: (ok: boolean) => void): void

License

MIT

About

Event Loop IndexedDB wrapper

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors