Overview
Enhanced IndexedDB storage with Dexie.js — schema versioning and transactions.
@localmode/dexie
Enhanced IndexedDB storage adapter using Dexie.js. Provides schema versioning, compound indexes, and transactional operations for VectorDB storage.
Features
- 🗄️ Schema Versioning — Automatic database migrations with Dexie.js
- 🔄 Transactions — Atomic operations across multiple object stores
- 📇 Compound Indexes — Efficient queries on collection-scoped data
- 📦 ~15KB — Lightweight Dexie.js dependency
Installation
bash pnpm install @localmode/dexie @localmode/core bash npm install @localmode/dexie @localmode/core bash yarn add @localmode/dexie @localmode/core bash bun add @localmode/dexie @localmode/core Quick Start
import { DexieStorage } from '@localmode/dexie';
import { createVectorDB, embed, ingest } from '@localmode/core';
import { transformers } from '@localmode/transformers';
// Create storage
const storage = new DexieStorage({ name: 'my-app' });
// Use with VectorDB
const db = await createVectorDB({
name: 'documents',
dimensions: 384,
storage,
});
// Ingest documents
const model = transformers.embedding('Xenova/bge-small-en-v1.5');
await ingest({
db,
model,
documents: [
{ text: 'Local-first AI is the future', metadata: { source: 'blog' } },
{ text: 'Privacy-preserving machine learning', metadata: { source: 'paper' } },
],
});The ingest() function is part of the RAG pipeline. It chunks, embeds, and stores documents in a single call.
Configuration
Prop
Type
Why Dexie?
Dexie.js wraps IndexedDB with a cleaner API and adds features that are useful for production applications:
- Schema versioning — Define table schemas declaratively with automatic migrations
- Transactions — Atomic operations ensure data consistency (e.g., clearing a collection deletes documents, vectors, and indexes atomically)
- Error handling — Better error messages than raw IndexedDB
- Compound queries — Efficient
where('collectionId').equals(id)lookups via indexes
Transaction Support
DexieStorage uses Dexie's built-in transactions for atomic operations. When clearing a collection or the entire database, all related stores are updated atomically — if any step fails, the entire operation rolls back:
// clearCollection() atomically deletes documents, vectors, and index for a collection
await db.clear('my-collection');
// clear() atomically clears all four stores: documents, vectors, indexes, collectionsThis prevents data corruption from partial writes (e.g., documents deleted but vectors left orphaned).
Storage Fallback
Gracefully fallback when IndexedDB is unavailable (e.g., Safari private browsing):
import { MemoryStorage } from '@localmode/core';
import { DexieStorage } from '@localmode/dexie';
let storage: DexieStorage | MemoryStorage;
try {
storage = new DexieStorage({ name: 'my-app' });
await storage.open();
} catch (error) {
console.warn('DexieStorage unavailable, falling back to memory:', error);
storage = new MemoryStorage();
}Comparison
| Adapter | Package | Bundle Size | Transactions | Auto-Fallback | Best For |
|---|---|---|---|---|---|
IndexedDBStorage | @localmode/core | 0KB (built-in) | No | No | Simple apps, zero extra deps |
DexieStorage | @localmode/dexie | ~15KB | Yes | No | Production apps needing schema versioning |
IDBStorage | @localmode/idb | ~3KB | No | No | Minimal bundle size |
LocalForageStorage | @localmode/localforage | ~10KB | No | Yes | Max browser compatibility |