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

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;
}

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