Skip to content

Simple & lightweight IndexedDB wrapper for modern browsers.

Notifications You must be signed in to change notification settings

adriengibrat/asyncdb

Repository files navigation

code style: prettier

asyncdb

asyncdb is a simple & lightweight IndexedDB wrapper for modern browsers, bundled in 3 flavours:

Install

With npm:

npm install asyncdb

With yarn:

yarn add asyncdb

Import

You can import just what you need (or the whole module) in your javascript / typescript codebase:

import { openDB, deleteDB, compare, range } from 'asyncdb'
// or
// import * as asyncdb from 'asyncdb'

From unpkg (for prototyping)

Import module directly from html with module script tag:

<script type="module">
	import { openDB } from 'https://unpkg.com/asyncdb';
	const blog = openDatabase("blog");
</script>

Dynamic import are also possible, usefull for REPL/console tests & debug:

const { openDatabase } = await import("https://unpkg.com/asyncdb");
const blog = openDatabase("blog");

For IE and older browsers compatibility, use the global compat flavor with simple script tag:

<script src="https://unpkg.com/asyncdb/global.support.min.js"></script>
<script>
	var blog = asyncdb.openDatabase("blog");
</script>

Browser support

For IE & Egde support of objectStore(...).getAll, objectStore(...).getAllKeys, index(...).getAll, and index(...).getAllKeys (or to use it in Safari 10.1 worker), you must also import IndexedDB-getAll-shim.

Examples

(async () => {
  const { openDatabase } = await import("https://unpkg.com/asyncdb");
  // open or create blog database v1
  const db = await openDatabase("blog", 1, {
    upgrade(db) {
      // create table
      const posts = db.createObjectStore("posts", { autoIncrement: true });
      // create indexes
      posts.createIndex("title", "title", { unique: false });
      posts.createIndex("tag", "tags", { multiEntry: true });
      // insert data
      posts.add({ title: "My article", tags: ["awesome", "me"] });
      posts.add({ title: "Other article", tags: ["awesome", "other"] });
    }
  });
  // read all blog posts
  const posts = await db.objectStore("posts").getAll();
  for (const post of posts) {
    console.log(post);
  }
})();

Ready to be copy-pasted in your devtool console: select, ctrl+c, ctrl+shift+j, ctrl+v!

Async iteration

You may prefer to iterate asynchronously with for await...of:

// read all blog posts
for await (const post of db.objectStore("posts")) {
  console.log(post);
}
// update all blog posts using cursor
const cursor = db.objectStore("posts").cursor();
for await (const entry of cursor) {
  entry.update({ ...entry.value, author: "me" });
}
// delete all blog post after #2 using cursor
const cursor = db.objectStore("posts").cursor(IDBKeyRange.lowerBound(2));
for await (const entry of cursor) {
  entry.delete();
}

for await...of is supported by recent browsers, it uses Symbol.asyncIterator under the hood.
For Edge and older browsers, you'll need to transpile your code using babel with async-generator plugin (see the rollup config of this repository for a working example).

Async manipulation

You also may dare to use the iterator helpers:

// wrap all blog post titles in html headings
const headlines = AsyncIterator.from(db.objectStore("posts")).map(
  ({ title }) => `<h2>${title}</h2>`
);
for await (const headline of headlines) {
  console.log(headline);
}

AsyncIterator is yet a stage 2 proposal, only provided by a few libraries like core-js@3 & IxJS.

You can import one core-js or some IxJS modules to enjoy iterator helpers.

This is how to import the convenience core-js module with both AsyncIterator & Iterator constructors:

import "core-js/proposals/iterator-helpers";

And this are the IxJS modules required for the previous example:

import { AsyncIterableX as AsyncIterator } from "ix/asynciterable/asynciterablex";
import "ix/add/asynciterable/from";
import "ix/add/asynciterable-operators/map";
import "ix/add/asynciterable-operators/toarray";

N.B. Unfortunately IxJS modules are not unpkg.com ready & core-js does not provide es modules yet :/, so you're stuck with some sort of bundler/transpiler (babel, webpack, rollup or parcel...).