Docs / api

Database API

The Database class is the main entry point for DexBee. It manages connections, transactions, and provides access to tables and migration functionality.

Class: Database

Constructor

new Database(name: string, schema: DatabaseSchema)

Creates a new Database instance with the specified name and schema.

Parameters:

  • name - The database name
  • schema - The database schema definition

Example:

import { Database } from 'dexbee-js';

const schema = {
  version: 1,
  tables: {
    users: {
      schema: {
        id: { type: 'number', required: true },
        name: { type: 'string', required: true }
      },
      primaryKey: 'id',
      autoIncrement: true
    }
  }
};

const db = new Database('myapp', schema);

Static Methods

Database.create()

static create(name: string, schema: DatabaseSchema): Database

Creates a new Database instance. Alias for the constructor.

Database.connect()

static async connect(name: string, schema: DatabaseSchema): Promise<Database>

Creates and immediately connects to a database.

Example:

const db = await Database.connect('myapp', schema);

Instance Methods

connect()

async connect(): Promise<void>

Establishes a connection to the IndexedDB database. Must be called before using the database.

Example:

await db.connect();

close()

close(): void

Closes the database connection and aborts any active transactions.

Example:

db.close();

isConnected()

isConnected(): boolean

Returns whether the database is currently connected.

Returns: boolean - True if connected, false otherwise

table()

table<T = any>(tableName: string): Table<T>

Gets a Table instance for the specified table name.

Parameters:

  • tableName - Name of the table
  • T - TypeScript type for the table records (optional)

Returns: Table<T> - A Table instance for querying

Example:

interface User {
  id: number;
  name: string;
  email: string;
}

const usersTable = db.table<User>('users');
const user = await usersTable.findById(1);

Transaction Methods

transaction()

async transaction(options: TransactionOptions): Promise<ITransactionWrapper>

Creates a new transaction with the specified options.

Parameters:

  • options - Transaction configuration

Returns: Promise<ITransactionWrapper> - A transaction wrapper

Example:

const tx = await db.transaction({
  stores: ['users', 'posts'],
  mode: 'readwrite'
});

withTransaction()

async withTransaction<T>(
  options: TransactionOptions,
  callback: (tx: ITransactionWrapper) => Promise<T>
): Promise<T>

Executes a callback within a transaction and automatically handles commit/abort.

Parameters:

  • options - Transaction configuration
  • callback - Function to execute within the transaction

Returns: Promise<T> - The callback’s return value

Example:

const result = await db.withTransaction({
  stores: ['users'],
  mode: 'readwrite'
}, async (tx) => {
  const store = tx.getStore('users');
  await store.add({ name: 'John', email: 'john@example.com' });
  return 'User created';
});

withReadTransaction()

async withReadTransaction<T>(
  stores: string[],
  callback: (tx: ITransactionWrapper) => Promise<T>
): Promise<T>

Convenience method for read-only transactions.

Parameters:

  • stores - Array of store names to access
  • callback - Function to execute within the transaction

Example:

const users = await db.withReadTransaction(['users'], async (tx) => {
  const store = tx.getStore('users');
  return await store.getAll();
});

withWriteTransaction()

async withWriteTransaction<T>(
  stores: string[],
  callback: (tx: ITransactionWrapper) => Promise<T>
): Promise<T>

Convenience method for read-write transactions.

Parameters:

  • stores - Array of store names to access
  • callback - Function to execute within the transaction

Example:

await db.withWriteTransaction(['users'], async (tx) => {
  const store = tx.getStore('users');
  await store.put({ id: 1, name: 'Jane', email: 'jane@example.com' });
});

Data Validation Methods

validateData()

validateData(tableName: string, data: any): void

Validates data against the table schema. Throws an error if validation fails.

Parameters:

  • tableName - Name of the table
  • data - Data to validate

Example:

try {
  db.validateData('users', { name: 'John' }); // Missing required fields
} catch (error) {
  console.error('Validation failed:', error);
}

applyDefaults()

applyDefaults(tableName: string, data: any): any

Applies default values to data based on the table schema.

Parameters:

  • tableName - Name of the table
  • data - Data to process

Returns: Data with defaults applied

Example:

const userData = { name: 'John' };
const withDefaults = db.applyDefaults('users', userData);
// withDefaults might include createdAt: new Date()

Transaction Utility Methods

getActiveTransactionCount()

getActiveTransactionCount(): number

Returns the number of currently active transactions.

Returns: number - Count of active transactions

abortAllTransactions()

async abortAllTransactions(): Promise<void>

Aborts all active transactions. Useful for cleanup or error handling.

Migration Methods

migrate()

async migrate(
  newSchema: DatabaseSchema, 
  options?: MigrationOptions
): Promise<MigrationResult>

Migrates the database to a new schema version.

Parameters:

  • newSchema - The target schema
  • options - Migration options (optional)

Returns: Promise<MigrationResult> - Migration result details

Example:

const newSchema = {
  version: 2,
  tables: {
    users: {
      schema: {
        id: { type: 'number', required: true },
        name: { type: 'string', required: true },
        email: { type: 'string', unique: true },
        createdAt: { type: 'date', default: () => new Date() }
      },
      primaryKey: 'id',
      autoIncrement: true
    }
  }
};

const result = await db.migrate(newSchema, {
  validateEachStep: true
});

Interfaces

TransactionOptions

interface TransactionOptions {
  stores: string[];
  mode: 'readonly' | 'readwrite';
  durability?: 'default' | 'strict' | 'relaxed';
}

MigrationOptions

interface MigrationOptions {
  dryRun?: boolean;
  validateEachStep?: boolean;
  batchSize?: number;
}

Error Handling

The Database class throws DexBeeError instances for various error conditions:

import { DexBeeError, DexBeeErrorCode } from 'dexbee-js';

try {
  await db.connect();
} catch (error) {
  if (error instanceof DexBeeError) {
    switch (error.code) {
      case DexBeeErrorCode.CONNECTION_FAILED:
        // Handle connection error
        break;
      case DexBeeErrorCode.SCHEMA_VALIDATION_FAILED:
        // Handle schema error
        break;
      default:
        // Handle other errors
    }
  }
}

Best Practices

Connection Management

// Good: Connect once, reuse instance
const db = await Database.connect('myapp', schema);

// Use throughout your app
export { db };

// Clean up when app closes
window.addEventListener('beforeunload', () => {
  db.close();
});

Transaction Scope

// Good: Use withTransaction for automatic cleanup
await db.withWriteTransaction(['users'], async (tx) => {
  // All operations in this block are atomic
  const store = tx.getStore('users');
  await store.add(user1);
  await store.add(user2);
  // Automatically commits or aborts
});

Error Handling

// Good: Handle specific error types
try {
  await db.connect();
} catch (error) {
  if (error instanceof DexBeeError) {
    // Handle DexBee-specific errors
    console.error(`DexBee error (${error.code}): ${error.message}`);
  } else {
    // Handle other errors
    console.error('Unexpected error:', error);
  }
}