A small wrapper that makes IndexedDB usable with promises and enhanced TypeScript support
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Promise-based database interface with shortcut methods for common operations, eliminating the need for explicit transaction management in simple cases.
Create transactions with enhanced promise-based interfaces.
/**
* Start a new transaction for a single store
* @param storeNames - The object store this transaction needs
* @param mode - Transaction mode (readonly, readwrite, versionchange)
* @param options - Transaction options including durability
* @returns Enhanced transaction interface
*/
transaction<Name extends StoreNames<DBTypes>, Mode extends IDBTransactionMode = 'readonly'>(
storeNames: Name,
mode?: Mode,
options?: IDBTransactionOptions
): IDBPTransaction<DBTypes, [Name], Mode>;
/**
* Start a new transaction for multiple stores
* @param storeNames - Array of object stores this transaction needs
* @param mode - Transaction mode (readonly, readwrite, versionchange)
* @param options - Transaction options including durability
* @returns Enhanced transaction interface
*/
transaction<Names extends ArrayLike<StoreNames<DBTypes>>, Mode extends IDBTransactionMode = 'readonly'>(
storeNames: Names,
mode?: Mode,
options?: IDBTransactionOptions
): IDBPTransaction<DBTypes, Names, Mode>;Usage Examples:
// Single store transaction
const tx = db.transaction("users", "readwrite");
const userStore = tx.objectStore("users");
await userStore.add({ id: "1", name: "Alice" });
await tx.done; // Wait for transaction completion
// Multiple store transaction
const tx2 = db.transaction(["users", "posts"], "readwrite");
const userStore2 = tx2.objectStore("users");
const postStore = tx2.objectStore("posts");
await userStore2.add({ id: "1", name: "Bob" });
await postStore.add({ id: 1, authorId: "1", title: "Hello World" });
await tx2.done;
// Transaction with durability options
const tx3 = db.transaction("users", "readwrite", {
durability: "strict" // Ensure data is written to disk immediately
});
// Different durability options
const fastTx = db.transaction("cache", "readwrite", {
durability: "relaxed" // Better performance, less durability guarantees
});
const defaultTx = db.transaction("users", "readwrite", {
durability: "default" // Browser default behavior
});Create and delete object stores during database upgrades.
/**
* Creates a new object store
* Throws "InvalidStateError" if not called within an upgrade transaction
* @param name - Name of the object store
* @param optionalParameters - Store configuration options
* @returns Enhanced object store interface
*/
createObjectStore<Name extends StoreNames<DBTypes>>(
name: Name,
optionalParameters?: IDBObjectStoreParameters
): IDBPObjectStore<DBTypes, ArrayLike<StoreNames<DBTypes>>, Name, 'versionchange'>;
/**
* Deletes the object store with the given name
* Throws "InvalidStateError" if not called within an upgrade transaction
* @param name - Name of the object store to delete
*/
deleteObjectStore(name: StoreNames<DBTypes>): void;Usage Examples:
// During database upgrade
const db = await openDB("my-database", 2, {
upgrade(db, oldVersion) {
if (oldVersion < 1) {
// Create object store with auto-incrementing keys
const userStore = db.createObjectStore("users", {
keyPath: "id",
autoIncrement: true
});
// Create indexes
userStore.createIndex("email", "email", { unique: true });
userStore.createIndex("name", "name");
}
if (oldVersion < 2) {
// Create additional store
const postStore = db.createObjectStore("posts", {
keyPath: "id",
autoIncrement: true
});
postStore.createIndex("author", "authorId");
// Remove old store if needed
if (db.objectStoreNames.contains("old_store")) {
db.deleteObjectStore("old_store");
}
}
}
});Direct database operations that automatically create and manage transactions.
/**
* Add a value to a store
* Rejects if an item of a given key already exists in the store
* This creates a transaction automatically
* @param storeName - Name of the store
* @param value - Value to add
* @param key - Optional key (if not using keyPath)
* @returns Promise resolving to the key of the added item
*/
add<Name extends StoreNames<DBTypes>>(
storeName: Name,
value: StoreValue<DBTypes, Name>,
key?: StoreKey<DBTypes, Name> | IDBKeyRange
): Promise<StoreKey<DBTypes, Name>>;/**
* Put an item in the database
* Replaces any item with the same key
* This creates a transaction automatically
* @param storeName - Name of the store
* @param value - Value to put
* @param key - Optional key (if not using keyPath)
* @returns Promise resolving to the key of the stored item
*/
put<Name extends StoreNames<DBTypes>>(
storeName: Name,
value: StoreValue<DBTypes, Name>,
key?: StoreKey<DBTypes, Name> | IDBKeyRange
): Promise<StoreKey<DBTypes, Name>>;/**
* Retrieves the value of the first record in a store matching the query
* Resolves with undefined if no match is found
* This creates a transaction automatically
* @param storeName - Name of the store
* @param query - Key or key range to match
* @returns Promise resolving to the value or undefined
*/
get<Name extends StoreNames<DBTypes>>(
storeName: Name,
query: StoreKey<DBTypes, Name> | IDBKeyRange
): Promise<StoreValue<DBTypes, Name> | undefined>;
/**
* Retrieves the value of the first record in an index matching the query
* Resolves with undefined if no match is found
* This creates a transaction automatically
* @param storeName - Name of the store
* @param indexName - Name of the index within the store
* @param query - Index key or key range to match
* @returns Promise resolving to the value or undefined
*/
getFromIndex<Name extends StoreNames<DBTypes>, IndexName extends IndexNames<DBTypes, Name>>(
storeName: Name,
indexName: IndexName,
query: IndexKey<DBTypes, Name, IndexName> | IDBKeyRange
): Promise<StoreValue<DBTypes, Name> | undefined>;
/**
* Retrieves all values in a store that match the query
* This creates a transaction automatically
* @param storeName - Name of the store
* @param query - Key or key range to match (optional)
* @param count - Maximum number of values to return (optional)
* @returns Promise resolving to array of matching values
*/
getAll<Name extends StoreNames<DBTypes>>(
storeName: Name,
query?: StoreKey<DBTypes, Name> | IDBKeyRange | null,
count?: number
): Promise<StoreValue<DBTypes, Name>[]>;
/**
* Retrieves all values in an index that match the query
* This creates a transaction automatically
* @param storeName - Name of the store
* @param indexName - Name of the index within the store
* @param query - Index key or key range to match (optional)
* @param count - Maximum number of values to return (optional)
* @returns Promise resolving to array of matching values
*/
getAllFromIndex<Name extends StoreNames<DBTypes>, IndexName extends IndexNames<DBTypes, Name>>(
storeName: Name,
indexName: IndexName,
query?: IndexKey<DBTypes, Name, IndexName> | IDBKeyRange | null,
count?: number
): Promise<StoreValue<DBTypes, Name>[]>;/**
* Retrieves the key of the first record in a store that matches the query
* Resolves with undefined if no match is found
* @param storeName - Name of the store
* @param query - Key or key range to match
* @returns Promise resolving to the key or undefined
*/
getKey<Name extends StoreNames<DBTypes>>(
storeName: Name,
query: StoreKey<DBTypes, Name> | IDBKeyRange
): Promise<StoreKey<DBTypes, Name> | undefined>;
/**
* Retrieves the keys of records in a store matching the query
* @param storeName - Name of the store
* @param query - Key or key range to match (optional)
* @param count - Maximum number of keys to return (optional)
* @returns Promise resolving to array of matching keys
*/
getAllKeys<Name extends StoreNames<DBTypes>>(
storeName: Name,
query?: StoreKey<DBTypes, Name> | IDBKeyRange | null,
count?: number
): Promise<StoreKey<DBTypes, Name>[]>;/**
* Deletes records in a store matching the given query
* This creates a transaction automatically
* @param storeName - Name of the store
* @param key - Key or key range to delete
* @returns Promise that resolves when deletion is complete
*/
delete<Name extends StoreNames<DBTypes>>(
storeName: Name,
key: StoreKey<DBTypes, Name> | IDBKeyRange
): Promise<void>;
/**
* Deletes all records in a store
* This creates a transaction automatically
* @param storeName - Name of the store
* @returns Promise that resolves when clearing is complete
*/
clear(name: StoreNames<DBTypes>): Promise<void>;/**
* Retrieves the number of records matching the given query in a store
* This creates a transaction automatically
* @param storeName - Name of the store
* @param key - Key or key range to count (optional)
* @returns Promise resolving to the count
*/
count<Name extends StoreNames<DBTypes>>(
storeName: Name,
key?: StoreKey<DBTypes, Name> | IDBKeyRange | null
): Promise<number>;
/**
* Retrieves the number of records matching the given query in an index
* This creates a transaction automatically
* @param storeName - Name of the store
* @param indexName - Name of the index within the store
* @param key - Index key or key range to count (optional)
* @returns Promise resolving to the count
*/
countFromIndex<Name extends StoreNames<DBTypes>, IndexName extends IndexNames<DBTypes, Name>>(
storeName: Name,
indexName: IndexName,
key?: IndexKey<DBTypes, Name, IndexName> | IDBKeyRange | null
): Promise<number>;Shortcut Method Usage Examples:
import { openDB } from "idb";
const db = await openDB("my-database");
// Simple operations with automatic transaction management
await db.add("users", { name: "Alice", email: "alice@example.com" });
await db.put("users", { id: 1, name: "Bob", email: "bob@example.com" });
// Get operations
const user = await db.get("users", 1);
const userByEmail = await db.getFromIndex("users", "email", "alice@example.com");
const allUsers = await db.getAll("users");
const activeUsers = await db.getAllFromIndex("users", "status", "active");
// Key operations
const userKey = await db.getKey("users", IDBKeyRange.bound(1, 10));
const allUserKeys = await db.getAllKeys("users");
// Count operations
const totalUsers = await db.count("users");
const activeUserCount = await db.countFromIndex("users", "status", "active");
// Delete operations
await db.delete("users", 1);
await db.clear("users"); // Delete all users
// Working with key ranges
const recentUsers = await db.getAll("users", IDBKeyRange.lowerBound(100));
const userRange = await db.getAll("users", IDBKeyRange.bound(1, 10));Enhanced database interface properties and metadata.
/**
* The names of stores in the database
*/
readonly objectStoreNames: TypedDOMStringList<StoreNames<DBTypes>>;Property Usage:
const db = await openDB("my-database");
// Check available stores
console.log("Available stores:", [...db.objectStoreNames]);
// Check if specific store exists
if (db.objectStoreNames.contains("users")) {
const users = await db.getAll("users");
}
// Iterate over store names
for (const storeName of db.objectStoreNames) {
const count = await db.count(storeName);
console.log(`${storeName}: ${count} records`);
}