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
Core database lifecycle management including opening databases with upgrade callbacks, deleting databases, and handling database events.
Opens a database and returns a promise-based enhanced IDBDatabase interface.
/**
* Opens a database and returns a promise for an enhanced IDBDatabase
* @param name - Name of the database
* @param version - Schema version, or undefined to open current version
* @param callbacks - Additional callbacks for database events
* @returns Promise resolving to enhanced database interface
*/
function openDB<DBTypes extends DBSchema | unknown = unknown>(
name: string,
version?: number,
{ blocked, upgrade, blocking, terminated }: OpenDBCallbacks<DBTypes> = {}
): Promise<IDBPDatabase<DBTypes>>;Usage Examples:
import { openDB } from "idb";
// Simple database opening
const db = await openDB("my-database");
// Database with version and upgrade
const db = await openDB("my-database", 2, {
upgrade(db, oldVersion, newVersion) {
if (oldVersion < 1) {
db.createObjectStore("users", { keyPath: "id" });
}
if (oldVersion < 2) {
const store = db.createObjectStore("posts", { keyPath: "id" });
store.createIndex("author", "authorId");
}
}
});
// Database with typed schema
interface MyDB {
users: {
key: string;
value: { id: string; name: string; email: string };
};
posts: {
key: number;
value: { id: number; title: string; authorId: string };
indexes: { author: string };
};
}
const typedDB = await openDB<MyDB>("my-database", 1, {
upgrade(db) {
const userStore = db.createObjectStore("users", { keyPath: "id" });
const postStore = db.createObjectStore("posts", { keyPath: "id", autoIncrement: true });
postStore.createIndex("author", "authorId");
}
});
// Error handling for database opening
try {
const db = await openDB("my-database", 2, {
upgrade(db, oldVersion) {
if (oldVersion < 1) {
db.createObjectStore("users", { keyPath: "id" });
}
},
blocked() {
console.log("Database blocked - close other tabs");
}
});
} catch (error) {
if (error.name === "VersionError") {
console.error("Invalid version specified");
} else {
console.error("Database opening failed:", error);
}
}Deletes a database entirely.
/**
* Deletes a database
* @param name - Name of the database to delete
* @param callbacks - Additional callbacks for deletion events
* @returns Promise that resolves when deletion is complete
*/
function deleteDB(
name: string,
{ blocked }: DeleteDBCallbacks = {}
): Promise<void>;Usage Examples:
import { deleteDB } from "idb";
// Simple database deletion
await deleteDB("my-database");
// Deletion with blocked callback
await deleteDB("my-database", {
blocked(currentVersion, event) {
console.log("Database deletion blocked by open connections");
}
});
// Error handling for database operations
try {
await deleteDB("my-database");
} catch (error) {
if (error.name === "NotFoundError") {
console.log("Database doesn't exist");
} else {
console.error("Deletion failed:", error);
}
}Configuration for handling database lifecycle events during opening and deletion.
interface OpenDBCallbacks<DBTypes extends DBSchema | unknown> {
/**
* Called if this version of the database has never been opened before.
* Use it to specify the schema for the database.
* @param database - Enhanced database instance for schema changes
* @param oldVersion - Last version of the database opened by the user
* @param newVersion - New version being opened
* @param transaction - The transaction for this upgrade
* @param event - The event object for the associated 'upgradeneeded' event
*/
upgrade?(
database: IDBPDatabase<DBTypes>,
oldVersion: number,
newVersion: number | null,
transaction: IDBPTransaction<DBTypes, StoreNames<DBTypes>[], 'versionchange'>,
event: IDBVersionChangeEvent
): void;
/**
* Called if there are older versions of the database open on the origin,
* so this version cannot open.
* @param currentVersion - Version of the database that's blocking this one
* @param blockedVersion - The version being blocked
* @param event - The event object for the associated 'blocked' event
*/
blocked?(
currentVersion: number,
blockedVersion: number | null,
event: IDBVersionChangeEvent
): void;
/**
* Called if this connection is blocking a future version of the database
* from opening.
* @param currentVersion - Version of the open database
* @param blockedVersion - The version being blocked
* @param event - The event object for the associated 'versionchange' event
*/
blocking?(
currentVersion: number,
blockedVersion: number | null,
event: IDBVersionChangeEvent
): void;
/**
* Called if the browser abnormally terminates the connection.
* This is not called when db.close() is called.
*/
terminated?(): void;
}
interface DeleteDBCallbacks {
/**
* Called if there are connections to this database open,
* so it cannot be deleted.
* @param currentVersion - Version of the database blocking deletion
* @param event - The event object for the associated 'blocked' event
*/
blocked?(currentVersion: number, event: IDBVersionChangeEvent): void;
}Database Event Usage:
const db = await openDB("my-database", 3, {
upgrade(db, oldVersion, newVersion, transaction, event) {
console.log(`Upgrading from ${oldVersion} to ${newVersion}`);
if (oldVersion < 1) {
db.createObjectStore("users", { keyPath: "id" });
}
if (oldVersion < 2) {
db.createObjectStore("settings", { keyPath: "key" });
}
if (oldVersion < 3) {
const userStore = transaction.objectStore("users");
userStore.createIndex("email", "email", { unique: true });
}
},
blocked(currentVersion, blockedVersion, event) {
console.log("Database opening blocked - close other tabs");
},
blocking(currentVersion, blockedVersion, event) {
console.log("This database connection is blocking a newer version");
// Consider closing the database
db.close();
},
terminated() {
console.log("Database connection terminated unexpectedly");
}
});Type definitions for defining strongly-typed database schemas.
/**
* Base interface for defining database schema types
*/
interface DBSchema {
[storeName: string]: DBSchemaValue;
}
/**
* Schema definition for an object store
*/
interface DBSchemaValue {
/** Type of keys used in this store */
key: IDBValidKey;
/** Type of values stored in this store */
value: any;
/** Optional index definitions */
indexes?: IndexKeys;
}
/**
* Index key mappings for an object store
*/
interface IndexKeys {
[indexName: string]: IDBValidKey;
}Schema Definition Examples:
// Simple schema with string keys
interface SimpleDB {
users: {
key: string;
value: { name: string; email: string };
};
}
// Complex schema with multiple stores and indexes
interface BlogDB {
users: {
key: string;
value: {
id: string;
username: string;
email: string;
createdAt: Date;
};
indexes: {
email: string;
username: string;
};
};
posts: {
key: number;
value: {
id: number;
title: string;
content: string;
authorId: string;
publishedAt: Date;
tags: string[];
};
indexes: {
author: string;
published: Date;
tag: string;
};
};
comments: {
key: number;
value: {
id: number;
postId: number;
authorId: string;
content: string;
createdAt: Date;
};
indexes: {
post: number;
author: string;
};
};
}