or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

database-management.mderror-handling.mdevents.mdindex.mdlive-queries.mdquery-building.mdschema-management.mdtable-operations.mdutility-functions.md
tile.json

tessl/npm-dexie

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

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/dexie@4.2.x

To install, run

npx @tessl/cli install tessl/npm-dexie@4.2.0

index.mddocs/

Dexie.js

Dexie.js is a minimalistic wrapper for IndexedDB - the standard database in the browser. It provides a reactive, promise-based API with advanced querying capabilities, automatic transaction management, and schema evolution. Widely used by over 100,000 websites and applications.

Package Information

  • Package Name: dexie
  • Package Type: npm
  • Language: TypeScript/JavaScript
  • Installation: npm install dexie

Core Imports

import Dexie from "dexie";

Named imports:

import { Dexie, liveQuery, cmp } from "dexie";

For CommonJS:

const Dexie = require("dexie");

Legacy script tag:

<script src="https://unpkg.com/dexie/dist/dexie.js"></script>

Basic Usage

import Dexie from "dexie";

// Define database
const db = new Dexie("MyDatabase");
db.version(1).stores({
  friends: "++id, name, age",
  messages: "++id, friendId, message, timestamp"
});

// CRUD operations
await db.friends.add({ name: "Alice", age: 25 });
const friend = await db.friends.get(1);
const adults = await db.friends.where("age").above(18).toArray();
await db.friends.update(1, { age: 26 });
await db.friends.delete(1);

// Live queries (reactive)
import { liveQuery } from "dexie";
const friends$ = liveQuery(() => db.friends.toArray());
friends$.subscribe(friends => console.log("Friends updated:", friends));

Architecture

Dexie.js is built around several key components:

  • Database Management: Dexie class handles connections, schema versioning, and transactions
  • Table Operations: Table class provides CRUD operations and query initiation
  • Query Building: WhereClause and Collection classes offer chainable query methods
  • Transaction System: Automatic transaction management with explicit transaction support
  • Schema Evolution: Version-based schema management with upgrade functions
  • Live Queries: Reactive queries using Observables that auto-update on data changes
  • Type Safety: Full TypeScript support with generic type preservation

Capabilities

Database Management

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

class Dexie {
  constructor(name: string, options?: DexieOptions);
  version(versionNumber: number): Version;
  open(): PromiseExtended<Dexie>;
  close(options?: { disableAutoOpen?: boolean }): void;
  delete(options?: { disableAutoOpen?: boolean }): Promise<void>;
  transaction<T>(mode: TransactionMode, tables: string[], scope: () => T | PromiseLike<T>): Promise<T>;
  table(tableName: string): Table<any, any>;
}

interface DexieOptions {
  addons?: Array<(db: Dexie) => void>;
  autoOpen?: boolean;
  indexedDB?: IDBFactory;
  IDBKeyRange?: typeof IDBKeyRange;
  allowEmptyDB?: boolean;
  modifyChunkSize?: number;
  chromeTransactionDurability?: "default" | "strict" | "relaxed";
  cache?: "immutable" | "cloned" | "disabled";
}

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

Database Management

Table Operations

CRUD operations, bulk operations, and query initiation for database tables.

interface Table<T = any, TKey = IndexableType, TInsertType = T> {
  // CRUD operations
  get(key: IndexableType): Promise<T | undefined>;
  add(item: TInsertType, key?: TKey): Promise<TKey>;
  put(item: TInsertType, key?: TKey): Promise<TKey>;
  update(key: IndexableType, changes: UpdateSpec<T>): Promise<number>;
  delete(key: IndexableType): Promise<void>;
  clear(): Promise<void>;
  
  // Query initiation
  where(index: string): WhereClause<T, TKey, TInsertType>;
  filter(predicate: (obj: T) => boolean): Collection<T, TKey, TInsertType>;
  orderBy(index: string): Collection<T, TKey, TInsertType>;
  
  // Bulk operations
  bulkAdd(items: readonly TInsertType[], keys?: readonly TKey[], options?: BulkOptions): Promise<TKey>;
  bulkPut(items: readonly TInsertType[], keys?: readonly TKey[], options?: BulkOptions): Promise<TKey>;
  bulkUpdate(changes: readonly { key: IndexableType; changes: UpdateSpec<T> }[]): Promise<number>;
  bulkDelete(keys: readonly IndexableType[]): Promise<void>;
  bulkGet(keys: readonly IndexableType[]): Promise<(T | undefined)[]>;
}

type IndexableType = string | number | Date | ArrayBuffer | ArrayBufferView | DataView | Array<Array<void>>;

type UpdateSpec<T> = Partial<T> | { [keyPath: string]: any };

interface BulkOptions {
  allKeys?: boolean;
  ignoreOnsuccess?: boolean;
}

Table Operations

Query Building

Advanced query building with indexed lookups, filtering, and result manipulation.

interface WhereClause<T = any, TKey = IndexableType, TInsertType = T> {
  // Comparison operators
  equals(value: IndexableType): Collection<T, TKey, TInsertType>;
  above(value: any): Collection<T, TKey, TInsertType>;
  aboveOrEqual(value: any): Collection<T, TKey, TInsertType>;
  below(value: any): Collection<T, TKey, TInsertType>;
  belowOrEqual(value: any): Collection<T, TKey, TInsertType>;
  between(lower: any, upper: any, includeLower?: boolean, includeUpper?: boolean): Collection<T, TKey, TInsertType>;
  
  // String operations
  startsWith(prefix: string): Collection<T, TKey, TInsertType>;
  startsWithIgnoreCase(prefix: string): Collection<T, TKey, TInsertType>;
  
  // Array operations
  anyOf(keys: readonly IndexableType[]): Collection<T, TKey, TInsertType>;
  noneOf(keys: readonly IndexableType[]): Collection<T, TKey, TInsertType>;
  inAnyRange(ranges: readonly { 0: any; 1: any }[], options?: RangeOptions): Collection<T, TKey, TInsertType>;
}

interface Collection<T = any, TKey = IndexableType, TInsertType = T> {
  // Query refinement
  and(predicate: (obj: T) => boolean): Collection<T, TKey, TInsertType>;
  filter(predicate: (obj: T) => boolean): Collection<T, TKey, TInsertType>;
  limit(count: number): Collection<T, TKey, TInsertType>;
  offset(count: number): Collection<T, TKey, TInsertType>;
  reverse(): Collection<T, TKey, TInsertType>;
  
  // Execution methods
  toArray(): Promise<T[]>;
  count(): Promise<number>;
  first(): Promise<T | undefined>;
  each(callback: (obj: T, cursor: { key: any; primaryKey: TKey }) => void): Promise<void>;
  
  // Mutation methods
  modify(changes: UpdateSpec<T> | ((obj: T, ctx: { value: T }) => void)): Promise<number>;
  delete(): Promise<number>;
}

interface RangeOptions {
  includeLowers?: boolean;
  includeUppers?: boolean;
}

Query Building

Schema Management

Database versioning, schema definition, and migration management.

interface Version {
  stores(schema: { [tableName: string]: string | null }): Version;
  upgrade(upgradeFunction: (trans: Transaction) => PromiseLike<any> | void): Version;
}

interface Transaction {
  db: Dexie;
  active: boolean;
  mode: IDBTransactionMode;
  storeNames: string[];
  table(tableName: string): Table<any, any>;
  abort(): void;
}

Schema Management

Live Queries

Reactive query system that automatically updates when underlying data changes.

function liveQuery<T>(querier: () => T | Promise<T>): Observable<T>;

interface Observable<T> {
  subscribe(observer: Observer<T> | ((value: T) => void)): Subscription;
}

interface Observer<T> {
  next: (value: T) => void;
  error?: (error: any) => void;
  complete?: () => void;
}

interface Subscription {
  unsubscribe(): void;
}

Live Queries

Utility Functions

Helper functions for comparison, property modification, and range operations.

function cmp(a: any, b: any): number;

class PropModification {
  constructor(spec: PropModSpec);
  execute(value: any): any;
}

function add(value: number | bigint | any[]): PropModification;
function remove(value: number | bigint | any[]): PropModification;
function replacePrefix(oldPrefix: string, newPrefix: string): PropModification;

class RangeSet {
  constructor(fromOrTree?: any, to?: any);
  add(rangeOrKey: any): RangeSet;
  addKey(key: any): RangeSet;
  addKeys(keys: any[]): RangeSet;
}

function mergeRanges(target: IntervalTree, newSet: IntervalTree): void;
function rangesOverlap(rangeSet1: IntervalTree, rangeSet2: IntervalTree): boolean;

Utility Functions

Error Handling

Comprehensive error handling system with specific error types, enhanced promise catching, and recovery strategies.

class DexieError extends Error {
  name: string;
  stack?: string;
  inner?: any;
}

// Dexie-specific errors
class OpenFailedError extends DexieError {}
class SchemaError extends DexieError {}
class TransactionInactiveError extends DexieError {}
class ReadOnlyError extends DexieError {}

// Enhanced promise catching
interface PromiseExtended<T> extends Promise<T> {
  catch<TResult = never>(
    onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null
  ): PromiseExtended<T | TResult>;
  catch<TResult = never>(
    ExceptionType: Function,
    onrejected?: (reason: any) => TResult | PromiseLike<TResult>
  ): PromiseExtended<T | TResult>;
}

Error Handling

Events and Hooks

Database and table-level event system for validation, auditing, and extending functionality.

interface DexieEvent {
  fire(...args: any[]): any;
  subscribe(fn: (...args: any[]) => any): void;
  unsubscribe(fn: (...args: any[]) => any): void;
}

interface DbEvents {
  ready: DexieEvent;
  populate: DexieEvent;
  blocked: DexieEvent;
  versionchange: DexieEvent;
  close: DexieEvent;
}

interface TableHooks<T = any, TKey = any> {
  creating: DexieEvent;
  reading: DexieEvent;
  updating: DexieEvent;
  deleting: DexieEvent;
}

Events and Hooks

Types

type PromiseExtended<T> = Promise<T> & {
  timeout(ms: number, errorMessage?: string | Error): PromiseExtended<T>;
};

interface TableSchema {
  name: string;
  primKey: IndexSpec;
  indexes: IndexSpec[];
  mappedClass?: Function;
}

interface IndexSpec {
  name: string;
  keyPath: string | string[];
  unique?: boolean;
  multi?: boolean;
  auto?: boolean;
  compound?: boolean;
  src: string;
}

abstract class Entity {
  protected _db?: Dexie;
  protected table(): Table<this>;
}

interface DexieEvent {
  subscribers: Function[];
  fire(...args: any[]): any;
  subscribe(fn: (...args: any[]) => any): void;
  unsubscribe(fn: (...args: any[]) => any): void;
}