Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

openIndexedDB

Opens an IndexedDB database and sets up object stores if needed.

TypeScript
Copied!
1/**
2 * Opens an IndexedDB database and sets up object stores if needed.
3 *
4 * @param dbName - The name of the database.
5 * @param version - Optional version number; increments trigger upgrade.
6 * @param setupStores - Callback to create/modify object stores during upgrade.
7 * @returns A Promise that resolves with the IDBDatabase instance.
8 */
9export function openIndexedDB(
10  dbName: string,
11  version?: number,
12  setupStores?: (db: IDBDatabase) => void
13): Promise<IDBDatabase> {
14  return new Promise((resolve, reject) => {
15    const request = indexedDB.open(dbName, version);
16
17    request.onerror = () => {
18      reject(new Error(`Failed to open IndexedDB: ${request.error?.message}`));
19    };
20
21    request.onsuccess = () => {
22      resolve(request.result);
23    };
24
25    request.onupgradeneeded = () => {
26      if (setupStores) {
27        setupStores(request.result);
28      }
29    };
30  });
31}
  • Upgrade-Aware Structure

    Automatically triggers the setupStores callback on version upgrades, allowing schema evolution without manual rechecking.

  • Encapsulated Error Handling

    Catches and forwards onerror failures with a descriptive error, which simplifies downstream debugging.

  • Flexible Initialization

    Accepts optional versioning and store setup logic, making it adaptable for both basic and advanced database use cases.

  • Promise-Based API

    Wraps the native IndexedDB API in a Promise, making it more ergonomic for use with async/await and modern codebases.

  • Minimal Boilerplate

    Centralizes IndexedDB connection logic in one reusable utility, reducing duplication and setup code throughout the application.

Tests | Examples

TypeScript
Copied!
1import 'fake-indexeddb/auto';
2
3test('openIndexedDB creates a new store if it does not exist', async () => {
4  const db = await openIndexedDB('TestDB', 'TestStore');
5  expect(db.name).toBe('TestDB');
6  expect(db.objectStoreNames.contains('TestStore')).toBe(true);
7  db.close();
8});

Common Use Cases

  • Initializing Client-Side Databases

    Open and prepare an IndexedDB instance when an app starts or a feature is initialized.

  • Setting Up Object Stores During First Use

    Automatically create needed stores like users, settings, or logs on first launch or version upgrades.

  • Schema Migration Handling

    Use versioned upgrades to handle schema changes without losing existing data.

  • Feature-Specific Database Isolation

    Create separate databases for modular features (e.g., offline storage, file cache).

  • Testing IndexedDB Utilities

    Programmatically create and tear down test databases with specific store configurations.

Codebase: Utilities -> Storage -> openIndexedDB | Yevhen Klymentiev