CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-dexie

A minimalistic wrapper for IndexedDB providing reactive queries, transactions, and schema management

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

database-management.mddocs/

Database Management

Core database functionality including connection management, schema definition, versioning, and transaction handling.

Capabilities

Dexie Constructor

Creates a new database instance.

/**
 * Creates a new Dexie database instance
 * @param name - Database name (must be unique per origin)
 * @param options - Optional configuration options
 */
constructor(name: string, options?: DexieOptions);

interface DexieOptions {
  /** Add-on functions to apply to the database */
  addons?: Array<(db: Dexie) => void>;
  /** Whether to automatically open the database (default: true) */
  autoOpen?: boolean;
  /** Custom IndexedDB implementation (for testing/Node.js) */
  indexedDB?: IDBFactory;
  /** Custom IDBKeyRange implementation */
  IDBKeyRange?: typeof IDBKeyRange;
  /** Allow opening empty database without schema (default: false) */
  allowEmptyDB?: boolean;
  /** Chunk size for modify operations */
  modifyChunkSize?: number;
  /** Chrome transaction durability setting */
  chromeTransactionDurability?: "default" | "strict" | "relaxed";
  /** Cache strategy for queries and results */
  cache?: "immutable" | "cloned" | "disabled";
}

Usage Examples:

import Dexie from "dexie";

// Basic database creation
const db = new Dexie("MyAppDatabase");

// Database with options
const db = new Dexie("MyAppDatabase", {
  autoOpen: false,
  cache: "immutable",
  modifyChunkSize: 100
});

Database Opening

Opens the database connection.

/**
 * Opens the database, creating it if it doesn't exist
 * @returns Promise that resolves to the database instance
 */
open(): PromiseExtended<Dexie>;

Usage Examples:

// Auto-open (default behavior)
const db = new Dexie("MyDatabase");
db.version(1).stores({ friends: "++id, name, age" });
// Database opens automatically when first used

// Manual open
const db = new Dexie("MyDatabase", { autoOpen: false });
db.version(1).stores({ friends: "++id, name, age" });
await db.open();

// Handle open errors
try {
  await db.open();
  console.log("Database opened successfully");
} catch (error) {
  console.error("Failed to open database:", error);
}

Database Closing

Closes the database connection.

/**
 * Closes the database connection
 * @param options - Closure options
 */
close(options?: { disableAutoOpen?: boolean }): void;

Usage Examples:

// Close database
db.close();

// Close and prevent auto-reopening
db.close({ disableAutoOpen: true });

// Temporarily close database
db.close();
// Database will reopen automatically on next operation unless disableAutoOpen was set

Database Deletion

Deletes the entire database.

/**
 * Deletes the entire database and all its data
 * @param options - Deletion options
 * @returns Promise that resolves when deletion completes
 */
delete(options?: { disableAutoOpen?: boolean }): Promise<void>;

Usage Examples:

// Delete database
await db.delete();

// Delete and prevent auto-recreation
await db.delete({ disableAutoOpen: true });

// Safe deletion with error handling
try {
  await db.delete();
  console.log("Database deleted successfully");
} catch (error) {
  console.error("Failed to delete database:", error);
}

Schema Versioning

Defines database schema versions for evolution and migration.

/**
 * Defines a database schema version
 * @param versionNumber - Version number (must be sequential, starting from 1)
 * @returns Version instance for chaining
 */
version(versionNumber: number): Version;

interface Version {
  /** Define table schemas for this version */
  stores(schema: { [tableName: string]: string | null }): Version;
  /** Define upgrade function for migrating from previous version */
  upgrade(upgradeFunction: (trans: Transaction) => PromiseLike<any> | void): Version;
}

Schema Syntax:

  • "++id" - Auto-incrementing primary key
  • "id" - Non-auto-incrementing primary key
  • "id, name, age" - Primary key with indexes on name and age
  • "id, *tags" - Multi-entry index (for array values)
  • "id, [firstName+lastName]" - Compound index
  • null - Delete table in this version

Usage Examples:

// Basic schema definition
db.version(1).stores({
  friends: "++id, name, age",
  messages: "++id, friendId, message, timestamp"
});

// Schema evolution
db.version(1).stores({
  friends: "++id, name, age"
});

db.version(2)
  .stores({
    friends: "++id, name, age, email", // Add email index
    messages: "++id, friendId, message, timestamp"
  })
  .upgrade(trans => {
    // Migrate existing data
    return trans.friends.toCollection().modify(friend => {
      friend.email = friend.email || null;
    });
  });

db.version(3).stores({
  friends: "++id, name, age, email",
  messages: "++id, friendId, message, timestamp",
  groups: "++id, name, [ownerId+name]" // Add new table with compound index
});

// Delete table in version 4
db.version(4).stores({
  friends: "++id, name, age, email",
  messages: null, // Delete messages table
  groups: "++id, name, [ownerId+name]"
});

Transaction Management

Creates explicit transactions for atomic operations across multiple tables.

/**
 * Creates an explicit transaction
 * @param mode - Transaction mode ('r'/'readonly' or 'rw'/'readwrite')
 * @param tables - Array of table names to include in transaction
 * @param scope - Function to execute within the transaction
 * @returns Promise that resolves to the scope function's result
 */
transaction<T>(
  mode: TransactionMode, 
  tables: string[], 
  scope: () => T | PromiseLike<T>
): Promise<T>;

type TransactionMode = "r" | "rw" | "readonly" | "readwrite";

interface Transaction {
  /** Database reference */
  db: Dexie;
  /** Whether transaction is still active */
  active: boolean;
  /** Transaction mode */
  mode: IDBTransactionMode;
  /** Table names included in transaction */
  storeNames: string[];
  /** Parent transaction (for sub-transactions) */
  parent?: Transaction;
  /** Get table bound to this transaction */
  table(tableName: string): Table<any, any>;
  /** Abort the transaction */
  abort(): void;
}

Usage Examples:

// Read-only transaction
const result = await db.transaction("readonly", ["friends", "messages"], async () => {
  const friends = await db.friends.toArray();
  const messages = await db.messages.toArray();
  return { friends, messages };
});

// Read-write transaction
await db.transaction("readwrite", ["friends", "messages"], async () => {
  const newFriend = await db.friends.add({ name: "Alice", age: 25 });
  await db.messages.add({
    friendId: newFriend,
    message: "Welcome!",
    timestamp: Date.now()
  });
});

// Transaction with error handling
try {
  await db.transaction("rw", ["friends"], async () => {
    await db.friends.add({ name: "Bob", age: 30 });
    await db.friends.add({ name: "Charlie", age: 35 });
    // If any operation fails, entire transaction is rolled back
  });
} catch (error) {
  console.error("Transaction failed:", error);
}

// Access transaction object
await db.transaction("rw", ["friends"], async (trans) => {
  const friends = trans.table("friends");
  await friends.add({ name: "David", age: 40 });
});

Table Access

Accesses database tables for operations.

/**
 * Gets a table instance for performing operations
 * @param tableName - Name of the table
 * @returns Table instance
 */
table(tableName: string): Table<any, any>;
table<T>(tableName: string): Table<T, any>;
table<T, Key>(tableName: string): Table<T, Key>;
table<T, Key, TInsertType>(tableName: string): Table<T, Key, TInsertType>;

Usage Examples:

// Access table with inferred types
const friends = db.table("friends");

// Access table with explicit typing
interface Friend {
  id: number;
  name: string;
  age: number;
}

const typedFriends = db.table<Friend, number>("friends");
await typedFriends.add({ name: "Alice", age: 25 });

Database Properties

Key database properties and metadata.

interface Dexie {
  /** Database name */
  readonly name: string;
  /** Current version number */
  readonly verno: number;
  /** All tables in the database */
  readonly tables: Table[];
  /** VIP instance for priority operations */
  readonly vip: Dexie;
  /** Whether database is currently open */
  readonly isOpen: boolean;
  /** Whether database has failed to open or had an error */
  readonly hasFailed: boolean;
  /** Whether database has been explicitly closed */
  readonly hasBeenClosed: boolean;
  /** Whether database was opened with auto-schema (no version specified) */
  readonly dynamicallyOpened: boolean;
  /** Native IndexedDB database instance (may be null if closed) */
  readonly idbdb: IDBDatabase | null;
}

Usage Examples:

console.log("Database name:", db.name);
console.log("Current version:", db.verno);
console.log("Available tables:", db.tables.map(t => t.name));
console.log("Database open:", db.isOpen);
console.log("Database failed:", db.hasFailed);
console.log("Database closed:", db.hasBeenClosed);
console.log("Auto-schema mode:", db.dynamicallyOpened);

// Check native IndexedDB instance
if (db.idbdb) {
  console.log("Native IDB version:", db.idbdb.version);
  console.log("Native IDB store names:", Array.from(db.idbdb.objectStoreNames));
}

// Use VIP instance for priority operations
await db.vip.friends.add({ name: "VIP User", age: 30 });

// Check database status before operations
if (db.hasBeenClosed) {
  console.log("Database was explicitly closed");
}

if (db.hasFailed) {
  console.log("Database has encountered errors");
}

Static Properties

Static utilities available on the Dexie constructor.

interface DexieConstructor {
  /** Library version */
  static readonly version: string;
  /** Semantic version */
  static readonly semVer: string;
  /** Maximum IndexedDB key value */
  static readonly maxKey: any;
  /** Minimum IndexedDB key value */
  static readonly minKey: any;
  /** Global addon registry */
  static addons: Array<(db: Dexie) => void>;
  /** Current active transaction */
  static currentTransaction: Transaction | null;
  
  /** Wait for external promises in transactions */
  static waitFor<T>(promise: PromiseLike<T>, timeoutMs?: number): Promise<T>;
  /** Run code outside transaction context */
  static ignoreTransaction<T>(fn: () => T): T;
  /** Run with VIP priority */
  static vip<T>(fn: () => T): T;
  
  /** Delete a database by name */
  static delete(databaseName: string): Promise<void>;
  /** Check if a database exists */
  static exists(databaseName: string): Promise<boolean>;
  /** Get list of all database names */
  static getDatabaseNames(): Promise<string[]>;
  static getDatabaseNames<R>(thenShortcut: ThenShortcut<string[], R>): Promise<R>;
  
  /** Convert generator function to async function */
  static async<T>(generatorFn: Function): (...args: any[]) => Promise<T>;
  /** Spawn a generator function with arguments */
  static spawn<T>(generatorFn: Function, args?: any[], thiz?: any): Promise<T>;
}

Usage Examples:

console.log("Dexie version:", Dexie.version);
console.log("Semantic version:", Dexie.semVer);
console.log("Max key:", Dexie.maxKey);
console.log("Min key:", Dexie.minKey);

// Database management operations
const dbExists = await Dexie.exists("MyDatabase");
if (dbExists) {
  console.log("Database exists");
}

// Get all database names
const dbNames = await Dexie.getDatabaseNames();
console.log("Available databases:", dbNames);

// Delete a database
await Dexie.delete("OldDatabase");

// Wait for external promise in transaction
await db.transaction("rw", ["friends"], async () => {
  const externalData = await Dexie.waitFor(fetch("/api/friends"));
  const friends = await externalData.json();
  await db.friends.bulkAdd(friends);
});

// Check current transaction
if (Dexie.currentTransaction) {
  console.log("Currently in transaction");
}

// Run with VIP priority
Dexie.vip(() => {
  return db.friends.add({ name: "Priority User", age: 25 });
});

// Run code outside transaction context
const result = Dexie.ignoreTransaction(() => {
  // This code runs outside any current transaction
  return someNonTransactionalOperation();
});

// Using async/spawn with generators (legacy support)
const asyncFn = Dexie.async(function* () {
  const result1 = yield somePromise();
  const result2 = yield anotherPromise();
  return result1 + result2;
});

const spawnResult = await Dexie.spawn(function* () {
  return yield someGenerator();
});

Static Utility Methods

Utility functions available on the Dexie constructor for common operations.

interface DexieUtilities {
  /** Get property value by key path */
  static getByKeyPath(obj: Object, keyPath: string | string[]): any;
  /** Set property value by key path */
  static setByKeyPath(obj: Object, keyPath: string | string[], value: any): void;
  /** Delete property by key path */
  static delByKeyPath(obj: Object, keyPath: string | string[]): void;
  /** Create shallow clone of object */
  static shallowClone<T>(obj: T): T;
  /** Create deep clone of object */
  static deepClone<T>(obj: T): T;
  /** Compare two IndexedDB keys */
  static cmp(a: any, b: any): number;
  /** Schedule function to run as soon as possible */
  static asap(fn: Function): void;
  /** Debug mode control */
  static debug: false | true | "dexie";
}

Usage Examples:

// Working with key paths
const obj = { user: { profile: { name: "John" } } };

// Get nested value
const name = Dexie.getByKeyPath(obj, "user.profile.name"); // "John"
const nameArray = Dexie.getByKeyPath(obj, ["user", "profile", "name"]); // "John"

// Set nested value
Dexie.setByKeyPath(obj, "user.profile.age", 25);
console.log(obj.user.profile.age); // 25

// Delete nested property
Dexie.delByKeyPath(obj, "user.profile.name");
console.log(obj.user.profile.name); // undefined

// Object cloning
const original = { a: 1, b: { c: 2 } };
const shallow = Dexie.shallowClone(original); // { a: 1, b: { c: 2 } }
const deep = Dexie.deepClone(original); // { a: 1, b: { c: 2 } }

// Note: shallow.b === original.b (same reference)
// Note: deep.b !== original.b (different reference)

// Key comparison (follows IndexedDB key ordering)
console.log(Dexie.cmp("a", "b")); // -1 (a < b)
console.log(Dexie.cmp(1, 2)); // -1 (1 < 2)
console.log(Dexie.cmp([1, 2], [1, 3])); // -1 ([1,2] < [1,3])

// Schedule immediate execution
Dexie.asap(() => {
  console.log("This runs as soon as possible");
});

// Debug mode
Dexie.debug = true; // Enable debug logging
Dexie.debug = "dexie"; // Enable debug with Dexie stack frames
Dexie.debug = false; // Disable debug

Error Classes and Dependencies

Error classes and development utilities available on the Dexie constructor.

interface DexieErrorClasses {
  /** Base class for all Dexie errors */
  static DexieError: typeof DexieError;
  /** Database failed to open */
  static OpenFailedError: typeof OpenFailedError;
  /** Version change error during upgrade */
  static VersionChangeError: typeof VersionChangeError;
  /** Schema definition error */
  static SchemaError: typeof SchemaError;
  /** Database upgrade error */
  static UpgradeError: typeof UpgradeError;
  /** Invalid table name or reference */
  static InvalidTableError: typeof InvalidTableError;
  /** Missing IndexedDB API */
  static MissingAPIError: typeof MissingAPIError;
  /** Database doesn't exist */
  static NoSuchDatabaseError: typeof NoSuchDatabaseError;
  /** Invalid argument passed to method */
  static InvalidArgumentError: typeof InvalidArgumentError;
  /** Sub-transaction constraint violation */
  static SubTransactionError: typeof SubTransactionError;
  /** Unsupported operation */
  static UnsupportedError: typeof UnsupportedError;
  /** Internal Dexie error */
  static InternalError: typeof InternalError;
  /** Database was closed */
  static DatabaseClosedError: typeof DatabaseClosedError;
  /** Transaction committed prematurely */
  static PrematureCommitError: typeof PrematureCommitError;
}

interface DexieDependencies {
  /** DOM dependencies for browser/Node.js compatibility */
  static dependencies: {
    indexedDB: IDBFactory;
    IDBKeyRange: typeof IDBKeyRange;
  };
  /** Error name constants */
  static errnames: DexieErrors;
}

Usage Examples:

// Using error classes
try {
  await db.open();
} catch (error) {
  if (error instanceof Dexie.OpenFailedError) {
    console.log("Failed to open database:", error.message);
  } else if (error instanceof Dexie.VersionChangeError) {
    console.log("Version change error:", error.message);
  } else if (error instanceof Dexie.DexieError) {
    console.log("General Dexie error:", error.message);
  }
}

// Checking error types by name
try {
  await db.table("nonexistent").get(1);
} catch (error) {
  if (error.name === Dexie.errnames.InvalidTable) {
    console.log("Invalid table error");
  }
}

// Custom error handling
function handleDexieError(error: any) {
  switch (error.constructor) {
    case Dexie.DatabaseClosedError:
      console.log("Database is closed, attempting to reopen...");
      return db.open();
    case Dexie.NoSuchDatabaseError:
      console.log("Database doesn't exist, creating new one...");
      return createNewDatabase();
    default:
      console.error("Unhandled Dexie error:", error);
      throw error;
  }
}

// Accessing DOM dependencies (useful for Node.js setup)
console.log("IndexedDB implementation:", Dexie.dependencies.indexedDB);
console.log("IDBKeyRange implementation:", Dexie.dependencies.IDBKeyRange);

// Setting custom dependencies (Node.js example)
// const FDBFactory = require('fake-indexeddb/lib/FDBFactory');
// const FDBKeyRange = require('fake-indexeddb/lib/FDBKeyRange');
// 
// Object.assign(Dexie.dependencies, {
//   indexedDB: new FDBFactory(),
//   IDBKeyRange: FDBKeyRange
// });

Middleware System

Register and manage middleware for extending database functionality.

/**
 * Register middleware for extending database operations
 * @param middleware - Middleware specification
 * @returns Database instance for chaining
 */
use(middleware: Middleware<DBCore>): this;

/**
 * Unregister middleware by function reference or name
 * @param spec - Middleware specification to remove
 * @returns Database instance for chaining
 */
unuse(spec: { stack: keyof DexieStacks; create: Function }): this;
unuse(spec: { stack: keyof DexieStacks; name: string }): this;

interface Middleware<TStack> {
  /** Target middleware stack */
  stack: keyof DexieStacks;
  /** Factory function that creates the middleware */
  create: (downlevelDatabase: TStack) => TStack;
  /** Priority level (lower numbers run first, default: 10) */
  level?: number;
  /** Optional name for the middleware */
  name?: string;
}

Usage Examples:

// Custom logging middleware
const loggingMiddleware = {
  stack: "dbcore" as const,
  name: "logging",
  create: (downlevelDatabase) => ({
    ...downlevelDatabase,
    table(name) {
      const table = downlevelDatabase.table(name);
      return {
        ...table,
        mutate(req) {
          console.log(`${req.type} operation on table ${name}:`, req);
          return table.mutate(req).then(result => {
            console.log(`${req.type} completed:`, result);
            return result;
          });
        }
      };
    }
  })
};

// Register middleware
db.use(loggingMiddleware);

// Performance monitoring middleware
const performanceMiddleware = {
  stack: "dbcore" as const,
  level: 1, // Run early
  create: (downlevelDatabase) => ({
    ...downlevelDatabase,
    table(name) {
      const table = downlevelDatabase.table(name);
      return {
        ...table,
        query(req) {
          const start = performance.now();
          return table.query(req).then(result => {
            const duration = performance.now() - start;
            console.log(`Query on ${name} took ${duration}ms`);
            return result;
          });
        }
      };
    }
  })
};

db.use(performanceMiddleware);

// Remove middleware by name
db.unuse({ stack: "dbcore", name: "logging" });

// Remove middleware by function reference
db.unuse({ stack: "dbcore", create: performanceMiddleware.create });

Database Events

Handle database lifecycle and operational events.

interface DbEvents {
  /** Database ready event - fires when database is successfully opened */
  ready: DexieOnReadyEvent;
  /** Database blocked event - fires when database operations are blocked */
  blocked: DexieEvent;
  /** Version change event - fires when another connection wants to upgrade/delete database */
  versionchange: DexieVersionChangeEvent;
  /** Database close event - fires when database connection is closed */
  close: DexieCloseEvent;
  /** Populate event - fires during database creation for initial data setup */
  populate: DexiePopulateEvent;
}

interface DexieOnReadyEvent {
  /** Subscribe to ready event with optional sticky behavior */
  subscribe(fn: (vipDb: Dexie) => any, bSticky?: boolean): void;
  /** Unsubscribe from ready event */
  unsubscribe(fn: (vipDb: Dexie) => any): void;
  /** Fire ready event (internal use) */
  fire(vipDb: Dexie): any;
}

interface DbEventFns {
  /** Subscribe to events with a single function call */
  (eventName: "ready", subscriber: (vipDb: Dexie) => any, bSticky?: boolean): void;
  (eventName: "blocked", subscriber: (event: IDBVersionChangeEvent) => any): void;
  (eventName: "versionchange", subscriber: (event: IDBVersionChangeEvent) => any): void;
  (eventName: "close", subscriber: (event: Event) => any): void;
  (eventName: "populate", subscriber: (trans: Transaction) => any): void;
}

/**
 * Subscribe to database events using 'once' - automatically unsubscribes after first trigger
 * @param eventName - Name of the event to subscribe to
 * @param callback - Function to call when event fires
 */
once: DbEventFns;

Usage Examples:

// Ready event - database successfully opened
db.on("ready", (vipDb) => {
  console.log("Database is ready!");
  // You can perform VIP operations here
  return vipDb.friends.count();
});

// Sticky ready subscription - will fire immediately if db is already open
db.on("ready", (vipDb) => {
  console.log("This will fire immediately if db is already open");
}, true); // bSticky = true

// Blocked event - database operations blocked by another connection
db.on("blocked", (event) => {
  console.log("Database operations are blocked", event);
});

// Version change event - another connection wants to upgrade/delete
db.on("versionchange", (event) => {
  console.log("Another connection is requesting version change", event);
  if (event.newVersion === null) {
    console.log("Database is being deleted");
  } else {
    console.log(`Upgrading to version ${event.newVersion}`);
  }
  // Default behavior: close database to allow upgrade
  db.close({ disableAutoOpen: false });
});

// Close event - database connection closed
db.on("close", (event) => {
  console.log("Database connection closed", event);
});

// Populate event - initial data setup during database creation
db.on("populate", (trans) => {
  console.log("Populating initial data");
  // Add initial data to tables
  trans.friends.add({ name: "John", age: 30 });
  trans.friends.add({ name: "Jane", age: 25 });
});

// Using once() for single-use subscriptions
db.once("ready", (vipDb) => {
  console.log("This will only fire once");
});

db.once("blocked", (event) => {
  console.log("This blocked handler will only fire once");
});

// Multiple event handlers
db.on("ready", () => console.log("Handler 1"));
db.on("ready", () => console.log("Handler 2"));

// Unsubscribe from events
const readyHandler = (vipDb) => console.log("Ready!");
db.on("ready", readyHandler);
db.on.ready.unsubscribe(readyHandler);

Database Status Methods

Methods to check the current status and state of the database connection.

/**
 * Check if the database is currently open
 * @returns True if database is open and ready for use
 */
isOpen(): boolean;

/**
 * Check if the database has been closed
 * @returns True if database has been explicitly closed
 */
hasBeenClosed(): boolean;

/**
 * Check if the database has failed to open
 * @returns True if database opening failed
 */
hasFailed(): boolean;

/**
 * Check if database was opened dynamically (without schema)
 * @returns True if opened without predefined schema
 */
dynamicallyOpened(): boolean;

/**
 * Get the native IndexedDB database instance
 * @returns Native IDBDatabase instance or null if closed
 */
backendDB(): IDBDatabase | null;

Usage Examples:

// Check database status before operations
if (db.isOpen()) {
  await db.friends.add({ name: "Alice", age: 25 });
} else {
  console.log("Database is not open, attempting to open...");
  await db.open();
}

// Handle closed databases
if (db.hasBeenClosed()) {
  console.log("Database was explicitly closed");
  // Reopen if needed
  await db.open();
}

// Handle failed database connections
if (db.hasFailed()) {
  console.error("Database failed to open");
  // Implement fallback logic or error handling
}

// Check if database was dynamically opened
if (db.dynamicallyOpened()) {
  console.log("Database opened without predefined schema");
  console.log("Available tables:", db.tables.map(t => t.name));
}

// Access native IndexedDB instance for advanced operations
const nativeDB = db.backendDB();
if (nativeDB) {
  console.log("Native DB version:", nativeDB.version);
  console.log("Object stores:", Array.from(nativeDB.objectStoreNames));
  
  // You can use native IndexedDB APIs if needed
  // (though this is rarely necessary with Dexie)
  const transaction = nativeDB.transaction(["friends"], "readonly");
  const store = transaction.objectStore("friends");
}

Additional Static Methods

Additional static utility methods available on the Dexie class.

/**
 * Check if a database exists
 * @param name - Database name to check
 * @returns Promise resolving to true if database exists
 */
static exists(name: string): Promise<boolean>;

/**
 * Delete a database by name
 * @param name - Database name to delete
 * @returns Promise that resolves when deletion is complete
 */
static delete(databaseName: string): Promise<void>;

/**
 * Ignore current transaction context
 * @param scopeFunc - Function to execute outside current transaction
 * @returns Result of the scope function
 */
static ignoreTransaction<T>(scopeFunc: () => T): T;

/**
 * Wait for a promise or function result
 * @param promiseOrFunction - Promise or function to wait for
 * @param optionalTimeout - Optional timeout in milliseconds
 * @returns Promise that resolves to the result
 */
static waitFor<T>(promiseOrFunction: T | (() => T), optionalTimeout?: number): Promise<T>;

/**
 * Current active transaction
 * @returns Current transaction or null if none active
 */
static currentTransaction: Transaction | null;

Usage Examples:

// Check if database exists before operations
const exists = await Dexie.exists("MyDatabase");
if (exists) {
  console.log("Database exists");
} else {
  console.log("Database does not exist");
}

// Static delete (without creating instance)
await Dexie.delete("OldDatabase");
console.log("Database deleted");

// Ignore current transaction for logging
await db.transaction("rw", ["friends"], async () => {
  await db.friends.add({ name: "Alice", age: 25 });
  
  // Log this operation in a separate transaction
  Dexie.ignoreTransaction(() => {
    db.logs.add({ action: "user_added", timestamp: Date.now() });
  });
});

// Wait for external promise within transaction
await db.transaction("rw", ["friends"], async () => {
  const externalData = await Dexie.waitFor(
    fetch("/api/user-data").then(r => r.json()),
    5000 // 5 second timeout
  );
  
  await db.friends.add(externalData);
});

// Check current transaction
if (Dexie.currentTransaction) {
  console.log("Currently in transaction:", Dexie.currentTransaction.mode);
} else {
  console.log("No active transaction");
}

Install with Tessl CLI

npx tessl i tessl/npm-dexie

docs

database-management.md

error-handling.md

events.md

index.md

live-queries.md

query-building.md

schema-management.md

table-operations.md

utility-functions.md

tile.json