Skip to content

tintin10q/simple-indexedDB

Repository files navigation

simple-indexedDB

A simple indexedDB promised based wrapper class.

First Look:

import {IndexedDBObjectStore, createIndexeddatabase} from "simple-indexeddb"
// or just copy the code into your file its only ~200 lines of code
await createIndexeddatabase("my-db", {mystore: {});
const store = await new IndexedDBObjectStore("my-db", "mystore")
await store.put("test", 137)
console.log(await store.get("test")) // 137

Motivation

There is a bunch of annoying ugly boilerplate involved when dealing with IndexedDB API. When dealing with the IndexedDB you want an instance of the IDBObjectStore class. But to get it you have to go through this:

// writing and reading indexdb in vanilla js
let db;
const DBOpenRequest = window.indexedDB.open('db-test');

DBOpenRequest.onerror = event => console.error("Error loading database.");
DBOpenRequest.onsuccess = event => {db = DBOpenRequest.result;};

// writing to the database
let transaction = db
    .transaction(["test"], "readwrite")
    .objectStore("test")
    .add("test", 137);

// reading from the database 
let result;
transaction.onsuccess(() => {
    db.transaction(["test"])
        .objectStore("test")
        .get("test").onsuccess((event) => {
        result = event.target.result;
    })
});

This project reduces this boiler plates to a nice single promise based class. This class allows you to think that you can access the IDBObjectStore class directly without having to think about creating transactions:

import IndexedDBObjectStore from "simple-indexeddb"

const store = await new IndexedDBObjectStore("my-db", "my-store")
await store.put('test', 137)
console.log(await store.get('test')) // 137

This is useful for instance when you need to store data from within a service worker/web worker. Using this class also makes it a lot harder to run into uncommited transactions.

The class is only about ~200 lines of code, and you could take out the methods you don't need. This allows for just dropping the code in your project without having to install it as a dependency. There is a simple-indexeddb.ts and simple-indexeddb.js version.

Usage:

Creating Databases:

Creating databases can be quite confusing using indexedDB. Use the createIndexeddatabase function to create many databases easily in a single transaction. The function returns a promise that resolves to the latest version number. Changes are only made to the database if needed.

import createIndexeddatabase from "create-indexeddatabase" // or just copy the file

// creates the animals, plants, trees, and flowers datastores in the garden database. 
await createIndexeddatabase("garden", {
    animals: {keyPath: "id", autoIncrement: false},
    plants: {keyPath: "id", autoIncrement: true},
    trees: {autoIncrement: true},
    flowers: {}, // default = {keyPath: null, autoIncrement: false}
})

If you don't know what these options mean then look at here. The createIndexeddatabase function also accepts Map objects. There is a create-indexeddatabase.ts and create-indexeddatabase.js version.

Interacting With the Database Objectstores:

Now that you have a database you can interact with it using the IndexedDBObjectStore class. I have implemented most of the methods from IDBObjectStore but none of the cursor/index stuff (yet). This class automatically sets up transactions for you with a IDBDatabase object.

const key = "Test";
const data = 137;
const query = IDBKeyRange.lowerBound(100); // you can also pass strings as query

import IndexedDBObjectStore from "simple-indexeddb"

let store = await new IndexedDBObjectStore("my-db", "my-store")

// Properties
console.log(store.db, store.dbname, store.objectstorename)

// Instance Methods:
await store.add(data, key); // use to add key value pairs
await store.put(data, key); // use to update key value pairs

await store.add(data);
await store.put(data); // leave key out if your key mode allows it  

await store.get(key);
await store.getJson(key);
await store.delete(key);
await store.getAll();
await store.getAll(query);
await store.getAll(query, count);
await store.getKey(key);
await store.getAllKeys(); // all keys
await store.getAllKeys(query); // all keys that satisfy query
await store.getAllKeys(query, count);
await store.count();
await store.count(query);
await store.clear();

await store.close(); // Don't use it after closing 
delete store;

// specify create options if a store maybe doesn't exist
const mystoreai = await new IndexedDBObjectStore("my-db", "my-storeai", {autoIncrement: true, version: 2})
// if this creates a new store you have to increase the version again
const apples = await new IndexedDBObjectStore("my-db", "my-storeai", {autoIncrement: true, version: 3})
// its easier to use the createIndexeddatabase function to create databases.

Download

You easily can download the files using:

ts-version

wget https://raw.githubusercontent.com/tintin10q/simple-indexedDB/main/simple-indexeddb.ts
wget https://raw.githubusercontent.com/tintin10q/simple-indexedDB/main/create-indexeddatabase.ts

js-version

wget https://raw.githubusercontent.com/tintin10q/simple-indexedDB/main/simple-indexeddb.js 
wget https://raw.githubusercontent.com/tintin10q/simple-indexedDB/main/create-indexeddatabase.js

Feel free to submit a pull request.

About

A simple indexedDB wrapper

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published