@qualified-cactus/promised-db
TypeScript icon, indicating that this package has built-in type declarations

3.1.2 • Public • Published

Promised DB - A Typescript wrapper for IndexedDB

It is highly recommended to use this library with Typescript.

API Documentation

How to use

Step 0: Get this package from NPM

npm install @qualified-cactus/promised-db

Step 1: Define your data structure

Use type ObjectStoreDef and class IndexDef to define object store(s) and index(es) respectively. It is recommened to group related definitions in a namespace or module to avoid repetitive name such as "TodoTaskTypeWithoutKey", "TodoTaskObjectStore", etc...

namespace TodoTask {
    // define TypeWithoutKey if you use auto-generated inline key(s)
    export interface TypeWithoutKey {
        name: string
        completed: number // 0 for false, 1 for true
    }
    export interface Type extends TypeWithoutKey {
        id: number
    }

    export const ObjectStore: ObjectStoreDef<Type, number, TypeWithoutKey> = {
        name: "todo-tasks",
        options: {
            keyPath: "id",
            autoIncrement: true
        }
    }
    export const NameIndex = new IndexDef<string>(
        "todo-task-name-index", // index name
        "name", // index path
        { unique: true } // index's options
    )
    export const CompletedIndex = new IndexDef<number>(
        "todo-task-completed-index", // index name
        "completed", // index path
    )
}

Step 2: Define your database

Use the class DatabaseDef to define a database.

const TodoTaskDbDef = new DatabaseDef(
    "todo-tasks-db", // db name 
    1, // version
    
    // upgrade handler
    (db, oldVersion, newVersion) => {
        if (oldVersion < 1) {
            const objectStore = db.createObjectStore(TodoTask.ObjectStore)
            objectStore.createIndex(TodoTask.NameIndex)
            objectStore.createIndex(TodoTask.CompletedIndex)
        }
    }
)

Step 3: Open DB and start a transaction

async function doOperation() {

    const db: Database = await TodoTaskDbDef.open()
    await db.transaction(
        [TodoTask.ObjectStore],  // transaction's scope
        "readwrite",    // mode
        async (transaction) => {

            // find the first completed todo-task in db and delete it
            const todoTaskObjectStore = transaction.objectStore(TodoTask.ObjectStore)
            const completedIndex = todoTaskObjectStore.index(TodoTask.CompletedIndex)
            const task = await completedIndex.get(1)    
            if (task) {
                await todoTaskObjectStore.delete(task.id)
            }

            // key range can be created from Index definition
            const nameIndex = todoTaskObjectStore.index(TodoTask.NameIndex)
            // get all tasks with name greater than "bazz"
            const tasksList = await nameIndex.getAll(TodoTask.NameIndex.lowerBound("bazz"))

            // iterate over keys of index / objectstore
            await nameIndex.iterator.iterateKeys(async (cursor)=>{
                console.log(cursor.key)  // access index key
                console.log(cursor.primaryKey) // access primary key

                // break iteration if key equals "foo"
                if (cursor.key === "foo") {
                    return true // return true to break iteration early 
                }
            })

            // iterate over objects of index / objectstore 
            await nameIndex.iterator.iterateValues(async (cursor)=>{
                console.log(cursor.key)  // access index key
                console.log(cursor.primaryKey) // access primary key
                console.log(cursor.value) // access object

                await cursor.update({...cursor.value, name: "new name"}) // update value using cursor
                await cursor.delete() // or delete value using cursor
            },{
                query: TodoTask.NameIndex.lowerBound("a"), // iterate over name starting with "a",
                direction: "prev" // descending order
            })
        }
    )
}

WARNING: Perform other long-running async operation (fetching api, etc...) inside transaction will cause TransactionInactiveError. The reason is that IndexedDB autocommit when there is no pending database operation within a brief period of time.

Readme

Keywords

none

Package Sidebar

Install

npm i @qualified-cactus/promised-db

Weekly Downloads

1

Version

3.1.2

License

MIT

Unpacked Size

38.3 kB

Total Files

15

Last publish

Collaborators

  • qualified-cactus