diff --git a/packages/docs/audits/dexie-evaluation-2026-01.md b/packages/docs/audits/dexie-evaluation-2026-01.md deleted file mode 100644 index 498ff0795..000000000 --- a/packages/docs/audits/dexie-evaluation-2026-01.md +++ /dev/null @@ -1,504 +0,0 @@ ---- -title: Dexie.js Evaluation Audit -date: 2026-01-07 -author: Team ---- - -## Summary - -This audit evaluates whether Dexie.js would benefit the CoRATES codebase. After analyzing current IndexedDB usage patterns, planned local-first features, and the `y-dexie` add-on for Yjs integration, the recommendation is: **adopt Dexie.js with y-dexie** to unify all IndexedDB storage into a single database. - -## Key Discovery: y-dexie - -The `y-dexie` add-on allows storing Y.js documents alongside traditional data in a single Dexie database. This changes the calculus significantly. - -### y-indexeddb vs y-dexie Comparison - -| Feature | y-indexeddb | y-dexie | -| ----------------------------------------- | ----------- | ------- | -| Persist single document | Yes | Yes | -| Garbage collect historical updates | Yes | Yes | -| Multiple documents in same database | No | Yes | -| Store docs as properties on indexed items | No | Yes | -| Sync with dexie-cloud | No | Yes | -| Optimized multi-document sync protocol | No | Yes | - -**Current limitation**: `y-indexeddb` creates one IndexedDB database per Y.Doc (`corates-project-{projectId}`). This makes it impossible to: - -- Query across documents -- Store documents as properties on existing objects (e.g., a checklist row) -- Integrate with other app data in the same database - -**y-dexie solution**: Store multiple Y.Docs in a single database, potentially as properties on checklist/project rows. - -## Current IndexedDB Usage - -### 1. Yjs Document Persistence (`y-indexeddb`) - -**Location**: `packages/web/src/primitives/useProject/index.js` - -```javascript -import { IndexeddbPersistence } from 'y-indexeddb'; -connectionEntry.indexeddbProvider = new IndexeddbPersistence(`corates-project-${projectId}`, connectionEntry.ydoc); -``` - -**Purpose**: Persist Yjs CRDT documents for offline support and fast loading. - -**Current Limitation**: Creates a separate IndexedDB database per project. This fragments storage and prevents unified queries. - -**Assessment**: Strong candidate for migration to `y-dexie` to unify with other app data. - -### 2. PDF Cache (`pdfCache.js`) - -**Location**: `packages/web/src/primitives/pdfCache.js` - -**Current Implementation**: Raw IndexedDB API (~300 lines) - -```javascript -// Manual database opening -const request = indexedDB.open(DB_NAME, DB_VERSION); -request.onupgradeneeded = event => { - const db = event.target.result; - const store = db.createObjectStore(PDF_STORE_NAME, { keyPath: 'id' }); - store.createIndex('projectId', 'projectId', { unique: false }); - // ... -}; - -// Manual transactions for every operation -const transaction = db.transaction(PDF_STORE_NAME, 'readwrite'); -const store = transaction.objectStore(PDF_STORE_NAME); -const request = store.put(record); -``` - -**Pain Points**: - -- Verbose boilerplate for every operation (30+ lines per function) -- Manual Promise wrapping around IndexedDB events -- Manual cursor iteration for queries -- No built-in migration support beyond version numbers - -**Assessment**: Strong candidate for Dexie migration. Would reduce code by ~60%. - -### 3. localStorage Usage (Multiple Files) - -**Locations**: 49+ usages across auth, layout, reconciliation, recents - -**Current Patterns**: - -- Auth flow state (`pendingEmail`, `oauthSignup`, `magicLinkSignup`) -- UI preferences (`sidebarWidth`, `sidebarMode`) -- Navigation state (`reconciliation-nav-*`) -- Recent items (`recents-nav`) -- Query cache snapshots - -**Assessment**: localStorage is appropriate for small key-value data. No benefit from Dexie here. - -## Planned Features Requiring IndexedDB - -### Operation Queue (from Local-First Roadmap) - -**Requirement**: "Implement persistent IndexedDB op-queue library (client) and `/api/sync/ops` endpoint (server)" - -**Data Model**: - -```typescript -interface QueuedOperation { - id: string; // UUID - idempotencyKey: string; // For server replay - type: string; // Operation type - payload: unknown; // Operation data - status: 'pending' | 'syncing' | 'applied' | 'failed'; - createdAt: number; - attempts: number; - lastAttempt?: number; - error?: string; -} -``` - -**Required Queries**: - -- Get all pending ops (ordered by `createdAt`) -- Update status by ID -- Delete applied ops -- Count pending ops (for UI feedback) -- Bulk insert ops - -**Assessment**: Perfect Dexie use case. Dexie provides: - -- Clean schema definitions -- Indexed queries without manual cursor iteration -- Transaction helpers -- Built-in promises - -## Dexie Benefits Analysis - -### Code Reduction - -**Before (raw IndexedDB)**: - -```javascript -async function getPendingOps() { - const db = await getDb(); - return new Promise((resolve, reject) => { - const transaction = db.transaction('ops', 'readonly'); - const store = transaction.objectStore('ops'); - const index = store.index('status'); - const keyRange = IDBKeyRange.only('pending'); - const request = index.openCursor(keyRange); - const results = []; - request.onsuccess = event => { - const cursor = event.target.result; - if (cursor) { - results.push(cursor.value); - cursor.continue(); - } else { - results.sort((a, b) => a.createdAt - b.createdAt); - resolve(results); - } - }; - request.onerror = () => reject(request.error); - }); -} -``` - -**After (Dexie)**: - -```javascript -async function getPendingOps() { - return db.ops.where('status').equals('pending').sortBy('createdAt'); -} -``` - -### Schema Migrations - -**Raw IndexedDB**: Manual version checks in `onupgradeneeded` - -**Dexie**: Declarative schema versioning - -```javascript -const db = new Dexie('corates-ops'); -db.version(1).stores({ - ops: '++id, idempotencyKey, status, createdAt', -}); -db.version(2).stores({ - ops: '++id, idempotencyKey, status, createdAt, [status+createdAt]', -}); -``` - -### Type Safety - -Dexie 4.x has excellent TypeScript support: - -```typescript -interface Operation { - id?: number; - idempotencyKey: string; - status: 'pending' | 'syncing' | 'applied' | 'failed'; - // ... -} - -class OperationsDB extends Dexie { - ops!: Table; - - constructor() { - super('corates-ops'); - this.version(1).stores({ - ops: '++id, idempotencyKey, status, createdAt', - }); - } -} -``` - -### Bulk Operations - -**Raw IndexedDB**: Manual loop with individual puts - -**Dexie**: Native bulk methods - -```javascript -await db.ops.bulkAdd(operations); -await db.ops.bulkPut(updates); -await db.ops.bulkDelete(ids); -``` - -## Bundle Size Impact - -| Library | Minified | Gzipped | -| ----------- | -------- | ------- | -| Dexie 4.x | ~45 KB | ~15 KB | -| y-dexie | ~5 KB | ~2 KB | -| y-indexeddb | ~8 KB | ~3 KB | - -**Current bundle**: Already includes y-indexeddb (~3KB gzipped). - -**With unified Dexie**: Replace y-indexeddb with Dexie + y-dexie = ~17KB gzipped total (+14KB net). - -**Assessment**: Acceptable increase for the unified storage benefits and code reduction. - -## y-dexie Integration - -### How y-dexie Works - -y-dexie stores Y.Docs as properties on Dexie table rows: - -```javascript -import Dexie from 'dexie'; -import { DexieYProvider } from 'y-dexie'; - -const db = new Dexie('corates'); -db.version(1).stores({ - projects: 'id, name, updatedAt', - checklists: 'id, projectId, type, status', - pdfs: 'id, projectId, studyId, cachedAt', - ops: '++id, idempotencyKey, status, createdAt', -}); - -// Y.Doc is stored as a property on the project row -const provider = new DexieYProvider(db, 'projects', projectId, ydoc); -``` - -### Benefits for CoRATES - -1. **Single database**: All app data (projects, checklists, PDFs, ops, Y.Docs) in one IndexedDB -2. **Unified queries**: Can query projects by name AND include their Y.Doc state -3. **Atomic operations**: Transactions can span Y.Doc updates and regular data -4. **Simpler cleanup**: Delete project row = delete Y.Doc automatically -5. **Future dexie-cloud**: If we ever want cloud sync beyond Yjs, dexie-cloud works with y-dexie - -## Recommended Adoption Strategy - -### Phase 1: Unified Database Setup - -Create a single Dexie database for all app data: - -```javascript -// packages/web/src/primitives/db.js -import Dexie from 'dexie'; - -class CoratesDB extends Dexie { - projects; - checklists; - pdfs; - ops; - - constructor() { - super('corates'); - this.version(1).stores({ - // Y.Docs stored as properties on project rows via y-dexie - projects: 'id, orgId, updatedAt', - // Checklist metadata (Y.Doc content stored on project) - checklists: 'id, projectId, studyId, type, status', - // PDF cache - pdfs: 'id, projectId, studyId, cachedAt', - // Operation queue for offline sync - ops: '++id, idempotencyKey, status, createdAt, [status+createdAt]', - }); - } -} - -export const db = new CoratesDB(); -``` - -### Phase 2: Migrate Yjs Persistence to y-dexie - -Replace `y-indexeddb` with `y-dexie`: - -```javascript -// packages/web/src/primitives/useProject/index.js -import { DexieYProvider } from 'y-dexie'; -import { db } from '../db.js'; - -// Before (y-indexeddb) -// connectionEntry.indexeddbProvider = new IndexeddbPersistence( -// `corates-project-${projectId}`, -// connectionEntry.ydoc -// ); - -// After (y-dexie) -connectionEntry.dexieProvider = new DexieYProvider(db, 'projects', projectId, connectionEntry.ydoc); -``` - -### Phase 3: Operation Queue (New Code) - -Use the same Dexie database for the planned operation queue: - -```javascript -// packages/web/src/primitives/opQueue.js -import { db } from './db.js'; - -export async function queueOperation(op) { - return db.ops.add({ - ...op, - status: 'pending', - createdAt: Date.now(), - attempts: 0, - }); -} - -export async function getPendingOps() { - return db.ops.where('status').equals('pending').sortBy('createdAt'); -} - -export async function markSynced(ids) { - return db.ops.where('id').anyOf(ids).modify({ status: 'applied' }); -} -``` - -### Phase 4: PDF Cache Migration - -Migrate `pdfCache.js` to use the unified database: - -```javascript -// packages/web/src/primitives/pdfCache.js (refactored) -import { db } from './db.js'; - -export async function getCachedPdf(projectId, studyId, fileName) { - const id = `${projectId}:${studyId}:${fileName}`; - const record = await db.pdfs.get(id); - return record?.data ?? null; -} - -export async function cachePdf(projectId, studyId, fileName, data) { - if (data.byteLength > MAX_SINGLE_FILE_SIZE) return false; - await evictIfNeeded(data.byteLength); - - await db.pdfs.put({ - id: `${projectId}:${studyId}:${fileName}`, - projectId, - studyId, - fileName, - data, - size: data.byteLength, - cachedAt: Date.now(), - }); - return true; -} - -async function evictIfNeeded(requiredSpace) { - const all = await db.pdfs.orderBy('cachedAt').toArray(); - let totalSize = all.reduce((sum, p) => sum + p.size, 0); - const targetSize = MAX_CACHE_SIZE_BYTES - requiredSpace; - - const toDelete = []; - for (const entry of all) { - if (totalSize <= targetSize) break; - toDelete.push(entry.id); - totalSize -= entry.size; - } - - if (toDelete.length) { - await db.pdfs.bulkDelete(toDelete); - } -} -``` - -## Data Migration - -When switching from y-indexeddb to y-dexie, existing Y.Doc data needs migration: - -```javascript -// One-time migration script -import { IndexeddbPersistence } from 'y-indexeddb'; -import { DexieYProvider } from 'y-dexie'; -import * as Y from 'yjs'; -import { db } from './db.js'; - -async function migrateProject(projectId) { - // 1. Load from old y-indexeddb - const tempDoc = new Y.Doc(); - const oldProvider = new IndexeddbPersistence(`corates-project-${projectId}`, tempDoc); - await oldProvider.whenSynced; - - // 2. Save to new y-dexie - const newProvider = new DexieYProvider(db, 'projects', projectId, tempDoc); - await newProvider.whenSynced; - - // 3. Delete old database - await indexedDB.deleteDatabase(`corates-project-${projectId}`); - - // 4. Clean up - oldProvider.destroy(); - newProvider.destroy(); - tempDoc.destroy(); -} -``` - -## What NOT to Use Dexie For - -1. **Small key-value data**: Keep localStorage for: - - UI preferences - - Auth flow state - - Navigation state -2. **Query cache**: TanStack Query handles this already - -## Y.js Ecosystem Compatibility - -Dexie + y-dexie integrates with the Y.js ecosystem CoRATES may use: - -**Already compatible**: - -- Y.Doc persistence (via y-dexie) -- WebSocket sync (unchanged) -- Durable Object relay (unchanged) - -**Future potential**: - -- Rich-text editors: TipTap, ProseMirror, Lexical, Quill -- Code editors: CodeMirror, Monaco -- Drawing: Excalidraw, tldraw -- Block editors: BlockSuite/AFFiNE - -## Alternatives Considered - -| Library | Pros | Cons | -| ------------------------- | --------------------------------------------- | ------------------------- | -| **Dexie.js + y-dexie** | Unified storage, Y.js integration, TypeScript | Migration effort | -| **Dexie.js (no y-dexie)** | Clean API, TypeScript support | Separate Y.js storage | -| **y-indexeddb (current)** | Purpose-built for Y.js | One DB per doc, isolated | -| **idb (Jake Archibald)** | Minimal wrapper, Promise-based | No Y.js, less query power | -| **PouchDB** | Sync built-in | Heavy, CouchDB-centric | -| **localForage** | Simple API | No indexing, no queries | -| **Raw IndexedDB** | No dependency | Verbose, error-prone | - -**Recommendation**: Dexie + y-dexie provides the best unified solution. - -## Implementation Checklist - -- [ ] Add `dexie` and `y-dexie` to `packages/web/package.json` -- [ ] Create unified `db.js` with schema for projects, checklists, pdfs, ops -- [ ] Migrate `useProject/index.js` from y-indexeddb to y-dexie -- [ ] Add migration script for existing y-indexeddb data -- [ ] Create `opQueue.js` using unified database -- [ ] Migrate `pdfCache.js` to use unified database -- [ ] Remove `y-indexeddb` dependency -- [ ] Update testing guide with Dexie mocking patterns -- [ ] Clean up old per-project IndexedDB databases - -## Risks - -1. **Migration complexity**: Need to migrate existing Y.Doc data from y-indexeddb -2. **y-dexie maturity**: Newer than y-indexeddb, less battle-tested -3. **Bundle size**: +14KB gzipped net increase -4. **Learning curve**: Team needs to learn Dexie API - -## Mitigation - -- Start with op queue (new code, no migration) -- Test y-dexie thoroughly before full migration -- Keep y-indexeddb as fallback during transition -- Migrate one project type at a time - -## Conclusion - -**Adopt Dexie.js** for: - -- The planned operation queue (immediate) -- PDF cache (optional, when time permits) - -**Keep current approach** for: - -- Yjs persistence (y-indexeddb) -- Simple key-value data (localStorage) -- Query cache (TanStack Query) - -The primary benefit is in the operation queue implementation, which is a core requirement for the local-first roadmap. Dexie will reduce complexity and improve maintainability for this critical feature. diff --git a/packages/docs/audits/local-first-roadmap.md b/packages/docs/audits/local-first-roadmap.md deleted file mode 100644 index c3dae1507..000000000 --- a/packages/docs/audits/local-first-roadmap.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Local-First Sync Roadmap (CoRATES) -date: 2026-01-07 -author: Team ---- - -This roadmap turns the strategy from `docs/plans/local-first-sync-strategy.md` into a concrete, time-boxed plan with owners, milestones, and acceptance criteria. It is intentionally pragmatic: ship small, measure, and expand. - -Timeline overview - -- Immediate (0–2 weeks) - - Inventory endpoints and sync domains (who owns which endpoints). - - Add `GET /api/metadata` scaffold returning `{ apiVersion, minSupportedClient, cacheVersion, features }`. - - Add boot-time client check against `minSupportedClient` and non-blocking UI banner. - - Move a small set of canonical Zod schemas into `packages/shared` (start with user/session DTOs). - -- Short (2–8 weeks) - - CI: generate TypeScript client from `openapi.json` and fail PRs if out-of-date. - - Implement `cacheVersion` propagation and persisted query invalidation on change. - - Implement persistent IndexedDB op-queue library (client) and `/api/sync/ops` endpoint (server). - - Add telemetry for client-version and op-queue backlog size. - -- Medium (2–6 months) - - Move document sync to Yjs Durable Object relay (if not already), add migration plan for doc schema versions. - - Add server-side reconciliation endpoints and idempotent replay handling. - - Add integration tests for offline replay, Yjs sync, and forced-upgrade flows. - -- Long (6+ months) - - Harden monitoring/alerting (alerts for high backlog, deprecated-client usage > X%). - - Full migration of remaining Zod schemas into `packages/shared` and strict CI gating. - - Optional: evaluate GraphQL for read-heavy aggregation endpoints (pilot only). - -Owners & acceptance criteria - -- Infrastructure: @backend-owner — scaffold `/api/metadata`, CI typegen, telemetry hooks. -- Client: @frontend-owner — boot-time version check, SW/BroadcastChannel update path, op-queue client library. -- Sync primitives: @sync-owner — Yjs relay, reconciliation endpoints, doc migrations. - -Acceptance criteria (per milestone) - -- Inventory & metadata scaffold - - Inventory file committed listing endpoints and whether they use Yjs/REST. - - `/api/metadata` responds with valid JSON and is documented in OpenAPI. - - Client shows non-blocking banner when `clientVersion < minSupportedClient`. - -- CI typegen - - `openapi.json` updates produce regenerated client code via CI job. - - PRs that don't include the regenerated files fail the CI job. - -- Op-queue & replay - - Client persists ops to IndexedDB and can replay to `/api/sync/ops` with idempotency keys. - - Server accepts op batches, validates with Zod, and returns a checkpoint. - - Integration test demonstrates offline queue replay success. - -Risks & mitigations - -- Risk: Forced upgrades will frustrate users. Mitigation: Use staged rollout, server-side adapters, and telemetry-driven cutoff. -- Risk: Yjs migration complexity. Mitigation: Use schemaVersion metadata and one-time server-side migration handlers. - -Next immediate tasks (this sprint) - -1. Generate endpoint inventory (owner: @backend-owner). -2. Implement `/api/metadata` scaffold and add to OpenAPI (owner: @backend-owner). -3. Add client boot-time check and non-blocking banner (owner: @frontend-owner). -4. Move `user`/`session` Zod schemas into `packages/shared` and update imports (owner: @shared-owner). - -Where to record progress - -- Use `docs/plans/local-first-sync-strategy.md` for strategy context. -- Use this roadmap file for milestone status and linking PRs. -- Update the repo TODO (project board) with tickets referenced by milestone. - -Questions before we start - -- Do you want CI to automatically commit generated clients (and require a PR for that change), or should CI only fail and expect authors to commit regeneration output? -- Who should I list as `@backend-owner`, `@frontend-owner`, and `@sync-owner` (I can default to existing repo leads if you prefer). - ---- - -I can now: (A) generate the endpoint inventory, (B) scaffold `/api/metadata` and add OpenAPI entry, or (C) start moving Zod schemas into `packages/shared`. Which should I do next? diff --git a/packages/docs/audits/local-first-sync-strategy.md b/packages/docs/audits/local-first-sync-strategy.md deleted file mode 100644 index 77ad121f9..000000000 --- a/packages/docs/audits/local-first-sync-strategy.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: Local-First Sync Strategy (CoRATES) -date: 2026-01-07 -author: Team ---- - -## Summary - -This document describes a pragmatic strategy to keep the `web` client and the `workers` backend in sync for a local-first application. It covers which data must stay synchronized, recommended synchronization primitives (CRDTs, event-log, snapshots), contract and versioning practices, offline/queue handling, security considerations, testing, and a small rollout roadmap. - -**Goals** - -- Preserve local-first UX (work offline, seamless conflict resolution for collaborative docs). -- Keep client and server types and validation in strict alignment. -- Minimize forced client upgrades while retaining a safe migration path. -- Maintain robust security (auth, SSRF, input validation) and observability for sync problems. - -## Scope - -- Applies to `packages/web` (client) and `packages/workers` (server) in this repo. -- Emphasizes document-level collaboration, operation queues (mutations), auth/session state, derived indexes and query caches, and attachments. - -## What must stay in sync (priority order) - -- Live collaborative documents and checklist state (CRDT — Yjs) -- Operation queues / mutation logs (client-driven commands) -- Auth/session & user profile state (authoritative on server) -- Query cache / persisted IndexedDB snapshots (client caches) -- Derived server-side indexes, summaries, and search -- Attachments and signed URL availability - -## Recommended primitives and when to use them - -- CRDTs (Yjs): document bodies, checklist items, real-time multi-user edits. -- Event-log / append-only ops: user actions that are not easy CRDTs (e.g., domain-specific commands, exports, server-only transforms). -- Snapshot + deltas: large state (search indexes, generated summaries) where streaming every op is expensive. -- REST endpoints: commands, file upload, server reconciliation, and metadata. -- Optional GraphQL: read-heavy aggregations if the UI requires highly flexible client-shaped queries. Not recommended for primary CRDT sync. - -## Contracts and validation - -- Keep canonical DTOs and Zod schemas in `packages/shared` and import them from both `web` and `workers`. -- Publish and maintain `openapi.json` from the `workers` package; generate TypeScript clients and runtime validators for the web build in CI. -- Server must validate every incoming payload with Zod and fail fast with clear error codes (use the existing error helpers). - -## Versioning, compatibility and forcing updates - -- Use semantic API versioning for breaking changes and keep changes additive-first. -- Add a small metadata endpoint `/api/metadata` or `/api/compat` that returns: - - `apiVersion` (server) - - `minSupportedClient` (semver) - - `features`/capabilities -- Client reports its `clientVersion` on requests (header) and performs a boot-time check. If the server responds that the client is too old, the client shows a blocking upgrade UI. -- Service worker & BroadcastChannel based approach: server changes `minSupportedClient` — SW detects it and broadcasts a force-reload message to all tabs. This is less disruptive than immediate hard-blocks. -- Server-side adapters: provide temporary acceptance of legacy payloads for a migration window, translating to the canonical model. - -## Offline-first & operation queue - -- Persist a local operation queue in IndexedDB (attach idempotency keys and causal metadata). -- On reconnect, replay queued operations in order to a reconciliation endpoint (server validates and returns canonical state/checkpoint). -- Provide per-op status (pending, syncing, applied, failed) and UI feedback for conflicts or retries. - -## Query cache hygiene - -- On auth or session changes, clear in-memory query cache (`queryClient.clear()`), clear persisted caches (`clearPersistedQueryCache()`), and trigger `session().refetch()` (already implemented in `better-auth-store`). -- Expose a `cacheVersion` server-side value in `/api/metadata`; clients can force invalidate persisted caches if `cacheVersion` changes. - -## Security - -- Server-side must re-validate everything (Zod), never trust client -- Keep SSRF protection for proxy endpoints (already implemented in `packages/workers/src/lib/ssrf-protection.js`). -- Require auth for mutation endpoints, and rate-limit or challenge suspicious sync clients. - -## CI / Developer workflows - -- Generate and commit client types from `openapi.json` during CI; fail PRs if generated types diverge. -- Add unit tests that exercise generated client against a local worker (or mocked OpenAPI responses). -- Linting and schema checks: enforce Zod schemas for incoming request validation in `workers`. - -## Testing and monitoring - -- Integration tests for: - - Yjs document sync via Durable Objects or WebSocket relay - - Offline queue replay and idempotency checks - - Version negotiation and forced upgrade flows -- Add telemetry for: client-version distribution, number of queued ops per client, sync failure rates, backlog size, and time-to-replay. - -## Migration & rollout strategy - -1. Add `minSupportedClient` to `/api/metadata` and ship server-side capability flags. -2. Add client-side boot check + non-blocking UI banner for deprecation. -3. For breaking changes: provide server-side adapter accepting old payloads for a 2–8 week window while migrating clients. -4. After the window, bump `minSupportedClient` and use SW/BroadcastChannel to force updates. - -## Roadmap (concrete next steps) - -1. Inventory repo: list endpoints, identify which domains use Yjs vs REST (I can generate this list). -2. Move canonical Zod DTOs to `packages/shared` and import them in server & client. -3. Add `/api/metadata` and expose `minSupportedClient` and `cacheVersion`. -4. Add CI job that regenerates client types from `openapi.json` and fails if uncommitted. -5. Implement an IndexedDB-backed op queue library and a server reconciliation endpoint. -6. Add monitoring for client-version and sync metrics. - -## Risks & tradeoffs - -- CRDTs (Yjs) add complexity but are the best UX for real-time document collaboration. -- GraphQL can simplify client query shapes but complicates offline persistence and cache invalidation for local-first apps. -- Forcing upgrades is disruptive; prefer staged rollout with server adapters and telemetry-driven cutoff. - -## Appendix: recommended endpoints - -- `GET /api/metadata` → { apiVersion, minSupportedClient, cacheVersion, features } -- `POST /api/sync/ops` → accept op batches and return { checkpoint } -- `POST /api/reconcile/doc/:id` → server reconciliation for doc snapshots - ---- - -If you want, I can: (A) generate the endpoint inventory now, (B) move selected Zod schemas to `packages/shared`, or (C) scaffold `/api/metadata` and CI typegen. Which should I start? diff --git a/packages/docs/audits/migration-strategy-sequencing-2026-01.md b/packages/docs/audits/migration-strategy-sequencing-2026-01.md deleted file mode 100644 index 271721a58..000000000 --- a/packages/docs/audits/migration-strategy-sequencing-2026-01.md +++ /dev/null @@ -1,441 +0,0 @@ ---- -title: Migration Strategy & Sequencing Plan -date: 2026-01-07 -author: Team ---- - -## Executive Summary - -**Recommendation: Execute all three migrations in a specific sequence** - -**Total Effort**: 25-35 hours over 2-3 weeks -**Risk Level**: Low (each is independent or loosely coupled) -**Value**: High (improves architecture, testing, and scalability) - -### Quick Recommendation - -| Phase | Migration | Duration | Priority | Dependencies | -| ------------ | ---------------- | ----------- | ----------------- | ------------------------------ | -| **Week 1** | Codecov | 1.5 hours | P0 (Quick Win) | None | -| **Week 1-2** | Zod OpenAPI Hono | 15-20 hours | P1 (High Value) | None | -| **Week 2-3** | Single Domain | 5-7 hours | P2 (Architecture) | Zod OpenAPI Hono (recommended) | -| **Week 3+** | Dexie + y-dexie | 3-5 days | P3 (Optimization) | All above | - ---- - -## Migration Sequencing Analysis - -### Dependency Graph - -``` -Codecov - ├─ No dependencies - ├─ Enables: Coverage tracking for all future work - └─ Blocks: Nothing - -Zod OpenAPI Hono - ├─ No hard dependencies - ├─ Optional prerequisite for: Single Domain (cleaner routing) - ├─ Improves: Single domain consolidation (already structured API routes) - └─ Blocks: Nothing - -Single Domain Consolidation - ├─ Optional: Works without Zod OpenAPI Hono, but better if done first - ├─ Depends on: Having API routes (Hono-based or any other) - ├─ Enables: Cleaner auth, simpler architecture - └─ Blocks: Nothing (optional optimization) - -Dexie + y-dexie - ├─ No hard dependencies on above three - ├─ Works independently: Frontend storage optimization - ├─ Benefits from: Single domain (simpler API calls with /api) - └─ Blocks: Nothing -``` - -### Option A: Recommended Sequence (Logical Order) - -``` -Week 1: Codecov (1.5 hrs) - ↓ -Week 1-2: Zod OpenAPI Hono (15-20 hrs) - ↓ -Week 2-3: Single Domain (5-7 hrs) [API routes already using Zod] - ↓ -Week 3+: Dexie + y-dexie (3-5 days) -``` - -**Rationale**: - -1. **Codecov first**: Immediate visibility, enables tracking of coverage during other migrations -2. **Zod OpenAPI Hono second**: Refactors API to be more structured (beneficial for domain consolidation) -3. **Single Domain third**: Consolidates the now-clean Zod-based routes, merges workers -4. **Dexie last**: Frontend storage, works best after API is finalized - -**Total Timeline**: 2-3 weeks -**Parallelization**: Could run Zod OpenAPI + Single Domain in parallel, but not recommended (routing changes overlap) - -### Option B: Fastest Path (Parallel Where Possible) - -``` -Week 1: Codecov (1.5 hrs) -Week 1-2: Single Domain (5-7 hrs) [with plain Hono routes] - + Dexie Planning (read-only) -Week 2-3: Zod OpenAPI Hono (15-20 hrs) [now in merged worker] -Week 3+: Dexie + y-dexie (3-5 days) -``` - -**Pros**: Single Domain done earlier, Codecov + Single Domain run semi-parallel -**Cons**: Zod OpenAPI migration is bigger (whole merged worker), less clean separation - -### Option C: Independent Path (Staggered) - -``` -Week 1: Codecov (1.5 hrs) -Week 1-2: Zod OpenAPI Hono (15-20 hrs) [workers package stays separate] -Week 3-4: Dexie + y-dexie (3-5 days) [frontend optimization] -Later: Single Domain (5-7 hrs) [if desired as final optimization] -``` - -**Pros**: No blocking dependencies, can stop at any point, Dexie doesn't wait -**Cons**: Single Domain happens later, less cohesive overall improvement - ---- - -## Recommended Sequence: Option A - -### Phase 1: Codecov (Week 1, 1.5 hours) - -**Why First?** - -- Smallest effort, immediate ROI -- Enables coverage tracking for all subsequent migrations -- Provides visibility into test quality -- Motivates testing during refactors - -**During Zod/Domain/Dexie work**: Coverage metrics help validate changes don't break tests - -**Actions**: - -1. Configure Vitest coverage in web + workers packages -2. Add GitHub Actions workflow with codecov action -3. Set coverage thresholds (70% lines, 65% branches) -4. Add codecov badge to README - -**Outcome**: Coverage visible on all PRs, trend data starts accruing - ---- - -### Phase 2: Zod OpenAPI Hono (Week 1-2, 15-20 hours) - -**Why Second?** - -- Refactors API structure before domain consolidation -- Consolidation is simpler with structured routes -- Improves type safety across the board -- Easier to test with Codecov in place - -**Dependency**: None (Codecov is optional but helpful) - -**Blocks**: None (but makes Single Domain easier) - -**Actions**: - -1. Install `@hono/zod-openapi` in workers package -2. Create schemas for all endpoints (auth, projects, checklists, etc.) -3. Migrate routes incrementally (auth → projects → checklists → reconciliation → pdf) -4. Update error handling hook for consistency -5. Test each route group -6. Generate OpenAPI docs at `/doc` -7. Remove manual `api-docs.yaml` and `openapi.json` - -**Effort Breakdown**: - -- Setup: 1-2 hours -- Auth routes: 2-3 hours -- CRUD routes: 4-6 hours -- Sync/Reconciliation routes: 4-6 hours -- PDF/Utility routes: 2-3 hours -- Testing & validation: 3-4 hours - -**Outcome**: Type-safe, documented API; routes ready for consolidation - ---- - -### Phase 3: Single Domain (Week 2-3, 5-7 hours) - -**Why Third?** - -- Zod OpenAPI routes are clean, well-structured -- Moving structured routes is simpler than raw Hono -- Builds on improved type safety -- Simplified structure easier to test - -**Dependency**: Ideally Zod OpenAPI Hono (but not hard requirement) - -**Actions**: - -1. Move `packages/workers/src` routes to `packages/landing/api/` (1-2 hours) -2. Update landing `wrangler.jsonc` with Durable Objects config -3. Consolidate routing logic in landing worker (1-2 hours) -4. Update `VITE_API_URL` to `/api` (30 min) -5. Remove CORS middleware, simplify auth cookies (1 hour) -6. Consolidate CI/CD workflows (1-2 hours) -7. Test all endpoints, auth flow (1-2 hours) - -**Outcome**: Single deployment, simpler architecture, better security - ---- - -### Phase 4: Dexie + y-dexie (Week 3+, 3-5 days) - -**Why Last?** - -- Frontend storage, independent of API architecture -- Benefits from simpler API calls with `/api` (single domain) -- Can be parallelized with other work after Phase 3 -- Largest effort, good to tackle when infrastructure is stable - -**Dependency**: Single Domain makes `/api` calls simpler, but not required - -**Actions**: - -1. Install `dexie` and `y-dexie` (30 min) -2. Create unified database schema for projects, checklists, pdfs, ops (2 hours) -3. Migrate `useProject` from y-indexeddb to y-dexie (3-4 hours) -4. Create operation queue using unified database (2-3 hours) -5. Migrate PDF cache to unified database (2-3 hours) -6. Data migration script for existing users (2-3 hours) -7. Testing & validation (2-3 hours) -8. Remove y-indexeddb dependency (30 min) - -**Outcome**: Unified IndexedDB storage, better offline support, reduced database fragmentation - ---- - -## Effort & Timeline Comparison - -### Recommended Sequence (Option A) - -| Week | Phase | Duration | Cumulative | -| ------------ | ---------------- | -------------------- | ------------- | -| **Week 1** | Codecov | 1.5 hrs | 1.5 hrs | -| **Week 1-2** | Zod OpenAPI Hono | 15-20 hrs | 16.5-21.5 hrs | -| **Week 2-3** | Single Domain | 5-7 hrs | 21.5-28.5 hrs | -| **Week 3+** | Dexie + y-dexie | 3-5 days (24-40 hrs) | 45.5-68.5 hrs | - -**Total**: ~25-35 hours of development + code review (spread over 3 weeks) - -### Parallelization Opportunities - -**Can run in parallel**: - -- Codecov + any other phase (just setup in parallel) -- Zod OpenAPI + Dexie planning (read-only research) -- Single Domain + unrelated bug fixes -- Dexie implementation + other features - -**Cannot run in parallel**: - -- Zod OpenAPI + Single Domain (both touch routing) -- Single Domain + API structure changes (merge worker) - ---- - -## Risk Assessment - -### Per-Migration Risks - -| Migration | Risk | Mitigation | Recommendation | -| ----------------- | ------ | -------------------------------------- | ------------------------- | -| **Codecov** | Low | Zero runtime impact | ✅ Safe, do first | -| **Zod OpenAPI** | Medium | Incremental migration, test per route | ✅ Safe, do second | -| **Single Domain** | Medium | Careful routing order (API before SPA) | ✅ Safe if done after Zod | -| **Dexie** | Medium | Thorough testing of offline/sync | ✅ Safe, last | - -### Combined Risk - -**Overall Risk: Low** - -Each migration: - -- Has gradual implementation paths -- Includes testing checkpoints -- Can be rolled back independently -- Doesn't break existing functionality during transition - -**Recommendation**: Execute all three in recommended order - ---- - -## Value & Impact Analysis - -### Business Impact - -| Migration | Developer Productivity | Code Quality | User Experience | Security | -| -------------------- | ---------------------- | ------------ | --------------- | -------- | -| **Codecov** | +Low | +High | None | None | -| **Zod OpenAPI Hono** | +High | +High | +Medium | +Medium | -| **Single Domain** | +Medium | +Medium | +Low | +High | -| **Dexie** | +Low | +Medium | +High | None | - -### Feature Impact - -| Feature | Before | After | Impact | -| ------------------------ | ------------------------- | ------------------------- | ------ | -| **API Documentation** | Manual YAML | Auto-generated OpenAPI | Huge | -| **Type Safety** | Partial (Zod only) | Complete (Zod → Response) | High | -| **Offline Support** | Works, fragmented DB | Unified storage | Medium | -| **Auth Security** | SameSite=Lax, CORS | SameSite=Strict, no CORS | High | -| **Developer Experience** | Multiple wrangler configs | Single config | Medium | -| **Test Visibility** | Unknown | Tracked coverage | Medium | - -### Total Value - -**High**: Improves architecture, security, documentation, and DX significantly - ---- - -## Execution Plan - -### Pre-Migration Checklist - -- [ ] Code review of all three audit documents -- [ ] Team alignment on migration order -- [ ] Create GitHub issues for each phase -- [ ] Assign owners/reviewers -- [ ] Set up Codecov account (free tier) - -### Phase 1: Codecov - -**Owner**: Any team member -**Duration**: 1.5 hours -**PR Requirements**: None (additive) -**Checklist**: - -- [ ] Add coverage config to Vitest -- [ ] Create GitHub Actions workflow -- [ ] Test coverage generation locally -- [ ] Verify codecov action works on PR -- [ ] Add badge to README -- [ ] Document in testing guide - -### Phase 2: Zod OpenAPI Hono - -**Owner**: Backend specialist -**Duration**: 15-20 hours -**PR Strategy**: Per-route-group PRs (auth, projects, checklists, etc.) -**Checklist**: - -- [ ] PR 1: Setup + auth routes -- [ ] PR 2: CRUD routes (projects, users, etc.) -- [ ] PR 3: Sync routes (documents, reconciliation) -- [ ] PR 4: Utility routes (PDF, avatars, etc.) -- [ ] PR 5: Remove manual OpenAPI files -- [ ] Coverage: Should be 100% (validation errors in tests) - -### Phase 3: Single Domain - -**Owner**: Devops/Full-stack -**Duration**: 5-7 hours -**PR Strategy**: Monolithic (single PR with checklist) -**Checklist**: - -- [ ] PR: Move routes, consolidate worker, update CI/CD -- [ ] Test: All endpoints, auth, SPA routing -- [ ] Coverage: No regressions -- [ ] DNS: Update records - -### Phase 4: Dexie + y-dexie - -**Owner**: Frontend specialist -**Duration**: 3-5 days -**PR Strategy**: Per-component PRs (unified db, useProject, op queue, pdf cache) -**Checklist**: - -- [ ] PR 1: Unified database schema -- [ ] PR 2: Migrate useProject to y-dexie -- [ ] PR 3: Operation queue -- [ ] PR 4: PDF cache migration -- [ ] PR 5: Data migration script -- [ ] Coverage: +5-10% (offline scenarios) - ---- - -## Decision Matrix - -### Should We Do All Three? - -| Question | Answer | Score | -| -------------------------------- | ----------------------- | ------- | -| Do they improve the codebase? | Yes (all three) | +20 | -| Do they have acceptable risk? | Yes (low) | +15 | -| Do we have bandwidth? | Yes (25-35 hrs) | +15 | -| Can we sequence safely? | Yes (clear order) | +15 | -| Do they align with architecture? | Yes (all complementary) | +15 | -| **Total Score** | **+80** | **YES** | - -### Confidence Level - -- **Codecov**: Very High (essential, no risk) -- **Zod OpenAPI Hono**: High (improves API, well-defined scope) -- **Single Domain**: High (simplifies, reduces surface area) -- **Dexie**: High (improves offline, lower priority) - -**Recommendation: Execute all four migrations in recommended sequence** - ---- - -## Alternative: Minimum Viable Path - -If bandwidth is limited, prioritize: - -1. **Codecov** (1.5 hours) - Essential visibility -2. **Zod OpenAPI Hono** (15-20 hours) - Highest developer benefit -3. **Skip Single Domain** (defer to later) -4. **Skip Dexie** (defer to later) - -This achieves 70% of the benefit in ~40% of the effort. - ---- - -## Contingency Plans - -### If Zod OpenAPI Hono causes issues: - -- Rollback to plain Hono (git revert) -- Keep y-indexeddb (works fine) -- Skip Single Domain (no impact) - -### If Single Domain causes issues: - -- Rollback to separate deployments -- Workers package stays deployed at api subdomain -- Revert routing changes (git revert) - -### If Dexie causes issues: - -- Rollback to y-indexeddb -- Use operation queue without Dexie -- Use PDF cache without Dexie (y-indexeddb alone) - -**No migration requires keeping broken code; all can rollback cleanly.** - ---- - -## Summary & Recommendation - -| Aspect | Decision | -| ------------------------ | ------------------------------ | -| **Execute all three?** | ✅ Yes | -| **Recommended order?** | Codecov → Zod → Domain → Dexie | -| **Total effort?** | 25-35 hours over 2-3 weeks | -| **Risk level?** | Low | -| **Value?** | High | -| **Start date?** | Immediate (Week 1) | -| **Expected completion?** | Week 3-4 | - -### Final Recommendation - -**Proceed with all three migrations in the recommended sequence.** Each builds on the previous work, improving architecture incrementally. The total effort is reasonable for the value delivered, and risk is manageable with proper testing and rollback plans. - -Start with Codecov this week, Zod OpenAPI Hono next week, Single Domain consolidation the week after, and Dexie + y-dexie the following week. diff --git a/packages/docs/audits/single-domain-consolidation-2026-01.md b/packages/docs/audits/single-domain-consolidation-2026-01.md deleted file mode 100644 index 337060cd7..000000000 --- a/packages/docs/audits/single-domain-consolidation-2026-01.md +++ /dev/null @@ -1,422 +0,0 @@ ---- -title: Single Domain Consolidation Evaluation -date: 2026-01-07 -author: Team ---- - -## Summary - -This audit evaluates consolidating the frontend and backend API under a single domain (`corates.org`) instead of using a subdomain for the API (`api.corates.org`). - -**Recommendation: Migrate to single domain** - -**Confidence: High** - -Using a single domain simplifies architecture, improves security, reduces CORS complexity, and enables better cookie handling for authentication. - -## Current Architecture - -### Current Deployment - -**Landing/Web Package** (`packages/landing/`) - -- Deployed to `corates.org` and `www.corates.org` -- Contains frontend (SolidJS app) served by landing worker -- Wrangler config: - ```jsonc - { - "name": "corates", - "routes": [ - { "pattern": "corates.org/*", "zone_name": "corates.org" }, - { "pattern": "www.corates.org/*", "zone_name": "corates.org" }, - ], - "vars": { - "VITE_API_URL": "https://api.corates.org", - }, - } - ``` - -**Workers Package** (`packages/workers/`) - -- Deployed separately as `corates-workers` -- Routes API calls (auth, projects, checklists, etc.) -- Currently expected to be at `https://api.corates.org` - -### Current Routing Issues - -1. **Separate Deployments**: Two distinct Cloudflare Workers need separate configuration -2. **CORS Required**: Frontend at `corates.org` calling `api.corates.org` requires CORS middleware -3. **Cookie Scope**: Auth cookies must include `domain=.corates.org` to work across subdomains -4. **Environment Complexity**: Two wrangler configs, two CI/CD deployments, two DNS records -5. **CSRF Protection**: Requires trusted origin whitelist (current mitigation works, but single domain is simpler) - -## Single Domain Architecture - -### Proposed Setup - -**Single Worker** combining landing + API on `corates.org`: - -``` -corates.org/ - / → SPA frontend (index.html) - /app.js → Static asset - /api/* → API endpoints (/api/auth, /api/projects, etc.) - /health → Health check - /doc → OpenAPI docs -``` - -**Benefits**: - -```jsonc -{ - "name": "corates", - "routes": [ - { "pattern": "corates.org/*", "zone_name": "corates.org" }, - { "pattern": "www.corates.org/*", "zone_name": "corates.org" }, - ], - "vars": { - "VITE_API_URL": "/api", // Relative URL, same domain! - }, -} -``` - -### Implementation Approach - -#### Option A: Merge Workers (Recommended) - -Consolidate `packages/workers/src/index.js` into the landing worker: - -```javascript -// packages/landing/worker.js -import { Hono } from 'hono'; -import apiApp from './api/index.js'; // Hono app with all routes - -const app = new Hono(); - -// API routes first (more specific) -app.route('/api', apiApp); - -// Fallback to SPA shell for all other routes -app.all('*', async c => { - const asset = await c.env.ASSETS.fetch(c.req.raw); - - if (asset.status !== 404) { - return asset; - } - - // 404 or HTML → serve app.html (SPA shell) - const appHtml = await c.env.ASSETS.fetch(new URL('/app.html', c.req.url)); - - if (appHtml.status === 404) { - return asset; - } - - return new Response(appHtml.body, { - status: 200, - headers: new Headers(appHtml.headers), - }); -}); - -export default app; -export { UserSession, ProjectDoc, EmailQueue }; // Durable Objects -``` - -**Effort**: 2-4 hours - -- Move API routes from workers package to landing worker -- Consolidate Durable Objects exports -- Update middleware imports -- Test routing - -#### Option B: Reverse Proxy (Quick Alternative) - -Keep workers as separate deployment, use reverse proxy: - -```javascript -// packages/landing/worker.js -export default { - async fetch(request, env) { - // Route /api/* to workers subdomain - const url = new URL(request.url); - - if (url.pathname.startsWith('/api')) { - const apiUrl = new URL(url.pathname, 'https://corates-workers.example.com'); - apiUrl.search = url.search; - return fetch(apiUrl, request); - } - - // ... rest of SPA routing - }, -}; -``` - -**Effort**: 1-2 hours (quick test) -**Trade-off**: Still two deployments, but hides subdomain from frontend - -### Migration Path - -#### Phase 1: Add API Routes to Landing Worker (1-2 hours) - -1. Move `packages/workers/src` routes to `packages/landing/api/` -2. Import Durable Objects in landing worker -3. Copy middleware from workers package -4. Update `wrangler.jsonc` with durable objects config -5. Test API endpoints at `/api/health` - -#### Phase 2: Update Frontend Configuration (30 minutes) - -```javascript -// packages/web/.env.local -VITE_API_URL = /api # Changed from https:/ / api.corates.org; -``` - -Update any hardcoded API URLs in code: - -```javascript -// Before -const API_URL = 'https://api.corates.org'; -const response = await fetch(`${API_URL}/auth/me`); - -// After -const API_URL = '/api'; -const response = await fetch(`${API_URL}/auth/me`); -``` - -#### Phase 3: Remove CORS Middleware (1 hour) - -Since frontend and API are same domain, CORS is unnecessary: - -```javascript -// DELETE: packages/workers/src/middleware/cors.js - -// In API routes, remove: -app.use('*', async (c, next) => { - const corsMiddleware = createCorsMiddleware(c.env); - return corsMiddleware(c, next); -}); -``` - -CORS middleware can stay for external API consumers (if applicable). - -#### Phase 4: Simplify Auth Cookies (30 minutes) - -Cookies now auto-scope to domain: - -```javascript -// Before: Must specify domain and SameSite -response.headers.set('Set-Cookie', `auth=${token}; Domain=.corates.org; Path=/; SameSite=Lax; Secure; HttpOnly`); - -// After: Simpler (domain is implicit) -response.headers.set('Set-Cookie', `auth=${token}; Path=/; SameSite=Strict; Secure; HttpOnly`); -``` - -Can now use `SameSite=Strict` (more secure) since no cross-domain redirects. - -#### Phase 5: Update CI/CD (1-2 hours) - -**Before**: Deploy landing + workers separately - -```yaml -# .github/workflows/deploy-landing.yml -# .github/workflows/deploy-workers.yml (separate) -``` - -**After**: Single deployment - -```yaml -# .github/workflows/deploy.yml -jobs: - deploy-corates: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: pnpm install - - run: pnpm build - - run: pnpm deploy --projects=landing -``` - -#### Phase 6: Decommission Workers Deployment (30 minutes) - -1. Delete `packages/workers/wrangler.jsonc` -2. Archive workers package (or keep for reference) -3. Remove workers deployment from CI/CD -4. Update DNS: Remove `api` subdomain record - -### Total Migration Effort - -| Phase | Effort | Notes | -| ------------------------- | ------------- | -------------------------- | -| 1. Add routes to landing | 1-2 hours | Most time-consuming | -| 2. Update frontend config | 30 min | Simple env var changes | -| 3. Remove CORS | 1 hour | Clean up unnecessary code | -| 4. Simplify auth cookies | 30 min | Actually improves security | -| 5. Update CI/CD | 1-2 hours | Consolidate workflows | -| 6. Decommission workers | 30 min | Final cleanup | -| **Total** | **5-7 hours** | Can be done incrementally | - -## Benefits - -### 1. Simplified Architecture - -**Before**: - -- 2 wrangler configs -- 2 deployments (landing + workers) -- 2 DNS records (corates.org + api.corates.org) -- CORS middleware -- Subdomain management - -**After**: - -- 1 wrangler config -- 1 deployment -- 1 DNS record -- No CORS needed (internal) -- Simpler mental model - -### 2. Improved Security - -| Aspect | Before | After | -| --------------- | ------------------------------------ | ----------------------------- | -| Cookie SameSite | Lax (allows cross-origin) | Strict (only same-site) | -| CSRF Risk | Moderate (subdomain bypass possible) | Minimal (same origin) | -| Cookie Scope | Domain=.corates.org (broad) | Implicit to domain (narrower) | -| Attack Surface | Larger (subdomains) | Smaller (single origin) | - -### 3. Better Developer Experience - -- One codebase, one deployment -- Relative API URLs (`/api`) instead of absolute (`https://api.corates.org`) -- Easier local testing (no need to mock API_URL env var) -- Simpler wrangler config - -### 4. Reduced Operational Complexity - -- Single CI/CD pipeline -- No subdomain DNS issues -- Easier rollbacks (one deployment instead of two) -- Single worker log stream -- Single rate limiting/DDoS protection config - -### 5. Better Cookie Handling - -```javascript -// Before: Auth tokens available to subdomains (security risk) -Set-Cookie: auth=token; Domain=.corates.org; Path=/ - -// After: Auth tokens scoped to exact domain (secure) -Set-Cookie: auth=token; Path=/; SameSite=Strict -``` - -## Concerns & Mitigations - -| Concern | Impact | Mitigation | -| ----------------------------- | ------ | ------------------------------------------------- | -| Loss of subdomain separation | Low | Single domain is cleaner anyway | -| Route conflicts (/api vs SPA) | Low | API routes first, then SPA catch-all | -| Worker size limits | Low | Combined size still well under Cloudflare limits | -| CORS for external consumers | Medium | Keep CORS headers for `/api/*` (optional feature) | -| Rollback complexity | Low | Single deployment = easier rollback | - -## Testing Checklist - -- [ ] API routes respond at `/api/health` -- [ ] Frontend loads at `/` -- [ ] API calls work with relative URL `/api/auth/me` -- [ ] Auth cookies set with `SameSite=Strict` -- [ ] SPA routing works (404s → app.html) -- [ ] Static assets load (JS, CSS, images) -- [ ] Both `corates.org` and `www.corates.org` work -- [ ] OpenAPI docs at `/api/doc` -- [ ] Health check at `/api/health` - -## Decision: Migrate to Single Domain - -**Confidence: High** - -Rationale: - -- ✅ Significantly simpler architecture -- ✅ Better security (stricter SameSite, no CORS bypass risks) -- ✅ Easier to deploy and maintain -- ✅ Better developer experience -- ✅ Moderate effort (5-7 hours) -- ✅ Can be done incrementally (Phase 1 → 2 → 3, etc.) -- ⚠️ Requires careful routing order (API before SPA catch-all) -- ⚠️ Some local development setup changes (but simpler overall) - -## Implementation Checklist - -- [ ] Move `/packages/workers/src` routes to `/packages/landing/api/` -- [ ] Copy Durable Objects config from workers to landing wrangler -- [ ] Import Durable Objects in landing worker.js -- [ ] Copy middleware (auth, security headers, etc.) to landing -- [ ] Update landing worker.js routing (API → SPA fallback) -- [ ] Change `VITE_API_URL` from `https://api.corates.org` to `/api` -- [ ] Remove hardcoded API URLs in frontend code -- [ ] Remove CORS middleware (keep security headers) -- [ ] Update auth cookie logic (remove Domain, add SameSite=Strict) -- [ ] Consolidate CI/CD workflows -- [ ] Test all API endpoints -- [ ] Test SPA routing (404s, deep links) -- [ ] Test auth flow end-to-end -- [ ] Remove `api.corates.org` DNS record -- [ ] Archive or delete workers package - -## Related Considerations - -### External API Consumers (If Applicable) - -If other services call the API, keep CORS headers: - -```javascript -// In landing worker, keep CORS for /api routes if needed -app.use( - '/api/*', - cors({ - origin: 'https://trusted-domain.com', - credentials: true, - }), -); -``` - -### API Versioning - -Single domain simplifies API versioning: - -``` -/api/v1/projects (old version) -/api/v2/projects (new version) -``` - -Or continue with header-based versioning: - -```javascript -GET / api / projects; -Accept: application / vnd.corates.v2 + json; -``` - -## Effort Estimate - -**Total**: 5-7 hours spread over 1-2 days - -- Does not require extensive testing per phase -- Can be broken into smaller PRs -- Low risk of breaking existing functionality - -## Next Steps - -1. **Review** this evaluation with team -2. **Start Phase 1** (move routes, 1-2 hours) -3. **Test Phase 1** (API endpoints respond) -4. **Complete Phases 2-6** (incrementally) -5. **Remove old workers deployment** (final cleanup) - ---- - -## References - -- [Cloudflare Workers Routing](https://developers.cloudflare.com/workers/configuration/routing/) -- [HTTP Cookies - SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) -- [CORS Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) -- [Hono Routing](https://hono.dev/api/routing) diff --git a/packages/docs/audits/zod-openapi-hono-codecov-evaluation-2026-01.md b/packages/docs/audits/zod-openapi-hono-codecov-evaluation-2026-01.md deleted file mode 100644 index b0d950f54..000000000 --- a/packages/docs/audits/zod-openapi-hono-codecov-evaluation-2026-01.md +++ /dev/null @@ -1,458 +0,0 @@ ---- -title: Zod OpenAPI Hono and Codecov Evaluation Audit -date: 2026-01-07 -author: Team ---- - -## Summary - -This audit evaluates two tools for the CoRATES backend and testing infrastructure: - -1. **Zod OpenAPI Hono**: An extended Hono class with built-in OpenAPI spec generation and Zod validation -2. **Codecov**: Code coverage tracking and reporting service - -**Recommendation: Adopt both tools** - -- **Zod OpenAPI Hono**: High-value addition to improve API documentation, type safety, and reduce manual OpenAPI maintenance -- **Codecov**: Low-cost, high-value for ensuring test coverage doesn't regress - -## Zod OpenAPI Hono - -### Current State - -**Location**: `packages/workers/src/` (API routes) - -Currently: - -- Using plain Hono for route handling -- Using Zod for request validation (good) -- Maintaining OpenAPI spec manually in `openapi.json` and `api-docs.yaml` (error-prone) -- Route handlers don't auto-validate requests -- OpenAPI docs are often out of sync with actual implementation - -### What Zod OpenAPI Hono Provides - -1. **Single Source of Truth**: Define schemas with Zod, auto-generate OpenAPI spec -2. **Type-Safe Validation**: `c.req.valid('json')` guarantees validated data -3. **Auto-Generated OpenAPI Docs**: Available at `/doc` endpoint -4. **Middleware Support**: Per-route middleware configuration -5. **Error Handling Hooks**: Centralized validation error formatting -6. **RPC Mode**: Type-safe client generation from routes - -### Current Workers Package Structure - -``` -packages/workers/src/ - routes/ - auth.js # Better Auth integration - projects.js # Project CRUD - checklists.js # Checklist operations - reconciliation.js # Reconciliation endpoints - documents.js # Document sync endpoints - pdf.js # PDF upload/proxy - db/ - schema.js # Drizzle schema - operations.js # Database operations - utils/ - errors.js # Error definitions - validation.js # Shared Zod schemas -``` - -### Migration Strategy - -#### Phase 1: Setup (1-2 hours) - -```javascript -// workers/src/app.js -import { OpenAPIHono } from '@hono/zod-openapi'; -import { z } from '@hono/zod-openapi'; - -const app = new OpenAPIHono({ - defaultHook: (result, c) => { - if (!result.success) { - return c.json( - { - ok: false, - errors: result.error.flatten(), - }, - 422, - ); - } - }, -}); - -app.doc('/doc', { - openapi: '3.0.0', - info: { - version: '1.0.0', - title: 'CoRATES API', - }, -}); - -export default app; -``` - -#### Phase 2: Convert Routes (2-4 hours per route file) - -**Before** (current Hono): - -```javascript -app.post('/projects', async c => { - const body = await c.req.json(); - // Manual validation - if (!body.name) return c.json({ error: 'Missing name' }, 400); - - // Implementation... -}); -``` - -**After** (Zod OpenAPI Hono): - -```javascript -import { createRoute } from '@hono/zod-openapi'; - -const CreateProjectSchema = z.object({ - name: z.string().min(1).openapi({ example: 'My Project' }), - description: z.string().optional().openapi({ example: 'Project description' }), -}); - -const ProjectResponseSchema = z - .object({ - id: z.string().openapi({ example: 'proj_123' }), - name: z.string(), - createdAt: z.string().datetime(), - }) - .openapi('Project'); - -const route = createRoute({ - method: 'post', - path: '/projects', - request: { - body: { - content: { - 'application/json': { - schema: CreateProjectSchema, - }, - }, - }, - }, - responses: { - 200: { - content: { - 'application/json': { - schema: ProjectResponseSchema, - }, - }, - description: 'Project created', - }, - 422: { - content: { - 'application/json': { - schema: z.object({ - ok: z.boolean(), - errors: z.any(), - }), - }, - }, - description: 'Validation error', - }, - }, -}); - -app.openapi(route, async c => { - const { name, description } = c.req.valid('json'); - // Implementation - body is already validated -}); -``` - -#### Phase 3: Migrate Existing Routes - -Priority order: - -1. Auth routes (highest impact on consistency) -2. CRUD routes (projects, checklists) -3. Sync routes (documents) -4. Utility routes (PDF, etc.) - -#### Phase 4: Remove Manual OpenAPI Files - -- Delete `api-docs.yaml` (auto-generated now) -- Delete manual `openapi.json` maintenance -- CI/CD auto-generates docs from routes - -### Benefits - -| Benefit | Impact | Effort | -| ------------------------------------ | ------ | ------ | -| Auto-generated OpenAPI docs | High | Low | -| Type-safe validation | High | Medium | -| Single source of truth | High | Low | -| Reduced manual docs maintenance | Medium | Low | -| Better IDE autocomplete for requests | Medium | None | -| Unified error handling | Medium | Low | - -### Concerns & Mitigations - -| Concern | Mitigation | -| ---------------------------------- | ------------------------------------------------ | -| Learning curve for team | Documentation, pair programming | -| Breaking change to existing routes | Gradual migration, old routes stay working | -| Integration with Better Auth | Better Auth doesn't use Hono routes, can coexist | -| Validation error format changes | Customize with defaultHook | -| Middleware per-route configuration | Fully supported via `middleware` property | - -### Dependencies - -```json -{ - "hono": "^4.x", - "zod": "^3.x", - "@hono/zod-openapi": "^0.x" -} -``` - -**Bundle impact**: ~25KB gzipped (acceptable given benefits) - -### Testing Impact - -Zod OpenAPI Hono improves testability: - -```javascript -// vitest -import { hc } from 'hono/client'; -import { describe, it, expect } from 'vitest'; -import app from './app.js'; - -describe('POST /projects', () => { - it('creates a project', async () => { - const client = hc(app); - const response = await client.projects.$post({ - json: { name: 'Test Project' }, - }); - expect(response.status).toBe(200); - }); - - it('rejects missing name', async () => { - const client = hc(app); - const response = await client.projects.$post({ - json: { description: 'No name' }, - }); - expect(response.status).toBe(422); - }); -}); -``` - -### Effort Estimate - -- Setup: 1-2 hours -- Migrate 5 route files: 8-12 hours -- Testing & validation: 4-6 hours -- **Total**: ~15-20 hours (2-3 days) - -### Decision: Recommended - -**Confidence: High** - -Zod OpenAPI Hono: - -- ✅ Reduces manual OpenAPI maintenance (major pain point) -- ✅ Improves type safety (fewer bugs) -- ✅ Gradual migration possible (low risk) -- ✅ Better developer experience -- ✅ Actively maintained (Hono middleware org) -- ⚠️ Requires learning new API (mitigated by documentation) - ---- - -## Codecov - -### Current State - -**Location**: CI/CD configuration - -Currently: - -- Using Vitest for unit tests (good) -- Running tests in CI/CD (good) -- **Not tracking code coverage** (gap) -- No visibility into which code paths lack tests -- Risk of untested code being merged - -### What Codecov Provides - -1. **Coverage Tracking**: Automatically measure test coverage on each PR -2. **Coverage Reports**: Visual diffs showing coverage changes -3. **Coverage Badges**: Display coverage percentage in README -4. **Threshold Enforcement**: Fail CI if coverage drops below threshold -5. **Trend Analysis**: Track coverage over time -6. **Web Dashboard**: Browse coverage per file/function -7. **GitHub Integration**: Comments on PRs with coverage info - -### Codecov Setup - -#### Step 1: Install Action (free tier) - -Add to GitHub Actions workflow (`.github/workflows/test.yml`): - -```yaml -name: Tests - -on: [push, pull_request] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v2 - - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'pnpm' - - - run: pnpm install - - run: pnpm test:coverage # Generate coverage reports - - - uses: codecov/codecov-action@v3 - with: - files: ./coverage/coverage-final.json - flags: unittests - fail_ci_if_error: false -``` - -#### Step 2: Configure Vitest Coverage - -In `packages/web/vitest.config.js` and `packages/workers/vitest.config.js`: - -```javascript -export default defineConfig({ - test: { - coverage: { - provider: 'v8', - reporter: ['text', 'json', 'html', 'lcov'], - exclude: ['node_modules/', 'dist/', '**/*.test.js', '**/types.ts'], - }, - }, -}); -``` - -#### Step 3: Add Coverage Script - -In `package.json`: - -```json -{ - "scripts": { - "test": "vitest", - "test:coverage": "vitest run --coverage" - } -} -``` - -#### Step 4: Set Coverage Threshold (Optional) - -```javascript -export default defineConfig({ - test: { - coverage: { - lines: 70, - functions: 70, - branches: 65, - statements: 70, - }, - }, -}); -``` - -### Benefits - -| Benefit | Impact | Effort | -| -------------------------------- | ------ | ------ | -| Visibility into coverage | High | None | -| Catch untested code before merge | High | Low | -| Track coverage trends | Medium | None | -| Motivate test writing | Medium | None | -| GitHub PR integration | Medium | Low | - -### Concerns & Mitigations - -| Concern | Mitigation | -| ------------------------------------------ | --------------------------------------------------- | -| Coverage % doesn't guarantee quality | Set reasonable thresholds (70-80%), use code review | -| False sense of security from high coverage | Emphasize meaningful tests, not just % | -| CI slowdown from coverage generation | Codecov runs async, doesn't block | -| Need to maintain coverage | Start at current level, incrementally improve | - -### Costs - -- **Free tier**: Yes (perfect for open source/small teams) -- **Paid tier**: Starts at $10-20/month if more advanced features needed -- **For CoRATES**: Free tier is sufficient - -### Effort Estimate - -- Setup Vitest coverage: 30 minutes -- Configure GitHub Actions: 30 minutes -- Set thresholds: 15 minutes -- **Total**: ~1.5 hours (mostly one-time setup) - -### Decision: Recommended - -**Confidence: Very High** - -Codecov: - -- ✅ Minimal setup effort -- ✅ Free for all usage levels (CoRATES scenario) -- ✅ Improves test visibility -- ✅ Prevents coverage regressions -- ✅ Motivates test writing -- ✅ GitHub integration is excellent -- ⚠️ Only useful if tests are actively written (mitigated by team discipline) - ---- - -## Implementation Checklist - -### Zod OpenAPI Hono - -- [ ] Install `@hono/zod-openapi` in workers package -- [ ] Create `app.js` with OpenAPIHono setup and defaultHook -- [ ] Migrate auth routes to use createRoute + app.openapi -- [ ] Migrate project routes -- [ ] Migrate checklist routes -- [ ] Migrate reconciliation routes -- [ ] Migrate document sync routes -- [ ] Migrate PDF routes -- [ ] Test all routes with new validation -- [ ] Remove manual openapi.json and api-docs.yaml -- [ ] Update API documentation -- [ ] Configure /doc endpoint in wrangler config - -### Codecov - -- [ ] Add coverage reporter to Vitest config (web + workers) -- [ ] Add `test:coverage` script to root package.json -- [ ] Create GitHub Actions workflow or update existing -- [ ] Configure codecov action in workflow -- [ ] Set coverage thresholds in Vitest config -- [ ] Add codecov badge to README -- [ ] Verify coverage reports on first PR - ---- - -## Next Steps - -1. **Quick Win**: Implement Codecov (1.5 hours, immediate benefit) -2. **Medium Effort**: Migrate Zod OpenAPI Hono (15-20 hours, high value) -3. **Long-term**: Maintain >70% coverage as new code is added - ---- - -## References - -- [Zod OpenAPI Hono Docs](https://github.com/honojs/middleware/tree/main/packages/zod-openapi) -- [Zod Documentation](https://zod.dev) -- [Hono Documentation](https://hono.dev) -- [Codecov Documentation](https://docs.codecov.io) -- [Vitest Coverage](https://vitest.dev/guide/coverage.html) diff --git a/packages/docs/glossary.md b/packages/docs/glossary.md index 49c93dfdc..dff21e9b0 100644 --- a/packages/docs/glossary.md +++ b/packages/docs/glossary.md @@ -102,13 +102,17 @@ Cloudflare's distributed computing primitive providing: Browser-based persistent storage used for offline-first capabilities: -- **corates-query-cache** - TanStack Query cache (projects, orgs, subscriptions) -- **corates-auth-cache** - Better Auth session and avatar cache -- **corates-pdf-cache** - PDF file cache -- **corates-form-state** - Form auto-save state -- **y-indexeddb-{projectId}** - Per-project Yjs document persistence - -**Related:** [Offline/Local-First Audit](audits/offline-local-first-audit-2026-01.md) +- **corates** - Unified Dexie database containing: + - `projects` - Y.Doc persistence (via y-dexie) + - `pdfs` - PDF file cache with LRU eviction + - `avatars` - User avatar cache + - `formStates` - Form auto-save for OAuth redirects + - `queryCache` - TanStack Query persistence + - `localChecklists` - Offline practice checklists + - `localChecklistPdfs` - PDFs for local checklists + - `ops` - Operation queue for offline mutations (future) + +**Related:** [Offline/Local-First Audit](audits/offline-local-first-audit-2026-01.md), [db.js](../web/src/primitives/db.js) ### TanStack Query (React Query) diff --git a/packages/docs/plans/sse-real-time-sync.md b/packages/docs/plans/sse-real-time-sync.md deleted file mode 100644 index a3ef01fb9..000000000 --- a/packages/docs/plans/sse-real-time-sync.md +++ /dev/null @@ -1,337 +0,0 @@ -# SSE Real-Time Sync Plan - -## Overview - -Implement Server-Sent Events (SSE) for real-time state synchronization while maintaining local-first offline capabilities. The goal is to ensure users always see the most up-to-date information when online, while gracefully degrading to cached data when offline. - -## Current Pain Points - -1. **Subscription staleness** - After Stripe checkout, user may see old plan until manual refresh -2. **Webhook race conditions** - User returns from external flow before webhook processes -3. **Cross-tab inconsistency** - Changes in one tab don't reflect in others -4. **Cache invalidation complexity** - Multiple caching layers (TanStack Query, IndexedDB) cause sync issues - -## Architecture Principles - -### Local-First Requirements - -- Cached data available immediately on page load -- App remains functional when offline -- Subscription entitlements enforced from cached data -- Clear UI indication when using cached vs fresh data - -### Real-Time Requirements - -- Push updates for critical state changes (subscription, org membership) -- No polling overhead for idle users -- Automatic reconnection on network recovery -- Graceful degradation when SSE unavailable - -## Proposed Architecture - -**Reuse existing UserSession Durable Object** - Already has WebSocket management, internal notify endpoint, and pending notification queue for offline users. - -``` - +------------------+ - | Stripe/OAuth | - +--------+---------+ - | - v webhook -+-------------+ WebSocket +----------------+----------------+ -| Browser |<-----------| Workers API | UserSession | -| (SolidJS) |----------->| (Hono) | (existing DO) | -+-------------+ fetch +----------------+----------------+ - | | - v v - IndexedDB D1 Database - (offline cache) (source of truth) -``` - -### Existing UserSession Features (Already Implemented) - -- WebSocket connection management per user -- Internal `/notify` POST endpoint for pushing events -- Pending notification queue (stored when user offline, delivered on reconnect) -- Authentication via session cookies -- Broadcast to all connected clients for same user - -## Implementation Plan - -### Phase 1: Event Emission from Webhooks/Actions - -#### 1.1 Helper to Send Events to UserSession - -Create a utility to send events to a user's UserSession DO: - -```js -// packages/workers/src/lib/notify.js -export async function notifyUser(env, userId, event) { - const id = env.USER_SESSION.idFromName(userId); - const stub = env.USER_SESSION.get(id); - await stub.fetch( - new Request('https://internal/notify', { - method: 'POST', - body: JSON.stringify(event), - }), - ); -} -``` - -#### 1.2 Emit Events from Stripe Webhooks - -Update Better Auth Stripe plugin config to emit events: - -```js -// In auth/config.js stripe plugin config -onSubscriptionComplete: async ({ subscription }) => { - await notifyUser(env, subscription.referenceId, { - type: 'subscription:updated', - data: { tier: subscription.plan, status: subscription.status } - }); -}, -onSubscriptionUpdate: async ({ subscription }) => { - await notifyUser(env, subscription.referenceId, { - type: 'subscription:updated', - data: { tier: subscription.plan, status: subscription.status } - }); -}, -onSubscriptionCancel: async ({ subscription }) => { - await notifyUser(env, subscription.referenceId, { - type: 'subscription:canceled', - data: { tier: subscription.plan, cancelAt: subscription.cancelAt } - }); -} -``` - -#### 1.3 Emit Events from Org Actions - -Add event emission to org membership changes in API routes. - -| Event | Payload | Trigger | -| ----------------------- | ----------------------------- | -------------- | -| `subscription:updated` | `{ tier, status, periodEnd }` | Stripe webhook | -| `subscription:canceled` | `{ tier, cancelAt }` | Stripe webhook | -| `org:member-added` | `{ orgId, userId, role }` | API action | -| `org:member-removed` | `{ orgId, userId }` | API action | -| `org:role-changed` | `{ orgId, userId, role }` | API action | -| `project:shared` | `{ projectId, orgId }` | API action | -| `heartbeat` | `{ timestamp }` | Every 30s | - -### Phase 2: Frontend Integration - -#### 2.1 WebSocket Hook (or extend existing) - -Check if there's already a hook connecting to UserSession, otherwise create: - -```js -// packages/web/src/primitives/useNotifications.js -// Manages WebSocket connection to UserSession DO -// Handles reconnection with exponential backoff -// Dispatches events to appropriate handlers -``` - -#### 2.2 Query Invalidation on Events - -```js -// When event received, invalidate relevant queries -ws.addEventListener('message', event => { - const data = JSON.parse(event.data); - if (data.type === 'subscription:updated') { - queryClient.invalidateQueries({ queryKey: ['subscription'] }); - } -}); -``` - -#### 2.3 Optimistic + Confirmed Pattern - -```js -// 1. Show optimistic update immediately -// 2. SSE confirms when backend processes -// 3. If no confirmation within timeout, refetch -``` - -### Phase 3: Caching Strategy Overhaul - -#### 3.1 Data Classification - -| Data Type | Cache Strategy | SSE Updates | Offline Access | -| --------------- | ---------------------------- | ----------- | --------------- | -| Subscription | Short stale (30s), persist | Yes | Yes (read-only) | -| Org members | Medium stale (2min), persist | Yes | Yes | -| Projects list | Medium stale (2min), persist | No | Yes | -| Project content | Yjs (existing) | N/A | Yes (full sync) | -| User profile | Long stale (10min), persist | No | Yes | - -#### 3.2 Unified Cache Layer - -Replace fragmented caching with single TanStack Query setup: - -```js -// packages/web/src/lib/queryClient.js - -// Critical data: short stale, SSE-invalidated -const criticalQueryDefaults = { - staleTime: 1000 * 30, // 30 seconds - gcTime: 1000 * 60 * 60, // 1 hour (for offline) - refetchOnWindowFocus: true, - refetchOnReconnect: true, -}; - -// Standard data: longer stale -const standardQueryDefaults = { - staleTime: 1000 * 60 * 2, // 2 minutes - gcTime: 1000 * 60 * 60, // 1 hour -}; -``` - -#### 3.3 Remove Manual localStorage Caching - -The `useSubscription` manual localStorage cache should be removed (already done). Rely solely on TanStack Query + IndexedDB persister. - -### Phase 4: Offline Indicators - -#### 4.1 Connection Status - -```jsx -// Show when using cached data - - - -``` - -#### 4.2 Sync Status - -```jsx -// Show SSE connection state - - - -``` - -## Event Flow Examples - -### Subscription Upgrade Flow - -``` -1. User clicks "Upgrade to Pro" -2. Frontend calls POST /api/billing/checkout -3. User redirected to Stripe Checkout -4. User completes payment -5. Stripe sends webhook to /api/auth/stripe/webhook -6. Webhook handler: - a. Updates subscription in D1 - b. Sends event to EventHub DO -7. EventHub broadcasts "subscription:updated" via SSE -8. Frontend receives SSE event -9. Frontend invalidates subscription query -10. Fresh data fetched, UI updates to Pro -11. User redirected to /settings/billing?success=true -12. Page shows success toast with correct plan -``` - -### Offline to Online Transition - -``` -1. User opens app while offline -2. TanStack Query loads from IndexedDB persister -3. UI renders with cached subscription data -4. Network becomes available -5. SSE connection established -6. Queries marked stale are refetched -7. Any missed events replayed via Last-Event-ID -8. UI updates with fresh data -9. Offline indicator hidden -``` - -## Technical Considerations - -### Cloudflare Workers Constraints - -- **No long-lived connections in Workers** - Must use Durable Objects for SSE -- **Hibernation** - DO can hibernate, need to handle reconnection -- **Costs** - DO duration billing, but SSE is lightweight - -### SSE vs WebSocket - -| Feature | SSE | WebSocket | -| --------------- | ------------------ | ----------------------- | -| Direction | Server to client | Bidirectional | -| Reconnection | Built-in | Manual | -| Browser support | Universal | Universal | -| Complexity | Simple | More complex | -| Use case fit | Push notifications | Real-time collaboration | - -**Recommendation**: Use SSE for state sync (simpler, sufficient). Keep existing Yjs WebSocket for document collaboration. - -### Security - -- SSE endpoint requires valid session -- Events scoped to user's orgs only -- No sensitive data in events (just invalidation signals) -- Rate limiting on reconnection - -## Migration Path - -### Step 1: Infrastructure (Non-Breaking) - -- Add EventHub DO -- Add SSE endpoint -- Add useSSE hook (disabled by default) - -### Step 2: Subscription Sync - -- Enable SSE for subscription events -- Add webhook event emission -- Test end-to-end flow - -### Step 3: Org Events - -- Add org membership events -- Update relevant webhooks/API handlers - -### Step 4: Remove Old Caching - -- Remove manual localStorage caches -- Simplify useSubscription -- Update cache configuration - -## Files to Create/Modify - -### New Files - -- `packages/workers/src/lib/notify.js` - Helper to send events to UserSession DO -- `packages/web/src/primitives/useNotifications.js` - WebSocket hook (if not existing) -- `packages/web/src/components/common/SyncIndicator.jsx` - Connection status UI - -### Modified Files - -- `packages/workers/src/auth/config.js` - Add Stripe webhook event emission -- `packages/workers/src/routes/org/*.js` - Add org action event emission -- `packages/web/src/lib/queryClient.js` - Adjust cache settings -- `packages/web/src/primitives/useSubscription.js` - Integrate with notifications -- `packages/web/src/App.jsx` - Add notifications provider/connection - -## Success Metrics - -1. **Subscription updates visible within 2s of webhook** (vs current manual refresh) -2. **Zero reported "wrong plan displayed" issues** -3. **Offline functionality unchanged** -4. **Cross-tab consistency** within 1s - -## Open Questions - -1. Should we replay missed events on reconnection, or just invalidate all critical queries? -2. Do we need SSE for project-level events (collaborator added, etc.)? -3. Should heartbeat interval be configurable? - -## Timeline Estimate - -Since we're reusing existing UserSession DO infrastructure: - -- Phase 1 (Event Emission): 2-3 hours -- Phase 2 (Frontend Integration): 2-3 hours -- Phase 3 (Caching Overhaul): 2-3 hours -- Phase 4 (Offline Indicators): 1-2 hours -- Testing & Polish: 2-3 hours - -**Total: ~10-14 hours** (reduced from 15-20 by reusing UserSession) diff --git a/packages/docs/plans/zod-openapi-hono-migration.md b/packages/docs/plans/zod-openapi-hono-migration.md new file mode 100644 index 000000000..5bc4fc97e --- /dev/null +++ b/packages/docs/plans/zod-openapi-hono-migration.md @@ -0,0 +1,719 @@ +# Zod OpenAPI Hono Migration Plan + +## Overview + +This plan outlines the incremental migration from plain Hono with manual Zod validation to `@hono/zod-openapi`. The migration will be done route-by-route to ensure tests continue to pass and minimize risk. + +## Current State + +- **Framework**: Hono v4.11.3 with Zod v4.3.5 +- **Validation**: Centralized in `packages/workers/src/config/validation.js` using `validateRequest()` and `validateQueryParams()` middleware +- **OpenAPI**: Manually maintained via `scripts/generate-openapi.mjs` parsing route files +- **Testing**: Vitest with `@cloudflare/vitest-pool-workers`, 29+ test files +- **Route Files**: 16+ route files organized under `src/routes/` + +## Goals + +1. Auto-generate OpenAPI spec from route definitions (single source of truth) +2. Type-safe request/response validation using `c.req.valid()` +3. Maintain existing error format via `defaultHook` +4. Keep tests passing throughout migration +5. Gradual migration - old and new patterns can coexist + +## Migration Phases + +--- + +### Phase 1: Setup and Infrastructure + +**Estimated files changed**: 3-4 + +#### 1.1 Install Dependencies + +```bash +pnpm add @hono/zod-openapi --filter @corates/workers +``` + +Note: This package re-exports Zod with OpenAPI extensions. We'll need to update imports gradually. + +#### 1.2 Create OpenAPI App Factory + +Create `packages/workers/src/lib/openapi.js`: + +```javascript +import { OpenAPIHono } from '@hono/zod-openapi'; +import { createValidationError, createMultiFieldValidationError } from '@corates/shared'; + +/** + * Creates an OpenAPIHono app with standardized error handling + * that matches existing validation error format + */ +export function createOpenAPIApp() { + return new OpenAPIHono({ + defaultHook: (result, c) => { + if (!result.success) { + // Map to existing error format for backwards compatibility + const issues = result.error.issues; + + if (issues.length === 1) { + const issue = issues[0]; + const field = issue.path.join('.') || 'root'; + const error = createValidationError(field, mapZodErrorToValidationCode(issue), undefined, issue.code); + return c.json(error, error.statusCode); + } + + const validationErrors = issues.map(issue => ({ + field: issue.path.join('.') || 'root', + code: mapZodErrorToValidationCode(issue), + message: issue.message, + zodCode: issue.code, + })); + + const error = createMultiFieldValidationError(validationErrors); + return c.json(error, error.statusCode); + } + }, + }); +} + +// Re-use existing mapping logic +function mapZodErrorToValidationCode(issue) { + const kind = issue.code; + switch (kind) { + case 'too_small': + if (issue.type === 'string' && issue.minimum === 1) { + return 'VALIDATION_FIELD_REQUIRED'; + } + return 'VALIDATION_FIELD_TOO_SHORT'; + case 'too_big': + return 'VALIDATION_FIELD_TOO_LONG'; + case 'invalid_string': + return 'VALIDATION_FIELD_INVALID_FORMAT'; + case 'invalid_type': + return 'VALIDATION_FIELD_INVALID_FORMAT'; + default: + return 'VALIDATION_FAILED'; + } +} +``` + +#### 1.3 Create Shared Response Schemas + +Create `packages/workers/src/config/openapi-schemas.js`: + +```javascript +import { z } from '@hono/zod-openapi'; + +// Common error response schema +export const ErrorResponseSchema = z + .object({ + code: z.string().openapi({ example: 'VALIDATION_FIELD_REQUIRED' }), + message: z.string().openapi({ example: 'Field is required' }), + statusCode: z.number().openapi({ example: 400 }), + field: z.string().optional().openapi({ example: 'name' }), + details: z.any().optional(), + }) + .openapi('ErrorResponse'); + +// Success response for mutations +export const SuccessResponseSchema = z + .object({ + success: z.literal(true), + }) + .openapi('SuccessResponse'); + +// Pagination metadata +export const PaginationSchema = z + .object({ + cursor: z.string().optional(), + hasMore: z.boolean(), + total: z.number().optional(), + }) + .openapi('Pagination'); +``` + +#### 1.4 Update Documentation Endpoint + +Update `packages/workers/src/docs.js` to serve auto-generated OpenAPI spec: + +```javascript +// Add endpoint to serve generated OpenAPI JSON +app.doc('/api/openapi.json', { + openapi: '3.1.0', + info: { + title: 'CoRATES API', + version: '1.0.0', + description: 'API for CoRATES research collaboration platform', + }, + servers: [ + { url: 'https://api.corates.org', description: 'Production' }, + { url: 'http://localhost:8787', description: 'Development' }, + ], +}); +``` + +#### 1.5 Tests for This Phase + +- [ ] Verify `createOpenAPIApp()` returns valid Hono instance +- [ ] Verify error format matches existing `createValidationError` output +- [ ] Verify `/api/openapi.json` returns valid OpenAPI 3.1 spec + +--- + +### Phase 2: Pilot Migration - Contact Route + +**Target file**: `packages/workers/src/routes/contact.js` + +**Why this route?** + +- Simple, single endpoint (POST /api/contact) +- No auth middleware dependencies +- Has existing test coverage +- Low risk for pilot + +#### 2.1 Current Implementation + +```javascript +// Current pattern in contact.js +app.post('/', validateRequest(contactSchema), async c => { + const { email, message } = c.get('validatedBody'); + // ... +}); +``` + +#### 2.2 Migrated Implementation + +```javascript +import { createRoute, z } from '@hono/zod-openapi'; +import { createOpenAPIApp } from '@/lib/openapi.js'; +import { ErrorResponseSchema } from '@/config/openapi-schemas.js'; + +const contactRoutes = createOpenAPIApp(); + +// Define schemas with OpenAPI metadata +const ContactRequestSchema = z + .object({ + email: z.string().email().openapi({ + example: 'user@example.com', + description: 'Contact email address', + }), + name: z.string().min(1).max(100).openapi({ + example: 'John Doe', + description: 'Contact name', + }), + message: z.string().min(10).max(5000).openapi({ + example: 'I have a question about...', + description: 'Message content', + }), + }) + .openapi('ContactRequest'); + +const ContactResponseSchema = z + .object({ + success: z.literal(true), + messageId: z.string().optional(), + }) + .openapi('ContactResponse'); + +// Define route with full OpenAPI spec +const submitContactRoute = createRoute({ + method: 'post', + path: '/', + tags: ['Contact'], + summary: 'Submit contact form', + description: 'Submit a contact form message', + request: { + body: { + content: { + 'application/json': { + schema: ContactRequestSchema, + }, + }, + required: true, + }, + }, + responses: { + 200: { + content: { + 'application/json': { + schema: ContactResponseSchema, + }, + }, + description: 'Message sent successfully', + }, + 400: { + content: { + 'application/json': { + schema: ErrorResponseSchema, + }, + }, + description: 'Validation error', + }, + 429: { + content: { + 'application/json': { + schema: ErrorResponseSchema, + }, + }, + description: 'Rate limited', + }, + }, +}); + +// Register route with handler +contactRoutes.openapi(submitContactRoute, async c => { + // Body is validated and typed + const { email, name, message } = c.req.valid('json'); + + // Existing implementation... +}); + +export { contactRoutes }; +``` + +#### 2.3 Test Updates + +Update `packages/workers/src/routes/__tests__/contact.test.js`: + +- [ ] Verify 200 response on valid input (should work unchanged) +- [ ] Verify 400 response format matches existing error structure +- [ ] Add test for OpenAPI route metadata availability + +#### 2.4 Verification Checklist + +- [ ] `pnpm test --filter @corates/workers` passes +- [ ] Contact form works in development +- [ ] Error responses match existing format exactly +- [ ] OpenAPI spec includes new route definition + +--- + +### Phase 3: User Routes Migration + +**Target file**: `packages/workers/src/routes/users.js` + +**Endpoints**: + +- `GET /api/users/search` - Search users (query params) +- `GET /api/users/:id` - Get user by ID (path params) + +This phase tests query parameter and path parameter validation. + +#### 3.1 Schema Definitions + +```javascript +import { z } from '@hono/zod-openapi'; + +// Path parameters +const UserIdParamSchema = z.object({ + id: z + .string() + .min(1) + .openapi({ + param: { name: 'id', in: 'path' }, + example: 'user_abc123', + }), +}); + +// Query parameters +const UserSearchQuerySchema = z.object({ + q: z + .string() + .min(2) + .openapi({ + param: { name: 'q', in: 'query' }, + example: 'john', + description: 'Search query (min 2 chars)', + }), + projectId: z + .string() + .uuid() + .optional() + .openapi({ + param: { name: 'projectId', in: 'query' }, + description: 'Filter by project membership', + }), + limit: z + .string() + .optional() + .transform(v => Math.min(Math.max(1, parseInt(v || '10')), 20)) + .openapi({ + param: { name: 'limit', in: 'query' }, + example: '10', + }), +}); + +// Response schemas +const UserSchema = z + .object({ + id: z.string(), + name: z.string().nullable(), + email: z.string().email(), + displayName: z.string().nullable(), + image: z.string().nullable(), + }) + .openapi('User'); + +const UserSearchResponseSchema = z.array(UserSchema).openapi('UserSearchResponse'); +``` + +#### 3.2 Route Definitions + +```javascript +const searchUsersRoute = createRoute({ + method: 'get', + path: '/search', + tags: ['Users'], + summary: 'Search users', + security: [{ cookieAuth: [] }], + middleware: [requireAuth], + request: { + query: UserSearchQuerySchema, + }, + responses: { + 200: { + content: { 'application/json': { schema: UserSearchResponseSchema } }, + description: 'Search results', + }, + 401: { + content: { 'application/json': { schema: ErrorResponseSchema } }, + description: 'Unauthorized', + }, + }, +}); + +userRoutes.openapi(searchUsersRoute, async c => { + const { q, projectId, limit } = c.req.valid('query'); + // ...existing implementation +}); +``` + +#### 3.3 Tests to Update + +- [ ] `packages/workers/src/routes/__tests__/users.test.js` +- [ ] Verify query param validation (q too short) +- [ ] Verify auth middleware still works with new pattern + +--- + +### Phase 4: Project Routes Migration (Core CRUD) + +**Target files**: + +- `packages/workers/src/routes/orgs/projects.js` +- `packages/workers/src/routes/orgs/index.js` + +This is the most complex migration - tests project creation, update, delete with: + +- Path parameters (orgId, projectId) +- Body validation +- Multiple middleware (auth, org membership, entitlements, quotas) +- Response schemas + +#### 4.1 Schema Definitions + +```javascript +// Path parameters +const OrgProjectParamsSchema = z.object({ + orgId: z + .string() + .uuid() + .openapi({ + param: { name: 'orgId', in: 'path' }, + example: 'org_abc123', + }), + projectId: z + .string() + .uuid() + .optional() + .openapi({ + param: { name: 'projectId', in: 'path' }, + example: 'proj_xyz789', + }), +}); + +// Existing schemas enhanced with OpenAPI metadata +const CreateProjectSchema = z + .object({ + name: z + .string() + .min(1) + .max(255) + .transform(v => v.trim()) + .openapi({ + example: 'My Research Project', + description: 'Project name (1-255 chars)', + }), + description: z + .string() + .max(2000) + .optional() + .transform(v => v?.trim() || null) + .openapi({ + example: 'A systematic review of...', + description: 'Optional project description', + }), + }) + .openapi('CreateProjectRequest'); + +const ProjectSchema = z + .object({ + id: z.string().uuid(), + name: z.string(), + description: z.string().nullable(), + orgId: z.string().uuid(), + role: z.enum(['owner', 'member']), + createdAt: z.string().datetime(), + updatedAt: z.string().datetime(), + createdBy: z.string(), + }) + .openapi('Project'); +``` + +#### 4.2 Middleware Integration + +The key challenge is integrating existing middleware with `createRoute`: + +```javascript +const createProjectRoute = createRoute({ + method: 'post', + path: '/', + tags: ['Projects'], + summary: 'Create a new project', + security: [{ cookieAuth: [] }], + // Middleware chain defined here + middleware: [ + requireOrgMembership(), + requireOrgWriteAccess(), + requireEntitlement('project.create'), + requireQuota('projects.max', getProjectCount, 1), + ], + request: { + params: OrgProjectParamsSchema.pick({ orgId: true }), + body: { + content: { 'application/json': { schema: CreateProjectSchema } }, + required: true, + }, + }, + responses: { + 201: { + content: { 'application/json': { schema: ProjectSchema } }, + description: 'Project created', + }, + 400: { + /* validation error */ + }, + 401: { + /* unauthorized */ + }, + 403: { + /* forbidden - not org member or no write access */ + }, + 429: { + /* quota exceeded */ + }, + }, +}); +``` + +#### 4.3 Tests to Update + +- [ ] `packages/workers/src/routes/__tests__/projects.test.js` (847 lines) +- [ ] Verify all CRUD operations work +- [ ] Verify middleware chain execution order +- [ ] Verify error responses match existing format + +--- + +### Phase 5: Member Routes Migration + +**Target file**: `packages/workers/src/routes/orgs/members.js` + +Endpoints: + +- `GET /api/orgs/:orgId/projects/:projectId/members` - List members +- `POST /api/orgs/:orgId/projects/:projectId/members` - Add member +- `PUT /api/orgs/:orgId/projects/:projectId/members/:userId` - Update role +- `DELETE /api/orgs/:orgId/projects/:projectId/members/:userId` - Remove member + +--- + +### Phase 6: Invitation Routes Migration + +**Target file**: `packages/workers/src/routes/orgs/invitations.js` + +Endpoints: + +- `GET /api/orgs/:orgId/projects/:projectId/invitations` - List invitations +- `POST /api/orgs/:orgId/projects/:projectId/invitations` - Create invitation +- `DELETE /api/orgs/:orgId/projects/:projectId/invitations/:id` - Revoke invitation +- `POST /api/invitations/accept` - Accept invitation (public) + +--- + +### Phase 7: Billing Routes Migration + +**Target file**: `packages/workers/src/routes/billing/index.js` and sub-routes + +Complex routes with Stripe integration: + +- Subscription management +- Checkout sessions +- Portal sessions +- Webhooks (special handling - raw body needed) + +**Note**: Webhook routes may need to remain as plain Hono routes due to raw body requirements. + +--- + +### Phase 8: Admin Routes Migration + +**Target file**: `packages/workers/src/routes/admin/index.js` + +Admin-only routes with strict access control: + +- User management +- Storage management +- Impersonation + +--- + +### Phase 9: Remaining Routes + +- `packages/workers/src/routes/email.js` +- `packages/workers/src/routes/avatars.js` +- `packages/workers/src/routes/google-drive.js` +- `packages/workers/src/routes/account-merge.js` +- `packages/workers/src/routes/database.js` +- `packages/workers/src/routes/orgs/pdfs.js` + +--- + +### Phase 10: Main App Integration + +**Target file**: `packages/workers/src/index.js` + +1. Convert main app to `OpenAPIHono` +2. Mount all migrated routes +3. Configure OpenAPI documentation endpoint +4. Remove legacy OpenAPI generation script + +```javascript +import { OpenAPIHono } from '@hono/zod-openapi'; + +const app = new OpenAPIHono(); + +// ... mount routes ... + +// OpenAPI JSON endpoint +app.doc('/api/openapi.json', { + openapi: '3.1.0', + info: { + title: 'CoRATES API', + version: '1.0.0', + }, + servers: [{ url: 'https://api.corates.org', description: 'Production' }], +}); + +// Swagger UI (development only) +app.get('/docs', swaggerUI({ url: '/api/openapi.json' })); +``` + +--- + +### Phase 11: Cleanup + +1. Remove `packages/workers/scripts/generate-openapi.mjs` +2. Remove `packages/workers/api-docs.yaml` +3. Update `packages/workers/openapi.json` to be auto-generated +4. Remove old `validateRequest` / `validateQueryParams` middleware (or deprecate) +5. Update imports across all files to use `@hono/zod-openapi` z + +--- + +## Testing Strategy + +### Per-Phase Testing + +After each phase: + +1. Run full test suite: `pnpm test --filter @corates/workers` +2. Run affected tests in watch mode during development +3. Manual verification of affected endpoints +4. Verify OpenAPI spec generation + +### Regression Testing Checklist + +- [ ] All existing tests pass without modification (where possible) +- [ ] Error response format unchanged +- [ ] Auth middleware works correctly +- [ ] Rate limiting works correctly +- [ ] CORS headers unchanged +- [ ] WebSocket endpoints unaffected + +### New Tests to Add + +- [ ] OpenAPI spec validation test +- [ ] Schema consistency tests (request/response match) +- [ ] Middleware chain order tests + +--- + +## Rollback Strategy + +Each phase can be rolled back independently: + +1. Routes use either old pattern or new pattern +2. Main app can mount both `Hono` and `OpenAPIHono` routes +3. Keep `validateRequest` middleware until full migration complete +4. Git tags at end of each phase for easy rollback + +--- + +## Timeline Estimate + +| Phase | Description | Complexity | Files | +| ----- | ---------------------- | ---------- | ----- | +| 1 | Setup & Infrastructure | Low | 3-4 | +| 2 | Contact Route (Pilot) | Low | 2 | +| 3 | User Routes | Medium | 2 | +| 4 | Project Routes | High | 3 | +| 5 | Member Routes | Medium | 2 | +| 6 | Invitation Routes | Medium | 2 | +| 7 | Billing Routes | High | 6 | +| 8 | Admin Routes | Medium | 3 | +| 9 | Remaining Routes | Medium | 6 | +| 10 | Main App Integration | Medium | 2 | +| 11 | Cleanup | Low | 4 | + +--- + +## Dependencies + +```json +{ + "@hono/zod-openapi": "^0.x" +} +``` + +**Zod v4 Compatibility**: Confirmed. `@hono/zod-openapi` has `"zod": "^4.0.0"` as a peer dependency, which matches our existing `zod: ^4.3.5`. No version conflicts or import changes needed. + +--- + +## Open Questions + +1. ~~**Zod version compatibility**~~: Confirmed - `@hono/zod-openapi` supports Zod v4. +2. **Webhook handling**: Stripe webhooks need raw body - can this work with OpenAPIHono? +3. **Auth route integration**: Better Auth routes are separate - do they need migration? +4. **TypeScript support**: Current codebase is JS - consider adding JSDoc types for better DX. + +--- + +## Success Criteria + +- [ ] All 29+ test files pass +- [ ] OpenAPI spec auto-generated and valid +- [ ] Error responses match existing format +- [ ] No breaking changes to API consumers +- [ ] Documentation available at `/docs` +- [ ] Manual OpenAPI files removed diff --git a/packages/mcp/src/docs/dexie/llms.txt b/packages/mcp/src/docs/dexie/llms.txt new file mode 100644 index 000000000..9d0d5ed0b --- /dev/null +++ b/packages/mcp/src/docs/dexie/llms.txt @@ -0,0 +1,10569 @@ +### Docs Home + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This section provides a comprehensive guide to getting started with Dexie.js, covering fundamental concepts, installation, and basic usage. Whether you're new to Dexie or IndexedDB, this area will help you understand the core functionalities and how to integrate Dexie into your projects. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section provides an introduction to Dexie.js, covering fundamental concepts and common use cases. It aims to guide users through the initial steps of understanding and implementing Dexie.js in their projects. Topics include getting started, understanding the basics of database operations, and exploring framework-specific integrations. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +The `Hello World` example in the Dexie.js documentation serves as a basic introduction to getting started with the library. It typically demonstrates the fundamental steps of initializing a Dexie database, defining a simple schema, and performing basic CRUD (Create, Read, Update, Delete) operations. This serves as a practical entry point for new users to quickly grasp the core concepts and syntax of Dexie.js. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +The Dexie.js documentation covers a wide range of topics, from understanding the core concepts and basic usage to advanced features and best practices. You can find information on setting up your database, defining schemas, performing CRUD operations, and implementing more complex queries. The documentation also includes specific guides for integrating Dexie.js with different JavaScript frameworks. + +-------------------------------- + +### Tutorial > Getting Started with Dexie.js + +Source: https://dexie.org/docs/cloud/consistency + +This is a beginner-friendly guide to getting started with Dexie.js. It covers the fundamental concepts, installation, and basic usage of the library, including setting up your database and performing simple read and write operations. The goal is to provide a quick and easy entry point for new users. + +-------------------------------- + +### Docs Home > Tutorial > Getting Started with Dexie.js > Hello World + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +This tutorial guides you through the initial steps of setting up and using Dexie.js, your JavaScript database wrapper. It covers the fundamental concepts, from defining your database schema to performing basic CRUD (Create, Read, Update, Delete) operations. The "Hello World" example is typically the first step in learning any new library, providing a simple, runnable demonstration of its core functionality. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/web-hooks + +The 'Docs Home' page serves as the entry point to the Dexie.js documentation. It typically provides an overview of the library, links to major sections, and guidance on how to navigate the documentation. + +-------------------------------- + +### Docs Home > Getting Started + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Getting started with Dexie.js involves understanding its core concepts and API. The documentation provides several tutorials and guides, including "Hello World" and "Understanding the basics," to help you quickly grasp how to use Dexie.js in your projects. Framework-specific guides for Angular, React, Svelte, and Vue are also available. + +-------------------------------- + +### Getting Started > Tutorial + +Source: https://dexie.org/docs/cloud/Member + +This section provides a step-by-step tutorial for getting started with Dexie.js. It covers the fundamental concepts and operations, enabling you to quickly set up and interact with your database. Whether you are new to IndexedDB or looking for a more streamlined approach, this tutorial will guide you through the essential steps. + +-------------------------------- + +### Understanding the basics + +Source: https://dexie.org/docs/DerivedWork + +This section covers the fundamental concepts of Dexie.js, including how to get started, understand the core API, and implement common database operations. It serves as a starting point for new users to grasp the essential features and architecture of Dexie. + +-------------------------------- + +### Tutorial > Understanding the basics + +Source: https://dexie.org/docs/cloud/consistency + +This section covers the fundamental concepts of Dexie.js, such as database definition, table schemas, transactions, and querying. Understanding these basics is essential for effectively using Dexie.js in your projects. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This is a general section dedicated to explaining the fundamental principles and architecture of Dexie.js. It delves into the core concepts that underpin the library, helping users build a solid understanding of how Dexie.js operates and how to best utilize its features. + +-------------------------------- + +### Tutorial > Understanding the basics + +Source: https://dexie.org/docs/DerivedWork + +Understanding the basics of Dexie.js is fundamental to using it effectively. This includes grasping concepts like database creation, schema definition, table operations (CRUD), and transactions. A solid understanding of these core principles will enable you to build more complex applications and troubleshoot issues efficiently. The documentation often covers these topics in detail, providing clear explanations and examples. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The 'Docs Home' page serves as the main entry point for the Dexie.js documentation. It typically provides an overview of the library, links to key sections, and introductory information for new users. + +-------------------------------- + +### Dexie.js API Documentation > Tutorial + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js offers a variety of tutorials to help users get started and master its features. These include guides for integrating with frameworks like Angular, React, Svelte, and Vue, as well as fundamental topics like 'Hello World', 'Understanding the basics', and 'Migrating existing DB to Dexie'. Advanced topics like 'Building Addons' and 'Design' are also covered. + +-------------------------------- + +### Understanding the basics + +Source: https://dexie.org/docs/cloud/Member + +This section covers the basics of using Dexie.js. It explains the core concepts, such as database creation, schema definition, and basic CRUD (Create, Read, Update, Delete) operations. Understanding these fundamentals is crucial for effectively utilizing Dexie.js in your projects. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/web-hooks + +The 'Understanding the basics' tutorial covers the fundamental concepts of Dexie.js, including database creation, schema definition, and basic CRUD operations. It aims to provide a solid foundation for developers new to the library, explaining how Dexie simplifies the IndexedDB API and introduces features like promise-based operations and automatic version management. + +-------------------------------- + +### Docs Home > Tutorial > Understanding the basics + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Understanding the basics of Dexie.js is crucial for effective usage. This section likely covers fundamental concepts such as database creation, schema definition, table access, and basic data manipulation (CRUD operations). It aims to provide a solid foundation for developers new to Dexie, explaining its core API and how it simplifies interactions with IndexedDB. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/Promise/Promise.on + +Dexie offers a comprehensive set of tutorials to help developers get started and master its features. These tutorials cover various aspects, from basic setup and "Hello World" examples to more advanced topics like integrating Dexie with popular frameworks such as Angular, React, Svelte, and Vue. There are also guides on migrating existing databases to Dexie and understanding fundamental concepts. + +-------------------------------- + +### Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/cloud/Member + +This is the main documentation portal for Dexie Cloud, offering comprehensive guides, tutorials, and API references. It serves as the central resource for learning how to implement and manage synchronized applications with Dexie Cloud. + +-------------------------------- + +### Docs Home > Understanding the basics + +Source: https://dexie.org/docs/cloud/UserLogin + +This section covers the fundamental concepts of Dexie.js, helping you understand its core features and how to get started with database operations. It includes explanations of database creation, table definitions, and basic CRUD (Create, Read, Update, Delete) operations. Familiarizing yourself with these basics will provide a solid foundation for using Dexie.js effectively. + +-------------------------------- + +### Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/cloud/limits + +The official Dexie Cloud documentation provides comprehensive guides, API references, and examples for developing cloud-connected applications. It covers everything from initial setup and configuration to advanced topics like custom authentication and deployment. + +-------------------------------- + +### Tutorial > Hello World + +Source: https://dexie.org/docs/inbound + +The 'Hello World' tutorial for Dexie.js serves as an introductory example to demonstrate the basic setup and usage of the library. It typically involves creating a simple database, defining a table, adding a record, and then retrieving it. This exercise helps new users quickly grasp the fundamental concepts and syntax of Dexie.js. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/Promise/Promise + +The `Dexie Cloud Quickstart` guide provides a rapid introduction to setting up and using Dexie Cloud. It typically covers the essential steps for initializing the cloud service, defining your schema, implementing basic authentication, and enabling data synchronization. This guide is ideal for developers looking to quickly get started with Dexie Cloud. + +-------------------------------- + +### Docs Home > Understanding the basics + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This section delves into the fundamental concepts of Dexie.js. You'll gain a solid understanding of how Dexie simplifies IndexedDB operations, including database schema definition, table management, and querying data. Mastering these basics is crucial for effective use of Dexie. + +-------------------------------- + +### Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The Dexie Cloud Docs offer comprehensive documentation for the Dexie Cloud add-on. They cover installation, configuration, core concepts, API references, and best practices, serving as the primary resource for developers using Dexie Cloud. + +-------------------------------- + +### Tutorial > Hello World + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The 'Hello World' tutorial for Dexie.js is designed to provide a quick and easy introduction to its basic usage. It typically involves setting up a simple database, defining a schema, and performing basic CRUD (Create, Read, Update, Delete) operations. This serves as a gentle introduction to the library's core concepts and API. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/cloud/UserLogin + +This is the main documentation hub for Dexie Cloud, providing comprehensive guides, tutorials, and API references. Whether you're getting started or looking for advanced features, this section serves as the primary resource for all things Dexie Cloud. + +-------------------------------- + +### Dexie Cloud Quickstart + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The Dexie Cloud Quickstart guide provides a fast-paced introduction to setting up and using Dexie Cloud. It covers the essential steps to get your first synchronized application up and running. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Understanding the basics of Dexie.js is crucial for effective use. This includes grasping concepts like databases, tables (object stores), indexes, transactions, and queries. The `Understanding the basics` section likely covers these fundamental elements, explaining how Dexie.js abstracts the underlying IndexedDB API to provide a more intuitive and developer-friendly experience for data management in web applications. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The Dexie Cloud Quickstart guide provides a streamlined introduction to setting up and using Dexie Cloud. It typically walks users through the essential steps to get a basic real-time application up and running quickly. + +-------------------------------- + +### Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/cloud/consistency + +The Dexie Cloud Quickstart guide provides a fast-paced introduction to setting up and using Dexie Cloud. It covers the essential steps to get a basic synchronization setup running in your application. + +-------------------------------- + +### Understanding the basics + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Understanding the basics of Dexie.js involves grasping its core concepts such as database instances, object stores, indexes, and transactions. Once these fundamentals are clear, you can effectively utilize Dexie's API for data manipulation and querying. + +-------------------------------- + +### Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The Dexie Cloud Quickstart guide provides a streamlined introduction to setting up and using Dexie Cloud. It walks you through the essential steps, from initial configuration to implementing basic synchronization and authentication, allowing you to get started quickly. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The Dexie Cloud Quickstart guide provides a fast-track introduction to setting up and using Dexie Cloud. It walks you through the essential steps to get a basic Dexie Cloud application running. + +-------------------------------- + +### Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The Dexie Cloud Quickstart guide provides a streamlined introduction to setting up and using Dexie Cloud. It walks you through the essential steps required to get a basic synchronized application running, covering schema definition, client configuration, and initial data synchronization. This is the ideal starting point for new users looking to quickly leverage Dexie Cloud's capabilities. + +-------------------------------- + +### Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/cloud/limits + +The Dexie Cloud Quickstart guide provides a streamlined introduction to setting up and using Dexie Cloud. It walks you through the essential steps, from creating a project and configuring your database to implementing basic synchronization and authentication, enabling you to get started quickly. + +-------------------------------- + +### Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/DerivedWork + +The Dexie Cloud Quickstart guide provides a streamlined introduction to setting up and using Dexie Cloud. It walks you through the essential steps to get a basic synchronization setup running, enabling you to quickly start building collaborative applications. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This tutorial section offers a step-by-step guide to learning and applying Dexie.js. It walks users through practical examples and scenarios, facilitating a hands-on learning experience to master the library's functionalities. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js offers a variety of tutorials to help you get started and master its features. These include guides for integrating Dexie with popular frameworks like Angular, React, Svelte, and Vue. You can also find tutorials on building addons, consuming Dexie as a module, and understanding the core concepts of the library. Specific tutorials cover getting started with Dexie Cloud, migrating existing databases, and a 'Hello World' example for a quick introduction. + +-------------------------------- + +### Tutorial > Understanding the basics + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Understanding the basics of Dexie.js involves grasping its core concepts, such as database schema definition, table operations, and transaction management. The library's promise-based API simplifies asynchronous operations, making it easier to work with IndexedDB. Familiarizing yourself with these fundamentals is key to effectively utilizing Dexie for your web application's data storage needs. + +-------------------------------- + +### Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/cloud/Member + +The Dexie Cloud Quickstart guide offers a fast-paced introduction to setting up and using Dexie Cloud. It walks you through the essential steps to get a basic synchronized application running, making it easy to get started quickly. + +-------------------------------- + +### Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +The Dexie Cloud Docs provide comprehensive documentation for the Dexie Cloud add-on. This includes guides, API references, and tutorials to help developers understand and utilize its features. Navigating the Dexie Cloud Docs is essential for anyone building applications that require real-time data synchronization, offline capabilities, and cloud-based data management. + +-------------------------------- + +### Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/cloud/consistency + +This is the main documentation hub for Dexie Cloud, covering all aspects of its features, setup, and usage. It's the best place to start when learning about Dexie Cloud. + +-------------------------------- + +### Docs Home > Tutorial + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +Dexie.js offers a comprehensive tutorial section covering various aspects of using the library, from getting started with basic examples like "Hello World" to more advanced topics. It includes guides for integrating Dexie.js with popular JavaScript frameworks such as Angular, React, Svelte, and Vue. The tutorials also touch upon migrating existing databases and understanding the core concepts. + +-------------------------------- + +### Docs Home > Tutorial > Design + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The Design section of the documentation delves into the architectural principles and design decisions behind Dexie.js. It may explain why certain choices were made, the benefits of the library's design, and how it aims to solve the challenges of working with IndexedDB. Understanding the design can provide deeper insights into the library's capabilities and limitations. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The Dexie Cloud Quickstart guide is designed to help you get up and running with Dexie Cloud as quickly as possible. It typically includes essential steps for setting up your database, configuring authentication, and implementing basic synchronization, providing a hands-on introduction to the service. + +-------------------------------- + +### Dexie.js Documentation > Tutorial + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +This section provides a comprehensive tutorial on getting started with Dexie.js. It covers various aspects, including setting up Dexie.js in different JavaScript frameworks like Angular, React, Svelte, and Vue. You'll find guides on understanding the basics, creating a 'Hello World' example, and migrating existing databases to Dexie.js. Best practices for building addons and consuming Dexie.js as a module are also discussed. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/cloud/UserLogin + +The Dexie Cloud Quickstart guide offers a fast-paced introduction to setting up and running a basic application with Dexie Cloud. It covers the essential steps from database setup to basic synchronization and user management, enabling you to get a functional application running quickly. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The Dexie Cloud Quickstart guide provides a fast-paced introduction to setting up and using Dexie Cloud. It focuses on the essential steps to get a basic application running with cloud synchronization and authentication, allowing you to quickly experience the core functionalities. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This page contains the official documentation for Dexie Cloud. It serves as a central resource for understanding Dexie Cloud's features, configuration, and best practices. + +-------------------------------- + +### Docs Home > Tutorial + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +This section covers various tutorials designed to help you get started and become proficient with Dexie.js. It includes guides for integrating Dexie.js with popular frontend frameworks like Angular, React, Svelte, and Vue. You'll also find tutorials on understanding the core concepts, building addons, consuming Dexie as a module, and migrating existing databases to Dexie. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie Cloud offers a Quickstart guide to help developers get up and running with the service rapidly. This guide typically covers the essential steps for setting up a project, configuring the cloud add-on, and performing basic synchronization, enabling users to quickly experiment with and integrate Dexie Cloud into their applications. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/index + +Dexie.js offers various tutorials to help you get started and utilize its features effectively. These include guides for integrating Dexie.js with popular frameworks like Angular, React, Svelte, and Vue. There are also tutorials on understanding the basics, building addons, consuming Dexie.js as a module, and migrating existing databases. A 'Hello World' example is available for a quick introduction, and specific guides for Dexie Cloud and TypeScript are also provided. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Dexie Cloud Quickstart provides a streamlined introduction to setting up and using Dexie Cloud for the first time. It guides you through the essential steps, from creating a project to enabling basic synchronization, enabling you to get a cloud-connected application running quickly. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This section provides links and navigation to the official documentation for Dexie Cloud. It serves as the central hub for all information related to Dexie Cloud features, usage, and best practices. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The 'Hello World' example serves as a basic introduction to Dexie.js, demonstrating a minimal setup and a simple database operation. It's designed for absolute beginners to quickly see Dexie.js in action and understand its core functionality. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/cloud/Member + +This guide provides an overview of TypeScript support in Dexie.js. It explains how to leverage TypeScript for improved type safety and developer productivity when working with Dexie.js databases. This includes setting up types for your database schema and using them throughout your application. + +-------------------------------- + +### Tutorial > Understanding the basics + +Source: https://dexie.org/docs/inbound + +Understanding the basics of Dexie.js is crucial for effective usage. This includes grasping concepts like database schema definition, table operations, transaction management, and querying with `where()`. Familiarizing yourself with how Dexie abstracts IndexedDB's complexities will enable you to build robust and performant data-driven applications. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/limits + +Dexie.js offers a structured approach to learning and using its features through tutorials. These tutorials cover various aspects, from getting started with basic concepts like "Hello World" and understanding the basics, to more advanced topics such as integrating Dexie with popular frameworks like Angular, React, and Svelte, or migrating existing databases. + +-------------------------------- + +### Tutorial > Getting Started with Dexie.js + +Source: https://dexie.org/docs/Collection/Collection + +Getting started with Dexie.js is straightforward. The process involves installing the library, creating a Dexie database instance, defining your database schema, and then opening the database. The documentation provides a step-by-step guide for beginners to quickly set up and start using Dexie.js. + +-------------------------------- + +### Docs Home > Tutorial + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This tutorial walks you through the process of creating a simple "Hello World" application using Dexie.js. It covers setting up a database, defining tables, and performing basic CRUD operations. This is an excellent starting point for understanding Dexie's core capabilities in a practical context. + +-------------------------------- + +### Tutorial > Design + +Source: https://dexie.org/docs/cloud/consistency + +This section delves into the design principles and architectural decisions behind Dexie.js. Understanding the design helps in appreciating its features and how it interacts with IndexedDB. It covers the core concepts that make Dexie.js a powerful tool for web development. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/Dexie/Dexie.on + +The Dexie Cloud Quickstart guide provides a streamlined path to getting started with Dexie Cloud. It covers the essential steps for setting up a project, configuring synchronization, and implementing basic features. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/Releasing-Dexie + +Getting started with Dexie.js is streamlined with various tutorials catering to different frameworks. Whether you're using Angular, React, Svelte, or Vue, there are dedicated guides to help you integrate Dexie.js into your project. The "Hello World" example provides a basic introduction, while tutorials on "Understanding the basics" and "Migrating existing DB to Dexie" offer deeper insights. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The Dexie Cloud API documentation details the various endpoints and methods available for interacting with the Dexie Cloud backend service. This includes APIs for authentication, data synchronization, user management, and more. + +-------------------------------- + +### Dexie.js Documentation > Typescript + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +Dexie.js offers robust support for TypeScript, enabling type safety and improved developer experience. This documentation covers the usage of TypeScript with Dexie.js, including how to define schemas and interact with your database in a type-safe manner. Although an older version of TypeScript documentation exists, the current documentation reflects the latest practices. + +-------------------------------- + +### Tutorial > Hello World + +Source: https://dexie.org/docs/DerivedWork + +Getting started with Dexie.js involves understanding its core concepts and setting up your database schema. The 'Hello World' tutorial is a great entry point, demonstrating how to create a simple database, define tables, and perform basic CRUD operations. Following this tutorial will provide a hands-on experience with Dexie.js and build a foundation for more complex applications. It typically involves creating a Dexie instance, defining your schema using `Version.stores()`, and then interacting with the tables. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +The 'Tutorial' section offers a comprehensive guide to getting started with Dexie.js, covering various aspects from basic setup to advanced usage. It includes a 'Hello World' example, guidance on integrating Dexie.js with popular frameworks like Angular, React, Svelte, and Vue, and tips for migrating existing databases. This section is ideal for developers new to Dexie.js or looking to deepen their understanding of its capabilities. + +-------------------------------- + +### Tutorial > Hello World + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +The 'Hello World' tutorial for Dexie.js typically demonstrates the basic steps of creating a database, defining its schema, and performing simple CRUD (Create, Read, Update, Delete) operations. This provides a foundational understanding of how to interact with Dexie, setting the stage for more complex functionalities. It's an essential first step for anyone new to the library. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Docs + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +This section likely contains comprehensive documentation for Dexie Cloud, covering its features, setup, and usage. It serves as the central resource for developers looking to implement cloud synchronization and related functionalities in their applications using Dexie.js. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/Member + +Dexie.js is a popular wrapper library for IndexedDB that simplifies database operations. It offers a more intuitive API, making it easier to work with the browser's built-in NoSQL database. This documentation provides a comprehensive guide to using Dexie.js, from basic setup to advanced features and integrations with various frontend frameworks. + +-------------------------------- + +### Inbound + +Source: https://dexie.org/docs/cloud/web-hooks + +The 'Inbound' section might refer to features or documentation related to data being imported into Dexie or received from external sources. This could include details on data ingestion processes or handling incoming data streams. + +-------------------------------- + +### Docs Home > Getting Started + +Source: https://dexie.org/docs/cloud/SyncState + +Getting started with Dexie.js is straightforward. You can install it via npm or yarn and then import it into your project. The documentation provides guides for setting up Dexie.js in various JavaScript frameworks like React, Vue, and Svelte, making integration seamless. + +-------------------------------- + +### Tutorial > Understanding the basics + +Source: https://dexie.org/docs/Promise/Promise + +Understanding the basics of Dexie.js involves grasping its core concepts: the `Dexie` instance representing your database, `Version` objects for managing schema changes, `Table` objects for data collections, and `Transaction` objects for atomic operations. Familiarity with these components will enable you to effectively structure and query your data. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This part of the documentation focuses on versioning and schema management in Dexie.js. It explains how to define and manage database schemas, including the use of `Version.stores()` for defining table structures and `Version.upgrade()` for handling database migrations between versions. + +-------------------------------- + +### Dexie.js API Documentation > Roadmap + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +The roadmap for Dexie.js outlines the planned features and improvements for future versions, specifically mentioning 'Road Map: Dexie 5.0'. This gives users insight into the future direction of the library and upcoming enhancements. + +-------------------------------- + +### Dexie.js Documentation > Roadmap + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +The roadmap for Dexie 5.0 outlines the planned features and improvements for the next major version. This includes enhancements to the core API, performance optimizations, and new functionalities aimed at further simplifying database management in web applications. + +-------------------------------- + +### Dexie.js API Documentation > Version + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +The `Version` object in Dexie.js represents a specific database schema version. It provides methods like `Version.stores()` for defining the schema for that version and `Version.upgrade()` for specifying the upgrade logic when migrating from a previous version to this one. This is fundamental for managing database schema evolution. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/cloud/consistency + +This document outlines best practices for using Dexie Cloud in your applications. It includes recommendations for schema design, data synchronization strategies, security, and performance optimization to ensure a robust and scalable solution. + +-------------------------------- + +### Tutorial > Hello World + +Source: https://dexie.org/docs/cloud/consistency + +The 'Hello World' example provides a minimal, working example of Dexie.js. It demonstrates the basic setup, including database definition and a simple operation, allowing you to see Dexie.js in action with the least amount of code. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreGetManyRequest + +Getting started with Dexie.js is straightforward. The library offers various integration guides for popular frameworks like React, Svelte, and Vue, enabling developers to quickly incorporate Dexie into their existing projects. These guides typically cover initial setup, database definition, and basic CRUD operations tailored to the framework's paradigm. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/inbound + +The Dexie Cloud Quickstart guide offers a streamlined path to implementing cloud features in your application. It covers the essential steps for setting up Dexie Cloud, defining your data schema, and enabling real-time synchronization and authentication, enabling you to get started quickly. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Getting started with Dexie.js is straightforward, especially when integrating it with popular JavaScript frameworks. Dexie provides dedicated tutorials for frameworks like Angular, React, Svelte, and Vue, guiding you through the setup and usage of Dexie within their respective ecosystems. These tutorials cover everything from basic setup to more advanced concepts, enabling you to leverage Dexie's capabilities effectively in your chosen framework. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/web-hooks + +Dexie.js provides several tutorials to help developers get started and master its features. These range from a basic 'Hello World' example to more advanced topics like integrating Dexie with popular frameworks (React, Angular, Vue, Svelte), consuming Dexie as a module, and understanding its core design principles. There are also guides on migrating existing databases to Dexie and best practices for effective usage. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/Promise/unhandledrejection-event + +Transactions are a fundamental concept in IndexedDB, ensuring data integrity by grouping operations. Dexie.js simplifies transaction management, allowing you to easily define and execute transactions. It provides clear events for transaction completion, abortion, and errors, making it easier to handle potential issues during data operations. + +-------------------------------- + +### Dexie.js API Documentation > Typescript + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js supports TypeScript for improved development experience and type safety. The documentation covers TypeScript integration, likely including type definitions and guidance on how to best utilize TypeScript with Dexie.js, distinguishing between older and current versions. + +-------------------------------- + +### Dexie-react-hooks + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The `useDocument()` hook from `dexie-react-hooks` provides a reactive way to fetch and subscribe to a single document (record) from your Dexie database within React components. It automatically updates the component when the document changes. + +-------------------------------- + +### Docs Home > Libs > dexie-react-hooks + +Source: https://dexie.org/docs/Dexie/Dexie.on + +The `useDocument()` hook from `dexie-react-hooks` provides a convenient way to get a single document from a Dexie.js database in React applications. It automatically subscribes to changes and updates the document when it changes. + +-------------------------------- + +### Dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `useDocument()` hook from `dexie-react-hooks` is designed to fetch and subscribe to a single document (or record) from your Dexie.js database. It automatically updates the component whenever the specified document changes, making it ideal for displaying and editing individual items. + +-------------------------------- + +### Dexie.js Documentation > Transaction + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +Transactions are fundamental to IndexedDB operations, ensuring data integrity. Dexie.js provides a `Transaction` object that allows you to manage these operations. You can abort a transaction using `Transaction.abort()`, and listen for completion or errors using `Transaction.on.complete` and `Transaction.on.error` respectively. `Transaction.table()` allows you to access a specific table within the transaction's scope. + +-------------------------------- + +### Docs Home > Getting Started + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +This section provides an introduction to getting started with Dexie.js, covering various frameworks and environments. Whether you are using React, Svelte, or Vue, you can find guidance on integrating Dexie.js into your project. The tutorials and examples aim to help you quickly set up and begin using Dexie.js for your data persistence needs. + +-------------------------------- + +### Understanding the basics > Understanding the flow > Second time + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +The database is simply opened and the promise resolves. + +-------------------------------- + +### Tutorial > Getting started with Dexie in Angular + +Source: https://dexie.org/docs/cloud/consistency + +This tutorial guides you through the process of integrating Dexie.js with Angular applications. It covers setting up Dexie, defining your database schema, and performing CRUD operations within your Angular components and services. By following this tutorial, you can leverage the power of IndexedDB with the structure and features of Angular. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie.js is designed with modern web development practices in mind, offering excellent integration with popular JavaScript frameworks. The documentation includes dedicated tutorials for getting started with Dexie.js in frameworks like Angular, React, Svelte, and Vue. These tutorials guide developers through setting up Dexie.js within the framework's ecosystem, managing database interactions, and leveraging Dexie.js features for efficient data handling in component-based architectures. + +-------------------------------- + +### Docs Home > Transaction + +Source: https://dexie.org/docs/Typescript-old + +Transactions are a fundamental concept in IndexedDB, ensuring data integrity by grouping operations that should either all succeed or all fail. Dexie.js provides a streamlined way to manage transactions, offering clear methods for aborting, completing, and handling errors within a transaction. Understanding transaction lifecycles is crucial for maintaining reliable data operations. + +-------------------------------- + +### Docs Home > Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section outlines the core concepts and entities within Dexie Cloud, such as `DBPermissionSet`, `DexieCloudOptions`, `Invite`, `Member`, `PersistedSyncState`, `Realm`, `Role`, `SyncState`, and `UserLogin`. Understanding these components is crucial for managing data access and synchronization in your Dexie Cloud application. + +-------------------------------- + +### Docs Home > Transaction + +Source: https://dexie.org/docs/cloud/Realm + +Transactions are a fundamental concept in IndexedDB, ensuring data consistency and atomicity. In Dexie.js, transactions are managed automatically for most operations, but you can also explicitly create and manage them for more control. Dexie.js provides events like `abort`, `complete`, and `error` that allow you to hook into the transaction lifecycle, enabling you to handle failures or confirm successful operations. + +-------------------------------- + +### Dexie.js API Documentation > Y.js + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js has integrations with Y.js, a framework for building collaborative offline-first applications. The documentation mentions `Y.js` and `y-dexie`, suggesting a seamless way to synchronize Dexie.js databases with Y.js data structures, enabling real-time collaboration. + +-------------------------------- + +### Dexie.js API Documentation > Transaction + +Source: https://dexie.org/docs/cloud/UserLogin + +Transactions are fundamental to IndexedDB operations, ensuring data integrity. Dexie.js simplifies transaction management. A transaction is an atomic unit of work. If any operation within a transaction fails, the entire transaction is rolled back, leaving the database in its original state. Dexie.js automatically manages transactions for most operations, but you can also explicitly create and manage them for more complex scenarios. + +-------------------------------- + +### Collection > Methods > and() + +Source: https://dexie.org/docs/Collection/Collection + +Add JS based criteria to collection. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/cloud/limits + +The roadmap for Dexie 5.0 outlines the planned features and improvements for the next major version of the library. It typically includes enhancements to the API, performance optimizations, and support for new web standards, guiding the future development of Dexie.js. + +-------------------------------- + +### Collection > Methods > first() + +Source: https://dexie.org/docs/Collection/Collection + +Get the first item in the collection. + +-------------------------------- + +### Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `useDocument()` hook from `dexie-react-hooks` provides a simple way to work with individual documents in your Dexie.js database within a React application. It automatically subscribes to changes in a specified document and returns the latest version, re-rendering your component whenever the document is updated. This hook is ideal for displaying and editing single records. + +-------------------------------- + +### Access Control Tables + +Source: https://dexie.org/docs/cloud/access-control + +Access Control tables need to be spelled exactly as in this sample and their primary keys needs to be spelled exactly the same. On top of that, you are free to index those properties you will need to query. The properties of objects in these tables are documented under each table below. We will walk through how to use these tables to share objects to others. + +-------------------------------- + +### Docs Home > Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `useDocument()` hook from `dexie-react-hooks` provides a convenient way to observe and interact with a single document (record) in your Dexie.js database within React components. It automatically subscribes to changes in the specified document and re-renders your component when the data updates, simplifying real-time data display. + +-------------------------------- + +### Dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +The `useDocument()` hook from `dexie-react-hooks` provides a convenient way to fetch and subscribe to a single document (or object) from your Dexie database within a React component. It automatically handles loading states and updates the component when the document changes, simplifying the process of displaying and editing individual records. + +-------------------------------- + +### Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `useDocument()` hook from `dexie-react-hooks` provides a convenient way to manage and react to changes in a single document (record) from your Dexie database within a React component. It automatically subscribes to changes and updates the component when the document is modified. + +-------------------------------- + +### Tutorial > ...ting Started with Dexie.js + +Source: https://dexie.org/docs/Promise/Promise + +Getting started with Dexie.js is straightforward, especially with the provided tutorials and examples. The core concept involves creating a `Dexie` instance, defining your database schema using `version().stores()`, and then interacting with your tables and data using the convenient API. The 'Hello World' example is a good starting point to understand the basic setup and operations. + +-------------------------------- + +### Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/cloud/consistency + +The `useDocument()` hook from `dexie-react-hooks` provides a convenient way to observe changes to a single document (or object) in your Dexie.js database within React components. It automatically updates the component when the specified document changes. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This document outlines the best practices for using Dexie Cloud effectively. It covers topics such as database schema design, security considerations, performance optimization, and managing data synchronization. Following these guidelines will help you build scalable and reliable applications. + +-------------------------------- + +### Dexie.js API Documentation > IndexedDB on Safari + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Specific issues related to IndexedDB on Safari are documented, including 'IndexedDB on Safari' and 'safari-issues'. This section likely details known limitations, bugs, or workarounds required when using Dexie.js with the Safari browser. + +-------------------------------- + +### Dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/DerivedWork + +The `useDocument()` hook from `dexie-react-hooks` is designed to fetch and subscribe to a single document (record) from a Dexie.js table. It automatically re-renders your component whenever the document changes, providing a reactive way to display and interact with individual data items. This hook simplifies the process of displaying and updating single records in React applications. + +-------------------------------- + +### Docs Home > Tutorial > Get started with Dexie Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Getting started with Dexie Cloud provides an introduction to Dexie's cloud synchronization service. This service allows you to synchronize your Dexie.js database across multiple devices and users seamlessly. The quickstart guide will likely walk you through the initial setup, including creating a Dexie Cloud project, configuring your database, and enabling synchronization. + +-------------------------------- + +### Dexie.js API > Transaction + +Source: https://dexie.org/docs/cloud/authentication + +A `Transaction` in Dexie.js is a fundamental concept for performing atomic operations on your database. It ensures that a set of operations either completes successfully or fails entirely, maintaining data integrity. You can abort a transaction explicitly using `abort()`, and you can monitor transaction lifecycle events through `on.abort`, `on.complete`, and `on.error`. The `table()` method allows you to access a specific table within the current transaction. + +-------------------------------- + +### Libs > dexie-react-hooks + +Source: https://dexie.org/docs/cloud/web-hooks + +The `useDocument()` hook from `dexie-react-hooks` is designed for fetching and managing a single document (record) from a Dexie table within a React component. It simplifies the process of displaying and updating individual data items reactively. + +-------------------------------- + +### Cloud > Dexie Cloud API + +Source: https://dexie.org/docs/cloud/Member + +This section provides a detailed overview of the Dexie Cloud API. It covers all the available methods, properties, and events related to managing your synchronized data, user authentication, and access control within the Dexie Cloud ecosystem. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/cloud/limits + +Transactions are a fundamental concept in IndexedDB, ensuring data integrity by grouping multiple operations into a single atomic unit. In Dexie.js, transactions provide a mechanism to perform read or write operations. You can abort a transaction if an error occurs, ensuring that no partial changes are committed. The transaction object also allows you to access tables within its scope and provides event handlers for completion, errors, and aborts. + +-------------------------------- + +### Tutorial > Getting Started with Dexie in React + +Source: https://dexie.org/docs/DerivedWork + +Dexie.js offers excellent integration with modern JavaScript frameworks. There are dedicated libraries and tutorials for getting started with Dexie in popular frameworks like React, Angular, Svelte, and Vue. These guides provide framework-specific examples and patterns for using Dexie effectively within your chosen environment, often leveraging reactive programming concepts for seamless data updates. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/cloud/Member + +Dexie.js supports TypeScript for enhanced type safety and developer productivity. The documentation covers how to set up and use Dexie with TypeScript, including defining database schemas, type inference for queries, and leveraging TypeScript's features for more robust data management. While there's an older 'Typescript (old)' section, the primary 'Typescript' documentation should be consulted for current best practices. + +-------------------------------- + +### Guide to the Source Code > Data Layer + +Source: https://dexie.org/docs/cloud/quickstart + +The Data Layer of the Dexie Cloud application is structured with key components. `db.ts` exports a singleton instance of `TodoDB`, which is a subclass of `Dexie` and handles database declarations and synchronization configurations. Data shapes are defined by `TodoItem` (a TypeScript interface) and `TodoList` (a class). The `TodoList` class encapsulates logic for operations like sharing and deleting, which involve transactions and aim to maintain consistency across offline use cases. The documentation emphasizes that while encapsulating logic in classes like `TodoList` is a matter of taste, it promotes correct model usage. If models are declared this way, they should be bound to their respective Dexie tables using `mapToClass()`. + +-------------------------------- + +### Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `useDocument()` hook from `dexie-react-hooks` provides a convenient way to subscribe to changes in a single document (row) from your Dexie.js database within a React component. It automatically updates the component when the document changes, simplifying real-time data display. + +-------------------------------- + +### Safari Issues + +Source: https://dexie.org/docs/cloud/consistency + +This document addresses specific issues and workarounds related to using Dexie.js with Safari browsers. It covers known limitations or quirks of Safari's IndexedDB implementation and how to handle them effectively. + +-------------------------------- + +### Collection > Methods > keys() + +Source: https://dexie.org/docs/Collection/Collection + +Retrieve an array containing all keys of the collection (index or primary key depending on where() clause). + +-------------------------------- + +### Collection > Methods > each() + +Source: https://dexie.org/docs/Collection/Collection + +Execute query and call a function for each item. + +-------------------------------- + +### Docs Home > Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The `useDocument()` hook from `dexie-react-hooks` is designed to easily fetch and subscribe to a single document (or object) from your Dexie database within a React component. It automatically handles setting up listeners for changes, ensuring that your component re-renders whenever the specified document is updated, providing real-time data display. + +-------------------------------- + +### Collection > Methods > eachKey() + +Source: https://dexie.org/docs/Collection/Collection + +Execute query on the index or primary key being used and call a function for each key. + +-------------------------------- + +### Y.js > y-dexie + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +Y.js is a framework for real-time collaborative applications that enables multiple users to edit documents simultaneously. `y-dexie` is a connector that integrates Y.js with Dexie.js, allowing you to leverage Dexie.js as a persistent storage backend for your collaborative Y.js documents. + +-------------------------------- + +### Guide to the Source Code > Visual Components + +Source: https://dexie.org/docs/cloud/quickstart + +The Visual Components section highlights several key parts of the UI and their associated Dexie Cloud features. `TodoLists` demonstrates the use of `useLiveQuery()`. `TodoListView` showcases the `usePermissions()` hook for managing user access and enabling inline editing without complex state management. `TodoItemView` provides another example of `usePermissions()` and inline editing. `SyncStatusIcon` illustrates `useObservable()` for reflecting the offline state to the user, and `Invites` shows how to present in-app invitations. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/cloud/custom-emails + +Transactions are a fundamental concept in Dexie.js for ensuring data integrity. A `Transaction` object represents a unit of work that is either fully committed or completely aborted. Dexie.js manages transactions automatically for most operations, but you can also explicitly create them using `db.transaction()`. This allows for grouping multiple operations that should succeed or fail together. The `Transaction` object provides methods like `abort()` and event hooks such as `on.abort`, `on.complete`, and `on.error` for fine-grained control and monitoring. + +-------------------------------- + +### Getting Started with Dexie.js + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +Getting started with Dexie.js is straightforward. The library is easy to install and integrate into your project. The documentation provides a "Hello World" example that demonstrates the basic setup and a simple database operation, helping you get up and running quickly. You can also find tutorials tailored for popular frameworks like Angular, React, Svelte, and Vue. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This guide provides recommendations and strategies for building secure, scalable, and efficient applications using Dexie Cloud. It covers topics like data modeling, synchronization patterns, and performance optimization. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This document outlines the future development plans and roadmap for Dexie.js, specifically focusing on version 5.0. It provides insights into upcoming features, architectural changes, and the overall direction of the project, allowing developers to anticipate future advancements. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud API + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section provides an overview of the Dexie Cloud API, detailing the various methods and properties available for interacting with Dexie Cloud services. It covers functionalities like authentication, synchronization, and data management. + +-------------------------------- + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +-------------------------------- + +### Docs Home > Y.js + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +Y.js is a framework for building collaborative applications. The `y-dexie` library acts as a persistence layer for Y.js, allowing you to store and synchronize Yjs documents using Dexie.js and IndexedDB. + +-------------------------------- + +### Docs Home > Getting Started > Started with Dexie in React + +Source: https://dexie.org/docs/cloud/UserLogin + +This tutorial guides you through the process of setting up and using Dexie.js in your React projects. It covers common patterns and best practices for integrating Dexie.js with React components, including managing database connections and performing reactive queries. Learn how to leverage Dexie.js to enhance your React application's data management capabilities. + +-------------------------------- + +### Docs Home > Cloud > Sharding and Scalability + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This guide discusses strategies for sharding and scaling your Dexie Cloud application. It covers techniques for handling large amounts of data and high traffic loads efficiently. + +-------------------------------- + +### Docs Home > Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The `useDocument()` hook from `dexie-react-hooks` is designed for fetching and subscribing to a single document (or item) from a Dexie.js table. It automatically updates the component when the data changes in the database. + +-------------------------------- + +### Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The Dexie Cloud Quickstart provides a streamlined path to getting your first Dexie Cloud application up and running. It typically involves minimal setup steps and guides you through the essential features, allowing you to quickly experience the core functionality of Dexie Cloud. + +-------------------------------- + +### Y.js + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +Y.js is a framework for building collaborative real-time applications. `y-dexie` is an integration library that connects Y.js with Dexie.js, allowing you to leverage Dexie.js as a persistence layer for Y.js documents. This combination enables efficient offline support and synchronization of collaborative data. By using `y-dexie`, your application can store Yjs documents locally using Dexie's IndexedDB capabilities and automatically synchronize changes across different clients and devices. + +-------------------------------- + +### Dexie.js API Documentation > Table Schema + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js allows defining table schemas to structure your database. The `Table Schema` describes the structure of each table, including its primary key and any defined indexes. This schema is crucial for database integrity and efficient querying. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/cloud/UserLogin + +This document outlines best practices for developing and deploying applications using Dexie.js Cloud. It covers recommendations for schema design, data synchronization, security, performance optimization, and error handling. Following these guidelines will help you build scalable, reliable, and maintainable applications. + +-------------------------------- + +### Dexie.js Documentation > safari-issues + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +This section addresses specific issues related to Safari browsers and their interaction with Dexie.js. It provides insights into potential workarounds and best practices to ensure smooth operation across different environments. + +-------------------------------- + +### Docs Home > Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This documentation describes the `db.cloud.configure()` method, which is used to initialize and configure the Dexie Cloud addon. It allows you to set up various options for authentication, synchronization, and other cloud-related features. + +-------------------------------- + +### Collection > Methods > desc() + +Source: https://dexie.org/docs/Collection/Collection + +Sort in descending order. + +-------------------------------- + +### Cloud > Sharding and Scalability + +Source: https://dexie.org/docs/cloud/consistency + +This guide discusses strategies for sharding and scaling your Dexie Cloud application. It covers techniques for handling large amounts of data and high traffic loads to ensure performance and reliability. + +-------------------------------- + +### Docs Home > Building Addons + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Building addons for Dexie.js allows you to extend its functionality. The documentation provides information on how to create and integrate custom addons, enabling you to tailor Dexie.js to your specific project needs. + +-------------------------------- + +### WhereClause > WhereClause.equals() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.equals()` method is used to filter records where a specific property matches a given value exactly. This is a fundamental method for equality checks in your queries. + +-------------------------------- + +### Dexie.js Documentation + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +IndexedDB, the underlying technology for Dexie.js, has certain limitations. Understanding these limitations is crucial for designing efficient and robust applications. These limitations can affect performance, data storage, and concurrency. + +-------------------------------- + +### safari-issues + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Safari issues often require specific workarounds or considerations when using IndexedDB, which Dexie.js abstracts. The documentation may contain sections detailing known issues in Safari and how to address them when using Dexie. + +-------------------------------- + +### Dexie.js Documentation > Libs > dexie-react-hooks + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +The `dexie-react-hooks` library provides a set of React hooks for seamlessly integrating Dexie.js into your React applications. `useLiveQuery()` enables you to subscribe to real-time changes in your database and automatically re-render your components when data changes. `useDocument()` fetches a single document, while `useObservable()` allows you to observe query results. `usePermissions()` helps manage access control within your application. + +-------------------------------- + +### Tutorial > Getting started with Dexie in Svelte + +Source: https://dexie.org/docs/cloud/consistency + +This tutorial guides you through using Dexie.js with Svelte applications. It explains how to integrate Dexie.js into your Svelte projects, manage database operations, and leverage reactivity for seamless data handling. + +-------------------------------- + +### Docs Home > Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `useDocument()` hook from `dexie-react-hooks` allows you to easily fetch and subscribe to a single document (record) from your Dexie.js database within a React component. It handles loading states, errors, and real-time updates automatically. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/DerivedWork + +The `Table` object represents a table in your database schema. It provides methods for interacting with the data within that table, such as adding, retrieving, updating, and deleting records. You can access a table through the `db.` property where `` is the name you defined for your table in the schema. For example, `db.friends` would give you access to the `friends` table. + +-------------------------------- + +### Cloud > Dexie Cloud API Limits + +Source: https://dexie.org/docs/cloud/Member + +This document outlines the API limits imposed by Dexie Cloud. Understanding these limits is essential for designing scalable applications and avoiding potential performance bottlenecks or service disruptions. + +-------------------------------- + +### Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/cloud/limits + +The `useDocument()` hook from `dexie-react-hooks` provides a convenient way to fetch and subscribe to a single document (record) from your Dexie database within React components. It automatically handles updates, ensuring your UI stays in sync with the database. + +-------------------------------- + +### Docs Home > safari-issues + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Safari issues specific to IndexedDB or Dexie.js are documented to help users troubleshoot and work around known problems in the Safari browser. This section provides solutions and workarounds for platform-specific quirks. + +-------------------------------- + +### Docs Home > Tutorial > Started with Dexie in Svelte + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +This tutorial guides you through integrating Dexie.js with Svelte applications. It will likely cover how to set up Dexie, define your database schema, and perform data operations within Svelte components. The focus will be on leveraging Dexie's capabilities for efficient client-side data management in a Svelte context, potentially including reactivity patterns. + +-------------------------------- + +### Dexie Cloud > Introduction + +Source: https://dexie.org/docs/cloud/consistency + +It can be a challenge to keep consistency in synced offline-first applications. You are working with data that is being copied across multiple devices - some of which might be offline while you perform an operation. Or you might be offline while you perform an operation that needs to be performed in a way that keeps the data 100% consistent at any point in time - and will be kept consistent after next sync - no matter what operations that have taken place by other users. +Dexie Cloud uses a combination of concepts that the application programmer can utilize in order to keep the data totally consistent at all times. + +-------------------------------- + +### Table > Table Schema + +Source: https://dexie.org/docs/DerivedWork + +The `Table.schema` property provides information about the schema of the table, including its primary key and indexes. This can be useful for understanding the structure of your data and for debugging purposes. For instance, you can inspect `db.friends.schema` to see the defined structure of the `friends` table. + +-------------------------------- + +### Collection > Methods > count() + +Source: https://dexie.org/docs/Collection/Collection + +Get the number of items in the collection. + +-------------------------------- + +### Collection > Collection.first() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.first()` method retrieves the first record from the collection that matches the query criteria. If no records are found, it returns `undefined`. + +-------------------------------- + +### See Sync in Action + +Source: https://dexie.org/docs/cloud/quickstart + +This section provides a step-by-step guide to experience the synchronization capabilities of Dexie Cloud in action. It involves installing a Progressive Web App (PWA) on a phone, logging in with different users on a computer and phone, and then performing actions like creating lists and sharing them. The guide encourages testing offline scenarios by turning off Wi-Fi and observing how changes sync once the connection is restored, including complex cases where one client modifies data while another creates new data simultaneously. + +-------------------------------- + +### Dexie.js API Documentation > Promise + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js provides enhanced Promise functionalities, including `Promise.PSD` (which might relate to Promise-specific data or context), `Promise.catch()`, `Promise.finally()`, and methods for handling errors like `Promise.on.error` and `Promise.onuncatched`. It also addresses the `unhandledrejection-event`. + +-------------------------------- + +### Tutorial > Best Practices + +Source: https://dexie.org/docs/cloud/consistency + +This section covers best practices for using Dexie.js effectively. It includes advice on database design, query optimization, transaction management, and error handling. Following these best practices can lead to more performant, reliable, and maintainable applications. + +-------------------------------- + +### Dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/cloud/Member + +The `useDocument()` hook from `dexie-react-hooks` provides a convenient way to fetch and subscribe to changes for a single document (or item) in your Dexie.js database within a React component. It automatically handles updates, ensuring your UI stays synchronized with the database. + +-------------------------------- + +### Version > Version.stores() + +Source: https://dexie.org/docs/Version/Version + +Specifies tables to be added, altered or deleted in this version. Each key in the schemaDefinition argument represents a table name and each value represents the primary key followed by the list of indexed properties. **NOTE: Unlike SQL, you don't need to specify all properties but only the one you wish to index.** Never index properties containing images, movies or large (huge) strings. Store them in IndexedDB, yes! but just don't index them! A rule of thumb: Are you going to put your property in a `where('...')` clause? If yes, index it, if not, don't. Large indexes will affect database performance and in extreme cases make it unstable. + +-------------------------------- + +### Tutorial > Typescript + +Source: https://dexie.org/docs/cloud/consistency + +This section provides information on using TypeScript with Dexie.js. It covers type definitions, best practices for integrating TypeScript into your Dexie.js projects, and how to leverage static typing for improved code quality and maintainability. + +-------------------------------- + +### Dexie.js API Documentation > IndexSpec + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js supports various types of indexes to optimize data retrieval. This includes `IndexSpec` for defining index properties, `Indexable Type` for specifying the data type of indexed values, and `MultiEntry Index` which is useful for indexing arrays within a database field. + +-------------------------------- + +### More to come + +Source: https://dexie.org/docs/roadmap/dexie5 + +Dexie aims for backward compatibility between major versions. While the plan is to maintain this compatibility as much as possible, there might be future breaking changes. These changes will be documented here. This document is continuously updated. To stay informed about updates, consider subscribing to our GitHub discussions or blog. + +-------------------------------- + +### Samples + +Source: https://dexie.org/docs/cloud/web-hooks + +The 'Samples' section provides practical examples and demonstrations of how to use Dexie.js in various scenarios. These code samples can be invaluable for understanding how to implement specific features or integrate Dexie into different types of applications. + +-------------------------------- + +### Cloud > Sharding and Scalability + +Source: https://dexie.org/docs/cloud/Member + +This guide discusses strategies for sharding and scaling your Dexie Cloud applications. It explores techniques for managing large datasets and high traffic loads by distributing data and processing across multiple servers or instances. + +-------------------------------- + +### Docs Home > Tutorial > Hello World + +Source: https://dexie.org/docs/Typescript-old + +Getting started with Dexie.js is designed to be simple and intuitive. The 'Hello World' example typically involves creating a Dexie database instance, defining its schema using `Version.stores()`, and then performing basic CRUD (Create, Read, Update, Delete) operations. This provides a foundational understanding of how to interact with Dexie. + +-------------------------------- + +### Cloud > db.cloud.userInteraction + +Source: https://dexie.org/docs/cloud/Member + +The `db.cloud.userInteraction` property indicates whether user interaction is currently required for cloud operations, such as resolving conflicts or authenticating. This can be used to provide feedback to the user or guide them through necessary steps. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud on Own Servers + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This guide explains how to deploy and manage Dexie Cloud on your own server infrastructure. It covers the necessary steps for self-hosting the Dexie Cloud backend services. + +-------------------------------- + +### Typescript (old) + +Source: https://dexie.org/docs/cloud/web-hooks + +Dexie.js has evolved over time, and there are separate documentation sections for different versions, including older TypeScript definitions. Understanding the differences between versions, particularly in API and features, is important for maintaining existing projects or choosing the right version for new development. + +-------------------------------- + +### Samples > Full-text search + +Source: https://dexie.org/docs/Table/Table + +This example demonstrates a simple implementation of full-text search within Dexie.js. It relies on multi-valued indexes and Dexie hooks to achieve this functionality. The core idea is to process the 'message' field and extract individual words, which are then stored in a multi-valued index named 'messageWords'. This allows for efficient searching of emails based on the presence of specific words within the message content. The provided code illustrates how to set up the database schema with the necessary indexes, define the hooks for populating the 'messageWords' index during item creation and updates, and then perform searches using the `startsWithIgnoreCase` method on the indexed words. + +-------------------------------- + +### Collection > Methods > or() + +Source: https://dexie.org/docs/Collection/Collection + +Logical OR operation. + +-------------------------------- + +### Y.js + +Source: https://dexie.org/docs/cloud/limits + +Y.js is a library for real-time collaborative editing. When combined with `y-dexie`, it enables real-time synchronization of Yjs documents using Dexie.js as the underlying storage mechanism. This allows for robust offline support and seamless collaboration in applications. + +-------------------------------- + +### Docs Home > Cloud > Sharding and Scalability + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Sharding and Scalability in Dexie Cloud address strategies for handling large datasets and high traffic. The documentation discusses techniques for partitioning data and optimizing performance as your application grows. + +-------------------------------- + +### Cloud > Dexie Cloud Quickstart + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Getting started with Dexie Cloud involves setting up the add-on and configuring your database for synchronization. The Quickstart guide provides a streamlined approach to integrate Dexie Cloud into your project, covering essential steps like authentication and initial data setup. Following the Quickstart will enable you to quickly experience the benefits of real-time data synchronization and offline capabilities. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud API + +Source: https://dexie.org/docs/cloud/UserLogin + +This section provides an overview of the Dexie Cloud API, detailing the various endpoints and functionalities available for interacting with your Dexie.js Cloud backend. It covers aspects like data management, user authentication, and synchronization controls, enabling programmatic access to cloud features. + +-------------------------------- + +### Collection > Methods > eachPrimaryKey() + +Source: https://dexie.org/docs/Collection/Collection + +Execute query on the index and call a function for each primary key that corresponds to the index. + +-------------------------------- + +### Y.js + +Source: https://dexie.org/docs/Releasing-Dexie + +Y.js is a library for collaborative editing, and `y-dexie` is an adapter that integrates Y.js with Dexie.js. This integration allows you to use Dexie.js as a persistence layer for Y.js, enabling real-time collaborative features in your applications by leveraging IndexedDB for local storage of collaborative documents. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section details advanced querying capabilities using the `WhereClause` API. It covers methods such as `anyOf()`, `anyOfIgnoreCase()`, `noneOf()`, and `inAnyRange()`, which are useful for querying data that matches any value within a specified set or range, or none of the values. + +-------------------------------- + +### Dexie.js API Documentation > Libs > dexie-react-hooks + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie-react-hooks is a library that provides React hooks for interacting with Dexie.js databases. It simplifies the process of managing database state within React applications. Key hooks include `useDocument()` for fetching single documents, `useLiveQuery()` for real-time data observation, and `useObservable()` for observable data streams. `usePermissions()` is also available for managing access control. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +Getting started with Dexie.js is straightforward, especially for developers working with popular JavaScript frameworks. Dexie offers dedicated integration guides and examples for React, Svelte, and Vue, enabling seamless adoption within these ecosystems. Whether you are building a new application or integrating Dexie into an existing one, the framework-specific tutorials provide a clear path to leverage Dexie's capabilities effectively. This focus on framework compatibility ensures that developers can quickly become productive and leverage the power of IndexedDB through Dexie's enhanced API. + +-------------------------------- + +### Docs Home > Typescript + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Dexie.js supports TypeScript, providing type definitions for its API. This enables static type checking, improving code quality and developer productivity. The documentation includes information on using Dexie.js with TypeScript. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/Releasing-Dexie + +Dexie.js offers comprehensive support for TypeScript, enabling better type safety and developer experience. This includes type definitions for the Dexie API and guidance on how to leverage TypeScript with your database schema. While there might be older TypeScript documentation, the current version aims to provide the most up-to-date and robust typing support. + +-------------------------------- + +### Version > Version.stores() + +Source: https://dexie.org/docs/cloud/Member + +The `Version.stores()` method is used to define the schema for a particular version of your Dexie.js database. You specify the tables and their corresponding indexes using a concise string format. This method is fundamental to setting up your database structure. + +-------------------------------- + +### Docs Home > ...started with Dexie in React + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This guide focuses on integrating Dexie.js with React applications. It covers setting up Dexie in a React environment, managing database connections, and utilizing Dexie's features within React components. Learn how to efficiently handle data persistence in your React projects. + +-------------------------------- + +### Docs Home > Version > Version.stores() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `Version.stores()` method is used to define the structure of your database tables within a specific version. You specify the table names and their primary keys, and optionally secondary indexes. This method is fundamental for setting up your Dexie database schema. + +-------------------------------- + +### API Reference > Classes > IndexSpec + +Source: https://dexie.org/docs/API-Reference + +An `IndexSpec` describes the specification for an index on a table. When defining your database schema using `db.version().stores()`, you provide index specifications as strings. This `IndexSpec` class might be relevant if you are programmatically manipulating or inspecting index definitions. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The `db.roles` property in Dexie Cloud allows for the management of user roles, which are fundamental to implementing access control. By assigning users to roles, you can grant or deny specific permissions. + +-------------------------------- + +### API Reference > Knowledge Base > Questions and Answers + +Source: https://dexie.org/docs/API-Reference + +This section addresses common questions and provides answers related to using Dexie. It serves as a knowledge base for developers, covering topics such as troubleshooting, best practices, and advanced usage scenarios. Consulting the Q&A can help resolve issues and deepen your understanding of Dexie. + +-------------------------------- + +### Table > Table.get() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie's `Table.get()` method retrieves a single record from the table based on its primary key. If a record with the specified key exists, it is returned; otherwise, `undefined` is returned. This is a fundamental operation for fetching individual items. + +-------------------------------- + +### Cloud > ...Dexie Cloud on Own Servers + +Source: https://dexie.org/docs/cloud/Member + +This guide provides instructions on how to deploy and manage Dexie Cloud on your own server infrastructure. It covers the necessary steps for setting up the backend services, configuring the environment, and ensuring smooth operation. + +-------------------------------- + +### Docs Home > Typescript + +Source: https://dexie.org/docs/cloud/UserLogin + +This section provides a comprehensive guide to using Dexie.js with TypeScript. It explains how to leverage TypeScript's static typing features to enhance code safety and developer productivity when working with Dexie.js databases. Learn to define interfaces, manage database versions, and benefit from autocompletion and type checking. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/UserLogin + +Dexie.js is a popular open-source wrapper for IndexedDB, designed to simplify database operations in web applications. It provides a more intuitive and robust API compared to the native IndexedDB API, offering features like Promises, simpler query syntax, and automatic schema management. This documentation covers the various aspects of Dexie.js, from basic usage to advanced features and cloud integration. + +-------------------------------- + +### Collection > Methods > last() + +Source: https://dexie.org/docs/Collection/Collection + +Get the last item in the collection. + +-------------------------------- + +### Collection > Methods > modify() + +Source: https://dexie.org/docs/Collection/Collection + +Modify all objects in the collection with given properties or function. + +-------------------------------- + +### Collection > Collection.toArray() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Collection.toArray()` method converts the entire collection into a JavaScript array. This is a fundamental method for retrieving all the filtered and processed records from a query. For example, `const allUsers = await db.users.where('isActive').equals(true).toArray();` fetches all active users. + +-------------------------------- + +### Docs Home > Cloud > Add demo users + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This guide explains how to add demo users to your Dexie Cloud application. This is useful for testing authentication and authorization flows without needing to create real user accounts. + +-------------------------------- + +### Docs Home > Cloud > Get started with Dexie Cloud + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Getting started with Dexie Cloud involves setting up your project and configuring the cloud synchronization. The "Get started with Dexie Cloud" guide walks you through the initial steps, including database setup and authentication. + +-------------------------------- + +### Table > Table.get() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js provides `Table.get()` to retrieve a single record from a table based on its primary key. It returns a promise that resolves with the record if found, or `undefined` if the record does not exist. This is a fundamental method for accessing individual data items. + +-------------------------------- + +### Deprecations > Breaking Changes in Dexie 2.0 > Transaction.complete (callback) + +Source: https://dexie.org/docs/Deprecations + +The `Transaction.complete` callback was a rarely used sugar for `trans.on('complete', callback)`. It was never documented on the wiki and has never been used in any sample or unit test. Use `trans.on('complete', callback)` instead. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud on Own Servers + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Running Dexie Cloud on your own servers provides greater control over your data and infrastructure. The documentation outlines the steps and considerations for self-hosting Dexie Cloud. + +-------------------------------- + +### Docs Home > Tutorial > Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Best Practices in Dexie.js focuses on providing guidelines and recommendations for using the library effectively. This includes advice on structuring your database schema, optimizing queries, handling transactions, managing errors, and maintaining performance. Following these best practices will help you build more robust, efficient, and maintainable applications with Dexie.js. + +-------------------------------- + +### Roadmap + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +The `safari-issues` section in the documentation likely addresses known problems or specific considerations when using Dexie.js or IndexedDB with the Safari browser. This could include workarounds for browser quirks, performance optimizations specific to Safari, or compatibility notes to ensure a smooth user experience across different browsers. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/cloud/Member + +This section outlines best practices for utilizing Dexie Cloud effectively. It covers topics such as schema design, data modeling, performance optimization, and security considerations to help you build scalable and reliable applications. + +-------------------------------- + +### Cloud > Dexie Cloud on Own Servers + +Source: https://dexie.org/docs/cloud/consistency + +This guide explains how to deploy and run Dexie Cloud on your own servers. It covers the necessary setup, configuration, and maintenance required to host the Dexie Cloud backend infrastructure yourself. + +-------------------------------- + +### Docs Home > Understanding the basics + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Getting started with Dexie.js involves including the library in your project and then defining your database schema. The schema defines your object stores (tables) and their indexes. Dexie.js then provides methods to interact with these stores, such as adding, retrieving, updating, and deleting data. The library's promise-based nature simplifies handling the asynchronous nature of IndexedDB. + +-------------------------------- + +### Dexie Cloud Quickstart + +Source: https://dexie.org/docs/cloud/quickstart + +This guide will help you create a simple offline-first app with storage and sync, deploy it to your own free static hosting on GitHub, install it on mobile, see it sync between mobile and desktop, and go through the code to learn the details. The app is an educational PWA with focus on clean, minimalistic and correct code. It is not super-fancy-advanced because the purpose is to understand the code. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/cloud/SyncState + +The roadmap for Dexie 5.0 outlines the future direction and planned features for the library. It indicates ongoing development and commitment to enhancing Dexie.js with new capabilities and improvements, suggesting exciting advancements for developers. + +-------------------------------- + +### Tutorial > Design + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +When designing applications with Dexie.js, it's important to consider the underlying IndexedDB limitations and best practices. This includes efficient schema design, proper indexing for fast queries, and effective use of transactions to maintain data integrity. Understanding how Dexie abstracts these concepts can lead to more performant and reliable applications. Planning your database structure and query patterns early on is crucial for scalability. + +-------------------------------- + +### Cloud > Consistency in Dexie Cloud + +Source: https://dexie.org/docs/cloud/consistency + +This section discusses consistency models in Dexie Cloud, explaining how data is kept synchronized across multiple clients and devices. It covers concepts like eventual consistency and how Dexie Cloud ensures data integrity in distributed environments. + +-------------------------------- + +### Indexable Type > Type order + +Source: https://dexie.org/docs/Indexable-Type + +Index keys of different types can be compared against each other. The following order applies: + 1. -Infinity + 2. number + 3. Infinity + 4. Date + 5. string + 6. TypedArray and ArrayBuffer + 7. Arrays + +-------------------------------- + +### Cloud > db.realms + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `db.realms` collection allows you to interact with realms in Dexie Cloud. Realms are fundamental organizational units in Dexie Cloud, often representing distinct sets of data or collaborative spaces. + +-------------------------------- + +### Docs Home > Cloud > Sharding and Scalability + +Source: https://dexie.org/docs/cloud/UserLogin + +This document discusses strategies for sharding and scaling your Dexie Cloud applications. It covers techniques for distributing data across multiple servers or databases to handle large amounts of data and high traffic loads, ensuring performance and availability as your application grows. + +-------------------------------- + +### 4. Play Around + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `App` component serves as the top-level container for the application. It renders the `CreateAnimal` component, which allows users to add new animals, and the `AnimalList` component, which displays the existing animals. Basic styling is also applied within this component to arrange the elements. + +-------------------------------- + +### Collection > Methods > primaryKeys() + +Source: https://dexie.org/docs/Collection/Collection + +Retrieve an array containing all primary keys of the collection. + +-------------------------------- + +### Tutorial > Get started with Dexie Cloud + +Source: https://dexie.org/docs/inbound + +Getting started with Dexie Cloud involves setting up your cloud-connected database and configuring the necessary authentication and synchronization options. The quickstart guide provides a step-by-step process to initialize Dexie Cloud, define your schema, and implement basic cloud features like real-time data syncing and user authentication. + +-------------------------------- + +### Getting Started with Dexie.js + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +Getting Started with Dexie.js is designed to be straightforward. The library aims to provide a user-friendly experience for developers new to IndexedDB or those looking for a more streamlined approach. The 'Hello World' example typically demonstrates the basic setup and a simple data operation, providing a quick entry point into using Dexie.js for your projects. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/inbound + +Getting started with Dexie.js in various popular JavaScript frameworks like React, Angular, Vue, and Svelte is streamlined with dedicated tutorials and examples. These guides walk you through setting up Dexie within your framework's project structure, defining your database schema, and performing basic data operations, making it easier to integrate Dexie into your existing or new projects. + +-------------------------------- + +### Docs Home > Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The `db.realms` collection in Dexie Cloud represents the different data partitions or scopes within your application. Realms are fundamental for organizing data and controlling access in a multi-tenant or multi-group environment. + +-------------------------------- + +### Table > Table.schema + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie provides a `Table.schema` property that exposes the schema definition for a given table. This includes information about the table's indexes, primary key, and other structural details. + +-------------------------------- + +### Roadmap + +Source: https://dexie.org/docs/cloud/web-hooks + +The 'Road Map: Dexie 5.0' section outlines the planned features, improvements, and changes for the upcoming major version of Dexie.js. It provides insight into the future direction of the library and what developers can expect in terms of new capabilities and potential breaking changes. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/Promise/unhandledrejection-event + +The roadmap for Dexie 5.0 outlines upcoming features and improvements for the library. This includes potential enhancements to the API, performance optimizations, and new functionalities aimed at further simplifying IndexedDB development and expanding its capabilities. + +-------------------------------- + +### Docs Home > ...ating existing DB to Dexie + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +Learn how to upgrade an existing IndexedDB database to work with Dexie.js. This guide explains the necessary steps and considerations when migrating your database schema and data to leverage Dexie's enhanced API. It ensures a smooth transition for your existing applications. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/web-hooks + +For Vue.js developers, Dexie.js can be integrated smoothly into applications. Tutorials would guide users on initializing Dexie instances, performing database operations from Vue components, and potentially using reactive patterns to keep the UI in sync with the database. + +-------------------------------- + +### Docs Home > Version > Version.stores() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `Version.stores()` method is crucial for defining the structure of your Dexie.js database. It allows you to specify the tables (collections) within your database and define their primary keys and indexes. Proper schema definition using `stores()` is fundamental for efficient data storage and retrieval. + +-------------------------------- + +### Docs Home > Inbound + +Source: https://dexie.org/docs/cloud/UserLogin + +This section focuses on inbound data processing and management within Dexie.js. It covers strategies for efficiently importing and handling data that comes into your application, ensuring data integrity and optimal performance during ingestion. + +-------------------------------- + +### liveQuery() + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `liveQuery()` function is a core utility in Dexie.js for creating reactive data subscriptions. It allows you to observe changes in your database and automatically receive updates whenever the queried data is modified. This is fundamental for building dynamic and responsive user interfaces. + +-------------------------------- + +### API Reference > Classes > Transaction + +Source: https://dexie.org/docs/API-Reference + +Transactions are fundamental to IndexedDB for ensuring data integrity. In Dexie, `Transaction` objects provide a scope for a set of database operations that must succeed or fail as a single unit. Operations within a transaction are atomic and isolated. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Dexie Cloud Best Practices guide developers on how to effectively utilize the cloud features for building scalable and robust applications. This includes advice on schema design, data synchronization strategies, performance optimization, and security considerations. Adhering to these practices ensures a smooth development process and a high-quality end product. + +-------------------------------- + +### safari-issues + +Source: https://dexie.org/docs/Promise/Promise + +Dexie.js has specific considerations for Safari browsers, particularly regarding IndexedDB performance and behavior. The documentation often includes sections dedicated to 'safari-issues' to highlight any known quirks or necessary workarounds to ensure consistent functionality across different browsers. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `TableSchema` interface in Dexie defines the structure of a table, including its name, primary key, and indexes. This information is crucial for understanding how data is organized and for optimizing queries. + +-------------------------------- + +### Tutorial > Building Addons + +Source: https://dexie.org/docs/Collection/Collection + +Building custom addons for Dexie.js allows you to extend its functionality or integrate it with other libraries. The documentation outlines the process of creating addons, which typically involves hooking into Dexie's internal mechanisms or providing additional utility functions that can be used with Dexie instances. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.equals() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause.equals()` method filters records where a specific index is exactly equal to the provided value. This is the most straightforward way to find records that match a precise criterion. It's fundamental for direct lookups based on indexed properties. + +-------------------------------- + +### Docs Home > Inbound + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section focuses on inbound data processing and handling within Dexie.js applications. It may cover strategies for receiving and integrating data from external sources into your IndexedDB database. + +-------------------------------- + +### Cloud > db.roles + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `db.roles` collection in Dexie Cloud is used to define and manage the different roles available in your application. Roles are fundamental to the access control system, allowing you to group users and assign permissions efficiently. + +-------------------------------- + +### Tutorial > Building Addons + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js includes a feature for **building addons**. This allows you to extend Dexie's core functionality or add custom behaviors. Addons can be used to integrate with other libraries, implement specific business logic, or provide specialized utility functions. The documentation outlines the process and best practices for creating and using Dexie addons. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/TableSchema + +The `Transaction` object in Dexie.js represents a database transaction. Transactions are fundamental to IndexedDB for ensuring data integrity. Dexie.js provides methods and events related to transactions, such as `Transaction.abort()`, `Transaction.on.abort`, `Transaction.on.complete`, and `Transaction.on.error`. These allow developers to manage and react to the lifecycle of a transaction. + +-------------------------------- + +### Permissions > manage + +Source: https://dexie.org/docs/cloud/access-control + +Full permissions on objects within the realm in a given set of tables. + +-------------------------------- + +### Docs Home > Inbound + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +This section likely discusses inbound data processing or integration strategies with Dexie.js. It might cover how to import data from external sources, handle incoming data streams, or set up mechanisms for receiving data from APIs or other services into your Dexie database. + +-------------------------------- + +### Docs Home > ... started with Dexie in Vue + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +Discover how to integrate Dexie.js seamlessly with Vue.js applications. This guide offers detailed instructions and code examples for setting up Dexie, performing database operations, and handling reactivity within your Vue components. Enhance your Vue apps with robust data persistence. + +-------------------------------- + +### Dexie.js API Documentation > ExportImport + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js provides functionalities for exporting and importing database content. This is useful for backup, migration, or sharing data between different environments. The `ExportImport` module likely contains methods or classes to facilitate these operations, allowing users to get data out of and into their Dexie databases. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section outlines the future development plans and upcoming features for Dexie.js, specifically focusing on version 5.0. It provides insights into the roadmap and the direction the library is heading. + +-------------------------------- + +### Docs Home > Tutorial > Started with Dexie in React + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +This tutorial focuses on integrating Dexie.js with React applications, leveraging the power of hooks for a more declarative and efficient data management experience. It will likely cover how to set up Dexie within a React project, manage database operations using hooks, and handle real-time data updates. This guide is essential for React developers looking to incorporate a robust client-side database into their applications. + +-------------------------------- + +### Collection > Methods > limit() + +Source: https://dexie.org/docs/Collection/Collection + +Limit the result to given number of items. + +-------------------------------- + +### Cloud > Add public data + +Source: https://dexie.org/docs/cloud/consistency + +This guide covers how to add public data to your Dexie Cloud application. Public data is accessible to all users, regardless of authentication status, and is often used for shared resources or general information. + +-------------------------------- + +### Roadmap + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +The `Road Map: Dexie 5.0` section outlines the planned features and improvements for the next major version of Dexie.js. This provides insight into the future direction of the library, including potential new APIs, performance enhancements, and support for emerging web standards. Developers can refer to the roadmap to anticipate upcoming changes and plan their projects accordingly. + +-------------------------------- + +### CLI Reference > clients + +Source: https://dexie.org/docs/cloud/cli + +The `clients` command provides a way to list all API clients associated with a database, along with the email addresses of their respective owners. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/web-hooks + +Dexie.js also offers support for Svelte applications. Getting started guides would focus on how to integrate Dexie's database capabilities within Svelte components, leveraging Svelte's reactivity to efficiently update the UI when data changes. + +-------------------------------- + +### Collection > Methods > eachUniqueKey() + +Source: https://dexie.org/docs/Collection/Collection + +Execute query on the index or primary key being used and call a function for each unique key. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +The roadmap for Dexie 5.0 outlines upcoming features and improvements for the library. This includes potential enhancements to the API, performance optimizations, and new functionalities. Staying informed about the roadmap can help you plan your development and leverage the latest advancements in Dexie.js. + +-------------------------------- + +### MultiEntry Index + +Source: https://dexie.org/docs/MultiEntry-Index + +A multiEntry index in indexedDB is an index that refers to an array property, and where each item in the array is indexed towards the object / record / document. It is similar to GIN index in PostgreSQL. In Dexie, an index is marked multiEntry by putting an asterisk (*) char in front of the index name in the schema as exemplified below: + +``` +var db = new Dexie('dbname'); +db.version(1).stores ({ + books: 'id, author, name, *categories' +}); +``` + +In this sample, books can be categorized by multiple categories. This is done by letting the book objects have an array property named 'categories' containing the category strings. See sample below: + +``` +db.books.put({ + id: 1, + name: 'Under the Dome', + author: 'Stephen King', + categories: ['sci-fi', 'thriller'] +}); +``` + +In the sample, we add a book with the multiple categories "sci-fi" and "thriller". Note that not just strings can be put in the array, but any Indexable types are valid. + +-------------------------------- + +### Libs + +Source: https://dexie.org/docs/Tutorial + +The `dexie-react-hooks` library provides a set of React hooks that simplify working with Dexie.js in React applications. Key hooks include `useLiveQuery` for reactive data fetching, `useDocument` for interacting with individual documents, and `usePermissions` for managing user permissions within Dexie Cloud. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.schema` property provides information about the schema of a particular table, including its primary key and indexes. This can be useful for introspection and understanding the database structure at runtime. While Dexie typically manages schema internally, accessing this property can offer insights into the defined structure. + +-------------------------------- + +### Docs Home > Cloud > Authentication in Dexie Cloud + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Authentication in Dexie Cloud can be handled using various methods, including email/password, social logins, and custom authentication providers. The documentation explains how to integrate these authentication flows into your application. + +-------------------------------- + +### Dexie.js API Documentation > Roadmap + +Source: https://dexie.org/docs/cloud/UserLogin + +Dexie.js has a roadmap for future development, with significant focus on version 5.0. This upcoming major release aims to introduce new features, performance improvements, and potentially breaking changes to modernize the library and address evolving web development needs. Staying informed about the roadmap helps developers plan their upgrades and leverage new capabilities. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DerivedWork + +The roadmap for Dexie 5.0 outlines upcoming features and improvements for the library. This typically includes enhancements to performance, new API additions, better developer experience, and potential support for newer web standards. Staying informed about the roadmap helps developers plan for future updates and leverage the latest capabilities of Dexie.js. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/Dexie/Dexie.on + +The roadmap for Dexie 5.0 outlines the planned features and improvements for the next major version of Dexie.js. It provides insights into the future direction of the library. + +-------------------------------- + +### Dexie.js > Table > Table.get() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js offers `Table.get()` for retrieving a single record from a table based on its primary key. This method returns a Promise that resolves with the record if found, or `undefined` if no record with the specified key exists. It's a fundamental operation for fetching specific data entries. + +-------------------------------- + +### Dexie.js Documentation > Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +The Dexie Cloud add-on streamlines the development of real-time, collaborative applications. It offers features like real-time data synchronization, authentication, and authorization, simplifying the backend complexities. This section details the Dexie Cloud API, including methods for configuring the service, managing users and permissions, and handling synchronization events. It also covers best practices for using Dexie Cloud, such as sharding and scalability, and how to deploy Dexie Cloud on your own servers. + +-------------------------------- + +### Dexie.js > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/safari-issues + +The roadmap for Dexie 5.0 outlines planned features and improvements for the next major version of the library. This typically includes enhancements to the core API, new features, performance optimizations, and potential breaking changes. Keeping an eye on the roadmap helps developers prepare for future updates and understand the future direction of Dexie.js. + +-------------------------------- + +### Cloud > db.cloud.permissions() + +Source: https://dexie.org/docs/cloud/limits + +The `db.cloud.permissions()` method provides a way to query and manage the permission sets associated with different roles or users in Dexie Cloud. This is fundamental for implementing fine-grained access control and ensuring data security within your application. + +-------------------------------- + +### Dexie.js > Transaction + +Source: https://dexie.org/docs/safari-issues + +Transactions are fundamental to maintaining data integrity in IndexedDB. Dexie.js simplifies transaction management by providing a clear API. When you perform multiple operations that should succeed or fail together, you wrap them in a transaction. The `db.transaction('tableName', 'readwrite', () => { ... })` syntax is commonly used. Dexie.js handles the transaction lifecycle, including commit and abort, making it easier to ensure atomic operations. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The Dexie 5.0 roadmap outlines the planned features, improvements, and future direction for the next major version of Dexie.js. This includes information about upcoming functionalities, potential breaking changes, and the overall vision for the library's evolution, helping developers prepare for future updates. + +-------------------------------- + +### Tutorial > Consuming Dexie as a module + +Source: https://dexie.org/docs/cloud/consistency + +This guide explains how to consume Dexie.js as a module within your project, likely using module bundlers like Webpack or Rollup. It covers import statements and how to initialize Dexie.js in a modular environment, ensuring efficient code management and dependency handling. + +-------------------------------- + +### Docs Home > Libs > liveQuery() + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The `liveQuery()` function is a fundamental part of Dexie.js for creating reactive data subscriptions. It allows you to observe changes in your database and automatically update your application's state or UI when relevant data is modified. + +-------------------------------- + +### Observe joined data + +Source: https://dexie.org/docs/Tutorial/React + +Do something similar to this sample and observe the result of a function similar to `getBandsStartingWithA()` (a function that compose a result from multiple related queries). Notice that any change that affects any of the queries will make the component rerender, including the related data. + +-------------------------------- + +### DBCore > DBCoreIndex + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `DBCoreIndex` interface represents an index within the `DBCore` API. It provides information about the index's key path and other properties. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie Cloud offers best practices for building scalable and robust applications. Topics include sharding and scalability, running Dexie Cloud on your own servers, and utilizing web hooks for custom integrations. The documentation provides guidance on setting up and optimizing your Dexie Cloud infrastructure. + +-------------------------------- + +### Tutorial > Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie.js provides best practices for working with its API and IndexedDB effectively. These guidelines often cover topics such as optimizing database schema design, writing efficient queries, managing transactions, handling errors gracefully, and leveraging Dexie.js features for better performance and maintainability. Following these best practices can lead to more robust, scalable, and performant applications. + +-------------------------------- + +### Dexie.js API Documentation > Table + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +The `Table` object in Dexie.js is central to interacting with database tables. It provides a rich API for data manipulation, including `add()`, `bulkAdd()`, `bulkDelete()`, `bulkGet()`, `bulkPut()`, `bulkUpdate()`, `clear()`, `count()`, `delete()`, `get()`, `put()`, `update()`, and `upsert()`. For querying, it offers `each()`, `filter()`, `limit()`, `offset()`, `orderBy()`, `reverse()`, `toArray()`, `toCollection()`, and `where()`. It also allows defining object classes with `defineClass()` and mapping them with `mapToClass()`. Properties like `Table.name` and `Table.schema` provide metadata about the table. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The Dexie.js roadmap outlines the planned features and improvements for future versions of the library. Specifically, the roadmap for Dexie 5.0 details upcoming enhancements, new functionalities, and potential breaking changes, providing insight into the future direction of Dexie.js. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.get()` method in Dexie.js retrieves a single record from a table based on its primary key. It takes the primary key as an argument and returns a promise that resolves with the record object if found, or `undefined` if no record with that key exists. This is a fundamental method for fetching specific data entries. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The Dexie.js roadmap outlines planned features and improvements for future versions, particularly focusing on Dexie 5.0. This provides insight into the future direction of the library and upcoming enhancements. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/cloud/UserLogin + +The roadmap outlines the future development plans for Dexie.js, specifically detailing the features and improvements planned for version 5.0. It provides insights into upcoming capabilities and the project's direction. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie.js offers support for TypeScript, enabling developers to leverage static typing for improved code quality and maintainability. This includes providing type definitions for the Dexie.js API, allowing for better autocompletion, compile-time error checking, and overall enhanced developer productivity when working with Dexie.js in TypeScript projects. The documentation includes a section on `Typescript` detailing how to integrate Dexie.js with TypeScript effectively. + +-------------------------------- + +### CLI Reference > undelete + +Source: https://dexie.org/docs/cloud/cli + +The `undelete` command allows you to restore a database that was previously marked for deletion. This command is only effective within the grace period specified in the `delete` command documentation. The example demonstrates how to delete a database, encounter a connection error due to deletion, reconnect, and then undelete it, after which warnings are no longer issued. + +-------------------------------- + +### Collection > Collection.where() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.where()` method is used to start building a query. You provide a predicate function or an object that specifies the criteria for filtering records. This is the starting point for retrieving specific data from your tables. + +-------------------------------- + +### Table > Table.where() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js's `Table.where()` method is the entry point for querying data. It allows you to specify criteria based on table properties, returning a `Collection` object. You can chain multiple `where()` clauses or use operators like `equals()`, `above()`, `below()`, `startsWith()` to define complex filters. This method is fundamental for retrieving specific data. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud API Limits + +Source: https://dexie.org/docs/cloud/UserLogin + +This document outlines the API limits imposed by Dexie Cloud. Understanding these limits is crucial for designing scalable applications and avoiding potential issues related to request rates, data transfer sizes, or concurrent connections. It helps in planning resource usage effectively. + +-------------------------------- + +### MultiEntry Index > Querying MultiEntry Indexes + +Source: https://dexie.org/docs/MultiEntry-Index + +All WhereClause operators are available for querying MultiEntry indexed objects. However, the operator's behaviours are not that intuitive as they are for normal indexes. For example, one should use WhereClause.equals() operator to query books is of a certain category, while a more semantic name would probably be `contains()`. The reason for this is to map with the way indexedDB works natively, and also to allow any operator and not tie multiEntry indexes to certain operators. + +``` +// Query all sci-fi books: +function getSciFiBooks() { + return db.books + .where('categories').equals('sci-fi') + .toArray (); +} +``` + +-------------------------------- + +### Dexie.js Documentation > Version + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +The `Version` API in Dexie.js is used for managing database schema versions and performing upgrades. `Version.stores()` defines the object stores (tables) and their schemas for a given version. `Version.upgrade()` allows you to define the logic for migrating data when the database version changes. This is essential for handling schema evolution over time. + +-------------------------------- + +### Cloud > Custom Emails in Dexie Cloud + +Source: https://dexie.org/docs/cloud/Member + +This guide explains how to configure custom email notifications within Dexie Cloud. You can customize emails for various events, such as invitation acceptance, password resets, or other user-related activities, enhancing the user experience. + +-------------------------------- + +### Docs Home > Tutorial > Best Practices + +Source: https://dexie.org/docs/Typescript-old + +Best practices for using Dexie.js involve several key principles. These include efficient schema design with appropriate indexes, proper transaction management to ensure data integrity, and leveraging Dexie's live query capabilities for responsive UIs. Additionally, understanding error handling and considering performance optimizations for large datasets are crucial for robust applications. + +-------------------------------- + +### Dexie > Dexie.table() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.table()` method returns a reference to a specific table (object store) within the database. You can then use this table reference to perform CRUD operations and queries on the data. It takes the table name as a string argument. This method is fundamental for interacting with your database's data. + +Example: +`const friendsTable = db.table('friends'); +friendsTable.toArray().then(console.log);` + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/cloud/Member + +This roadmap outlines the planned features and development trajectory for Dexie 5.0. It provides insights into upcoming improvements, new functionalities, and potential changes to the library's API. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/Tutorial + +The `Version.stores()` method is fundamental to defining your database schema in Dexie.js. It takes an object where keys are table names and values are primary key definitions. For example, `version(1).stores({ friends: '++id,name' })` defines a 'friends' table with an auto-incrementing primary key 'id' and an index on 'name'. + +-------------------------------- + +### Docs Home > Cloud > ...Dexie Cloud on Own Servers + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This guide explains how to deploy and manage Dexie Cloud on your own servers. It covers the necessary steps for setting up the backend infrastructure, configuring the service, and ensuring secure and reliable operation. This option provides greater control over your cloud environment. + +-------------------------------- + +### Docs Home > Y.js > y-dexie + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie.js integrates seamlessly with Y.js, a framework for building collaborative applications. The `y-dexie` addon allows you to use Dexie.js as a persistent storage backend for Yjs documents. This combination enables efficient synchronization of shared data across multiple clients, facilitating real-time collaboration. + +-------------------------------- + +### Docs Home > Cloud > Custom Emails in Dexie Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +Dexie Cloud allows for customization of email notifications, such as invitation emails or password reset emails. This guide explains how to tailor these emails to match your application's branding and messaging. + +-------------------------------- + +### Getting Started > ...started with Dexie in React + +Source: https://dexie.org/docs/cloud/Member + +This guide focuses on integrating Dexie.js with React applications. It introduces the `dexie-react-hooks` library, which provides convenient hooks for managing database operations within your React components. You'll learn how to perform common tasks like fetching data, updating records, and handling real-time updates in a declarative way. + +-------------------------------- + +### Collection > Construction + +Source: https://dexie.org/docs/Collection/Collection + +Collection constructor is private. Instances are returned from the WhereClause methods and some of the Table methods. + +-------------------------------- + +### API Reference > Classes > TableSchema + +Source: https://dexie.org/docs/API-Reference + +The `TableSchema` class represents the schema of a specific table, including its primary key and indexes. This class is useful for inspecting the structure of your database tables, particularly when dealing with dynamic schema management or introspection. + +-------------------------------- + +### API Reference > Transaction + +Source: https://dexie.org/docs/Collection/Collection + +Transactions are fundamental to IndexedDB operations for ensuring data integrity. Dexie.js simplifies transaction management by providing an automatic transaction system. You can explicitly define transactions using `db.transaction()` to group operations that must succeed or fail together. Dexie also handles transaction lifecycles, including completion and error events. + +-------------------------------- + +### Docs Home > Roadmap + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The roadmap for Dexie 5.0 outlines upcoming features and improvements for the library. This includes potential enhancements to the API, performance optimizations, and support for new IndexedDB features. Staying updated with the roadmap provides insights into the future direction of Dexie.js development. + +-------------------------------- + +### Guide to the Source Code > Roles and Access Control + +Source: https://dexie.org/docs/cloud/quickstart + +The Roles and Access Control configuration involves `roles.json` for defining permissions per role. The `configureApp.sh` script is a practical example of how to use the `dexie-cloud` CLI. This script is used to import roles and demo users, white-list application URLs, and create an `.env.local` file containing the necessary database URL for the application. + +-------------------------------- + +### Docs Home > Tutorial > started with Dexie in Vue + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +This tutorial demonstrates how to integrate Dexie.js with Vue.js applications. It will guide you through setting up Dexie, defining your database schema, and performing data operations within Vue components. The focus is on leveraging Dexie's features for efficient client-side data persistence and management in a Vue.js environment, potentially highlighting reactivity patterns. + +-------------------------------- + +### Collection > Methods > delete() + +Source: https://dexie.org/docs/Collection/Collection + +Delete all objects in the collection. + +-------------------------------- + +### Dexie Cloud Consistency Models > Choosing the Right Model + +Source: https://dexie.org/docs/cloud/consistency + +Use **server-authoritative consistency** for structured data with business rules, access control, and transactional integrity. Use **CRDT-based consistency** (Y.js) for unstructured collaborative content like documents, diagrams, and drawings. Both models can coexist in the same application, so use each where it fits best. + +-------------------------------- + +### Table > Table.add() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js's `Table.add()` method inserts a new record into a table. It takes the object to be inserted and returns a promise that resolves with the primary key of the newly added record. If the table has an auto-incrementing primary key, Dexie will manage its generation. This is a fundamental method for populating your database. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud API Limits + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This document details the API limits imposed by Dexie Cloud. Understanding these limits is crucial for designing scalable applications and avoiding potential issues related to request rates, data transfer, or storage capacity. It helps in planning your application's architecture effectively. + +-------------------------------- + +### Deprecations > Breaking Changes in Dexie 2.0 > Transaction.error (callback) + +Source: https://dexie.org/docs/Deprecations + +The `Transaction.error` callback was a rarely used sugar for `trans.on('error', callback)`. It was never documented on the wiki and has never been used in any sample or unit test. Use `trans.on('error', callback)` instead. + +-------------------------------- + +### Dexie.js API Documentation > Table + +Source: https://dexie.org/docs/cloud/UserLogin + +The `Table` object in Dexie.js represents a database table and provides methods for interacting with its data. You can perform operations like retrieving data using `toArray()`, `get()`, or `where()`, modifying data with `put()`, `add()`, or `delete()`, and manipulating the table structure. It also offers hooks for triggering custom logic during data operations. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DerivedWork + +The Dexie.js roadmap outlines the planned features and improvements for future versions, including the upcoming 5.0 release. It provides insights into the project's direction and upcoming enhancements, such as potential new APIs or performance optimizations. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/Promise/Promise + +Dexie Cloud introduces concepts like `Realm`, `Role`, and `Member` to manage data access and user permissions. Realms define the scope of data, roles define sets of permissions, and members are users assigned to specific roles within realms. This hierarchical structure allows for fine-grained control over who can access and modify what data in your application. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.permissions() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `db.cloud.permissions()` method is used to retrieve or manage permission settings for the current user or specific roles within your Dexie Cloud application. This is fundamental for implementing role-based access control (RBAC) and ensuring data security. + +-------------------------------- + +### Samples > Full-text search + +Source: https://dexie.org/docs/Table/Table + +To enable full-text search, Dexie hooks are utilized to automatically index the 'message' field. The `creating` hook is responsible for populating the `messageWords` index when a new email is added. It extracts all words from the `obj.message` and stores them in the `messageWords` array. The `updating` hook handles cases where the 'message' field is modified. If the 'message' property is updated, it re-indexes the new message content. If the 'message' property is deleted or its type changes to something other than a string, the corresponding `messageWords` index is cleared. This ensures that the full-text index remains consistent with the message content. + +-------------------------------- + +### Docs Home > Libs > dexie-react-hooks + +Source: https://dexie.org/docs/cloud/index + +The `dexie-react-hooks` library offers convenient React hooks for interacting with Dexie.js databases. `useLiveQuery` allows you to subscribe to changes in your data and automatically re-render your components when data updates. `useDocument` provides a way to fetch and observe a single document, while `useObservable` allows you to observe any live query. + +-------------------------------- + +### Docs Home > Version + +Source: https://dexie.org/docs/Dexie/Dexie.on + +`Version.stores()` is a method used to define the schema for a given database version. It allows you to specify the tables, their primary keys, and indexes. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.currentUserId + +Source: https://dexie.org/docs/cloud/UserLogin + +The `db.cloud.currentUserId` property returns the unique identifier of the currently authenticated user. This is often used for filtering data specific to the logged-in user or for auditing purposes. It's a fundamental piece of information for managing user-specific operations. + +-------------------------------- + +### IndexSpec + +Source: https://dexie.org/docs/IndexSpec + +The `IndexSpec` object represents the specification of an index or a primary key within a Dexie database. It holds properties that define the index's characteristics, such as its name, key path, uniqueness, and whether it supports multiple values or auto-increment. + +Key properties include: +- `name`: The name of the index. For compound indexes, this is the string defined in `Version.stores()`. +- `keyPath`: The path to the indexed property. For nested properties, it uses dot notation (e.g., `'props.shoeSize'`). For compound indexes, it's an array of key paths. +- `unique`: A boolean indicating if the index must contain unique values (primary keys are always unique). +- `multi`: A boolean indicating if the index should index each item in an array pointed to by `keyPath` (not supported in IE). +- `auto`: A boolean that, when true for a primary key, enables auto-incrementing behavior. +- `compound`: A boolean indicating if the index is a combination of two or more properties (not supported in IE). +- `src`: A canonical string representation of the index specification, used internally for comparing index definitions across versions during upgrades. + +-------------------------------- + +### Collection > Methods > filter() + +Source: https://dexie.org/docs/Collection/Collection + +Filter objects. + +-------------------------------- + +### Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/dexie-react-hooks/useDocument%28%29 + +The `useDocument` hook from `dexie-react-hooks` allows you to consume an Y.Doc within your React components. It takes an Y.Doc object as input and returns a `DexieYProvider`. This provider is responsible for handling document loading and updates. If the `dexie-cloud-addon` is also in use and a Dexie Cloud database is configured, the provider extends its functionality to support synchronization and awareness. This integration seamlessly works with the Y.js ecosystem, including text editors that support Y.js. + +-------------------------------- + +### Y.js + +Source: https://dexie.org/docs/Promise/Promise + +The `y-dexie` library bridges the gap between Yjs, a framework for building collaborative applications, and Dexie.js. It allows Yjs documents to be persisted and synchronized using Dexie.js as the backend storage. This combination enables powerful real-time collaborative features in your applications by leveraging Dexie.js's offline capabilities and Yjs's conflict-free replicated data types. + +-------------------------------- + +### Example: Sharable ToDo list + +Source: https://dexie.org/docs/cloud/access-control + +This example shows how to create shareable entities, how to share them and how to connect related entities to it. It consists of three functions: `createTodoList()` creates a shareable ToDo list, `shareTodoList()` shares the list to other users, `addTodoItem()` adds a todoItem related to the shared list that also inherits sharing, and `deleteTodoList()` deletes the todo-list along with all its related objects. + +-------------------------------- + +### Table > Table.delete() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.delete()` method removes a specific record from a table identified by its primary key. It takes the primary key value as an argument and returns a Promise that resolves when the deletion is complete. If no record with the specified key exists, the operation completes without error, but no record is deleted. This is a fundamental operation for managing data in your database. + +Example: +`db.friends.delete(456).then(() => { console.log('Friend deleted.'); });` + +-------------------------------- + +### IndexedDB on Safari + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js provides a robust mechanism for handling **IndexedDB on Safari** and other browsers. While Dexie aims for a consistent API across all browsers, there might be subtle differences or limitations in specific browser implementations. The documentation often includes notes or workarounds for such platform-specific behaviors, ensuring your application works reliably everywhere. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/consistency + +Dexie Cloud is a real-time backend synchronization service for Dexie.js applications. It provides features like automatic data synchronization across devices, offline support, and real-time collaboration. This section covers the core concepts and components of Dexie Cloud. + +-------------------------------- + +### Docs Home > Tutorial > Typescript + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +This section provides guidance on using Dexie.js with TypeScript. It covers setting up TypeScript definitions, defining database schemas with types, and leveraging TypeScript's features for enhanced type safety and developer productivity when working with Dexie. This ensures that your database interactions are robust and less prone to runtime errors. + +-------------------------------- + +### Docs Home > Roadmap + +Source: https://dexie.org/docs/cloud/Realm + +The roadmap for Dexie 5.0 outlines upcoming features and improvements for the library. This includes potential enhancements to the API, performance optimizations, and new functionalities aimed at further simplifying database development. Keeping an eye on the roadmap can help you plan for future updates and leverage new capabilities as they become available. + +-------------------------------- + +### MultiEntry Index + +Source: https://dexie.org/docs/Tutorial/Getting-started + +In Dexie.js, a `MultiEntry Index` is an index that can contain multiple values for a single record. This is particularly useful when dealing with array properties. When you define a `multiEntry` index on an array property, Dexie will create an index entry for each element within that array. This allows you to query for records that contain specific values within their array properties. + +Example: +`db.version(1).stores({ + documents: '++id, [tags+multiEntry]' +});` In this schema, `tags` is an array property, and the `[tags+multiEntry]` definition creates a multi-entry index on it. + +-------------------------------- + +### Dexie.js Documentation > Table + +Source: https://dexie.org/docs/Deprecations + +The `Table` object in Dexie.js represents a collection of records within your database. It provides a comprehensive set of methods for performing CRUD (Create, Read, Update, Delete) operations, querying data, and managing the table's schema. You can add, delete, get, and update single records or multiple records in bulk using methods like `add()`, `bulkAdd()`, `delete()`, `bulkDelete()`, `get()`, `bulkGet()`, `put()`, `bulkPut()`, and `update()`. + +-------------------------------- + +### Dexie.js API Documentation > Version + +Source: https://dexie.org/docs/cloud/UserLogin + +The `Version` object in Dexie.js is used to define the database schema and manage schema migrations. When you initialize Dexie, you specify a database name and a version number. Each version can have its own schema definition, and Dexie handles the upgrading or downgrading process automatically when the database version changes. The `stores()` method defines the tables and their schemas, while `upgrade()` allows you to define migration logic. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/cloud/consistency + +This section outlines the future roadmap for Dexie.js, specifically detailing the planned features and improvements for version 5.0. It gives users insight into upcoming developments and potential breaking changes. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.add()` method in Dexie.js is used to insert a new record into a table. It takes the object to be inserted as an argument and returns a promise that resolves with the primary key of the newly added record. If the table has an auto-incrementing primary key, the resolved value will be that key. This method is fundamental for populating your database with new data. + +-------------------------------- + +### Limitations of IndexedDB + +Source: https://dexie.org/docs/Releasing-Dexie + +IndexedDB, while powerful, has certain limitations that developers need to be aware of. These limitations can impact performance, data management, and cross-browser compatibility. Dexie.js helps to mitigate some of these by providing abstractions and workarounds, but a fundamental understanding of IndexedDB's constraints is still beneficial. + +-------------------------------- + +### Roadmap + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +The roadmap for Dexie 5.0 outlines upcoming features and improvements for the library. This includes potential enhancements to the API, performance optimizations, and new functionalities aimed at further simplifying database development. Keeping an eye on the roadmap helps developers anticipate future changes and plan their projects accordingly. + +-------------------------------- + +### Roadmap + +Source: https://dexie.org/docs/cloud/index + +The `Road Map: Dexie 5.0` section outlines the planned features and improvements for the upcoming major release of Dexie.js. This includes details on new functionalities, API changes, and performance enhancements that developers can expect in version 5.0, allowing them to prepare for the upgrade and leverage new capabilities. + +-------------------------------- + +### Docs Home > Best Practices + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Dexie.js offers best practices and guidelines for effectively using its features. These recommendations cover areas like database design, performance optimization, and error handling, helping you build more reliable and efficient applications. + +-------------------------------- + +### Tutorial > Getting Started with Dexie in Angular + +Source: https://dexie.org/docs/Collection/Collection + +Dexie.js can be easily integrated into various JavaScript frameworks, including Angular. The documentation provides guidance on how to set up and use Dexie.js within an Angular application, covering aspects like dependency injection and managing database instances. + +-------------------------------- + +### Dexie.js > Dexie.js + +Source: https://dexie.org/docs/safari-issues + +Dexie.js features `Dexie.js`, which is the main JavaScript file that contains the library's code. This file should be included in your project to use Dexie.js. It provides the core functionality for database interaction, schema management, and querying. The file itself is a self-contained module that exposes the Dexie API for your application to consume. + +-------------------------------- + +### Dexie.js Documentation + +Source: https://dexie.org/docs/Deprecations + +Dexie.js is a powerful wrapper for the native IndexedDB API, designed to simplify and enhance your database interactions in web applications. It offers a more intuitive and feature-rich API compared to the standard IndexedDB, making it easier to manage your data. Key advantages include declarative schema definitions, automatic database versioning, and robust support for real-time data synchronization, which is particularly useful for building collaborative applications. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The Roadmap for Dexie 5.0 outlines the planned features, improvements, and potential breaking changes for the upcoming major version of Dexie.js. It provides insight into the future direction of the library and helps developers prepare for the upgrade. + +-------------------------------- + +### Editing Email Templates + +Source: https://dexie.org/docs/cloud/custom-emails + +The email templates can be edited using a four-step process involving pulling, editing, testing, and pushing the templates. First, run `npx dexie-cloud@latest templates pull` to download the current templates. These templates are located in a `dexie-cloud` folder, with subdirectories for web and email templates. The email templates themselves are in Handlebars format, with separate files for subject and body, and variations for HTML and plain text. Available variables are documented within the template files. After editing, you can test them by sending to your own email using `npx dexie-cloud templates test-send `, with options to send to others or customize test data. Finally, when satisfied, publish the changes with `npx dexie-cloud templates push` and consider committing to version control. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/Tutorial/Getting-started + +Dexie.js facilitates the definition and management of database schemas through its `version()` and `stores()` methods. The `version()` method specifies a database version number, and the `stores()` method within it defines the object stores (tables) and their indexes. This declarative approach simplifies schema management and upgrades. You can define primary keys, unique indexes, and compound indexes within the `stores()` definition. + +Example: +`db.version(2).stores({ + friends: '++id, name, age', + pets: '++id, ownerId, type' +});` + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud on Own Servers + +Source: https://dexie.org/docs/cloud/UserLogin + +This guide provides instructions and considerations for deploying and running Dexie Cloud on your own servers, rather than using the managed cloud service. It covers self-hosting requirements, configuration, and maintenance aspects for users who need more control over their infrastructure. + +-------------------------------- + +### Guide to the Source Code > PWA stuff + +Source: https://dexie.org/docs/cloud/quickstart + +The PWA (Progressive Web App) related configurations are managed by `vite.config.ts` and `sw.ts`. `vite.config.ts` is responsible for configuring the PWA to make the application installable, including generating a web manifest with app icons, name, URL, and screenshots. `sw.ts` contains the Service Worker, which is minimal and primarily focuses on caching assets for offline use and activating Dexie Cloud's background synchronization. + +-------------------------------- + +### Dexie.js Documentation > WhereClause + +Source: https://dexie.org/docs/Deprecations + +Dexie.js includes extensive support for querying data using the `where()` method and its associated `WhereClause` object. This allows you to build complex queries based on various conditions. You can filter records by equality (`equals()`), inequality (`notEqual()`), range (`between()`, `above()`, `below()`), and pattern matching (`startsWith()`, `equalsIgnoreCase()`). The `anyOf()` and `noneOf()` methods enable querying for multiple values, making your data retrieval flexible and powerful. + +-------------------------------- + +### Collection > Collection.raw() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.raw()` method retrieves the raw data from the collection without applying any object mapping or class instantiation. This can be useful for performance-critical scenarios or when you need the exact data as stored in IndexedDB. + +-------------------------------- + +### Table > Table.put() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js's `Table.put()` method inserts or updates a record in a table. If a record with the same primary key already exists, it will be updated; otherwise, a new record will be inserted. This is a fundamental method for saving data, especially when dealing with synchronization or when the existence of a record is uncertain. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/cloud/best-practices + +Transactions are fundamental to maintaining data integrity in IndexedDB and are well-supported by Dexie.js. A transaction groups a set of database operations together, ensuring that they are either all completed successfully or none of them are. Dexie.js provides hooks for transaction events such as `Transaction.on.complete` and `Transaction.on.error`, allowing you to react to the outcome of a transaction. The `Transaction.table()` method can be used to access a specific table within the current transaction. + +-------------------------------- + +### Quick Reference > Add Items + +Source: https://dexie.org/docs/API-Reference + +Adding items to your Dexie database can be done using either `add()` for single objects or `bulkAdd()` for adding multiple objects efficiently. Both methods return promises that resolve when the operation is complete. These methods are fundamental for populating your database with data. + +-------------------------------- + +### Collection > Collection.keys() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.keys()` method retrieves all primary keys from a collection. This is useful when you only need the identifiers of the records that match your query criteria. + +-------------------------------- + +### API Reference > IndexSpec + +Source: https://dexie.org/docs/roadmap/dexie5 + +Index specifications (`IndexSpec`) are used to define indexes on your tables, enabling efficient querying and data retrieval. You can create single-field indexes, compound indexes, and multi-entry indexes. Proper index definition is crucial for performance, especially with large datasets. + +-------------------------------- + +### DBCore > DBCoreTable + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `DBCoreTable` interface represents a table within the `DBCore` API. It provides methods for performing basic operations like adding, getting, and deleting records. + +-------------------------------- + +### Docs Home > Y.js > y-dexie + +Source: https://dexie.org/docs/cloud/UserLogin + +Y.js is a CRDT (Conflict-free Replicated Data Type) framework that enables real-time collaboration and offline-first applications. `y-dexie` is an adapter that integrates Y.js with Dexie.js, allowing you to leverage Dexie.js as the persistence layer for Y.js documents. This combination facilitates building robust collaborative applications with offline capabilities. + +-------------------------------- + +### Libs > dexie-react-hooks + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `dexie-react-hooks` library provides a set of React hooks for interacting with Dexie.js databases. These hooks simplify common tasks such as fetching live query results (`useLiveQuery`), managing documents (`useDocument`), observing observable data (`useObservable`), and handling permissions (`usePermissions`). This library streamlines the integration of Dexie.js into React applications. + +-------------------------------- + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.first()` method retrieves the first record from a collection based on the current order. This is an efficient way to get a single record, often used + +-------------------------------- + +### Example JSON File + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +The example JSON file demonstrates the structure described by `DexieExportJsonStructure`. It includes the `formatName`, `formatVersion`, and `data` properties. Within `data`, you can see the `databaseName`, `databaseVersion`, an array of `tables` with their schemas and row counts, and finally, the `data` array containing objects for each table, including its `tableName`, `inbound` status, and `rows` of data. This structure is essential for correctly importing and exporting Dexie databases. + +-------------------------------- + +### Dexie.js API Documentation > Transaction + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Transactions in Dexie.js are essential for grouping database operations to ensure atomicity, consistency, isolation, and durability (ACID). Key methods include `Transaction.abort()` for canceling a transaction and `Transaction.table()` for accessing a specific table within the transaction. Event hooks like `Transaction.on.abort`, `Transaction.on.complete`, and `Transaction.on.error` allow for handling transaction lifecycle events. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.name` property simply returns the name of the table as a string. This is a straightforward way to access the identifier of the table you are currently working with. + +-------------------------------- + +### Docs Home > Libs > liveQuery() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `liveQuery()` function is a core feature that enables reactive queries in Dexie.js. It returns an observable that emits new results whenever the underlying data changes, ensuring that your application stays synchronized with the database in real-time. This is fundamental for dynamic user interfaces. + +-------------------------------- + +### replacePrefix() operator + +Source: https://dexie.org/docs/PropModification/replacePrefix%28%29 + +Performs a sync-consistent replacement of the leading parts of a string. The operation can be performed in order to consistently move sub trees when syncing data using Dexie Cloud. + +-------------------------------- + +### Collection > Methods > clone() + +Source: https://dexie.org/docs/Collection/Collection + +Clone the query before manipulating it further (Does not clone database items). + +-------------------------------- + +### Docs Home > Cloud > db.cloud.login() + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The `db.cloud.login()` method is the primary function for authenticating users with Dexie Cloud. It typically accepts user credentials or authentication tokens and establishes a logged-in session. This method is fundamental for securing your application and ensuring that only authenticated users can access protected resources. + +-------------------------------- + +### Storing real classes instead of just interfaces + +Source: https://dexie.org/docs/Typescript-old + +The `Contact` class serves as a practical example of a 'physical' class mapped to the `contacts` table. This class includes methods like `loadEmailsAndPhones()` for fetching related data and `save()` for persisting changes, including related email and phone entries. These methods demonstrate how you can implement business logic directly within your database objects. The `loadEmailsAndPhones()` method retrieves associated email and phone records, populating `emails` and `phones` array properties of the `Contact` instance. The `save()` method handles the complex task of synchronizing these arrays back to the database, ensuring data integrity by managing additions, updates, and deletions of related records. + +-------------------------------- + +### Cloud > db.realms + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `db.realms` collection pertains to the concept of 'realms' within Dexie Cloud, which often represent distinct sets of data or environments. This could be used for multi-tenancy scenarios or to segregate data for different purposes. Managing realms allows you to structure and isolate data effectively. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The roadmap for Dexie 5.0 outlines the planned features and improvements for the next major version of Dexie.js. This includes potential enhancements to the API, performance optimizations, and new functionalities aimed at further simplifying database development. Keeping an eye on the roadmap helps developers anticipate future changes and plan their projects accordingly. + +-------------------------------- + +### Libs > liveQuery() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `liveQuery()` function is a core feature that enables reactive queries. When you use `liveQuery()`, Dexie.js automatically tracks dependencies within the query. If any data relevant to the query changes, `liveQuery()` will re-execute the query and notify subscribers of the updated results. This is fundamental for building dynamic user interfaces that reflect real-time data changes. + +-------------------------------- + +### Dexie.js Documentation > Typescript + +Source: https://dexie.org/docs/Deprecations + +Dexie.js supports TypeScript for improved type safety and developer productivity. You can define your database schema using TypeScript interfaces and types, which enables compile-time checks and better autocompletion. This integration helps prevent common errors and makes it easier to refactor your database code. The library's typings are comprehensive, covering all aspects of the Dexie API. + +-------------------------------- + +### Dexie.js API Documentation > PropModification + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js offers operators for property modification within database operations. These include the `add()` operator for incrementing values, the `remove()` operator for decrementing values, and the `replacePrefix()` operator for string manipulation in indexed fields. These operators allow for more complex in-place modifications. + +-------------------------------- + +### IndexSpec > Properties > src + +Source: https://dexie.org/docs/IndexSpec + +The `src` property within an `IndexSpec` object holds a canonical string representation of how the index specification was generated. This canonical form is crucial for the Dexie upgrade framework, as it allows Dexie to compare index specifications across different database versions and detect necessary schema changes or migrations. + +-------------------------------- + +### Libs > dexie-react-hooks + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `dexie-react-hooks` library offers React hooks for seamlessly integrating Dexie.js into React applications. Hooks like `useLiveQuery()` provide real-time subscriptions to data changes, `useDocument()` fetches individual documents, and `usePermissions()` manages access control. These hooks abstract away much of the boilerplate code, making it easier to work with Dexie.js in a React context. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/Releasing-Dexie + +Transactions are fundamental to maintaining data integrity in IndexedDB. Dexie.js provides a robust transaction API. `Transaction.abort()` allows you to explicitly abort a transaction. You can also listen to transaction events like `Transaction.on.abort`, `Transaction.on.complete`, and `Transaction.on.error` to react to different transaction outcomes. `Transaction.table(tableName)` provides access to a specific table within the transaction's scope. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The Dexie.js roadmap outlines the planned features, improvements, and future directions for the library. Version 5.0 represents a significant upcoming release, and this section details the anticipated changes, new functionalities, and potential breaking changes that developers can expect. It helps the community stay informed about the library's evolution. + +-------------------------------- + +### Libs + +Source: https://dexie.org/docs/Releasing-Dexie + +The `dexie-react-hooks` library provides a set of React hooks for easily integrating Dexie.js into your React applications. `useLiveQuery()` is particularly useful for creating reactive queries that automatically update when the underlying data changes. `useObservable()` allows you to observe Dexie.js streams, and `useDocument()` simplifies working with individual documents. `usePermissions()` helps manage access control within your React components. + +-------------------------------- + +### Dexie.js API Documentation > Dexie + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie.js defines a comprehensive set of error types to help developers identify and handle specific issues that may arise during database operations. These errors include `Dexie.PrematureCommitError`, `Dexie.QuotaExceededError`, `Dexie.ReadOnlyError`, `Dexie.SchemaError`, `Dexie.SubTransactionError`, `Dexie.TimeoutError`, `Dexie.UnknownError`, `Dexie.UnsupportedError`, `Dexie.UpgradeError()`, `Dexie.VersionChangeError`, and `Dexie.VersionError`. Additionally, there is a general `DexieError` base class for all Dexie-related errors. + +-------------------------------- + +### Docs Home > Getting Started > Started with Dexie in Svelte + +Source: https://dexie.org/docs/cloud/UserLogin + +This tutorial focuses on integrating Dexie.js with Svelte applications. It provides step-by-step instructions and examples for setting up Dexie.js, defining schemas, and interacting with your database from Svelte components. Discover how Dexie.js can simplify data persistence in your Svelte projects. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +For more advanced querying with `WhereClause`, you can utilize methods like `anyOf()`, `noneOf()`, `startsWith()`, and their case-insensitive counterparts. `anyOf()` is useful for checking if a value exists in a list of possibilities, while `startsWith()` enables prefix-based searches, which can be particularly handy for text fields. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie Cloud supports running on your own servers, offering flexibility and control over your data infrastructure. The documentation for `Dexie Cloud on Own Servers` would provide guidance on setting up, configuring, and managing a self-hosted Dexie Cloud instance, allowing organizations to meet specific compliance or operational requirements. + +-------------------------------- + +### Dexie.js Documentation > Version + +Source: https://dexie.org/docs/Deprecations + +The `Version` object in Dexie.js is central to database schema management and upgrades. When you define your database schema using `db.version(versionNumber).stores({...})`, you are creating a new version of your database. The `upgrade()` method is used to define the logic for migrating data from an older version to a newer one. This includes creating or modifying tables, adding indexes, and migrating data, ensuring a smooth transition as your database schema evolves. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.startsWithAnyOf()` method allows you to find records where an indexed string property starts with any of the prefixes provided in an array. This enables searching for multiple possible starting patterns efficiently. + +-------------------------------- + +### Dexie.js API Documentation > WhereClause + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause` object is used for creating complex queries in Dexie.js. It allows you to filter data based on various conditions, including equality (`equals()`), ranges (`between()`, `above()`, `below()`), and pattern matching (`startsWith()`). You can also combine multiple conditions using logical OR (`anyOf()`) or AND operations implicitly by chaining `where()` clauses. Case-insensitive comparisons are also supported. + +-------------------------------- + +### Export and Import Database > Usage + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +The `peakImportFile(blob)` function, available since v1.0.0, is designed for scenarios where you need to inspect the metadata of an import file without initiating a full import. This can be useful for validation or for displaying information about the database contained within the file to the user before they confirm the import. The function returns an object containing `formatName`, `formatVersion`, and `data`, which itself includes `databaseName`, `databaseVersion`, and a list of `tables` with their respective row counts. This allows for detailed pre-import analysis. + +-------------------------------- + +### Docs Home > Libs > dexie-react-hooks > liveQuery() + +Source: https://dexie.org/docs/cloud/index + +The `liveQuery()` function is a core feature for reactive programming with Dexie.js. It enables you to create observables that emit new values whenever the underlying data in the database changes. This is fundamental for building real-time user interfaces that automatically reflect the latest data. + +-------------------------------- + +### Collection > Collection.primaryKeys() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.primaryKeys()` method is an alias for `Collection.keys()`, both retrieving all primary keys from a collection. + +-------------------------------- + +### Docs Home > Cloud > db.roles + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `db.roles` property in Dexie.js is part of the Dexie Cloud's access control system. It provides access to the defined roles within your application, allowing you to manage user roles and their associated permissions. This is fundamental for implementing role-based access control (RBAC). + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +Dexie.js 5.0 Roadmap outlines the planned features and improvements for the next major version of the library. This typically includes enhancements to performance, new API features, better support for emerging web standards, and potentially significant architectural changes. Reviewing the roadmap helps users anticipate future capabilities and plan their projects accordingly. + +-------------------------------- + +### Cloud > db.cloud.permissions() + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `db.cloud.permissions()` method provides a way to interact with the permission system in Dexie Cloud. It allows you to query or manage permissions associated with users, roles, or specific data items. This is fundamental for implementing fine-grained access control in your application, ensuring that users can only perform actions they are authorized to. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Transaction.table()` method allows you to get a reference to a specific table within the current transaction. This is useful for performing operations on a particular table inside a transaction block. + +-------------------------------- + +### Cloud > DBPermissionSet, DexieCloudOptions, Invite, Member, PersistedSyncState, Realm, Role, SyncState + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +Dexie.js Cloud introduces several data structures and concepts for managing cloud-based applications. These include `DBPermissionSet` for defining permission sets, `DexieCloudOptions` for configuring cloud settings, `Invite` for user invitations, `Member` for managing users, `PersistedSyncState` for tracking sync status, `Realm` for data partitioning, `Role` for user roles, and `SyncState` for the overall synchronization status. + +-------------------------------- + +### Roadmap + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The roadmap for Dexie 5.0 outlines planned features and improvements for the next major version. This includes potential enhancements to the API, performance optimizations, and new functionalities to further streamline database development. + +-------------------------------- + +### Build and deploy > How can I bundle my app as a native app for iOS and Google Play? + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +Make sure your app is a solid PWA first. PWAs are the best starting point for native packaging. + +Choose a tool: + * Capacitor: follow its setup docs to add platforms, copy the web build into the native projects and run builds with Xcode (iOS) and Android Studio (Android). + * Electron: follow its docs to wrap your web build in a desktop runtime — build the web UI, create a small main process that loads the built files, and use builders like `electron-builder` or `electron-forge` to produce installers; remember to configure signing/notarization and auto-updates. + * PWABuilder / TWA: use PWABuilder to generate an Android TWA wrapper or follow the TWA docs to create an AAB that links to your hosted PWA. + +Configure platform-specific settings: app id/package name, icons and splash screens, permissions, and any native plugins you need. + +Test on real devices and use platform tooling (Xcode for iOS, Android Studio / bundletool for Android) to create release builds and sign them. + +Follow the store submission guides to publish on App Store and Google Play (you'll need developer accounts, app listing assets, privacy policy, etc.). + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Transactions are fundamental to ensuring data integrity in IndexedDB. Dexie.js simplifies transaction management. You can initiate a transaction using `db.transaction('tableName', 'readwrite', async () => { ... })`. Within the transaction callback, you can access table objects and perform operations. Dexie automatically handles commit and abort based on whether an error occurs. Key transaction events like `on.complete`, `on.abort`, and `on.error` can be subscribed to for custom logic. + +-------------------------------- + +### Libs > dexie-react-hooks + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +The `dexie-react-hooks` library provides a set of React hooks that make it easier to use Dexie.js in your React applications. `useLiveQuery` is particularly powerful, allowing you to create reactive queries that automatically update your components when the underlying data changes. `useDocument` is useful for fetching and subscribing to individual documents. + +-------------------------------- + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides `Dexie.getDatabaseNames()` which returns + +-------------------------------- + +### DBCoreQuery + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `DBCoreQuery` interface is a fundamental part of Dexie's internal query mechanism. It defines a query by specifying both the `index` (which is of type `DBCoreIndex`) and the `range` (which is of type `KeyRange`). This structure allows Dexie to efficiently translate higher-level query operations into the low-level operations required by the underlying database, such as IndexedDB. It's crucial for understanding how Dexie optimizes data retrieval and filtering. + +-------------------------------- + +### WhereClause > WhereClause.startsWith() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.startsWith()` method is used to filter records where a string property begins with a specified prefix. This is particularly useful for searching text data. + +-------------------------------- + +### Version > Version.stores() + +Source: https://dexie.org/docs/DerivedWork + +The `Version.stores()` method is crucial for defining your database schema. It allows you to specify the object stores (tables) and their indexes, which are essential for efficient data retrieval and manipulation. Proper schema definition is key to a well-performing IndexedDB application. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +Dexie Cloud offers best practices for building scalable and reliable applications. This includes strategies for handling data consistency, managing synchronization states, and optimizing performance. Concepts like `Consistency in Dexie Cloud` and `Sharding and Scalability` are important for ensuring your application can handle growth and maintain data integrity. + +-------------------------------- + +### Y.js > y-dexie + +Source: https://dexie.org/docs/DerivedWork + +Y.js is a CRDT (Conflict-free Replicated Data Type) framework that enables collaborative editing and real-time synchronization of data. The `y-dexie` library acts as a connector, allowing you to persist Y.js documents in a Dexie.js database. This combination is powerful for building applications that require offline support and real-time collaboration features, ensuring data consistency across multiple clients. + +-------------------------------- + +### Dexie.js Documentation + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +Dexie.js provides several methods for interacting with tables. `Table.toCollection()` returns a `Collection` of all objects in the table. `Table.update()` allows you to update one or more records based on their primary keys. `Table.upsert()` is a convenient method that inserts a new record if it doesn't exist or updates it if it does. `Table.where()` is used to create a `WhereClause` object, which enables powerful querying capabilities based on various conditions. + +-------------------------------- + +### Understanding the basics > Understanding the flow > First time + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +The first time a browser hits the appdb.js code, the following happens: + 1. The database is created + 2. The populate event is triggered to allow the developer to populate the database + 3. The db.open() promise resolves + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Methods like `WhereClause.above()`, `WhereClause.below()`, and `WhereClause.between()` allow you to perform range-based queries on indexed fields. These are essential for efficiently retrieving data within specific numerical or date ranges. + +-------------------------------- + +### Dexie.js API Documentation > WhereClause + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +The `WhereClause` object in Dexie.js is used to construct queries based on specific conditions. It provides a wide range of methods for filtering data, including equality checks (`equals()`, `equalsIgnoreCase()`), range checks (`above()`, `aboveOrEqual()`, `below()`, `belowOrEqual()`, `between()`, `inAnyRange()`), set membership (`anyOf()`, `anyOfIgnoreCase()`, `noneOf()`), inequality (`notEqual()`), and string prefix matching (`startsWith()`, `startsWithAnyOf()`, `startsWithAnyOfIgnoreCase()`, `startsWithIgnoreCase()`). + +-------------------------------- + +### WhereClause > WhereClause.startsWithAnyOf() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.startsWithAnyOf()` method filters records where a specific property's string value begins with any of the prefixes provided in an array. This allows for more flexible prefix matching, accommodating multiple possible starting patterns. + +-------------------------------- + +### Table > Table.delete() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Table.delete()` method in Dexie.js is used to remove a specific record from a table. You provide the primary key of the record you wish to delete. This operation is performed within a transaction and will throw an error if the record does not exist or if the transaction is not in a writeable state. It's a fundamental method for managing data lifecycle. + +-------------------------------- + +### Docs Home > Cloud > db.roles + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The `db.roles` property allows you to interact with and manage user roles defined within Dexie Cloud. Roles are a fundamental part of access control, enabling you to group users and assign specific permissions to these groups, thereby simplifying permission management across your application. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.mapToClass()` method is an alternative to `defineClass()` for associating a JavaScript class with a table. It serves a similar purpose, enabling you to work with table records as instances of your custom class. This integration helps in creating a more structured and object-oriented approach to data management within your application. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +The `Transaction` object in Dexie.js represents a database transaction. Transactions are the fundamental mechanism for ensuring data integrity and consistency in IndexedDB. All database operations, such as reading and writing data, must be performed within a transaction. Dexie.js abstracts away much of the complexity of manual transaction management, but understanding the transaction lifecycle and its associated events is crucial for handling complex operations and errors effectively. + +-------------------------------- + +### Tutorial > Best Practices + +Source: https://dexie.org/docs/Collection/Collection + +Best practices for using Dexie.js involve understanding its asynchronous nature, proper transaction management, and efficient querying. Following these practices can lead to more performant and maintainable applications. This includes leveraging Dexie's capabilities for schema versioning and handling potential errors gracefully. + +-------------------------------- + +### Libs > dexie-react-hooks > useDocument() + +Source: https://dexie.org/docs/dexie-react-hooks/useDocument%28%29 + +The `useDocument` hook returns a `DexieYProvider` which can be passed to child components. This provider manages the loading and updating of the document. When `dexie-cloud-addon` is utilized with a configured Dexie Cloud database, the provider also enables sync and awareness features. This integration is designed to work smoothly with existing Y.js-compatible text editors and tools, providing a unified experience for collaborative editing. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +Transactions are fundamental to IndexedDB operations, ensuring data integrity by allowing operations to be performed atomically. Dexie.js simplifies transaction management. You can abort a transaction if an error occurs, and Dexie.js provides event listeners for `abort`, `complete`, and `error` events on transactions, allowing you to react to transaction lifecycle changes. The `transaction.table()` method allows you to access a specific table within the transaction context. + +-------------------------------- + +### API Reference > Collection > Collection.eachKey() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.eachKey()` method iterates over the primary keys of the records in a collection. It's more efficient than `each()` if you only need to process the keys of the matching records, for example, to perform further operations based on these keys. + +-------------------------------- + +### API Reference > Table + +Source: https://dexie.org/docs/cloud/consistency + +The `Table.schema` property provides detailed information about the schema of a table within Dexie.js. This includes details about the primary key, indexes, and other schema-related configurations. Understanding the table schema is crucial for optimizing queries and ensuring data integrity. It allows developers to inspect how data is structured and how indexes are defined, which can aid in performance tuning and debugging. + +-------------------------------- + +### Summary > Handy functions > persist + +Source: https://dexie.org/docs/StorageManager + +This function attempts to convert to persisted storage. It returns a promise resolved with `true` if storage was successfully persisted, `false` if not, and `undefined` if the API is not present. + +-------------------------------- + +### Libs > dexie-react-hooks + +Source: https://dexie.org/docs/Promise/unhandledrejection-event + +The `dexie-react-hooks` library provides a set of React hooks that simplify the integration of Dexie.js into React applications. Hooks like `useLiveQuery` allow you to easily fetch and subscribe to data changes, automatically re-rendering your components when the data updates. Other hooks provide utilities for managing documents, permissions, and observations. + +-------------------------------- + +### Dexie.js Documentation > WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +The `WhereClause` object in Dexie.js provides a rich set of methods for filtering and querying data. You can perform equality checks with `WhereClause.equals()` and `WhereClause.equalsIgnoreCase()`. Range-based queries can be done using `WhereClause.above()`, `WhereClause.aboveOrEqual()`, `WhereClause.below()`, `WhereClause.belowOrEqual()`, and `WhereClause.between()`. For more complex matching, methods like `WhereClause.anyOf()`, `WhereClause.anyOfIgnoreCase()`, `WhereClause.noneOf()`, and `WhereClause.inAnyRange()` are available. String-specific queries include `WhereClause.startsWith()`, `WhereClause.startsWithAnyOf()`, `WhereClause.startsWithAnyOfIgnoreCase()`, and `WhereClause.startsWithIgnoreCase()`. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The `WhereClause.startsWith()` method is used to find records where a string property begins with a specified prefix. This is a common requirement for implementing search functionalities like autocomplete suggestions. + +-------------------------------- + +### Dexie.js API Documentation > Libs > dexie-react-hooks + +Source: https://dexie.org/docs/cloud/UserLogin + +The `dexie-react-hooks` library provides React hooks for seamlessly integrating Dexie.js into your React applications. These hooks abstract away the complexities of managing database connections and subscriptions, allowing you to easily fetch and observe data in a declarative way. `useLiveQuery` is particularly useful for creating reactive UI components that automatically update when the underlying database changes. + +-------------------------------- + +### API Reference > Transaction + +Source: https://dexie.org/docs/cloud/consistency + +The `Transaction.table()` method allows you to access a specific table within the current transaction context. This is useful when you need to perform operations on a particular table inside a transaction. It ensures that all operations within the transaction are consistent and atomic. + +-------------------------------- + +### Safari Issues + +Source: https://dexie.org/docs/safari-issues + +This section details specific issues encountered when using Dexie.js with the Safari browser. It aims to provide solutions or workarounds for these problems, ensuring a smoother development experience for users targeting Safari. + +Safari has certain JavaScript engine quirks and IndexedDB implementations that can differ from other browsers. These differences might lead to unexpected behavior in some Dexie.js operations. The goal of this documentation is to make these issues transparent and offer practical advice. + +-------------------------------- + +### Promise-Specific Data (zone) + +Source: https://dexie.org/docs/API-Reference + +Dexie.js incorporates a Promise-specific data mechanism, similar in concept to Thread-local storage or Angular's zone.js, but without requiring external scripts or monkey-patching. This feature allows static properties to be associated with the currently executing Promise and its child Promises. This is crucial for Dexie's transaction API, as it enables code to be context-aware of the active transaction without the need for explicit transaction object passing. + +-------------------------------- + +### Example: A Simple Project Management Model > addTask + +Source: https://dexie.org/docs/cloud/access-control + +The `addTask()` function allows for the addition of new tasks to a project. It requires the project object, the task's title, and its description. Within a transaction, it adds a new record to the `db.tasks` table, associating the task with the `projectId` and `realmId` of the parent project. The 'done' status is initialized to 0, and the description is stored. + +-------------------------------- + +### Dexie.js > API Reference > DBCore + +Source: https://dexie.org/docs/safari-issues + +Dexie.js utilizes `DBCore`, which represents the core database interface. This layer abstracts the underlying IndexedDB API and provides a more consistent and predictable interface for Dexie.js operations. `DBCore` deals with fundamental database interactions like opening connections, managing transactions, and executing CRUD operations. Understanding `DBCore` can be helpful for advanced users or when debugging complex issues, as it exposes the low-level mechanisms through which Dexie.js interacts with the browser's IndexedDB implementation. + +-------------------------------- + +### Dexie-worker > Inbound + +Source: https://dexie.org/docs/cloud/Member + +This section discusses inbound operations or data flow into your Dexie.js database. It might cover methods for importing data, handling external data sources, or processing incoming information before storing it. + +-------------------------------- + +### Libs > liveQuery() + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +The `liveQuery()` function from Dexie.js enables you to create reactive queries. When you wrap a Dexie query with `liveQuery()`, it returns an observable that emits new results whenever the data queried is changed. This is fundamental for building dynamic user interfaces that reflect real-time data updates without manual polling. + +-------------------------------- + +### Best Practices > Understand Promises + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Make sure you learn at least the basic practices of A+ promises before diving too deep into Dexie. Understanding promises is crucial for effective asynchronous programming, especially when dealing with operations that return promises, such as database queries and API calls. This knowledge will help you write cleaner, more predictable, and more maintainable code, regardless of the libraries or frameworks you use. + +-------------------------------- + +### 4. Turn App into an Offline ToDo app + +Source: https://dexie.org/docs/Tutorial/Angular + +This sample demonstrates building a To-Do application with two components. For simplicity, these components interact directly with the database. In a production environment, it's advisable to route database actions and queries through dedicated services for better organization and maintainability. + +-------------------------------- + +### API Reference > Dexie + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The main `Dexie` constructor is the entry point for creating and managing your database. You can instantiate it with a database name and schema definition. Key methods include `Dexie.open()` to open the database, `Dexie.close()` to close it, and `Dexie.transaction()` to perform atomic operations. You can access tables via `Dexie.table('[tableName]')` or `Dexie.tables`. The `Dexie` object also exposes properties like `Dexie.verno` for the current database version and `Dexie.name` for the database name. Event listeners can be attached using `Dexie.on()` for events like `ready`, `populate`, `error`, and `close`. + +-------------------------------- + +### Cloud > db.realms + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +The `db.realms` object in Dexie Cloud pertains to the concept of realms, which are isolated environments for your data synchronization. Realms allow you to segregate data for different applications, tenants, or user groups, ensuring data privacy and organization. Managing realms through `db.realms` is key to structuring complex, multi-tenant applications. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/index + +The `Table` object in Dexie.js exposes properties like `name` and `schema` to provide information about the table's structure and its defined schema. The `name` property returns the name of the table, while `schema` provides access to the schema definition, which can be useful for introspection or dynamic operations. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The Roadmap for Dexie 5.0 outlines the planned features, improvements, and architectural changes for the upcoming major version of Dexie.js. This typically includes enhancements to the API, performance optimizations, new functionalities, and potentially breaking changes that developers should be aware of when planning their upgrades. Reviewing the roadmap helps the community understand the future direction of Dexie.js and prepare for new releases. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +This section likely covers best practices for utilizing Dexie Cloud effectively. It may include recommendations on database schema design for optimal synchronization, strategies for handling data consistency across devices, and efficient ways to manage user permissions and roles. Following these best practices can help ensure a smooth and reliable experience for your users and a more maintainable application. + +-------------------------------- + +### Docs Home > Getting Started > Started with Dexie in Vue + +Source: https://dexie.org/docs/cloud/UserLogin + +This tutorial demonstrates how to get started with Dexie.js in Vue.js applications. It covers the essential steps for initializing Dexie, defining your database schema, and performing data operations within your Vue components. Learn to seamlessly integrate Dexie.js for efficient data handling in your Vue projects. + +-------------------------------- + +### Dexie.js Documentation > Libs > dexie-react-hooks + +Source: https://dexie.org/docs/Deprecations + +Dexie.js provides official React hooks to simplify working with Dexie.js in React applications. The `useLiveQuery()` hook is particularly useful for subscribing to data changes and automatically re-rendering your components when the data changes. Other hooks like `useDocument()` and `useObservable()` offer more granular control over data fetching and state management, enabling you to build responsive and data-driven React UIs with ease. + +-------------------------------- + +### Docs Home > Cloud > Add demo users + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This guide explains how to add demo users to your Dexie Cloud application. Creating demo users is helpful for testing authentication flows, permission settings, and overall application behavior without requiring real user accounts. It simplifies the development and testing process. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.startsWith()` method queries records where an indexed string property begins with a specified prefix. This is efficient for performing prefix-based searches on text data. + +-------------------------------- + +### Cloud > Dexie Cloud on Own Servers + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Deploying Dexie Cloud on your own servers offers greater control over your infrastructure and data. This guide likely covers the steps involved in setting up a self-hosted Dexie Cloud environment, including server requirements, configuration, and maintenance. It's an option for organizations with specific security or compliance needs. + +-------------------------------- + +### API Reference > IndexSpec + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +When defining your database schema, you can specify `IndexSpec` objects to create indexes on your tables. An `IndexSpec` allows you to define the key path(s) for the index, whether it's a unique index, and if it should be a multi-entry index. You can also specify the order of the index (ascending or descending). Properly defined indexes are crucial for optimizing query performance, especially for large datasets, as they enable faster lookups and sorting. + +-------------------------------- + +### Docs Home > Tutorial > ...rted with Dexie in React + +Source: https://dexie.org/docs/Typescript-old + +Dexie.js integrates well with various JavaScript frameworks, including Angular, React, and Vue. The documentation provides specific tutorials for getting started with Dexie in each of these frameworks, highlighting how to set up the database and use Dexie's features within the framework's ecosystem. This enables developers to leverage Dexie's power in their preferred development environment. + +-------------------------------- + +### Collection > Collection.each() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.each()` method iterates over each record in the collection, executing a callback function for each one. This is an efficient way to process records one by one without loading the entire result set into memory. You can stop the iteration early by returning `false` from the callback. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.currentUserId + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `db.cloud.currentUserId` property returns the unique identifier of the currently logged-in user in Dexie Cloud. This ID can be used to associate data with specific users, implement access control, and perform user-centric operations within your application. It's a fundamental piece of information for managing user data. + +-------------------------------- + +### Docs Home > Transaction + +Source: https://dexie.org/docs/Dexie/Dexie.on + +The `Transaction.table()` method provides a way to access a specific table within the current transaction. This is useful for performing operations on a particular table without needing to specify its name repeatedly. + +-------------------------------- + +### Indexable Type + +Source: https://dexie.org/docs/Indexable-Type + +The following javascript types are possible to index: + * number + * Date + * string + * ArrayBuffer + * Typed arrays (Uint8Array, Float32Array, ..., etc) + * Arrays of (strings, numbers, Dates, ArrayBuffer, Typed array) or a mix of those. + +Note that all other types are non-indexable, including: + * boolean + * undefined + * Object + * null + +-------------------------------- + +### Dexie.js Documentation > Transaction + +Source: https://dexie.org/docs/Deprecations + +The `Transaction` object in Dexie.js represents a database transaction, which is a sequence of operations performed as a single logical unit of work. Transactions ensure data integrity by allowing operations to be either all committed or all aborted. You can interact with tables within a transaction using `transaction.table()`. Dexie also provides event hooks for `abort`, `complete`, and `error` events, allowing you to manage transaction lifecycle and handle potential issues gracefully. + +-------------------------------- + +### Docs Home > Typescript + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This section covers the Typecript support in Dexie.js, including how to leverage TypeScript for enhanced type safety and developer productivity. Learn about the available types and interfaces that facilitate working with Dexie in a strongly-typed environment. + +-------------------------------- + +### Cloud > Custom Emails + +Source: https://dexie.org/docs/cloud/index + +Dexie Cloud provides customization options for emails sent to users, such as invitation emails or password reset emails. The `Custom Emails in Dexie Cloud` documentation likely details how to configure these email templates and integrate them with your application's user management. This allows for a branded and personalized user experience. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/cloud/limits + +The `Table.schema` property in Dexie.js provides information about the schema of a specific table. This includes details about the primary key, indexes, and other constraints defined for the table. It allows you to inspect the table's structure programmatically. + +-------------------------------- + +### Collection > Collection.count() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.count()` method returns the number of records that match the current query criteria. This is useful for getting the size of a filtered or sorted result set without retrieving all the matching records. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.startsWithAnyOf() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.startsWithAnyOf()` method allows you to retrieve records where the indexed property (a string) starts with any of the prefixes provided in an array. This is useful for matching multiple potential starting patterns in a single query. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie Cloud provides a comprehensive set of features for managing access control and user permissions within your application. The `db.cloud.permissions()` method allows you to interact with the permission system, and related concepts like `DBPermissionSet`, `Member`, `Role`, and `UserLogin` define the structure and management of access rights. Features such as `Access Control in Dexie Cloud` and `Authentication in Dexie Cloud` highlight the security mechanisms in place to protect your data. + +-------------------------------- + +### Summary > Handy functions > showEstimatedQuota + +Source: https://dexie.org/docs/StorageManager + +This function queries the available disk quota. It returns a promise resolved with an object containing `quota` and `usage` numbers, or `undefined` if the API is not present. This function utilizes the `navigator.storage.estimate()` method. + +-------------------------------- + +### Cloud > Authentication in Dexie Cloud + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +Authentication in Dexie Cloud is handled through various methods, enabling secure user logins. You can integrate with existing authentication systems or use Dexie Cloud's built-in mechanisms. The documentation explains how to set up authentication, manage user sessions, and implement secure access to your synchronized data. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/Dexie/Dexie.on + +String matching methods such as `WhereClause.startsWith()`, `WhereClause.equalsIgnoreCase()`, and `WhereClause.startsWithIgnoreCase()` enable flexible text-based searches within your IndexedDB data. These are particularly useful for implementing search functionalities. + +-------------------------------- + +### Dexie.js Documentation > Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +Dexie Cloud is an optional add-on for Dexie.js that provides real-time synchronization, authentication, and authorization for your web applications. It simplifies the process of building collaborative and data-driven applications by handling complex backend synchronization logic. Key features include user management, role-based access control, and offline support. + +-------------------------------- + +### Example: A Simple Project Management Model > addComment + +Source: https://dexie.org/docs/cloud/access-control + +The `addComment()` function enables users to add comments to specific tasks. It takes the task object and the comment text as input. This function adds a new entry to the `db.comments` table, linking the comment to the task's ID and realm ID. It also records the timestamp of the comment. + +-------------------------------- + +### Summary > How to use it from your app > initStoragePersistence + +Source: https://dexie.org/docs/StorageManager + +This example demonstrates how to initialize storage persistence. It calls `tryPersistWithoutPromtingUser()` and logs a message indicating whether storage persistence is not possible, was successful silently, or if a user prompt might be needed later. + +-------------------------------- + +### Docs Home > Cloud > Add demo users + +Source: https://dexie.org/docs/cloud/UserLogin + +This guide explains how to add demo users to your Dexie.js Cloud application. Creating demo users is helpful for testing authentication flows, permission settings, and general application behavior without needing to create real user accounts. It streamlines the development and testing process. + +-------------------------------- + +### Samples in Summary + +Source: https://dexie.org/docs/MultiEntry-Index + +Dexie.js allows you to define your database schema and manage data through a fluent API. You can define your database name and versions, and then specify your object stores with their respective indexes. For example, the `books` store is defined with an `id` as the primary key and `author`, `name`, and `categories` as indexed properties. The `categories` property is marked as a MultiEntry index, allowing you to index and query based on individual elements within an array. Data insertion is straightforward using the `put` method, and you can retrieve data using various query methods like `where`, `equals`, `anyOf`, `startsWithAnyOfIgnoreCase`, and `or`. The `distinct` method can be used to ensure unique results. + +-------------------------------- + +### Cloud > Access Control in Dexie Cloud + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +Access Control in Dexie Cloud enables you to define granular permissions for users and roles, ensuring that data is only accessible to authorized individuals. You can manage permissions at the realm and table level, specifying which operations (read, write, delete) are allowed. This is fundamental for building secure, multi-user applications. + +-------------------------------- + +### Cloud > db.cloud.currentUserId + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `db.cloud.currentUserId` property returns the unique identifier of the currently logged-in user. This is a convenient way to access the user's ID for making authorization decisions, logging, or associating data with a specific user. It's a fundamental piece of information for managing user-specific data and permissions within your Dexie Cloud application. + +-------------------------------- + +### API Reference > Classes > Dexie + +Source: https://dexie.org/docs/API-Reference + +The `Dexie` class is the primary entry point for interacting with your IndexedDB database. You instantiate it with a database name and then define its schema using `version()` and `stores()`. This class provides methods for opening the database, managing versions, and accessing tables. + +-------------------------------- + +### Table > Table.mapToClass() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.mapToClass()` method allows you to associate a JavaScript class with a table. This means that when you retrieve records from this table, they will be instances of the specified class, enabling you to add custom methods and behavior to your data models. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie Cloud is a managed backend service for Dexie.js applications, providing features like authentication, authorization, real-time synchronization, and offline support. It simplifies the development of cloud-connected applications by handling much of the backend complexity. Key concepts include `DBPermissionSet`, `DexieCloudOptions`, `Invite`, `Member`, `PersistedSyncState`, `Realm`, `Role`, and `SyncState`. + +-------------------------------- + +### Table > Table.each() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Table.each()` method iterates over each record in a table or a collection, executing a callback function for each record. This is useful when you need to perform an action on every item without necessarily collecting them all into an array first. The callback function receives the record object and the primary key. For example, `db.friends.each(friend => console.log(friend.name))`. + +-------------------------------- + +### Cloud > Dexie Cloud REST API + +Source: https://dexie.org/docs/cloud/index + +Dexie Cloud offers a REST API that allows you to interact with your cloud database from external services or applications. The `Dexie Cloud REST API` documentation likely describes the available endpoints for data access, user management, and other cloud functionalities. This enables integration with other systems and backend services. + +-------------------------------- + +### Dexie.js Documentation > Cloud + +Source: https://dexie.org/docs/Deprecations + +Dexie.js offers a robust solution for real-time data synchronization and collaboration through Dexie Cloud. This cloud service allows you to easily synchronize data across multiple clients and users, manage permissions, and handle authentication. Features include real-time updates, conflict resolution, and a comprehensive API for integrating cloud functionalities into your application. Dexie Cloud also provides tools for managing users, roles, and permissions, ensuring secure access to your data. + +-------------------------------- + +### Docs Home > Libs > dexie-react-hooks > liveQuery() + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +The `liveQuery()` function, often used with `dexie-react-hooks`, is a powerful mechanism for creating reactive data subscriptions. When you wrap a Dexie query with `liveQuery()`, any changes to the queried data will automatically trigger an update to the observable returned by the function. This is fundamental for building real-time user interfaces that stay in sync with the database. + +-------------------------------- + +### Collection > Collection.last() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.last()` method retrieves the last record from the collection that matches the query criteria. If no records are found, it returns `undefined`. The order is determined by the sorting applied to the collection. + +-------------------------------- + +### Cloud > db.cloud.schema + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `db.cloud.schema` property provides access to the database schema definition as configured for Dexie Cloud. This includes information about tables, indexes, and relationships, which can be useful for introspection or dynamic operations. + +-------------------------------- + +### Cloud > db.cloud.login() + +Source: https://dexie.org/docs/Table/Table + +The `db.cloud.login()` and `db.cloud.logout()` methods are used for managing user authentication within Dexie Cloud. `login()` initiates the authentication process, typically involving user credentials or a third-party provider. `logout()` terminates the current user's session. These methods are fundamental for securing your application's data and personalizing the user experience. + +-------------------------------- + +### Releasing Dexie + +Source: https://dexie.org/docs/cloud/web-hooks + +The 'Releasing Dexie' section likely contains information pertinent to the process of developing, testing, and publishing new versions of the Dexie.js library. This could include guidelines for contributors or details about the release management strategy. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.toCollection()` method returns a `Collection` object that represents all the records in the table. This `Collection` object can then be further manipulated using methods like `filter()`, `orderBy()`, `limit()`, and `offset()` to build complex queries. It's a foundational method for constructing queries that involve multiple filtering and sorting criteria. + +-------------------------------- + +### Dexie.js API Documentation > Cloud + +Source: https://dexie.org/docs/cloud/UserLogin + +Dexie Cloud is an optional add-on that provides real-time data synchronization, authentication, and authorization for your Dexie.js applications. It simplifies the process of building collaborative and offline-first applications by handling complex synchronization logic and security concerns. Key features include real-time updates, conflict resolution, and role-based access control. + +-------------------------------- + +### Table > Table.where() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.where()` method initiates a query on a table. You can chain subsequent methods like `equals()`, `above()`, `below()`, `startsWith()`, etc., to define the filtering conditions for your query. This is the primary way to retrieve specific records based on index values. + +-------------------------------- + +### Get started with Dexie Cloud > Bootstrapping + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +No matter if you create a brand new app or adjust an existing one, this tutorial will guide you through the steps. You can use whatever framework you prefer but in this tutorial we'll be showing some sample components in React, so if you start on an empty paper, I'd recommend using vite to bootstrap a react app: +``` +npm create vite@latest my-app -- --template react-ts +``` + +Make sure to have dexie-related dependencies installed: +``` +npm install dexie +npm install dexie-cloud-addon +npm install dexie-react-hooks # If you are using react +``` + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The `WhereClause` API offers specific methods for string matching, including `startsWith()`, `startsWithAnyOf()`, and `startsWithIgnoreCase()`. These methods are essential for performing prefix-based searches within your text data in Dexie.js. + +-------------------------------- + +### WhereClause > WhereClause.startsWith() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.startsWith()` method filters records where a specific property's string value begins with a specified prefix. This is useful for implementing prefix-based searches, such as autocompletion. + +-------------------------------- + +### API Reference > Table Schema + +Source: https://dexie.org/docs/Collection/Collection + +Dexie.js provides comprehensive support for defining and managing database schemas. You can define tables, their properties, and indexes. This includes support for primary keys, compound indexes, and multi-entry indexes, allowing for efficient data organization and retrieval. The `Dexie.version()` method is used to define schema changes across different database versions. + +-------------------------------- + +### Table > Table.count() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.count()` method returns the number of records in the table. This is a quick way to get the total number of items without fetching them all. It returns a Promise that resolves with the count. + +-------------------------------- + +### Tutorial > Design + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Understanding the design principles behind Dexie.js is key to using it effectively. Dexie aims to provide a clean, intuitive, and performant API for IndexedDB, abstracting away much of the complexity. Its design focuses on developer experience, making it easier to handle asynchronous operations, define schemas, and query data with minimal boilerplate. + +-------------------------------- + +### Libs > liveQuery() + +Source: https://dexie.org/docs/DerivedWork + +The `liveQuery()` function, often used with `dexie-react-hooks`, allows you to create reactive queries that automatically update your UI when the underlying data changes. It takes a Dexie.js query function and returns an observable that emits new results whenever the data matching the query is modified. This is a fundamental tool for building dynamic and real-time user interfaces. + +-------------------------------- + +### Permissions > update + +Source: https://dexie.org/docs/cloud/access-control + +Permission to update a given set of properties in a given set of tables. Allowing `"*"` will allow updating all non-reserved properties (all properties but `realmId` and `owner`). `"*"` represents all properties except the reserved properties (`owner` and `realmId`). If you have `{update: {todoItems: "*"}}` permission, you can change the todoItems `title`, `done` fields etc but not its `owner` or `realmId`. In order to grant permissions for all fields including `owner` and `realmId` you have to specify them explicitly. + +-------------------------------- + +### Docs Home > Cloud > Consistency in Dexie Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Consistency in Dexie Cloud refers to ensuring that data remains synchronized and accurate across all connected clients and devices. Dexie Cloud employs various mechanisms to maintain data integrity and resolve conflicts, providing a consistent view of the data to all users. This is fundamental for collaborative and multi-device applications. + +-------------------------------- + +### Dexie > Dexie Constructor + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie` constructor is the entry point for creating and managing your IndexedDB database. You typically instantiate `Dexie` with a database name and a version number. This constructor allows you to define your database schema, including tables and their structures. It also provides methods for opening, closing, and interacting with the database. + +Example: +`const db = new Dexie('myDatabase');` +`db.version(1).stores({ friends: '++id, name, age' });` + +-------------------------------- + +### Collection > Collection.toArray() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.toArray()` method retrieves all records matching the current query criteria from a collection and returns them as a JavaScript array. This is a common way to fetch all relevant data for display or further processing in your application after applying filters, limits, and sorts. + +-------------------------------- + +### IndexSpec + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `IndexSpec` interface defines the properties of an index within a Dexie table schema. It includes the index name, the key path(s) to index, and options like `unique` or `multiEntry`. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +Dexie Cloud is an optional add-on that provides synchronization capabilities for your Dexie.js databases. It enables real-time data synchronization across multiple clients and devices, handling conflicts and ensuring data consistency. The documentation covers various aspects of Dexie Cloud, including authentication, permissions, schema management, and best practices for building cloud-enabled applications. + +-------------------------------- + +### Docs Home > Tutorial > Consuming Dexie as a module + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Consuming Dexie.js as a module refers to the process of integrating the library into your project using module bundlers like Webpack or Rollup. This approach promotes modularity and allows for better code management and optimization. The documentation likely explains how to import and use Dexie.js within a module-based JavaScript or TypeScript project. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/TableSchema + +The TableSchema constructor defines the structure of a table within a Dexie database. It takes the table name, primary key specification, an array of index specifications, and an optional instance template as arguments. This schema is crucial for organizing data and enabling efficient querying. The properties of a TableSchema object include `name` (the object store's name), `primKey` (the primary key specification), `indexes` (a list of index properties), and `instanceTemplate` (an object populated with indexed properties used for IDE code completion). If `Table.defineClass()` or `Table.mapToClass()` is used, non-indexed properties are also included in the template, and the mapped constructor function is stored in `mappedClass`. + +-------------------------------- + +### Tutorial > Design + +Source: https://dexie.org/docs/inbound + +The design philosophy behind Dexie.js emphasizes developer experience and productivity. It aims to provide a high-level abstraction over IndexedDB, making it easier to write, understand, and maintain database-related code. Key design principles include a promise-based API, automatic schema management, and powerful querying capabilities, all contributing to a more streamlined development process. + +-------------------------------- + +### Collection > Collection.until() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.until()` method allows you to specify a condition to stop iterating over a collection. It takes a callback function that returns `true` when the iteration should stop. This is useful for finding the first record that meets a certain criterion within a potentially larger set. + +-------------------------------- + +### Questions and Answers + +Source: https://dexie.org/docs/cloud/web-hooks + +The 'Questions and Answers' section is a resource for common queries and their solutions related to Dexie.js. It serves as a FAQ or knowledge base where users can find answers to frequently asked questions or troubleshoot common issues. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section is dedicated to the TypeScript API of Dexie.js. It details the available types and interfaces for using Dexie.js with TypeScript, ensuring type safety and improved developer experience for TypeScript projects. + +-------------------------------- + +### Dexie-react-hooks > useLiveQuery() + +Source: https://dexie.org/docs/DerivedWork + +The `useLiveQuery()` hook is a core feature of `dexie-react-hooks`, enabling you to create reactive queries that automatically update your UI when the underlying data changes. It takes a Dexie.js query function as an argument and returns the results, re-rendering your component whenever new data is available. This hook is fundamental for building dynamic and responsive user interfaces with Dexie.js and React. + +-------------------------------- + +### Docs Home > Version + +Source: https://dexie.org/docs/Dexie/Dexie.on + +`Version.upgrade()` is a method used to define the logic that runs when upgrading the database to a new version. This is where you can migrate data, add new tables, or modify existing ones. + +-------------------------------- + +### Typescript > Simplest Typescript Example + +Source: https://dexie.org/docs/Typescript + +If you are storing plain data and just want the a minimal get-started code in a single module. You can extend this sample with additional tables and corresponding interfaces: +### db.ts +```typescript +import { Dexie, type EntityTable } from "dexie" + +interface Friend { + id: number // This prop will be used as primary key (see below) + name: string + age: number +} + +const db = new Dexie("FriendsDatabase") as Dexie & { + friends: EntityTable +} + +// Schema declaration: +db.version(1).stores({ + friends: "++id, name, age", // primary key "id" (for the runtime!) +}) + +export type { Friend } +export { db } +``` +_SeeEntityTable_ + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Dexie Cloud Best Practices outline recommended strategies for building scalable, secure, and performant applications using Dexie Cloud. These guidelines cover aspects like schema design, synchronization strategies, and error handling. + +-------------------------------- + +### Roadmap + +Source: https://dexie.org/docs/Releasing-Dexie + +Dexie.js has a public roadmap that outlines the future development of the library. The "Road Map: Dexie 5.0" section details the planned features, improvements, and changes for the upcoming major version. This provides users with insight into the direction of the project and allows them to anticipate new capabilities or potential breaking changes. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/index + +Dexie.js offers a set of table-level operations for data manipulation and querying. These include methods like `get()` for retrieving a single record, `put()` and `upsert()` for adding or updating records, and `delete()` for removing them. For retrieving multiple records, `toArray()` fetches all records, while `toCollection()` returns a collection that can be further filtered or manipulated. `limit()` and `offset()` are used for pagination, and `orderBy()` and `reverse()` for sorting results. `where()` is the entry point for defining query conditions. Additionally, `mapToClass()` allows you to map table rows to JavaScript classes, enabling object-oriented access to your data. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.startsWith() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.startsWith()` method is used to filter records where the indexed property (which must be a string) begins with a specified prefix. This is particularly useful for text-based searches and auto-completion features. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/DerivedWork + +The `WhereClause.startsWith()` and its case-insensitive variants (`startsWithAnyOfIgnoreCase`, `startsWithIgnoreCase`) are useful for performing prefix-based searches on string properties. This is commonly used for features like autocomplete or searching for names that begin with a certain string. + +-------------------------------- + +### Table > Table.put() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js offers a `Table.put()` method for inserting or updating records. If a record with the same primary key already exists, it will be updated; otherwise, a new record will be inserted. This is a fundamental operation for managing data. For example, `await db.friends.put({ id: 1, name: 'Alice', age: 25 });` will either update friend with id 1 or create a new one. + +-------------------------------- + +### Samples > Full-text search + +Source: https://dexie.org/docs/Table/Table + +Dexie's multi-valued indexes, used in this full-text search sample, are a powerful feature for indexing array properties. They allow you to efficiently query elements within an array. For example, when searching for emails containing a word starting with 'v', the query `db.emails.where("messageWords").startsWithIgnoreCase("v")` targets the `messageWords` multi-valued index. The `.distinct()` ensures that each email is returned only once, even if it contains multiple words starting with 'v'. It's important to note that multi-valued index support varies across browsers; this feature is available in Opera, Firefox, and Chrome, but not in Internet Explorer. For IE compatibility, an alternative approach using custom views (as shown in `FullTextSearch2.js`) is recommended. + +-------------------------------- + +### Collection > Methods > offset() + +Source: https://dexie.org/docs/Collection/Collection + +Ignore N items before given offset and return the rest. + +-------------------------------- + +### Docs Home > Transaction + +Source: https://dexie.org/docs/inbound + +Transactions are fundamental to IndexedDB operations, ensuring data integrity. In Dexie.js, transactions are automatically managed for most operations. However, you can explicitly create transactions using `db.transaction()` for more control. Transactions guarantee that a set of operations are performed atomically: either all succeed, or none of them do. You can listen to transaction events like `on.abort`, `on.complete`, and `on.error` to handle different outcomes. + +-------------------------------- + +### Quick Reference > Schema Syntax + +Source: https://dexie.org/docs/API-Reference + +Dexie's schema syntax is concise and powerful. The `++id` denotes an auto-incremented primary key. An ampersand `&` indicates a unique key. An asterisk `*` denotes a multi-entry index, useful for array properties. Compound indexes, like `[A+B]`, allow you to index multiple properties together for more complex queries. + +-------------------------------- + +### Libs + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +The `liveQuery()` function, likely exported from `dexie-react-hooks` or a similar module, is a core feature for building reactive user interfaces with Dexie.js. It allows you to observe changes in your Dexie.js database and automatically trigger re-renders in your UI components when the observed data is updated. This is fundamental for creating dynamic applications that reflect real-time data changes without manual polling or state management. + +-------------------------------- + +### MultiEntry Index + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js allows you to define **multi-entry indexes**. These indexes are created on array properties and will create an index entry for each element within the array. This is incredibly useful for querying data where a field can have multiple values, such as tags associated with an item. For instance, if you have a `posts` table with a `tags` array property, a multi-entry index on `tags` would allow you to efficiently query for all posts that have a specific tag. + +-------------------------------- + +### Dexie Cloud Web Hooks > Operations + +Source: https://dexie.org/docs/cloud/web-hooks + +"upsert": An object was created or replaced +"update": An object was partially updated +"delete": An object was deleted + +-------------------------------- + +### Libs > dexie-react-hooks + +Source: https://dexie.org/docs/Promise/Promise + +Dexie-react-hooks is a library that provides React hooks for interacting with Dexie.js databases. These hooks simplify the process of integrating Dexie.js into React applications by abstracting away common patterns for data fetching, state management, and real-time updates. Key hooks include `useLiveQuery()` for reactive data fetching, `useDocument()` for working with individual documents, and `usePermissions()` for managing access control. + +-------------------------------- + +### WhereClause > WhereClause.startsWithAnyOfIgnoreCase() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.startsWithAnyOfIgnoreCase()` method is similar to `startsWithAnyOf()`, but the prefix matching is performed in a case-insensitive manner. This is beneficial for searching strings where capitalization should not affect the match. + +-------------------------------- + +### Tutorial > Best Practices + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Best practices for using Dexie.js are essential for building performant and maintainable applications. This includes understanding how to structure your database schema, optimize queries, and handle data synchronization. Following these guidelines will help you avoid common pitfalls and ensure your application runs smoothly, especially when dealing with large datasets or complex interactions. + +-------------------------------- + +### Cloud > db.cloud.invites + +Source: https://dexie.org/docs/cloud/consistency + +The `db.cloud.invites` property provides access to the collection of invites for sharing databases or realms. You can use this to manage invitations sent to other users. + +-------------------------------- + +### Tutorial > Building Addons + +Source: https://dexie.org/docs/cloud/consistency + +Learn how to build addons for Dexie.js. This section explains the architecture of Dexie.js and how you can extend its functionality to create custom solutions or integrations. It's designed for advanced users who want to deepen their understanding of Dexie.js or adapt it to specific needs. + +-------------------------------- + +### Dexie > Dexie.transaction() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Dexie.transaction()` method is fundamental for performing atomic operations within your Dexie.js database. It allows you to group multiple database operations (like reads and writes) into a single transaction. If any operation within the transaction fails, the entire transaction is rolled back, ensuring data consistency. You can specify the scope of the transaction by listing the tables involved and the mode (e.g., 'readonly', 'readwrite'). + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.startsWith() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause.startsWith()` method filters records where a specific string index begins with the provided prefix. This is highly efficient for searching text-based data and is commonly used for autocomplete or prefix-based filtering. It leverages IndexedDB's capabilities for string matching. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie Cloud offers features for managing user roles and permissions, enabling fine-grained access control. You can define `roles` within your Dexie Cloud application, and then assign `members` to these roles. This hierarchical structure allows for efficient management of what different users or groups can access and do within your application's data. Concepts like `DBPermissionSet` further define the granular permissions that can be granted. + +-------------------------------- + +### Dexie.js - Schema Syntax > Detailed Schema Syntax > Syntax For Indexes + +Source: https://dexie.org/docs/Version/Version + +Indexes can also be defined within the schema string. A `keyPath` by itself creates a standard index. Using `&keyPath` designates a unique index, meaning all keys for this path must be unique. For fields that are arrays, `*keyPath` creates a multi-valued index, where each array element is treated as a key to the object. Compound indexes for multiple key paths can be defined using `[keyPath1+keyPath2]`, creating an index that spans across `keyPath1` and `keyPath2`. Remember that `keyPath` can refer to a property name or a dotted path to a nested property. + +-------------------------------- + +### IndexSpec > Properties > name + +Source: https://dexie.org/docs/IndexSpec + +The `name` property in `IndexSpec` stores the name of the index. Typically, for non-compound indexes, the `name` is the same as the `keyPath`. However, for compound indexes, the `name` corresponds to the string definition provided in `Version.stores()`, while the `keyPath` becomes an array detailing the components of the compound index. + +-------------------------------- + +### Dexie Cloud Consistency Models > CRDT-Based Consistency (via Y.js) + +Source: https://dexie.org/docs/cloud/consistency + +Dexie Cloud also supports **Conflict-Free Replicated Data Types (CRDTs)** through the Y.js library. This model is perfect for collaborative text editing (TipTap, Monaco Editor), collaborative diagramming (tldraw, Excalidraw), real-time flowcharts (React Flow), shared whiteboards and drawings, and any scenario requiring character-by-character or element-by-element merge. CRDTs enable multiple users to edit the same document simultaneously without conflicts. Changes merge automatically based on mathematical properties of the data structure, eliminating the need for server-side conflict resolution. With Y.js integration, you get awareness (see other users' cursors and selections), automatic synchronization through Dexie Cloud's sync infrastructure, offline support with automatic merge when reconnecting, and a rich ecosystem of ready-to-use collaborative components. Note that Y.js documents are still subject to server-authoritative access control. + +-------------------------------- + +### Table > Table.each() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.each()` method iterates over each record in the table, executing a callback function for each one. This is an efficient way to process records one by one without loading the entire table into memory. You can stop the iteration early by returning `false` from the callback. + +-------------------------------- + +### WhereClause > ...use.startsWithIgnoreCase() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.startsWithIgnoreCase()` method performs a case-insensitive check to see if a string property starts with a specified prefix. This extends the functionality of `startsWith` to handle variations in capitalization. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.startsWithAnyOf() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause.startsWithAnyOf()` method selects records where a specific string index starts with any of the prefixes provided in an array. This allows for flexible prefix matching across multiple possibilities. It's an efficient way to query for records that begin with any of several patterns. + +-------------------------------- + +### Collection > Collection.first() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Collection.first()` method retrieves the first record from a collection. This is often used after a query or sorting operation to get a single specific record. It returns a Promise that resolves with the record object or `undefined` if the collection is empty. For example, `const firstFriend = await db.friends.orderBy('name').first();`. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie.js provides tools and guidance for migrating existing databases to its structure. Whether you are moving from a different database solution or an older version of IndexedDB, Dexie.js offers strategies to facilitate this transition. The tutorial `Migrating existing DB to Dexie` likely covers the steps involved in exporting data from your current database, defining the corresponding schema in Dexie.js, and importing the data, ensuring a smooth data migration process. + +-------------------------------- + +### Libs > liveQuery() + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `liveQuery()` function is a core part of Dexie.js's reactivity system, enabling you to create streams of data that automatically update when the underlying database changes. It takes a Dexie query as an argument and returns an Observable that emits new results whenever the data matching the query is modified. This is fundamental for building dynamic user interfaces that reflect the current state of the database in real-time. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/DerivedWork + +A `Transaction` in Dexie.js is a crucial concept for ensuring data integrity. It provides a mechanism to group multiple database operations together, ensuring that either all operations succeed, or none of them do (atomicity). This prevents your database from ending up in an inconsistent state. Transactions are automatically created by Dexie.js for most operations, but you can also explicitly create them for more control. You can monitor the lifecycle of a transaction using events like `on.complete` and `on.abort`. + +-------------------------------- + +### Version > Version.stores() > Schema Syntax + +Source: https://dexie.org/docs/Version/Version + +Dexie.js supports various schema definition syntaxes for indexing properties within object stores. Auto-incremented primary keys are denoted by '++'. Unique indexes are marked with '&'. Multi-entry indexes use '*'. Compound indexes or primary keys can be defined using '[A+B]', where A and B represent properties. Primary keys are implicitly unique. You can also define a multi-entry unique index using '&*' or a multi-entry compound index using '*[A+B]'. + +-------------------------------- + +### Cloud > Authentication in Dexie Cloud + +Source: https://dexie.org/docs/cloud/consistency + +This section describes the authentication mechanisms supported by Dexie Cloud. It covers how users can log in, how to manage authentication tokens, and how to integrate with different authentication providers. + +-------------------------------- + +### Libs > dexie-react-hooks + +Source: https://dexie.org/docs/cloud/index + +Dexie-react-hooks is a library that provides React hooks for interacting with Dexie.js databases. It simplifies the process of managing database state within React components. Key hooks include `useLiveQuery` for reactive queries that automatically update when data changes, `useDocument` for fetching and updating single documents, and `useObservable` for integrating with RxJS observables. `usePermissions` can be used to manage user permissions within your application. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/Releasing-Dexie + +Understanding the table schema is crucial for effective database design in Dexie.js. The schema defines the structure of your data, including the tables, their primary keys, and any indexes. Properly defining your schema allows for efficient querying and data manipulation. This section delves into the intricacies of Dexie.js table schemas. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Table Schema` in Dexie.js defines the structure of your database tables, including primary keys, indexes, and data types. When you define your database using `db.version(x).stores({...})`, you are essentially defining the table schemas. This schema definition is crucial for performance as it dictates how data is stored and how efficiently queries can be executed. You can also inspect the schema of an existing table via `table.schema`. + +-------------------------------- + +### Version > Version.stores() + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +The `Version.stores()` method is used to define the schema for a specific version of your database. You provide an object where keys are table names and values define the primary key and indexes for each table. For example, `db.version(1).stores({ friends: '++id, name, age' })` defines a table named `friends` with an auto-incrementing primary key `id`, and indexes on `name` and `age`. + +-------------------------------- + +### Example: A Simple Project Management Model + +Source: https://dexie.org/docs/cloud/access-control + +This example showcases a basic project management database using Dexie Cloud, emphasizing the use of roles for permission management. It defines custom roles such as "manager", "doer", and "commenter". The provided functions include `addProject()` for creating new projects, `addMember()` for adding members to projects, `addTask()` for adding tasks, `markAsDone()` for marking tasks as completed, and `addComment()` for adding comments to tasks. These operations are designed to interact with a Dexie database configured with the Dexie Cloud addon. + +-------------------------------- + +### Primary Keys > Generate your own random strings + +Source: https://dexie.org/docs/cloud/best-practices + +If you need to generate your own unique string identifiers for primary keys, you can simply declare the key as a regular string in your table's store definition (e.g., `id`). You can then use a custom function, such as `generateRandomString()`, to produce unique IDs like GUIDs before adding them to your database. This approach gives you full control over the ID generation process while still ensuring uniqueness. + +-------------------------------- + +### ...Use the StorageManager API + +Source: https://dexie.org/docs/cloud/web-hooks + +The `StorageManager` API, accessible through `navigator.storage`, provides insights into the storage quota and available space for your web application. While not a direct Dexie API, understanding these concepts is important for managing client-side storage effectively. Dexie.js operates within the constraints set by the browser's storage manager, and being aware of quotas can help prevent unexpected data loss or application failures. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +For advanced synchronization scenarios and to manage data consistency across distributed clients, Dexie Cloud offers features like `Sharding and Scalability`. This addresses how to handle large datasets and high volumes of concurrent access by distributing data across multiple servers or databases. Understanding these concepts is vital for applications expecting significant growth or operating in environments with complex data distribution requirements. + +-------------------------------- + +### Transaction > Transaction.table() + +Source: https://dexie.org/docs/DerivedWork + +The `Transaction.table()` method allows you to get a reference to a specific table within the context of the current transaction. This is useful when you need to perform operations on a particular table and want to ensure those operations are part of the ongoing transaction. For example, `tx.table('friends')` would give you a table instance for the 'friends' table within the transaction `tx`. + +-------------------------------- + +### Docs Home > Cloud > Sharding and Scalability + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +Sharding and Scalability in Dexie Cloud refers to strategies for handling large amounts of data and a high number of users efficiently. Sharding involves partitioning data across multiple databases or servers, while scalability ensures that the system can handle increasing loads. This section likely discusses how Dexie Cloud supports these concepts to build robust and growing applications. + +-------------------------------- + +### Transaction.table() + +Source: https://dexie.org/docs/Transaction/Transaction + +The `trans.table(nameName)` method returns a specific table from a transaction. This allows you to perform operations on a particular table within the scope of the ongoing transaction. + +-------------------------------- + +### Tutorial > Design + +Source: https://dexie.org/docs/Promise/Promise + +The design of Dexie.js focuses on providing a developer-friendly API that abstracts away the complexities of IndexedDB while maintaining its core strengths. It emphasizes clear naming conventions, intuitive method chaining, and robust error handling. The goal is to make working with client-side NoSQL databases a more pleasant and productive experience. + +-------------------------------- + +### Dexie Cloud CLI > databases + +Source: https://dexie.org/docs/cloud/cli + +List the databases you have credentials for in your dexie-cloud.key file. Can be handy when switching between multiple databases. The list shows which one of the databases that is currently selected. To switch to another database, use `npx dexie-cloud connect `. + +-------------------------------- + +### Dexie.js API Documentation > Cloud + +Source: https://dexie.org/docs/dexie-worker/dexie-worker + +Dexie Cloud is an extension that provides authentication, synchronization, and access control for IndexedDB databases. Key features include managing user authentication (`db.cloud.login()`, `db.cloud.logout()`, `db.cloud.currentUser`), handling permissions (`DBPermissionSet`, `Role`, `db.cloud.permissions()`), and synchronizing data (`db.cloud.sync()`, `db.cloud.syncState`, `db.cloud.events.syncComplete`). It also offers features like inviting users (`Invite`, `db.cloud.invites`) and configuring cloud options (`DexieCloudOptions`, `db.cloud.configure()`). + +-------------------------------- + +### Cloud > Access Control + +Source: https://dexie.org/docs/cloud/index + +Dexie Cloud offers comprehensive access control mechanisms to manage user permissions and data visibility. You can define roles and permissions using `DBPermissionSet`, `Role`, and `Member` objects. The `db.cloud.permissions()` method allows you to retrieve or set permissions for users or roles. Features like `Add public data` and `Access Control in Dexie Cloud` guides explain how to implement secure data access. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.startsWith() + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `WhereClause` object in Dexie.js is used for building string-based queries. `startsWith()`, `startsWithIgnoreCase()`, `startsWithAnyOf()`, and `startsWithAnyOfIgnoreCase()` allow you to efficiently search for records where a string property begins with a specific prefix or one of multiple prefixes. The case-insensitive variants are useful for flexible searching. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/cloud/custom-emails + +Dexie.js provides a structured approach to defining database schemas and managing versioning. The `Version` object, accessed via `db.version()`, is used to define the database structure, including tables and their indexes. The `stores()` method on a `Version` object specifies the collection of tables and their schemas, while the `upgrade()` method allows you to define logic for migrating data when the database version changes. This ensures that your database schema evolves gracefully and data is preserved across versions. + +-------------------------------- + +### API Reference > Collection > Collection.keys() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.keys()` method returns a collection of primary keys that match the criteria of the current collection. This is an efficient way to retrieve identifiers without fetching the entire data objects, often used for subsequent operations like deletion or updating specific records. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.schema + +Source: https://dexie.org/docs/Dexie/Dexie.on + +`db.cloud.schema` provides access to the database schema defined for Dexie Cloud. This includes information about tables, indexes, and relationships. + +-------------------------------- + +### Docs Home > Cloud > Authentication in Dexie Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section details the authentication mechanisms provided by Dexie Cloud. It covers how users can log in and how your application can manage user sessions and authentication states. + +-------------------------------- + +### Collection > Methods > distinct() + +Source: https://dexie.org/docs/Collection/Collection + +Remove duplicates of items with same primary key. + +-------------------------------- + +Source: https://dexie.org/docs/Promise/Promise + +Dexie.js version 5.0 roadmap focuses on significant enhancements and new features. While specific details might evolve, typical roadmap items include improved performance, expanded API capabilities, better developer tooling, and potentially new integrations or addons. Staying updated with the roadmap helps in planning for future development and leveraging the latest advancements. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie Cloud provides a REST API that enables interaction with your synchronized data from various clients and services. The `Dexie Cloud REST API` documentation outlines the available endpoints for performing operations such as querying data, creating new records, updating existing ones, and deleting data. This API is crucial for integrating Dexie Cloud with backend systems, serverless functions, or other applications that need to interact with your synchronized data. + +-------------------------------- + +### Table > Table.get() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.get()` method retrieves a single record from a table based on its primary key. It takes the primary key value as an argument and returns a Promise that resolves with the found record, or `undefined` if no record with the given key exists. This is a direct and efficient way to fetch a specific item when you know its unique identifier. + +Example: +`db.friends.get(123).then(friend => { if (friend) { console.log(friend.name); } });` + +-------------------------------- + +### Dexie.js API Documentation > Dexie.waitFor() + +Source: https://dexie.org/docs/Dexie/Dexie + +When using `Dexie.waitFor()`, it's crucial to adhere to certain guidelines to prevent transaction errors. Specifically, you should avoid accessing your own transaction within the operation that `Dexie.waitFor()` is waiting for. Instead, focus on operations that involve non-IndexedDB work or separate transactions. For instance, you are permitted to initiate a new top-level transaction or wait on other databases. This ensures that the primary transaction remains stable and available for use after the awaited operation completes. + +-------------------------------- + +### Table > Table.hook() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.hook()` method allows you to intercept and modify operations performed on a table. You can register callbacks for events like `creating`, `reading`, `updating`, and `deleting`. This is powerful for enforcing business logic, performing side effects, or modifying data before it's saved or retrieved. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie Cloud provides a REST API that allows you to interact with your synchronized data from various clients or services, not just those using the Dexie.js library directly. The `Dexie Cloud REST API` documentation would detail the available endpoints for performing CRUD operations, managing users, and accessing synchronization status. This enables integration with backend services, third-party applications, or even mobile applications that need to interact with your Dexie Cloud backend. + +-------------------------------- + +### Dexie.js > Dexie.transaction() + +Source: https://dexie.org/docs/safari-issues + +The `Dexie.transaction()` method is fundamental for performing atomic operations on your database. It ensures that a set of operations either completes successfully or is rolled back entirely, maintaining data consistency. When you call `db.transaction(mode, tables, callback)`, you specify the transaction mode (e.g., 'readonly', 'readwrite'), the tables involved, and a callback function containing your database operations. Inside the callback, you can access the transaction object to perform actions on the specified tables. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.startsWithIgnoreCase()` method is a case-insensitive version of `startsWith()`. It queries records where an indexed string property begins with a specified prefix, regardless of the case of the characters. + +-------------------------------- + +### Cloud > Sharding and Scalability + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Sharding and Scalability are important considerations when dealing with large datasets in Dexie Cloud. Sharding involves partitioning data across multiple database instances to improve performance and manageability. Dexie Cloud's architecture and features aim to support scalable solutions, allowing applications to handle growing amounts of data and user traffic effectively. Understanding these concepts is crucial for designing robust and future-proof applications. + +-------------------------------- + +### Dexie.js API > Libs > dexie-react-hooks + +Source: https://dexie.org/docs/cloud/authentication + +The `dexie-react-hooks` library provides React hooks for seamlessly integrating Dexie.js with your React applications. `useLiveQuery()` is a powerful hook that automatically subscribes to changes in your Dexie database and re-renders your component whenever relevant data updates. `useDocument()` simplifies fetching and updating a single document, while `useObservable()` allows you to observe Dexie collections. `usePermissions()` is specifically designed for managing access control within Dexie Cloud applications. + +-------------------------------- + +### API Reference > DBCore + +Source: https://dexie.org/docs/roadmap/dexie5 + +DBCore represents the core API for interacting with IndexedDB. It provides low-level access to database operations, including transactions, cursors, and schema management. Understanding DBCore can be beneficial for advanced use cases or when debugging specific issues. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.schema + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `db.cloud.schema` property provides access to the database schema defined for Dexie Cloud. This includes information about tables, indexes, and relationships, which is crucial for understanding the data structure and managing migrations. + +-------------------------------- + +### Docs Home > Getting Started + +Source: https://dexie.org/docs/cloud/index + +Getting started with Dexie.js is straightforward. You can install it via npm or yarn. After installation, you can create a Dexie database instance, define your object stores (tables), and start performing CRUD operations. Dexie handles the underlying IndexedDB creation and management for you. + +-------------------------------- + +### Example: A Simple Project Management Model > markAsDone + +Source: https://dexie.org/docs/cloud/access-control + +The `markAsDone()` function updates the status of a given task to indicate completion. It utilizes the `db.tasks.update()` method to modify the `done` field of the specified task. The `done` field is set to the current timestamp using `Date.now()`, providing a record of when the task was marked as completed. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The `db.cloud.schema` property reflects the database schema as understood by Dexie Cloud, potentially including cloud-specific metadata or configurations. It's related to how Dexie Cloud manages synchronization and data structure. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/Member + +Dexie Cloud is an add-on service for Dexie.js that provides real-time synchronization, authentication, and access control for your web applications. It simplifies the complexities of building collaborative and data-driven applications by handling data syncing across multiple clients and providing a robust backend. Key features include real-time updates, offline support, user management, and role-based permissions. The documentation covers essential aspects like authentication, permissions, data consistency, and deployment options. + +-------------------------------- + +### Libs > dexie-react-hooks + +Source: https://dexie.org/docs/cloud/web-hooks + +The `dexie-react-hooks` library provides a set of React hooks that integrate seamlessly with Dexie.js, enabling you to easily manage and interact with your Dexie database within React components. Key hooks include `useLiveQuery` for fetching live-updating query results, `useDocument` for working with individual documents, and `usePermissions` for managing access control. These hooks abstract away the imperative logic of setting up subscriptions and handling updates, making it declarative and efficient to use Dexie.js in React applications. + +-------------------------------- + +### Collection > Collection.limit() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.limit()` method restricts the number of records returned by a query. It takes an integer argument specifying the maximum number of records to include in the result set. This is often used in conjunction with `offset()` for pagination. + +-------------------------------- + +### Dexie.js API Documentation > Dexie.waitFor() + +Source: https://dexie.org/docs/Dexie/Dexie + +The example demonstrates how to dynamically lock additional tables within a transaction flow. Initially, only `db.friends` is locked for reading. Inside the transaction, `Dexie.waitFor()` is used to initiate a new top-level transaction that locks `db.pets` for reading. This nested transaction fetches all pets owned by 'Bert'. Once this nested operation is complete, the `bertWithPets` object is populated with an array of Bert's pets, effectively extending the initial 'friend' object with its related 'pets' data. + +-------------------------------- + +### Example: A Simple Project Management Model > addProject + +Source: https://dexie.org/docs/cloud/access-control + +The `addProject()` function facilitates the creation of a new project within the database. It operates within a transaction that includes `db.realms` and `db.projects`. Initially, it creates a new 'realm' for the project, assigning a name derived from the project's name and specifying that it 'represents' a project. Subsequently, it adds the project itself to the `projects` table, associating it with the newly created realm and storing its name and description. + +-------------------------------- + +### Collection > Collection.reverse() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.reverse()` method reverses the order of the records in the collection. This is useful when you want to retrieve records in descending order after applying filters or sorting in ascending order, or vice versa. + +-------------------------------- + +### Docs Home > Dexie-worker > Inbound + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This section details how to handle inbound data or requests within your Dexie.js application, particularly in the context of synchronization or external data sources. It covers strategies for processing incoming data efficiently and ensuring its integrity. + +-------------------------------- + +### Building Addons > Protected methods + +Source: https://dexie.org/docs/Tutorial/Building-Addons + +Dexie has protected methods and properties, often indicated by a leading underscore, which are not formally documented in the API Reference. You can inspect the source code to find these. Your addons can override these protected methods to alter the behavior of the database engine. While efforts are made to maintain backward compatibility for these, it's not guaranteed. For certainty, it's recommended to inform the Dexie team about your addon and its source code, or consider keeping your addon within a fork of Dexie.js/addons and submitting pull requests for updates. + +-------------------------------- + +### Table > Table.count() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.count()` method returns the number of records in a table or a collection. When called on a `Table` object, it returns the total number of records in that table. When called on a `Collection` object (e.g., after applying filters or limits), it returns the count of records matching the collection's criteria. This method returns a Promise that resolves with the count. + +Example: +`db.friends.count().then(count => { console.log(`Number of friends: ${count}`); });` + +-------------------------------- + +### Dexie.js Documentation > Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateResponse + +Dexie Cloud offers a comprehensive set of tools and features for managing cloud-based databases. You can configure cloud options using `db.cloud.configure()`, access the current user and their ID via `db.cloud.currentUser` and `db.cloud.currentUserId`, and manage invites and permissions. The API provides methods for logging in and out (`db.cloud.login()`, `db.cloud.logout()`), triggering synchronization (`db.cloud.sync()`), and accessing synchronization status (`db.cloud.syncState`, `db.cloud.events.syncComplete`). It also includes features for managing roles, realms, and permissions, as well as handling user interactions and service worker integration. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.startsWithAnyOfIgnoreCase()` method is a case-insensitive version of `startsWithAnyOf()`. It finds records where an indexed string property starts with any of the provided prefixes, ignoring the case of both the property and the prefixes. + +-------------------------------- + +### API Reference > Collection > Collection.eachPrimaryKey() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.eachPrimaryKey()` method iterates over the primary keys of the records in a collection. This is similar to `eachKey()` but specifically designed for collections where the primary key might not be the default identifier. It's an efficient way to access primary keys when needed. + +-------------------------------- + +### Chrome and Opera on IOS + +Source: https://dexie.org/docs/IndexedDB-on-Safari + +Due to Apple's restrictive policies on iOS, browsers like Chrome and Opera actually utilize Safari's browser engine in the backend. This means that even when running Chrome or Opera on an iOS device, the IndexedDB implementation is provided by Safari. This behavior is documented in issue #110. If your application needs to support older iPhone models, specifically iPhone 6 or below, it is recommended to include the indexedDB shim before loading Dexie.js. For users on iPhone 7 and above, the Safari engine version will be 10.3 or newer. + +-------------------------------- + +### Dexie.js API Documentation > Dexie.waitFor() + +Source: https://dexie.org/docs/Dexie/Dexie + +The `Dexie.waitFor()` method allows you to wait for non-IndexedDB Promises to complete while keeping the transaction alive. This means you can integrate operations like WebCrypto calls, `fetch()`, or `$.ajax()` within your Dexie transactions. When a `Dexie.waitFor()` promise resolves, it's guaranteed that the transaction is in an active state and can continue to be used. However, it's important to note that while the promise is executing, the transaction may temporarily become inactive. Therefore, any operations performed during this inactive period must not involve direct interaction with the transaction itself. Once the `Dexie.waitFor()` promise resolves, the transaction is guaranteed to be active again. + +-------------------------------- + +### Authentication in Dexie Cloud > Introduction + +Source: https://dexie.org/docs/cloud/authentication + +Dexie Cloud is for writing offline capable applications, which means that the typical use case is long-lived authentication sessions that lasts for months or until the user actively logs out from it. In the default setup, users will only need to authenticate the very first time they visit your app. There is no registration step for your users and they won't need to create any password, as authentication is performed over passwordless email OTP. The authentication step will result in a securely stored, non-exportable crypto key in your indexedDB that can reauthenticate future sync calls automatically without having to require further user interaction. + +-------------------------------- + +### /my/... endpoint + +Source: https://dexie.org/docs/cloud/rest-api + +The /my/... endpoint functions similarly to the /all/... endpoint, with the key difference being its focus on data accessible to the token subject. This means it retrieves objects that the token's associated user has access to. The token used with this endpoint should be issued to a specific subject (userId) and include only the "ACCESS_DB" scope. This ensures that the retrieved data is limited to what the user is authorized to view. + +-------------------------------- + +### WhereClause > WhereClause.startsWithIgnoreCase() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.startsWithIgnoreCase()` method filters records where a specific property's string value begins with a specified prefix, ignoring the case of both the property value and the prefix. This provides case-insensitive prefix matching. + +-------------------------------- + +### Dexie.js > Transactions > The Auto-Commit Behavior of IndexedDB Transactions + +Source: https://dexie.org/docs/API-Reference + +IndexedDB transactions are automatically committed once they are no longer actively used within the same task. This behavior necessitates careful handling of asynchronous operations. You must avoid calling any other asynchronous APIs and waiting for their completion while a transaction is active. Failure to do so will result in a `TransactionInactiveError` when you attempt to further utilize the transaction. This is a fundamental aspect of IndexedDB's transaction management and cannot be bypassed even by wrapping calls within Dexie.Promise. However, a significant improvement in Dexie 2.0.0-beta.6 allows you to wait for other asynchronous APIs while keeping the transaction active by using `Dexie.waitFor()`. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.schema + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The `db.cloud.schema` property allows you to inspect the database schema as defined for Dexie Cloud. This can be helpful for understanding how your data is structured and how it is being synchronized across different clients. It provides a clear view of the tables and their definitions within the cloud-enabled database. + +-------------------------------- + +### Table > Table.toCollection() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.toCollection()` method converts a table into a `Collection` object. This allows you to apply collection-specific methods like `filter()`, `limit()`, `offset()`, `sortBy()`, and `reverse()` to the entire table's content before fetching the results. + +-------------------------------- + +### Dexie Cloud Consistency Models > Consistency Concepts in Dexie Cloud > Globally Unique IDs + +Source: https://dexie.org/docs/cloud/consistency + +Globally unique IDs have the constraint that it is virtually impossible for two generated IDs to be equal. That constraint makes them avoid any conflict for add (insert) operations that occur on different offline clients. For example, CLIENT A adds an object with ID 'AaIHn9smowhaFixqlcb7C4u' and CLIENT B adds an object with 'BbIXypXaau8MefAQPb77ivL'. When CLIENT A syncs, 'AaIHn9smowhaFixqlcb7C4u' is inserted on the server. When CLIENT B syncs, 'BbIXypXaau8MefAQPb77ivL' is inserted, and 'AaIHn9smowhaFixqlcb7C4u' is retrieved back to CLIENT B. Subsequently, when CLIENT A pulls from the server, 'BbIXypXaau8MefAQPb77ivL' is retrieved back to CLIENT A. However, associative entities shall not have their own global ID but instead build up their primary key using the combination of the keys they refer to, using a compound primary key. + +-------------------------------- + +### Dexie Cloud > Custom Emails in Dexie Cloud > When emails are needed + +Source: https://dexie.org/docs/cloud/custom-emails + +Emails are sent out in the following use cases: + * Authentication / Registration: First time a user runs your application on a new device, Dexie Cloud needs to verify the user's identity. While you can replace this process entirely with your own implementation, many users opt to customize the built-in authentication provided by Dexie Cloud. The One-Time Password (OTP) messages sent to the user can also be customized as described later in this document. + * Invites: When a user of your app invites someone to share data (by creating a member object associated with the realm representing the data), an invite email may be sent to the invited user. In the default setup, this email includes a simple message about the invite and options to accept or reject it. This template can also be customized using the steps detailed below. + +-------------------------------- + +### Table > Table.mapToClass() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.mapToClass()` method is used to associate a JavaScript class with an object store (table). Instances of this class will be created when records are retrieved from the table, and properties of the records will be mapped to the class's properties. This allows you to work with your data using object-oriented paradigms, leveraging methods defined in your class. When you add or put objects of this class into the table, Dexie will automatically extract their properties. + +Example: +`class Friend { constructor(id, name) { this.id = id; this.name = name; } greet() { console.log(`Hello, my name is ${this.name}`); } } +db.friends.mapToClass(Friend);` + +-------------------------------- + +### Deploy in Azure + +Source: https://dexie.org/docs/cloud/premium-software + +To deploy the Dexie Cloud service in Azure, you first need to set up an Azure Database for PostgreSQL. After creating the database, clone the dexie-cloud repo and install its dependencies. Follow the Azure Webapps for Node.js guide to configure your Node.js app in Azure by adding a SQL Connection string named DEXIE_CLOUD pointing to your PostgreSQL instance and an application setting DXC_SECRET with a long random string. Ensure your app has database access via Azure portal settings and then deploy the dexie-cloud-server app using the Azure CLI. Finally, in your local repository, set the DXC_SECRET and DXC_URL environment variables and run `npm run init-cloud` to set up the database schema and tables. You can create multiple logical databases using `npx dexie-cloud create` and enable email channels for OTP authentication with `npm run init-email-channel `. + +-------------------------------- + +### Import file example for unsealing the schema + +Source: https://dexie.org/docs/cloud/cli + +To unseal the schema, set the `sealed` property to `false` in the import file. This allows clients to add new tables to the schema. + +-------------------------------- + +### Example: A Simple Project Management Model > updateComment + +Source: https://dexie.org/docs/cloud/access-control + +The `updateComment()` function allows for the modification of an existing comment. It takes the comment's ID and the new comment text as parameters. This function updates the comment record in the `db.comments` table, replacing the old comment with the new one and updating the timestamp to reflect the modification. + +-------------------------------- + +### Dexie Cloud > Consistency in Dexie Cloud + +Source: https://dexie.org/docs/cloud/consistency + +Offline clients may share the same subset of data - and perform operations that may yield one direct result on the offline database, but would have yielded another result after a sync where updated data from another client would make the original operation yield another result. Consistent add-, modify-, put- and delete operations are core concepts of Dexie Cloud and makes sure to not just sync individual objects but also the conditions used in the operations, so that the same operations can be re-executed on updated data to guarantee the same consistency at all times. +If you are new to Dexie Cloud, please visit the Dexie Cloud landing page. +If you prefer to jump right in to samples, here some shortcuts: + * Consistently delete own access to a todo-list + * Consistently delete a shared todo-list along with its todo items + * Consistently detect whether a todo-list is shared or not + * Consistently make a todo-list sharable and create a realm for its sharing + +-------------------------------- + +### Tutorial > Best Practices + +Source: https://dexie.org/docs/Promise/Promise + +Best practices for using Dexie.js Cloud revolve around efficient data synchronization, robust security, and optimal performance. This includes careful schema design, judicious use of indexes, implementing appropriate access control rules, and understanding the nuances of real-time updates and offline support. Following these guidelines ensures a smooth and reliable user experience for your applications. + +-------------------------------- + +### Dexie Cloud Best Practices > Primary Keys + +Source: https://dexie.org/docs/cloud/best-practices + +Primary Keys +☞ Don't use auto-incremented keys (`++id`). Use `@id` (auto-generated) or just `id`, providing own strings with entropy enough for global uniqueness, such as GUIDs. See examples. +☞ Primary key column must be string unless the primary key is a compound primary key, in which case it will be an array of strings or numbers. +☞ Primary keys on `@`-tables must be prefixed with a dedicated 3-letter defined in db.cloud.schema[tableName]. This rule does only apply in auto-generated primary keys (declared as `@` ) See db.cloud.schema +☞ For compound primary keys, they need to be composed from string columns only, or a combination of string and number columns and their composition must have entropy enough to be globally unique. See examples +☞ If one row has a 1-1 relationship with another row in the same or different table, it is wise to generate its ID from the computation of the other ID in order to allow consistent deletion of related rows (see example later down...). See examples +☞ Never change the primary keys of a table. If you need to migrate, create another table and migrate the data using REST or cli export / import. + +-------------------------------- + +### 4. Play Around + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `AnimalView` component is responsible for displaying individual animal information, including their name and age. It also includes a delete button. When this button is clicked, it calls an asynchronous `onDelete` function that uses `db.animals.delete(animal.animalId)` to remove the animal from the database table. + +-------------------------------- + +### Dexie > Dexie Constructor + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Dexie` constructor is the entry point for creating and managing your IndexedDB database. You instantiate it with a name and a version number, and then define your database schema using the `version()` method. This allows you to set up tables, indexes, and other database configurations. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Promise/unhandledrejection-event + +The `WhereClause` object is used for constructing complex queries against table data. It provides a rich set of methods for filtering records based on various conditions, including `above()`, `below()`, `between()`, `equals()`, `startsWith()`, and more. These methods allow for flexible and powerful data retrieval, going beyond the basic capabilities of raw IndexedDB. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie allows you to define table schemas programmatically. This involves specifying the primary key and any secondary indexes for the table. Proper schema definition is essential for efficient data retrieval and management. + +-------------------------------- + +### Docs Home > Version + +Source: https://dexie.org/docs/Typescript-old + +Dexie.js offers a straightforward approach to defining database schemas and managing versions. The `Version` object and its associated methods like `stores()` and `upgrade()` allow you to declare your tables, indexes, and define upgrade logic for migrating between database versions. This provides a robust mechanism for evolving your database structure over time. + +-------------------------------- + +### Dexie.js > Collection > Collection.eachKey() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides `Collection.eachKey()` for iterating over the primary keys of records in a collection. This is useful when you need to perform actions based on the keys without needing the full record data. The callback function receives the primary key and the value associated with that key. It returns a Promise that resolves when all keys have been iterated. + +-------------------------------- + +### WhereClause > WhereClause.anyOf() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.anyOf()` method filters records where a specific property's value matches any of the values provided in an array. This is a convenient way to query for multiple possible values for a single property. + +-------------------------------- + +### WhereClause > WhereClause.anyOf() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.anyOf()` method enables you to filter records where a property's value is present in a given array of values. This is a convenient way to check for multiple possible matches for a single property. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/web-hooks + +The 'Building Addons' section likely provides guidance on how to extend Dexie.js's functionality by creating custom addons. This could involve understanding Dexie's internal architecture and using its APIs to add new features or integrate with other libraries. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.notEqual() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.notEqual()` method is used to retrieve records where the indexed property's value is not equal to the specified value. This allows you to exclude specific records from your query results. + +-------------------------------- + +### Table > Table.toCollection() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.toCollection()` method converts a `Table` object into a `Collection` object. This is often done implicitly when you chain methods like `where()`, `filter()`, or `limit()` directly onto a table. However, calling `toCollection()` explicitly can be useful if you want to perform collection-specific operations without immediately applying a filter. It essentially prepares the table for further querying and manipulation as a collection. + +Example: +`db.friends.toCollection().count();` + +-------------------------------- + +### Promise > Syntax + +Source: https://dexie.org/docs/Promise/Promise + +The `Dexie.Promise` implementation adheres to the Promise/A+ specification. You can create and use `Dexie.Promise` instances similarly to native Promises, utilizing `resolve`, `reject`, `then`, `catch`, and `finally`. + +```javascript +return new Dexie.Promise(function (resolve, reject) { + // Do something and call resolve / reject when done. +}).then(function (result) { + // This code is called if resolve() was called in the Promise constructor +}).catch(function (error) { + // This code is called if reject() was called in the Promise constructor, or + // if an exception was thrown in either constructor or previous then() call. +}).finally(function () { + // This code will be called no matter if an error occurred or not. +}); +``` + +-------------------------------- + +### Promise > Promise + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie provides a `Dexie.Promise` object that wraps standard JavaScript Promises with additional Dexie-specific functionality. This includes features like `PSD` (Per-Scenario Data) for managing context within asynchronous operations. + +-------------------------------- + +### IndexSpec > Properties > keyPath + +Source: https://dexie.org/docs/IndexSpec + +The `keyPath` property in `IndexSpec` defines the path to the property that will be indexed. For direct properties of an object, `keyPath` is simply the property name (e.g., `'name'`). For nested properties, it uses dot notation to specify the path (e.g., `'props.shoeSize'`). For compound indexes, `keyPath` is an array of these individual key paths. + +-------------------------------- + +### Docs Home > WhereClause > ...use.startsWithIgnoreCase() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause.startsWithIgnoreCase()` method filters records where a specific string index begins with the provided prefix, ignoring case sensitivity. This is beneficial when you need to match text regardless of whether it's uppercase or lowercase. It enhances the flexibility of text-based searches. + +-------------------------------- + +### Docs Home > Design + +Source: https://dexie.org/docs/Dexie/Dexie.on + +The design of Dexie.js focuses on providing a developer-friendly API that abstracts away the complexities of IndexedDB. It emphasizes clarity, consistency, and performance. + +-------------------------------- + +### Database Versioning + +Source: https://dexie.org/docs/Tutorial/Design + +When changing the data architecture, such as splitting a 'name' field into 'firstName' and 'lastName' and indexing them, you can define a new version with the updated schema. Crucially, you can include an `.upgrade()` function to automatically transform the existing data. This function receives a transaction object and allows you to modify records in a collection, for example, by splitting the 'name' field and assigning the parts to 'firstName' and 'lastName', then deleting the original 'name' field. + +-------------------------------- + +### API Reference > Collection > Collection.eachUniqueKey() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.eachUniqueKey()` method iterates over the unique keys of the records in a collection. This is particularly useful when dealing with indexes that have unique constraints, allowing you to process each unique key efficiently. + +-------------------------------- + +### API Reference > POST and DELETE > POST + +Source: https://dexie.org/docs/cloud/rest-api + +The POST method is used to upsert data into a table. It requires the `Content-Type` to be `application/json` and the request body to be a JSON array of the data to be upserted. If the data is not an array, it's treated as a single upsert. The primary key, defined in your Dexie schema, determines how existing records are identified. If an object with the same primary key exists, it will be replaced; otherwise, it will be created. For the `/all` endpoint, the `realmId` property must be set, and the primary key can be omitted if it's auto-generated by the server. For `/my` and `/public` endpoints, `realmId` has default behaviors, and primary keys can also be omitted if auto-generated. + +-------------------------------- + +### Migrating existing DB to Dexie + +Source: https://dexie.org/docs/Tutorial/Migrating-existing-DB-to-Dexie + +A log window will display your existing database schema in Dexie format. Copy and paste that into your app code to get up running with Dexie. It will show something like the following: + +``` +Dumping Databases +================= +var db = new Dexie('tasks'); +db.version(0.2).stores({ + tasks: 'id,description,date,done', + notes: '++id,taskId,note' +}); + +Finished dumping databases +========================== +``` + +Just copy that code into your app and start querying your existing data with Dexie. + +-------------------------------- + +### Table > Table.reverse() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.reverse()` method reverses the order of records retrieved from the table. This is typically used after an `orderBy()` clause to fetch records in descending order if the index was specified for ascending order, or vice versa. + +-------------------------------- + +### Customizing login GUI > Example login dialog > Example login dialog + +Source: https://dexie.org/docs/cloud/authentication + +The `MyLoginDialog` component is responsible for rendering the custom login GUI. It observes the `ui` object, which contains properties like `type`, `title`, `alerts`, `fields`, `submitLabel`, `cancelLabel`, `onSubmit`, and `onCancel`. The component dynamically renders input fields based on `ui.fields`, displays alerts if present, and handles form submission and cancellation by calling the respective callbacks provided in the `ui` object. + +-------------------------------- + +### Tutorial > Getting started with Dexie in React + +Source: https://dexie.org/docs/cloud/consistency + +This tutorial walks you through integrating Dexie.js with React applications using the `dexie-react-hooks` library. It covers how to set up hooks for managing database state, performing queries, and handling real-time updates within your React components. + +-------------------------------- + +### ExportImport > Export and Import Database + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie provides methods for exporting and importing database content. This is useful for backing up data, migrating between databases, or sharing data between different instances. The export functionality typically serializes the database content into a format that can be easily re-imported. + +-------------------------------- + +### Detailed Sample Explained > Table 'users' + +Source: https://dexie.org/docs/Version/Version + +The 'users' table is defined with an auto-incrementing primary key named 'id'. It also features an index on the 'name' property, which can be of any data type. Additionally, there's a unique index on the 'username' property, ensuring that each username is distinct. A multi-index is applied to the 'email' property, allowing for multiple email addresses per user and the ability to index each one individually. This enables efficient searching for users based on specific email patterns, though it's noted that this specific feature has limited support in Internet Explorer. An index is also created on the nested property 'address.city', facilitating searches for users based on their city of residence. + +-------------------------------- + +### Example: A Simple Project Management Model > addMember + +Source: https://dexie.org/docs/cloud/access-control + +The `addMember()` function is responsible for adding a new member to a specific project. It takes the project object, the member's email and name, and an array of roles they should possess. This function adds a new record to the `db.members` table, linking the member to the project's `realmId` and setting an 'invite' flag to true, indicating an invitation process. + +-------------------------------- + +### templates reset + +Source: https://dexie.org/docs/cloud/cli + +Resets custom templates back to the default templates provided by the service. Any pushed templates will be deleted and the system will go back to using default templates again. This command will only affect the server and leave the local files as they are. You may delete them manually afterwards. + +-------------------------------- + +### Design > The Dexie class + +Source: https://dexie.org/docs/Tutorial/Design + +Dexie is both a class and a namespace. An instance of Dexie will represent a database connection. As namespace, it is used as an export area for functions, utilities, and classes. In a simple HTML browser environment this means that including "Dexie.js" will only add one property to window: window.Dexie. If you are utilizing a module environment like commonjs or ES modules, Dexie will be the default export that you get when requiring it. + +Dexie, as its backend indexedDB implementation, is an asynchronous database, meaning that any operation that requires a result won't be returned directly. Instead all such operations will return a Promise. Dexie also supports queuing operations, meaning you can start using the database directly after having defined it. In case open() hasn't been called, it will open it automatically and enqueue the operation to execute as soon as the database is finished opening. If open fails, queued operations will immediately fail with the error event from the open request. Notice also that you don't need to care for whether the database has been created or not. It all be created automatically first time use. You always define your schema and let the runtime decide whether to use that definition for creating the database or just for populating the table properties onto your db instance. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/Promise/Promise + +The `Table` object in Dexie.js represents a collection of objects in your database. It provides methods for adding, retrieving, updating, and deleting records. You can access a `Table` instance via `db.table('tableName')` or by using the `db.open()` method with a schema definition that includes table names. Each table has a unique name and a schema that defines its structure, including primary keys and indexes. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.schema + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `db.cloud.schema` property in Dexie.js allows you to inspect the database schema defined for Dexie Cloud. This includes information about the object stores (tables), their properties, and their indexes. It's useful for understanding the structure of your synchronized data and for debugging. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.persistedSyncState + +Source: https://dexie.org/docs/cloud/UserLogin + +The `db.cloud.persistedSyncState` property provides access to the persistent state of the synchronization process. This includes information about the last successful sync, pending changes, and other metadata necessary for resuming synchronization after interruptions or client restarts. + +-------------------------------- + +### Cloud > db.cloud.schema + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `db.cloud.schema` property provides access to the database schema as defined for Dexie Cloud. This schema dictates the structure of your data, including tables, indexes, and relationships. + +-------------------------------- + +### Dexie.js > API Reference > Dexie + +Source: https://dexie.org/docs/safari-issues + +The `Dexie` constructor is the primary entry point for creating and opening a Dexie.js database instance. You typically instantiate `Dexie` with a database name and a version number. The constructor allows you to define your database schema, including tables and their indexes, using a fluent API. For example, `new Dexie('myDatabase').version(1).stores(...)` is a common pattern. You can also provide options to the constructor for more advanced configurations. + +-------------------------------- + +### Table > Table.toArray() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.toArray()` method retrieves all records from a table or a filtered collection and returns them as a JavaScript array. This is a common way to fetch all relevant data for display or further processing in your application. + +-------------------------------- + +### Inbound + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The 'Inbound' section likely refers to data or messages coming into your application or system. In the context of Dexie, this could pertain to data synchronization, import processes, or handling incoming requests. + +-------------------------------- + +### API Reference > Collection > Collection.reverse() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.reverse()` method reverses the order of records in a collection. This is often used after an `orderBy()` clause to retrieve data in descending order, or simply to reverse the current order of the collection. + +-------------------------------- + +### Dexie Cloud Import > Import file example for creating or updating data + +Source: https://dexie.org/docs/cloud/cli + +To import or update data using the `import` command, structure your JSON file with a `data` property. This property contains objects for each `realmId`, followed by `tableName`, and then `primaryKey` for each record. For example, to add or modify products, you would specify the realm (e.g., `"rlm-public"`), the table (`"products"`), and then the product IDs (`"prd1"`, `"prd2"`) with their respective data. This allows for precise control over data manipulation within your Dexie Cloud database. + +-------------------------------- + +### Dexie > Dexie.name + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.name` property holds the name of the database instance. This is typically set when you instantiate `Dexie`. Accessing this property can be useful for logging or for dynamically referencing the database name in your code. + +Example: +`const db = new Dexie('myAppDB'); +console.log('Database name:', db.name);` + +-------------------------------- + +### Dexie > Dexie.open() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `open()` method is crucial for establishing a connection to your Dexie.js database. It takes a callback function that receives the database instance. Inside this callback, you define your database schema using `.version(x).stores({...})`. Dexie handles the database creation and schema migrations automatically. It's important to call `open()` and await its completion before performing any database operations. + +-------------------------------- + +### Version > Version.upgrade() + +Source: https://dexie.org/docs/cloud/Member + +The `Version.upgrade()` method is used to define migration logic when upgrading from a previous version of the database schema to the current one. Inside this method, you can write code to transform data, add or remove tables, or modify indexes to ensure data integrity and compatibility. + +-------------------------------- + +### DBCore > DBCoreKeyRange + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `DBCoreKeyRange` interface represents a range of keys for querying indexes. It allows you to specify lower and upper bounds for key lookups. + +-------------------------------- + +### Cloud > db.cloud.currentUser + +Source: https://dexie.org/docs/cloud/limits + +Accessing the currently logged-in user's information is made easy with `db.cloud.currentUser`. This property provides details about the authenticated user, such as their ID, email, and any custom properties you might have defined. It's crucial for implementing user-specific logic and permissions. + +-------------------------------- + +### Collection > Collection.reverse() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Collection.reverse()` method reverses the order of the records in a collection. If the collection is already sorted, `reverse()` will apply the reversal to the current sort order. This is useful for displaying data in descending order or when the default order needs to be inverted. It returns a new `Collection` instance with the reversed order. + +Example: +`db.friends.orderBy('name').reverse().toArray();` + +-------------------------------- + +### Summary > Handy functions > tryPersistWithoutPromtingUser + +Source: https://dexie.org/docs/StorageManager + +This function attempts to persist storage without prompting the user. It returns a promise that resolves with one of the following strings: "never" if persisting is not possible, "prompt" if persisting would be possible after prompting the user, or "persisted" if storage was silently persisted or already was persisted. It first checks if `navigator.storage.persisted` is available. If storage is already persisted, it returns "persisted". If the `navigator.permissions.query` API is not available, it returns "prompt" as it may be possible to prompt the user. If the permission state is "granted", it attempts to persist storage and returns "persisted" on success or throws an error on failure. If the permission state is "prompt", it returns "prompt". Otherwise, it returns "never". + +-------------------------------- + +### DBCore > DBCoreTransaction + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `DBCoreTransaction` represents a transaction at the `DBCore` level. It provides methods for executing operations within the transaction and managing its lifecycle. + +-------------------------------- + +### Docs Home > Version + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +Understand the `Version` API in Dexie.js, which is crucial for managing database schema changes over time. The `Version` object allows you to define database structures and handle upgrades gracefully. This ensures your application's data schema evolves correctly as your application grows. + +-------------------------------- + +### API Reference > IndexSpec + +Source: https://dexie.org/docs/Collection/Collection + +Dexie.js supports advanced indexing capabilities, including compound indexes and multi-entry indexes. Compound indexes allow you to index multiple properties together, enabling efficient queries based on combinations of fields. Multi-entry indexes are useful for indexing array properties, allowing you to query individual elements within those arrays. + +-------------------------------- + +### Table > Table.orderBy() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.orderBy()` method is used to specify the sorting order for queries against a table. You can provide an index name or a set of index names. This method is often chained with `where()` and followed by methods like `reverse()` or `limit()` to construct complex queries. + +-------------------------------- + +### Dexie > Dexie.semVer + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.semVer` property provides the semantic version string of the Dexie.js library. This is useful for checking the version compatibility or for logging purposes. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The `WhereClause.anyOf()` method is used to query records where a specific property matches any value in a given array. This is useful for performing OR-like conditions within your queries. For example, you could find all users whose IDs are in a specific list. + +-------------------------------- + +### Cloud > db.cloud.schema + +Source: https://dexie.org/docs/cloud/consistency + +The `db.cloud.schema` property allows you to access and potentially manage the schema of your Dexie Cloud database. It provides information about the tables and their structures as defined in the cloud context. + +-------------------------------- + +### Dexie > Dexie.getDatabaseNames() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.getDatabaseNames()` method retrieves a list of all IndexedDB databases accessible by the browser. It returns a Promise that resolves with an array of database names. This can be helpful for debugging or for applications that need to manage multiple databases. Note that browser security policies might restrict access to certain database names. + +Example: +`Dexie.getDatabaseNames().then(names => { console.log('Databases:', names); });` + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The `db.cloud.schema` property provides access to the database schema as defined for Dexie Cloud. This allows you to inspect or programmatically interact with your database structure. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/DerivedWork + +Methods like `WhereClause.anyOf()` and `WhereClause.noneOf()` allow you to query for records where a specific property matches any value in a given array or does not match any value in a given array, respectively. These are very useful for filtering data based on multiple possible values. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/Promise/Promise + +Dexie.js offers a comprehensive set of methods for querying and manipulating data within tables. Operations like `add()`, `put()`, `delete()`, `get()`, `toArray()`, and `count()` allow for basic CRUD (Create, Read, Update, Delete) operations. For more advanced querying, methods such as `where()`, `filter()`, `orderBy()`, `limit()`, and `offset()` can be chained together to construct complex queries. Collections can be iterated using `each()` or transformed into arrays with `toArray()`. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.currentUser + +Source: https://dexie.org/docs/cloud/UserLogin + +The `db.cloud.currentUser` property provides access to the currently logged-in user's information. This object typically contains details like the user's ID, email, and any associated roles or profile data. It's essential for personalizing the user experience and enforcing access control. + +-------------------------------- + +### Table > Table.defineClass() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie's `Table.defineClass()` method allows you to map a table to a JavaScript class. This enables you to work with your database records as instances of custom classes, allowing you to add methods and properties to your data models. + +-------------------------------- + +### API Reference > Table + +Source: https://dexie.org/docs/cloud/consistency + +The `Table.toCollection()` method returns a `Collection` instance representing all records in the table. A `Collection` is an iterable object that allows for further filtering, sorting, and manipulation of the records before they are retrieved. This method is foundational for building more complex queries and data processing pipelines within Dexie.js. + +-------------------------------- + +### WhereClause > WhereClause.anyOfIgnoreCase() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.anyOfIgnoreCase()` method functions similarly to `anyOf()`, but the comparison is performed in a case-insensitive manner. This is useful when you need to match string values without regard to their capitalization. + +-------------------------------- + +### API Reference > Dexie + +Source: https://dexie.org/docs/Collection/Collection + +Dexie.js offers a robust API for interacting with IndexedDB, simplifying database operations. It provides methods for managing tables, performing CRUD operations, querying data, and handling transactions. The API is designed to be intuitive and efficient, reducing the boilerplate code typically associated with direct IndexedDB usage. + +-------------------------------- + +### API Reference > Version + +Source: https://dexie.org/docs/cloud/consistency + +The `Version.stores()` method is used to define the structure of your database, including the tables (or object stores) and their indexes. You specify the schema for each table, including primary keys and other indexes, which Dexie.js uses to create and manage the database structure. + +-------------------------------- + +### Version > Version.upgrade() + +Source: https://dexie.org/docs/DerivedWork + +The `Version.upgrade()` method is used to handle database schema migrations. When you change your database schema (e.g., add new object stores or indexes), this method allows you to write logic to migrate existing data to the new structure. This ensures data integrity during schema updates. + +-------------------------------- + +### Response + +Source: https://dexie.org/docs/cloud/rest-api + +The response from POST /token provides the information you'll need to authenticate. The access token can be picked from the "accessToken" JSON property in the response body. To use this response in the other REST requests, make sure to include an "Authorization" header with the accessToken. The token is valid in one hour from the time it was requested. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/Promise/unhandledrejection-event + +The `Table` object in Dexie.js represents a database table and provides methods for interacting with its data. You can use methods like `toCollection()` to get all records, `update()` to modify existing records, `upsert()` to add or update records, and `where()` to query records based on specific criteria. These methods are designed to be intuitive and leverage promises for asynchronous operations. + +-------------------------------- + +### WhereClause > ...eClause.equalsIgnoreCase() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.equalsIgnoreCase()` method allows you to perform case-insensitive equality checks on string properties. This is useful when you need to match strings without regard to their capitalization. + +-------------------------------- + +### Tutorial > Best Practices + +Source: https://dexie.org/docs/inbound + +Best practices for using Dexie.js involve efficient schema design, proper transaction management, and optimized querying. Designing your database schema with clear relationships and appropriate indexes can significantly improve performance. Utilizing Dexie's features like `where()` clauses and `toArray()` judiciously, and understanding when to use explicit transactions, are key to building performant applications. + +-------------------------------- + +### Tutorial > Migrating existing DB to Dexie + +Source: https://dexie.org/docs/cloud/consistency + +This tutorial explains how to migrate an existing IndexedDB database to use Dexie.js. It covers strategies for adapting your current database schema and data to work with Dexie.js, ensuring a smooth transition and enabling you to take advantage of Dexie.js features. + +-------------------------------- + +### API Reference + +Source: https://dexie.org/docs/API-Reference + +Dexie.js is a popular JavaScript library that provides a wrapper around the IndexedDB API, making it easier and more intuitive to work with. It offers a promise-based API, a cleaner syntax, and helpful features like automatic schema versioning and transactional integrity. This reference provides details on the classes, sync functionalities, operators, filters, addons, and adapters available within Dexie. + +-------------------------------- + +### Cloud > db.cloud.schema + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `db.cloud.schema` property reflects the current database schema as understood by Dexie Cloud. This includes information about tables, indexes, and relationships that are relevant for synchronization and data management. Keeping this schema definition accurate is crucial for the proper functioning of Dexie Cloud services. + +-------------------------------- + +### Dexie.js - Schema Syntax > Detailed Schema Syntax > Syntax For Primary Key + +Source: https://dexie.org/docs/Version/Version + +The first entry in the schema string always represents the primary key. There are several ways to define the primary key: `++keyPath` signifies an autoincrementing primary key that must always be unique. `++` alone indicates a hidden autoincremented primary key, meaning it's auto-incremented but not directly visible on the objects. `keyPath` without any prefix means the primary key can be of any type and must be provided manually. Leaving the first entry blank results in a hidden primary key that is not auto-incremented. + +-------------------------------- + +### Version > Version.upgrade() + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +The `Version.upgrade()` method allows you to define logic that runs when the database schema is upgraded from a previous version to the current one. This is crucial for migrating data, creating new tables, or modifying existing ones without data loss. You can perform complex migrations within this method. + +-------------------------------- + +### Understanding the basics > Primary and secondary indexes + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +When declaring `friends: 'name, age'` the first property implicitly becomes the primary index (also called primary key). This declaration states that we want a table called 'friends' where the property 'name' is the primary key, and where we add a secondary index on 'age'. A primary key is a unique key, meaning you can never store two objects with the same primary key in the same table. For this reason, most examples you'll see will use a property 'id' or 'key' as primary key instead. You will also see examples using a `++` before the primary index, which makes it auto-incremented. You may also see examples with a `&` before a secondary index, making that index unique the same way as primary indexes are implicitly unique. + +-------------------------------- + +### Dexie.js > IndexSpec + +Source: https://dexie.org/docs/safari-issues + +Dexie.js offers the `IndexSpec` for defining indexes on your tables. An `IndexSpec` allows you to specify not only the property or properties to index but also various options such as whether the index should be unique, the direction of the index (ascending or descending), and whether it's a compound index. You can also define multi-entry indexes using `IndexSpec` when indexing array properties. + +-------------------------------- + +### Table > Table.defineClass() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js's `Table.defineClass()` method allows you to map a table to a JavaScript class. This means that every record retrieved from that table will be an instance of the specified class, inheriting its methods and properties. This approach greatly enhances code organization and allows you to encapsulate business logic directly within your data models, making your application more object-oriented. + +-------------------------------- + +### Collection > Collection.toArray() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Collection.toArray()` method is used to retrieve all records from a table or a collection as a JavaScript array. If called on a `Table` object directly, it fetches all records in that table. If called on a `Collection` object (e.g., after using `where()`, `filter()`, or `limit()`), it returns all records matching the collection's criteria. + +This method returns a Promise that resolves with the array of records. It's a convenient way to load all data from a table or a filtered subset into memory for further processing. Be mindful of performance when fetching large datasets. + +-------------------------------- + +### API Reference > Export and Import + +Source: https://dexie.org/docs/roadmap/dexie5 + +Dexie facilitates exporting and importing database content. This feature is useful for backing up data, migrating databases, or sharing data between applications. The export process typically generates a structured representation of the database, which can then be imported back into a Dexie database. + +-------------------------------- + +### Dexie > Dexie.semVer + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.semVer` property provides the semantic version of the Dexie.js library. This is useful for checking compatibility or for displaying version information within your application. It's a string that follows the standard semantic versioning format (e.g., '3.0.0'). + +Example: +`console.log('Using Dexie.js version:', Dexie.semVer);` + +-------------------------------- + +### Dexie.js > WhereClause + +Source: https://dexie.org/docs/Tutorial/Design + +You can retrieve objects from your Table instances using two primary methods: `Table.get()` and `Table.where()`. The `Table.get()` method is used to retrieve a single object based on its primary key. The `Table.where()` method, on the other hand, is designed for performing more advanced queries on your data. It allows you to specify criteria for filtering and selecting records based on indexed properties. + +-------------------------------- + +### Table > Table.orderBy() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.orderBy()` method specifies the property by which the records in a table or collection should be sorted. It takes the property name as an argument. You can chain this method with others like `reverse()` or `limit()` to control the sorting and retrieval of data. If no `orderBy()` is specified, Dexie may use the primary key for sorting by default, or the order might be undefined. + +Example: +`db.friends.orderBy('age').toArray();` + +-------------------------------- + +### Dexie Cloud - Membership + +Source: https://dexie.org/docs/cloud/access-control + +The `Member` interface defines the structure for objects in the 'members' table. Key properties include `id` (auto-generated primary key), `realmId`, `userId`, `email`, `name`, and invitation-related fields like `invite`, `invitedDate`, and `invitedBy`. It also includes fields for tracking acceptance (`accepted`) and rejection (`rejected`) of invitations, as well as user roles (`roles`) and detailed permissions (`permissions`). The `permissions` field allows specifying access rights for adding, updating, and managing tables and their properties, with '*' indicating all access. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers a declarative way to define your database schema using the `version()` method. Within the `version()` callback, you can define your tables, their schemas (columns and types), and indexes. Dexie handles the migration process automatically when the database version is updated. + +-------------------------------- + +### Dexie.js > Collection > Collection.each() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides the `Collection.each()` method, which iterates over all records in a collection and executes a callback function for each record. This is a powerful way to process each item individually without fetching them all into memory at once. The callback function receives the record and its key as arguments. It returns a Promise that resolves when all records have been processed. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/safari-issues + +Dexie.js offers a streamlined approach to interacting with IndexedDB. It abstracts away much of the complexity of the native IndexedDB API, allowing developers to focus on their application's logic rather than low-level database operations. Key features include Promise-based operations, automatic schema management, and support for transactions. The library aims to make IndexedDB more accessible and developer-friendly. + +-------------------------------- + +### Collection > Collection.offset() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.offset()` method skips a specified number of records from the beginning of the result set. It takes an integer argument representing the number of records to skip. This is commonly used with `limit()` for implementing pagination, allowing you to fetch records in chunks. + +-------------------------------- + +### API Reference > Promise + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +Dexie.js enhances the standard JavaScript `Promise` with additional features, particularly for managing asynchronous operations within a transactional context. It includes a `Promise.PSD` (Per-Second Data) which helps in maintaining context across asynchronous calls, especially useful for tracking transactions. Dexie also provides ways to handle unhandled promise rejections via `Promise.onuncatched` and the global `unhandledrejection` event, contributing to more robust error management in asynchronous code. + +-------------------------------- + +### Dexie.js > debug + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides the `Dexie.debug` property, which can be set to `true` to enable verbose logging of Dexie.js operations. This is extremely helpful for debugging and understanding the internal workings of the library, especially when diagnosing issues or optimizing performance. When enabled, Dexie.js will log detailed information about database opening, transaction handling, query execution, and more to the console. + +-------------------------------- + +### Examples > Create a component that adds some data + +Source: https://dexie.org/docs/Tutorial/Vue + +Writing to the database can be done using `Table.add()`, `Table.put()`, `Table.update()`, and `Collection.modify()`. This example demonstrates creating a simple Vue component that allows the user to add friends into the database using `Table.add()`. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +The `Table` object in Dexie.js represents a database table and provides methods for performing CRUD (Create, Read, Update, Delete) operations. You can use methods like `put()` to add or update records, `get()` to retrieve a single record, `toArray()` to get all records, and `where()` to query records based on specific criteria. The `schema` property provides information about the table's structure. + +-------------------------------- + +### MultiEntry Index > The distinct() operator + +Source: https://dexie.org/docs/MultiEntry-Index + +When querying multiEntry indexes, chances are that one may get multiple results of the same objects, if there are multiple index matches for the same item. It is therefore a good practice to always use Collection.distinct() in queries on multiEntry indexes. + +-------------------------------- + +### API Reference > Collection > Collection.limit() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.limit()` and `Collection.offset()` methods in Dexie.js are essential for implementing pagination. `limit()` specifies the maximum number of records to return from a collection, while `offset()` determines how many records to skip from the beginning. By combining these, you can efficiently retrieve data in chunks, which is crucial for displaying large datasets in user interfaces. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.startsWithIgnoreCase() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.startsWithIgnoreCase()` method filters records where the indexed property (a string) begins with a specified prefix, ignoring case sensitivity. This is useful for performing case-insensitive text searches. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.anyOf()` method allows you to query records where an indexed property matches any of the values provided in an array. This is a convenient way to perform an OR-like condition across multiple possible values for a single property. + +-------------------------------- + +### Table > Table.toArray() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Table.toArray()` method is used to retrieve all records from a table or a filtered collection as a JavaScript array. This is a common way to fetch data when you need to process a significant portion of it in memory. For example, `const allFriends = await db.friends.toArray();` would fetch all records from the 'friends' table. + +-------------------------------- + +### Samples > Full-text search + +Source: https://dexie.org/docs/Table/Table + +The `getAllWords` function is a helper utility used by the Dexie hooks to process the message text. It takes a string as input, splits it into individual words based on spaces, and then uses a `reduce` operation to create a unique set of words. Finally, it returns an array of these unique words. This processed array is then stored in the `messageWords` multi-valued index, enabling efficient searching for specific words within the email messages. + +-------------------------------- + +### API Reference > DBCore + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `DBCore` namespace represents the core interface of Dexie.js for interacting with IndexedDB. It defines various request types such as `DBCoreAddRequest`, `DBCoreCountRequest`, `DBCoreDeleteRequest`, `DBCoreGetRequest`, `DBCorePutRequest`, and `DBCoreQueryRequest`. It also defines types for cursors (`DBCoreCursor`), indexes (`DBCoreIndex`), and tables (`DBCoreTable`), along with schema definitions (`DBCoreSchema`, `DBCoreTableSchema`) and transaction management (`DBCoreTransaction`). This low-level interface allows for direct manipulation of the IndexedDB database. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Dexie Cloud Best Practices offers recommendations for optimizing your Dexie Cloud setup and usage. This includes advice on efficient schema design, effective synchronization strategies, managing costs, and ensuring data consistency and security. Following these guidelines will help you build scalable and reliable applications with Dexie Cloud. + +-------------------------------- + +### DBCore > Purpose + +Source: https://dexie.org/docs/DBCore/DBCore + +The purpose of DBCore is to be able to invoke middleware and to be performant and bulk-oriented. It is not intended to be a totally database-agnostic API. + +-------------------------------- + +### Dexie > Dexie.extend() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.extend()` method allows you to add custom methods or properties to the `Dexie` prototype. This is useful for creating reusable utility functions or adding global behaviors to all Dexie instances in your application. When you extend the `Dexie` prototype, these additions become available on every `Dexie` instance you create. + +Example: +`Dexie.prototype.logVersion = function() { console.log('Database version:', this.verno); };` +`db.logVersion();` + +-------------------------------- + +### Table > Table.update() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.update()` method updates specific properties of existing records in a table. It takes the primary key of the record and an object containing the properties to update. This is more efficient than fetching the entire record, modifying it, and then putting it back. + +-------------------------------- + +### Version > Version.stores() + +Source: https://dexie.org/docs/Download + +The `Version.stores()` method is used to define the schema of your database. You specify the tables and their primary keys, as well as any indexes you want to create. This method is crucial for setting up your database structure when you initialize or upgrade your Dexie database. + +-------------------------------- + +### templates pull + +Source: https://dexie.org/docs/cloud/cli + +The `npx dexie-cloud templates pull` command downloads all email and web templates to your file system, allowing you to edit them in a text editor. The templates are placed in `dexie-cloud/email-templates` and `dexie-cloud/web-templates` directories. For each email type, there are Handlebars templates for the subject, text body, HTML body, and a JSON file for test data. + +-------------------------------- + +### Y.js + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Y.js is a framework for building collaborative applications, and `y-dexie` is an integration that allows Y.js to use Dexie.js (and thus IndexedDB) as its persistence layer. This enables efficient offline support and synchronization for real-time collaborative features. + +-------------------------------- + +### Object Ownership + +Source: https://dexie.org/docs/cloud/access-control + +The ownership of objects are defined by the `owner` reserved property name of any object. The content of that property is the userId of the owner. An owner has full permissions on an object. This applies even if the object is connected to a realm where the user has limited permissions. For example if you have permissions `{add: ["comments"]}` within a realm but not `update` or `manage` permissions you can add new comments but also update or delete your own comments tied to that realm. You will not be able to update or delete other users' comments though. + +-------------------------------- + +### Tutorial > Get started with Dexie Cloud + +Source: https://dexie.org/docs/cloud/consistency + +Get started with Dexie Cloud, a real-time backend service that synchronizes data between your web application and your users' devices. This tutorial covers the initial setup, configuration, and basic usage of Dexie Cloud, enabling features like offline access and real-time collaboration. + +-------------------------------- + +### Best Practices + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Dexie.js offers best practices for building robust applications. This includes proper transaction handling, efficient indexing, and leveraging live queries for responsive UIs. Following these practices can lead to better performance and a more maintainable codebase. + +-------------------------------- + +### Docs Home > Table + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `Table` object in Dexie.js represents a database table and offers various methods for data manipulation. These include `toCollection()` for retrieving all records, `update()` for modifying existing records, `upsert()` for inserting or updating records, and `where()` for querying specific data based on criteria. These methods streamline common database interactions. + +-------------------------------- + +### WhereClause > WhereClause.below() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.below()` method filters records where a specific property's value is strictly less than a given value. This is the counterpart to `above()` and is used for finding items below a certain threshold. + +-------------------------------- + +### Y.js + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Y.js is a framework for building collaborative applications, and `y-dexie` is an adapter that allows Y.js to use Dexie.js (and thus IndexedDB) as its persistence layer. This integration enables seamless offline support and synchronization for collaborative features in your applications. By using `y-dexie`, you can leverage Dexie's robust IndexedDB handling for Y.js's real-time collaboration capabilities. + +-------------------------------- + +### Dexie > Dexie.tables + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.tables` property provides an object containing references to all the tables (object stores) defined in the database schema. You can access individual tables using their names as keys on this object. This property is useful for iterating over all tables or for dynamically accessing tables based on runtime information. + +Example: +`console.log('Tables available:', Object.keys(db.tables)); +console.log('Friends table schema:', db.tables.friends.schema);` + +-------------------------------- + +### Dexie > Dexie.name + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.name` property holds the name of the Dexie database instance. This is particularly useful when you have multiple database instances and need to refer to them by their designated names. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.anyOf() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.anyOf()` method allows you to retrieve records where the indexed property matches any of the values provided in an array. This is a convenient way to perform OR-like queries on a single property. + +-------------------------------- + +### Detailed Sample Explained > Table 'relations' + +Source: https://dexie.org/docs/Version/Version + +The 'relations' table is designed without a visibly defined primary key, but it inherently possesses an auto-incremented primary key managed internally by the database. This table includes indexes on the 'userId1', 'userId2', and 'relation' properties, which are crucial for efficiently querying relationship data. Furthermore, a compound index is established on the combination of 'userId1' and 'userId2' properties. This compound index is particularly useful for queries involving pairs of users, such as finding specific relationships between two users. Similar to the multi-index on emails in the 'users' table, this compound index feature is noted to have limited support in Internet Explorer. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.syncState + +Source: https://dexie.org/docs/cloud/UserLogin + +The `db.cloud.syncState` property provides information about the current status of the data synchronization process. It can indicate whether synchronization is in progress, completed, or if there are any errors or conflicts that need attention. + +-------------------------------- + +### API Reference > MultiEntry Index + +Source: https://dexie.org/docs/roadmap/dexie5 + +Dexie supports multi-entry indexes, which are particularly useful for querying array properties within your data. When a multi-entry index is defined on a property that contains an array, Dexie will create an index entry for each element in the array, allowing you to efficiently query for records based on the values within those arrays. + +-------------------------------- + +### Derived Work > Libraries > sync-server + +Source: https://dexie.org/docs/DerivedWork + +The `sync-server` library provides the backend component necessary to support the `sync-client`. It handles data storage, synchronization logic, and communication with multiple clients, enabling a robust real-time data synchronization system. + +-------------------------------- + +### WriteableTable and WriteableCollection + +Source: https://dexie.org/docs/Deprecations + +The `WriteableTable` and `WriteableCollection` have been obsolete since Dexie.js version 2.0.0. This change is part of a general cleanup of the Dexie codebase, as there's no longer a need to separate `Writeable` from non-`Writeable` Tables and Collections. The rationale behind this decision is that if a method like `put()` or `add()` is accessed within a readonly transaction, it's preferable to receive a rejected Promise rather than a runtime error indicating the method's non-existence. + +-------------------------------- + +### Docs Home > Version > Version.upgrade() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `Version.upgrade()` method provides a hook to perform actions when the database schema is upgraded to a new version. This is where you can write code to migrate data, create new tables, or modify existing ones. It ensures data integrity during schema evolution. + +-------------------------------- + +### API Reference > Table + +Source: https://dexie.org/docs/roadmap/dexie5 + +The `Table` object in Dexie represents a specific table within your IndexedDB database. It provides methods for adding, retrieving, updating, and deleting records. You can also define class mappings for table objects using `defineClass()` and `mapToClass()`, and set up hooks for various events like 'creating', 'reading', 'updating', and 'deleting'. + +-------------------------------- + +### Dexie > Dexie.getDatabaseNames() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Dexie.getDatabaseNames()` static method returns a Promise that resolves with an array of all available IndexedDB database names on the current origin. This can be useful for introspection or managing multiple databases. + +-------------------------------- + +### Compound Index + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js allows you to define compound indexes, which are indexes that consist of multiple properties. This is useful for optimizing queries that filter or sort by multiple fields simultaneously. You define compound indexes within the `stores()` configuration when setting up your database schema. For example, `stores({ friends: '++id, name, age' })` defines a primary key `id` and a compound index on `name` and `age`. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/inbound + +Dexie.js is a wrapper library for the browser's IndexedDB database. It simplifies the usage of IndexedDB by providing a more intuitive API, offering features like automatic schema versioning, promise-based operations, and powerful querying capabilities. Dexie aims to make working with IndexedDB a much more pleasant experience, abstracting away many of the complexities and boilerplate code associated with the native API. + +-------------------------------- + +### Dexie > Dexie Constructor + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The Dexie.js constructor is the entry point for creating and managing your database. You instantiate Dexie.js with a database name and a version number. This allows you to define your database schema and perform upgrades when necessary. For example, `new Dexie('myDatabase')` creates a new database instance named 'myDatabase'. You can then chain `.version(1).stores(...)` to define your schema for version 1. + +-------------------------------- + +### Dexie.js > API Reference > Collection + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides a comprehensive API for interacting with your database. The `Collection` object represents a set of records in a table and offers a rich set of methods for querying, manipulating, and retrieving data. You can perform operations such as filtering, sorting, limiting results, and iterating over collections. Methods like `and()`, `or()`, `filter()`, `sortBy()`, `limit()`, and `offset()` allow for sophisticated data retrieval. Additionally, `Collection` provides methods for direct data manipulation like `delete()`, `modify()`, and `clone()`. + +-------------------------------- + +### Table > Table.offset() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.offset()` method skips a specified number of records from the beginning of the table. It takes an integer argument representing the number of records to skip. This is commonly used with `limit()` for implementing pagination, allowing you to fetch records in chunks, especially after sorting. + +-------------------------------- + +### Releasing Dexie + +Source: https://dexie.org/docs/Releasing-Dexie + +This process is for lead contributors with access to publish on npm. It requires a dedicated master clone on your hard drive, for example `/c/repos/dexie-release`. + +-------------------------------- + +### API Reference > Dexie + +Source: https://dexie.org/docs/roadmap/dexie5 + +Dexie provides a high-level API for interacting with IndexedDB databases. This includes methods for opening, closing, and managing database connections, as well as performing CRUD operations on tables. Key methods include `Dexie.open()`, `Dexie.close()`, and `Dexie.table()` for accessing and manipulating data. + +-------------------------------- + +### Dexie.js > Dexie.defineClass() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides `Dexie.defineClass()` which allows you to define JavaScript classes that map directly to your database tables. Instances of these classes can be added to the table, and Dexie.js will handle the serialization and deserialization between the class instance and the stored data. This promotes object-oriented programming practices and makes working with your data more intuitive. + +-------------------------------- + +### API Reference > POST and DELETE + +Source: https://dexie.org/docs/cloud/rest-api + +Dexie Cloud REST endpoints support GET, POST, and DELETE methods for data interaction. POST and DELETE are used for mutating data, allowing for the creation, updating, and deletion of records within your database. + +-------------------------------- + +### Table > Table.get() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Table.get()` method retrieves a single record from a table based on its primary key. It returns a Promise that resolves with the record object if found, or `undefined` if no record with the specified key exists. For example, `const friend = await db.friends.get(456);` attempts to retrieve the friend with primary key 456. + +-------------------------------- + +### Dexie.js > When to use prototype and when not + +Source: https://dexie.org/docs/Tutorial/Building-Addons + +All inner classes (Collection, WhereClause, Table, Transaction, etc.) use prototype for all their methods. This is because it will optimize instance creations. But the main Dexie class itself does not use prototype for now since instance creation is more rare with the main class which is typically singleton. So to extend or override methods on the main class (Dexie), you should change the property on the given db instance that your addon retrieves as its first argument. For all other internal classes, such as Collection, WhereClause, Table, etc, all methods are prototyped, so you can override the prototype of those. + +-------------------------------- + +### ExportImport > Export and Import Database + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Export and Import Database` feature in Dexie.js allows you to save the entire content of your IndexedDB database to a file and later restore it. This is invaluable for backups, migrating data between environments, or providing users with a way to export their data. The process typically involves iterating through all tables, collecting the data, and then re-inserting it into a new or existing database. + +This functionality is often implemented as an add-on or a utility function, as it's not a core part of the basic CRUD operations. It requires careful handling of data serialization and deserialization to ensure data integrity during the export and import processes. + +-------------------------------- + +### Cloud > db.cloud.syncState + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `db.cloud.syncState` property provides information about the current status of the data synchronization process. This can include details about whether a sync is in progress, has failed, or has completed, allowing you to provide feedback to the user. + +-------------------------------- + +### API Reference > Collection > Collection.toArray() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.toArray()` method converts the entire collection into a JavaScript array. This is often the final step after applying filters, sorts, or limits to retrieve the desired data for your application's use. Be mindful of memory usage when dealing with very large collections. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table Schema` in Dexie.js defines the structure of your database tables, including the primary key and any defined indexes. When you create a new database version using `db.version(x).stores()`, you specify the schema for each table. This schema dictates how data is organized and how efficiently it can be queried. Properly defining your schema with appropriate indexes is crucial for optimal database performance. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The `db.cloud.syncState` property provides the current status of the synchronization process. This can indicate whether syncing is in progress, completed, or if there are any errors. + +-------------------------------- + +### Get started with Dexie in Angular > Create a file `db.ts` + +Source: https://dexie.org/docs/Tutorial/Angular + +Applications typically have one single Dexie instance declared as its own module. This is where you declare which tables you need and how each table shall be indexed. A Dexie instance is a singleton throughout the application - you do not need to create it on demand. Export the resulting `db` instance from your module so that you can use it from your services to write or query data. To make the best Typescript experience with Dexie.js, table properties (such as `db.todoLists` and `db.todoItems`) needs to be explicitly declared on a subclass of Dexie just to help out with the typings for your db instance, its tables and entity models. + +-------------------------------- + +### Dexie Cloud > Use `dexie-cloud` CLI + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The CLI can be used to switch between databases, export, import, and authorize colleagues. See all commands in the CLI docs. + +-------------------------------- + +### Docs Home > Table + +Source: https://dexie.org/docs/inbound + +The `Table` object in Dexie.js represents a database table. It provides methods for performing CRUD (Create, Read, Update, Delete) operations, querying data, and managing table schema. Key methods include `add()`, `put()`, `delete()`, `get()`, `where()`, and `toArray()`. The `Table` object is accessed through the `db.` property, where `` is the name of your table as defined in the database schema. + +-------------------------------- + +### Get started with Dexie Cloud > Declare a `db` (still local only) + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +Unless you already use Dexie (in which case you could just adjust it), create a new module `db.ts` where you declare the database. +_If migrating from vanilla Dexie.js to Dexie Cloud, make sure to remove any auto-incrementing keys (such as`++id` - replace with `@id` or just `id`) as primary keys has to be globally unique strings in Dexie Cloud._ +``` +// db.ts +import { Dexie } from 'dexie'; +import dexieCloud from 'dexie-cloud-addon'; + +export const db = new Dexie('mydb', { addons: [dexieCloud] }); + +db.version(1).stores({ + items: 'itemId', + animals: ' + @animalId, + name, + age, + [name+age]' +}); +``` + +In this example we declare 2 tables: `"items"` and `"animals"`.`"itemId"` is the primary key for `"items"` and `"animalId"` for `"animals"`. +Notice the `@` in `@animalId`. This makes it auto-generated and is totally optional but can be handy since it makes it easier to add new objects to the table. +Note that `animals` also declares some secondary indices `name`, `age` and a `[name+age]` (a compound index). These indices are here only to examplify. For this tutorial, we only need the 'name' index. _A rule of thumb here is to only declare secondary index if needed in a where- or orderBy expression. And don't worry - you can add or remove indices later_ + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/best-practices + +The `Table` object in Dexie.js represents a collection of records within your database. It provides a rich set of methods for performing operations such as adding, deleting, retrieving, and updating records. For instance, `Table.add()` inserts a new record, `Table.get()` retrieves a single record by its primary key, and `Table.toArray()` fetches all records in the table as an array. You can also use methods like `Table.filter()` and `Table.where()` to query specific subsets of data. + +-------------------------------- + +### Decoupling + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +The expression passed to useLiveQuery() must be a function that returns a promise. If you need to decouple your component from the db, you can provide the querying functions as callbacks instead. + +-------------------------------- + +### Tutorial > Best Practices + +Source: https://dexie.org/docs/cloud/best-practices + +Best practices for using Dexie.js involve designing an efficient database schema, leveraging its indexing capabilities for fast queries, and understanding transaction management. For Dexie Cloud, best practices include carefully defining permissions using `DBPermissionSet` and `Role` objects, implementing robust authentication flows, and considering scalability aspects. Properly handling errors and utilizing Dexie's reactive features, like `liveQuery()`, can lead to more performant and user-friendly applications. + +-------------------------------- + +### IndexSpec + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `IndexSpec` interface is used to define the structure of indexes within your Dexie.js database tables. When defining your schema using `db.version(x).stores({...})`, you specify index specifications, including key paths and options like `unique` or `multiEntry`. + +-------------------------------- + +### Libs > dexie-react-hooks > useObservable() + +Source: https://dexie.org/docs/dexie-react-hooks/useObservable%28%29 + +An object with a `subscribe` method taking a callback as 1st arg and optionally and error callback as 2nd arg, returning either an unsubscribe function or an object with an unsubscribe method. This pattern is compatible with several different observable libraries including ES Observable, RxJS, Svelte Store contract etc. If the object also has method `getValue()` (as is the case with RxJS BehaviourSubject), that method will be used to get the initial value. + +-------------------------------- + +### Dexie.js > 6. Pass some query params + +Source: https://dexie.org/docs/Tutorial/React + +This example improves the `FriendList` component by allowing a parent component to pass props that are used within the query. It also demonstrates the use of `async / await` for pedagogical reasons, making it simple to extend the function to perform more complex queries if needed. Two arguments are passed to `useLiveQuery()`: the async function and the dependencies. The callback is a plain async function that can compute any type of result based on what it queries. It can use `Promise.all()` to query things in parallel or sequentially. Any Dexie call along the way will be marked for observation, and the end result will become observed. Dependencies are needed when the querying function uses closures that affect the query, such as `minAge` and `maxAge` parameters. When a parent component passes new values for these, the query needs to be re-executed. + +-------------------------------- + +### Table > Table.add() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.add()` method inserts a new record into a table. If a record with the same primary key already exists, `add()` will throw a `ConstraintError`. This method is useful when you want to ensure that you are only inserting new records and want to be notified if a record with the same key already exists. It returns a Promise that resolves with the primary key of the newly added record. + +Example: +`db.friends.add({ name: 'Bob', age: 25 }).then(id => { console.log(`Added friend with id: ${id}`); });` + +-------------------------------- + +### DBCore > DBCoreCursor + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `DBCoreCursor` interface represents a cursor used for iterating over records in an index or table. It provides methods to move the cursor forward, get the current key and value, and update or delete the current record. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +Dexie.js is a robust wrapper for the IndexedDB API, designed to make database operations in web applications significantly more manageable and efficient. It abstracts away much of the complexity inherent in the native IndexedDB, providing a promise-based interface that aligns with modern JavaScript development practices. This allows developers to work with IndexedDB using familiar async/await syntax, leading to cleaner and more readable code. Key features include simplified schema definition, automatic database upgrades, and a more intuitive way to handle queries and data manipulation. + +-------------------------------- + +### Docs Home > Cloud > Consistency in Dexie Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section discusses how Dexie Cloud ensures data consistency across multiple clients and devices. It explains the mechanisms used to resolve conflicts and maintain a single source of truth. + +-------------------------------- + +### Table > Table.toArray() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.toArray()` method is used to retrieve all records from a table or a collection as a JavaScript array. If called on a `Table` object directly, it fetches all records in that table. If called on a `Collection` object (e.g., after using `where()`, `filter()`, or `limit()`), it returns all records matching the collection's criteria. + +This method returns a Promise that resolves with the array of records. It's a convenient way to load all data from a table or a filtered subset into memory for further processing. Be mindful of performance when fetching large datasets. + +-------------------------------- + +### Tutorial > Getting started with Dexie in Vue + +Source: https://dexie.org/docs/cloud/consistency + +This tutorial explains how to integrate Dexie.js with Vue.js applications. It covers setting up Dexie.js, defining your database, and performing data operations within your Vue components, enabling efficient client-side data management. + +-------------------------------- + +### Version > Version.upgrade() + +Source: https://dexie.org/docs/Table/Table + +The `Version.upgrade()` method is used to define the upgrade logic when migrating between database versions. It receives the old database instance and the transaction object. Inside this callback, you can perform operations like adding or removing tables, creating indexes, or migrating data from old structures to new ones. This ensures a smooth transition for your users when your application's data schema evolves. + +-------------------------------- + +### WhereClause > WhereClause.inAnyRange() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.inAnyRange()` method allows you to specify multiple non-overlapping ranges for a property. Records will be included if their property value falls within any of these specified ranges. + +-------------------------------- + +### Version > Version.stores() + +Source: https://dexie.org/docs/Table/Table + +The `Version.stores()` method is used to define the schema for a database version. It takes an object where keys are table names and values are index specifications. For example, `db.version(1).stores({ friends: '++id, name, age' })` defines a 'friends' table with an auto-incrementing primary key 'id', and indexes on 'name' and 'age'. This method is crucial for setting up your database structure when initializing or upgrading your Dexie database. + +-------------------------------- + +### Table > Table.upsert() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.upsert()` method is a convenience method that combines the functionality of `add()` and `put()`. It attempts to insert a record, and if a record with the same primary key already exists, it will update the existing record instead. This method is very useful for synchronizing data or when you don't need to differentiate between inserting a new record and updating an existing one. It returns a Promise that resolves with the primary key of the affected record. + +Example: +`db.friends.upsert({ id: 5, name: 'Charlie', age: 28 });` + +-------------------------------- + +### Dexie.js > MultiEntry Index + +Source: https://dexie.org/docs/safari-issues + +Dexie.js supports multi-entry indexes, which are a type of index that can store multiple values for a single record. This is particularly useful when dealing with array properties. When you define a multi-entry index on an array property, each element in the array will be indexed individually. This allows you to query for records that contain a specific value within the array, making searches on array data much more efficient. + +-------------------------------- + +### Permissions > add + +Source: https://dexie.org/docs/cloud/access-control + +Permission to add new objects to a given set of tables. Note that object ownership implies full permissions of an object. So unless a user specifies `{owner: null}` when adding an object, the user will keep control of the object and be able to delete it or update any field within it, no matter that user's other existing permissions. The **add** permission also grants the user the ability to move an object of the given types (tables) into this realm (by changing the realmId property). Note though that the same user also needs to either be owner of the object in the source realm, or to have **manage** permission in the source realm. + +-------------------------------- + +### WhereClause > WhereClause.notEqual() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.notEqual()` method filters out records where a property's value is exactly equal to a specified value. This is useful for excluding specific items from your query results. + +-------------------------------- + +### Docs Home > Transaction + +Source: https://dexie.org/docs/Dexie/Dexie.on + +The `Transaction.on.error` event allows you to handle errors that occur during a transaction. This is crucial for debugging and ensuring data integrity. You can attach listeners to this event to perform specific actions when an error is encountered within a transaction. + +-------------------------------- + +### >n limitations of IndexedDB + +Source: https://dexie.org/docs/Tutorial/Getting-started + +IndexedDB has certain limitations, especially concerning Safari's implementation. Safari historically had stricter quotas and could be more aggressive in clearing site data, potentially leading to unexpected data loss if not managed carefully. Dexie.js aims to abstract away many of these browser-specific quirks, but understanding potential limitations like storage quotas and background tab behavior is still important for robust application development. + +Developers should be aware of the storage quotas imposed by browsers, which can vary. Dexie provides mechanisms to handle potential quota errors, but proactive management of data size and usage is recommended. + +-------------------------------- + +### Docs Home > safari-issues + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This entry addresses specific issues or considerations related to using Dexie.js with the Safari browser. It may contain workarounds, explanations of browser-specific behaviors, or compatibility notes. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.syncState + +Source: https://dexie.org/docs/Dexie/Dexie.on + +`db.cloud.syncState` provides the current status of the synchronization process, indicating whether it is idle, syncing, or experiencing errors. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.each()` method in Dexie.js iterates over all records in a table, executing a callback function for each record. It returns a promise that resolves when the iteration is complete. This is a convenient way to process every record in a table, similar to `toArray()` but potentially more memory-efficient for very large tables as it processes records one by one. + +-------------------------------- + +### Quick Reference > Declare Database + +Source: https://dexie.org/docs/API-Reference + +Declaring your database schema in Dexie involves specifying the database name and then defining its tables and indexes. The `db.version(1).stores({...})` syntax is used for this purpose. You list table names followed by their primary key and any additional indexes you need for efficient querying. Importantly, you only declare indexed properties, not all columns like in SQL. + +-------------------------------- + +### 4. Play Around + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `AnimalList` component fetches animal data using the `useLiveQuery` hook from `dexie-react-hooks`. This hook ensures that the list of animals is updated in real-time whenever changes occur in the database. For each animal in the fetched list, it renders an `AnimalView` component to display the animal's details. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.offset()` and `Table.limit()` methods in Dexie.js are used for pagination. `offset()` specifies the number of records to skip from the beginning of the result set, while `limit()` specifies the maximum number of records to return. By combining these methods with `orderBy()`, you can implement efficient pagination to display data in chunks. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.anyOfIgnoreCase()` method is similar to `anyOf()`, but it performs a case-insensitive comparison when matching values in the provided array against the indexed property. This is useful for text-based searches where case should not be considered. + +-------------------------------- + +### ExportImport + +Source: https://dexie.org/docs/cloud/custom-emails + +The `Export and Import Database` feature in Dexie.js allows for seamless backup and restoration of your IndexedDB data. This is crucial for data migration, creating development environments, or simply ensuring data safety. The library provides utilities to export the entire database content into a file format (commonly JSON) and subsequently import it back into a Dexie database. This process simplifies data management and enhances the resilience of applications relying on local storage. + +-------------------------------- + +### Migrate Data + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +When migrating existing data, it is necessary to keep the old version declaration alongside the new one. Additionally, you must attach an `upgrade` function to the new version. This function will contain the logic to transform the data from the old schema to the new schema. The `upgrade` function receives a transaction object (`tx`), and you can use `tx.table('tableName').toCollection().modify(...)` to update individual records. + +-------------------------------- + +### Collection > Collection.and() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie's `Collection.and()` method allows you to combine multiple conditions using a logical AND. This is useful for creating more complex filter criteria that involve multiple properties or conditions. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/web-hooks + +Getting started with Dexie.js in React is made easy with the `dexie-react-hooks` library. This tutorial would likely cover how to set up your Dexie database instance, use hooks like `useLiveQuery` to fetch and display data reactively in your components, and manage database interactions within the React component lifecycle. + +-------------------------------- + +### IndexSpec > Properties > compound + +Source: https://dexie.org/docs/IndexSpec + +The `compound` property in `IndexSpec` is set to `true` when the index or primary key is composed of multiple properties. In such cases, the `keyPath` will be an array of strings, each representing a part of the compound key. It's important to note that this feature is not supported in Internet Explorer. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table` object represents a collection of records within your Dexie database. It provides methods for performing CRUD operations (Create, Read, Update, Delete) such as `add()`, `get()`, `put()`, `delete()`, and `clear()`. You can access a `Table` instance via `db.table('tableName')`. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.defineClass()` method in Dexie.js allows you to associate a JavaScript class with a table. This means that when you retrieve objects from this table, they will be instances of the specified class, automatically having its methods and properties available. This is a powerful feature for creating object-oriented data models and adding behavior directly to your database entities. + +-------------------------------- + +### Road Map: Dexie 5.0 > Type Safe Declaration + +Source: https://dexie.org/docs/roadmap/dexie5 + +Schema definition and typings can be declared in a single expression. Instead of having to declare .version().stores() after instanciating db, the db instanciation and the schema declaration can be done in a single expression. This new approach offers a more streamlined way to define your database schema and associated TypeScript typings, combining them into one declarative statement. This eliminates the need for separate version and store declarations, simplifying the setup process for new projects. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.below()` method creates a query condition to select records where a specific indexed property is strictly less than a given value. This is useful for range queries where you need to exclude the boundary value. + +-------------------------------- + +### Compound Index + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie allows you to define compound indexes, which are indexes that span multiple properties. This is done within the database schema definition. Compound indexes are useful for optimizing queries that filter or sort by multiple fields simultaneously, improving performance for complex data retrieval. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +Dexie.js offers a robust system for managing database versions and performing schema upgrades. The `Version` object and its associated methods, such as `stores()` and `upgrade()`, allow you to define your database schema and handle data migrations gracefully when updating to a new version. This ensures that your application's data remains consistent and accessible as your database evolves. + +-------------------------------- + +### Typescript > Example with Mapped Classes + +Source: https://dexie.org/docs/Typescript + +Here's an example of how to use mapped classes in Dexie 4. In this example, we split `db.ts` into three different modules: + * **db.ts** - _exports the singleton Dexie instance_. To be imported wherever your db is needed. + * **AppDB.ts** - _declaration of database schema_ + * **Friend.ts** - _Entity class example. You could have muliple modules like this_ + +### db.ts +```typescript +// db.ts +import AppDB from "./AppDB" + +export const db = new AppDB() +``` + +### AppDB.ts +```typescript +// AppDB.ts +import { Dexie, type EntityTable } from "dexie" +import Friend from "./Friend" + +export default class AppDB extends Dexie { + friends!: EntityTable + + constructor() { + super("FriendsDB") + this.version(1).stores({ + friends: "++id, name, age", + }) + this.friends.mapToClass(Friend) + } +} +``` + +### Friend.ts +```typescript +// Friend.ts + +import { Entity } from "dexie" +import type AppDB from "./AppDB" + +export default class Friend extends Entity { + id!: number + name!: string + age!: number + + // example method that access the DB: + async birthday() { + // this.db is inherited from Entity: + await this.db.friends.update(this.id, (friend) => ++friend.age) + } +} +``` + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js provides methods for efficiently adding multiple records to a table using `bulkAdd()`, updating multiple records with `bulkPut()`, and removing multiple records with `bulkDelete()`. These methods are optimized for performance by batching operations within a single transaction. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie provides a powerful mechanism for handling **database schema changes** through its versioning system. When you create or upgrade your database, you define different versions with their respective schemas. Dexie's `version()` method allows you to specify the database version and define schema changes, including table definitions and indexes, for each version. This ensures that your database schema evolves gracefully as your application grows. + +-------------------------------- + +### NPM and rollup + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +To integrate Dexie with NPM and the rollup bundler, you'll typically create a main JavaScript file (e.g., main.js). Import Dexie and then define your database schema and operations. The example shows creating a database named 'mydb' with a 'foo' table. It then puts a record into the table, retrieves it, and displays an alert with the retrieved data. After installing Dexie and rollup using npm, you can use the rollup command to bundle your main JavaScript file into a `bundle.js` file. Rollup is capable of resolving the `jsnext:main` attribute in Dexie's `package.json`, allowing you to import Dexie directly. + +-------------------------------- + +### Docs Home > safari-issues + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This section addresses specific issues or compatibility considerations related to Safari browsers when using Dexie.js. It provides workarounds or explanations for any known quirks or limitations encountered in the Safari environment. + +-------------------------------- + +### Collection > Collection.uniqueKeys() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.uniqueKeys()` method retrieves all unique primary keys from a collection. This can be useful for tasks like identifying distinct records based on their primary identifiers. + +-------------------------------- + +### WhereClause > WhereClause.equals() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.equals()` method filters records where a specific property's value exactly matches a given value. This is the most basic filtering condition, used for finding records with a precise match. + +-------------------------------- + +### Implementation Details + +Source: https://dexie.org/docs/Promise/Promise + +The Dexie.js implementation is a fork of promise-light, an A+ and ECMASCRIPT 6 compliant Promise implementation. It has been modified to be compliant with IndexedDB. This implementation utilizes a virtual Micro Task engine when possible, which replaces the need for functions like setImmediate() or setTimeout(). This is particularly useful for handling IndexedDB transactions in older browsers where native Promises might not fully support them. The Micro Task engine is designed to be invisible and undetectable to the user, ensuring continued A+ compliance. This approach was discussed in relation to the Promises A+ specification and is also relevant to understanding native Promise behavior in JavaScript. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +Dexie.js has a roadmap for future development, with version 5.0 being a significant upcoming release. This roadmap often outlines planned features, improvements, and architectural changes. Staying informed about the roadmap helps developers anticipate upcoming changes and plan their integration strategies accordingly. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +Dexie.js provides comprehensive support for TypeScript, enabling developers to leverage static typing for enhanced code quality and maintainability. This includes type definitions for the Dexie API, allowing for better autocompletion, compile-time error checking, and improved developer tooling. Whether you are using Dexie in a new TypeScript project or migrating an existing JavaScript project, the TypeScript integration ensures a smooth and type-safe development experience. Understanding how to define your database schema and interact with it using TypeScript generics can lead to more robust and less error-prone applications. + +-------------------------------- + +### WhereClause > WhereClause.equalsIgnoreCase() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.equalsIgnoreCase()` method filters records where a specific property's value matches a given value, ignoring the case of the strings. This is useful for performing case-insensitive equality checks on text fields. + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/cloud/index + +Dexie 5.0 is a major upcoming version that aims to introduce significant improvements and new features. The roadmap outlines the planned enhancements, which may include performance optimizations, expanded API capabilities, and enhanced developer experience. Staying updated with the roadmap helps in planning for future development. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Dexie.js provides a `WhereClause` object that allows for complex querying of data. Methods like `above()`, `below()`, `between()`, and `equals()` enable precise filtering of records based on specific criteria. For more advanced scenarios, `anyOf()`, `inAnyRange()`, and `noneOf()` offer powerful ways to query collections of values. The `IgnoreCase` variants of these methods (e.g., `equalsIgnoreCase()`, `startsWithIgnoreCase()`) provide case-insensitive filtering, which is particularly useful for text-based searches. + +-------------------------------- + +### Promise + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers a convenient way to work with promises through its `Promise` API. This includes methods for chaining asynchronous operations, handling errors, and managing concurrent tasks. Understanding Dexie's promise utilities can significantly improve the structure and readability of your asynchronous code. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +Dexie.js offers excellent support for TypeScript, enabling developers to leverage static typing for their database interactions. This improves code quality, reduces runtime errors, and enhances developer productivity by providing autocompletion and type checking. The library's TypeScript definitions cover its entire API, ensuring a seamless experience when working with complex database structures and queries. + +-------------------------------- + +### Table Schema + +Source: https://dexie.org/docs/Promise/Promise + +The `Table Schema` in Dexie.js defines the structure of your database tables, including primary keys, indexes, and potential auto-incrementing keys. When you define your database schema using `db.version(x).stores()`, you specify the names of your tables and their respective schemas. For example, `{'friends': '++id, name, age'}` defines a `friends` table with an auto-incrementing primary key `id`, a `name` index, and an `age` index. + +-------------------------------- + +### Collection > Collection.keys() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Collection.keys()` method returns a collection of the primary keys of the records in the current collection. This can be useful when you need to perform operations based on keys, such as deleting multiple records using `bulkDelete()`. For example, `const ids = await db.friends.where('age').above(30).keys();` retrieves the IDs of friends older than 30. + +-------------------------------- + +### Dexie.js + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js simplifies the process of working with IndexedDB by providing a more intuitive API. It abstracts away much of the complexity of the native IndexedDB API, offering features like promise-based operations, automatic schema upgrades, and a fluent query language. This makes database operations more manageable and less error-prone for developers. + +-------------------------------- + +### Dexie + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.js` constructor can be used to create a new database instance. You specify the database name and optionally a version number. This instance is then used to define your database schema and interact with the data. For example, `const db = new Dexie('myDatabase');` initializes a Dexie instance. You then typically chain `.version(1).stores({...})` to define the schema for the first version. + +-------------------------------- + +### Promise + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js enhances the standard `Promise` API by adding features like `Promise.PSD` (Persisted Stack Trace) for better debugging, especially in asynchronous code. It also provides convenient methods for error handling and managing the lifecycle of promises. Understanding how Dexie extends promises can lead to more maintainable and debuggable asynchronous code within your application. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.between() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.between()` method is used to retrieve records where the indexed property's value falls within a specified range, inclusive of both the lower and upper bounds. This is a common and efficient way to query data points that lie between two values. + +-------------------------------- + +### IndexSpec > Properties > multi + +Source: https://dexie.org/docs/IndexSpec + +The `multi` property in `IndexSpec` is relevant when the `keyPath` points to an array. If `multi` is set to `true`, Dexie will index each individual item within that array. This allows for querying based on the elements contained within an array property. However, this functionality is not supported in Internet Explorer. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/cloud/index + +Dexie Cloud provides a set of best practices to help you build scalable and maintainable applications. These include guidelines on schema design, data synchronization strategies, and efficient querying to optimize performance and ensure a smooth user experience. + +-------------------------------- + +### Dexie > Dexie.table() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.table(tableName)` method provides access to a specific table within the database. You can use this to perform operations on that table. For example, `db.table('friends')` returns a reference to the 'friends' table. + +-------------------------------- + +### How Much Data Can Be Stored? + +Source: https://dexie.org/docs/StorageManager + +Once storage is made persistent, the allocated quota can vary by device. Developers can inform users about available storage or implement actions when storage usage reaches a certain threshold. This can be achieved using the `StorageManager.estimate()` method, which provides an estimation of the available quota and current usage. + +-------------------------------- + +### Indexing Binary Data (IndexedDB 2.0) + +Source: https://dexie.org/docs/API-Reference + +IndexedDB 2.0 introduced support for indexing binary data types such as ArrayBuffer and TypedArrays. This feature is available in Chrome and Safari, and partially in Firefox (with a known bug when using binary primary keys, but it works correctly with binary indexes). This allows for efficient storage and retrieval of binary data within your IndexedDB database. + +-------------------------------- + +### Table > Table.put() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.put()` method is used to insert or update a record in a table. If a record with the same primary key already exists, it will be updated; otherwise, a new record will be inserted. This method is versatile as it handles both insertion and updating in a single operation. It takes the record object as an argument and returns a Promise that resolves with the primary key of the inserted or updated record. + +Example: +`db.friends.put({ id: 1, name: 'Alice', age: 30 });` + +-------------------------------- + +### Promise > Promise + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js provides a `Dexie.Promise` type that extends the native Promise API with additional features for better asynchronous programming. This includes enhanced error handling and debugging capabilities, making it easier to manage complex asynchronous workflows. + +-------------------------------- + +### Get started with Dexie in React + +Source: https://dexie.org/docs/Tutorial/React + +Applications typically have one single Dexie instance declared as its own module. This is where you declare which tables you need and how each table shall be indexed. A Dexie instance is a singleton throughout the application - you do not need to create it on demand. Export the resulting `db` instance from your module so that components or other modules can use it to query or write to the database. + +-------------------------------- + +### Dexie.js > API Reference > Promise + +Source: https://dexie.org/docs/safari-issues + +Dexie.js enhances the standard Promise API with features like `Promise.PSD` (Persistent Scope for Generators), which helps manage asynchronous contexts, especially when using generators. It also provides event handlers like `Promise.on.error` and `Promise.onuncatched` for global error handling of unhandled promise rejections, contributing to more robust asynchronous application development. + +-------------------------------- + +### Dexie > Dexie.debug + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.debug` property controls the level of debugging information logged by Dexie.js. Setting `Dexie.debug` to `true` enables verbose logging, which can be very helpful during development for understanding database operations and diagnosing issues. You can also set it to specific strings like `'dexie'` or `'sql'` for more targeted debugging. Remember to disable or reduce debugging in production environments for performance reasons. + +Example: +`Dexie.debug = true;` + +-------------------------------- + +### Things to play with > Make query parameters editable + +Source: https://dexie.org/docs/Tutorial/Svelte + +Add a new component that allows the user to specify `minAge` and `maxAge` and pass those into the props to ``. You will notice that updating the props will also be instantly reflected in the query results of your app (also demonstrated in this already cooked app). + +-------------------------------- + +### ExportProgress + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +The `ExportProgress` interface is used to provide progress updates during the export process. It is passed to the `ExportOptions.progressCallback` function and includes details about the total and completed tables and rows, as well as a `done` flag indicating the completion of the export. This allows users to monitor the progress of large database exports. + +-------------------------------- + +### 2. Be wise when catching promises! + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +For debugging purposes, logging errors is acceptable, but it's crucial to re-throw the error afterward. This ensures that the error propagation is not halted and that subsequent parts of the promise chain, or the caller, are still aware of the failure. Failing to re-throw an error after logging it can lead to unexpected behavior, such as a transaction committing when it should have aborted. + +-------------------------------- + +### Getting Started + +Source: https://dexie.org/docs/Tutorial + +Getting started with Dexie.js is straightforward. You can install it via npm or yarn. Once installed, you create a Dexie instance, defining your database schema using `version()` and `stores()`. This setup allows Dexie to manage database creation and upgrades automatically. + +-------------------------------- + +### Docs Home > Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The `db.cloud.schema` property reflects the database schema as understood by Dexie Cloud. It's important for ensuring that your local schema definition aligns with the schema used by the cloud synchronization service. + +-------------------------------- + +### Dexie > Dexie.transaction() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.transaction()` method is the primary way to initiate a database transaction. It takes the table names involved, the transaction mode (`'r'` for read, `'rw'` for read-write), and a callback function that contains the operations to be performed within the transaction. Transactions ensure data integrity by grouping operations that should succeed or fail together. Nested transactions are not supported; use `db.transaction()` for any operation that requires transactional integrity. + +Example: +`db.transaction('friends', 'rw', (trans) => { + trans.friends.add({ name: 'Charlie' }); +}).then(() => { + console.log('Transaction completed successfully.'); +}).catch((error) => { + console.error('Transaction failed:', error); +});` + +-------------------------------- + +### Table > Table.update() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.update()` method updates an existing record in a table. It takes the primary key of the record to update and an object containing the properties to modify. If the record does not exist, the update operation will fail. This method is useful for partial updates, where you only want to change specific fields of a record without providing the entire object. + +Example: +`db.friends.update(1, { age: 31 }).then(updated => { if (updated) console.log('Friend updated.'); });` + +-------------------------------- + +### Docs Home > Version + +Source: https://dexie.org/docs/cloud/SyncState + +Dexie.js offers a robust way to handle database schema and upgrades. The `Version` object allows you to define your database schema, including tables and their properties. The `upgrade()` method is crucial for managing schema migrations, ensuring your database structure evolves correctly as your application changes. + +-------------------------------- + +### Dexie > Dexie Constructor + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Dexie.js` constructor initializes a new Dexie database instance. You provide the database name and optionally a schema definition. This instance is your main interface for interacting with the database, including opening connections, defining schemas, and executing queries. + +-------------------------------- + +### Getting Started + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +Getting started with Dexie.js is straightforward. You can install it via npm or yarn. Once installed, you can create a new Dexie database instance and define your schema, including tables and their primary keys. The `version()` and `stores()` methods are central to defining and upgrading your database schema. + +-------------------------------- + +### Table > Table.clear() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Table.clear()` method is used to remove all records from a table. This operation is efficient and is often used when you need to reset the data in a table. For example, `await db.friends.clear();` will empty the 'friends' table. It returns a Promise that resolves when the operation is complete. + +-------------------------------- + +### Dexie Cloud Import > Import file format + +Source: https://dexie.org/docs/cloud/cli + +The import file format supports defining `roles` with granular permissions. For example, a "manager" role can have `"manage": "*"` permissions, granting full control within a realm. A "friend-maker" role can have permissions to `"add": ["friends"]` and `"update": {"friends": ["isGoodFriend"]}`. A "readonly" role would have empty permissions `{}`. Each role definition includes a `displayName`, `description`, and an optional `sortOrder`. + +-------------------------------- + +### Docs Home > Tutorial > Building Addons + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Building Addons for Dexie.js allows you to extend its functionality and tailor it to your specific project needs. This section likely covers the architecture of Dexie.js addons and provides guidance on how to create custom extensions. By developing addons, you can integrate Dexie.js with other libraries or implement unique features that are not part of the core library. + +-------------------------------- + +### WhereClause > WhereClause.notEqual() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.notEqual()` method filters records where a specific property's value is not equal to a given value. This is the inverse of `equals()` and is used to exclude records that match a specific criterion. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/custom-emails + +Dexie.js offers powerful table manipulation capabilities through its `Table` object. You can perform a wide range of operations including adding (`add`, `bulkAdd`), retrieving (`get`, `bulkGet`, `toArray`), updating (`update`, `bulkUpdate`, `upsert`), and deleting (`delete`, `bulkDelete`, `clear`) data. The `Table` object also supports advanced querying with `where()`, `filter()`, `orderBy()`, `limit()`, and `offset()`, as well as schema definition and class mapping via `defineClass()` and `mapToClass()`. + +-------------------------------- + +### Table > Table.clear() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.clear()` method removes all records from a table, effectively making it empty. This operation is performed within a transaction. After `clear()` is called, the table will contain no records. This is a destructive operation, so it should be used with caution. It returns a Promise that resolves when the operation is complete. + +Example: +`db.friends.clear().then(() => { console.log('Friends table cleared.'); });` + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js provides a rich set of methods for interacting with your database tables. You can perform common CRUD operations such as `add()`, `put()`, `delete()`, and `get()`. For bulk operations, `bulkAdd()`, `bulkPut()`, `bulkDelete()`, and `bulkGet()` are available for efficiency. You can also retrieve multiple records using `toArray()` or iterate over records with `each()`. The `count()` method returns the number of records in a table, and `clear()` removes all records. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.notEqual() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause.notEqual()` method filters records where a specific index is not equal to the provided value. This is the inverse of `equals()`, allowing you to retrieve all records except those matching a specific criterion. It's useful for excluding specific data points. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +Dexie.js simplifies working with IndexedDB by providing a more intuitive and robust API. It handles many of the complexities of IndexedDB, such as schema management, transaction handling, and error management, allowing developers to focus on their application logic rather than low-level database operations. This leads to faster development cycles and more reliable applications. + +-------------------------------- + +### Dexie.js > Collection > Collection.first() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides the `Collection.first()` method, which retrieves the first record in a collection based on the collection's current sort order. This is a convenient shortcut for getting the initial item in a sorted list. It returns a Promise that resolves with the first record, or `undefined` if the collection is empty. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/Member + +The `Table` object in Dexie.js represents a table (or object store) within your database. It provides a rich set of methods for interacting with the data in that specific table. You can perform operations such as counting records (`Table.count()`), retrieving individual records (`Table.get()`), fetching all records (`Table.toArray()`), filtering (`Table.filter()`), ordering (`Table.orderBy()`), and much more. The `Table` object also exposes properties like `Table.name` and `Table.schema` to access metadata about the table. + +-------------------------------- + +### Dexie.js > Consistent Tree Structures + +Source: https://dexie.org/docs/cloud/consistency + +One pattern for managing tree structures in a database is to have an indexed property representing the path to the parent node, such as `parentPath`. This makes it efficient to delete or list all descendants in one query without any need of recursion. The provided code examples demonstrate how to add new nodes, list direct children, list all descendants, load parents and ancestors, delete nodes and their descendants, and move subtrees with sync consistency. + +-------------------------------- + +### API Reference > Collection > Collection.each() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.each()` method in Dexie.js iterates over all records in a collection, executing a provided callback function for each record. Unlike `toArray()`, `each()` does not load all records into memory at once, making it more memory-efficient for large datasets. The callback function receives the current record as an argument. You can also use `return false;` from the callback to stop iteration early. + +-------------------------------- + +### Promise + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js extends the standard Promise API with additional features, particularly for managing asynchronous operations and their contexts. While standard Promise methods like `catch()` and `finally()` are available, Dexie's Promise extensions might offer more specialized handling for database-related asynchronous tasks, potentially including better error propagation or transaction management within promises. + +-------------------------------- + +### Dexie.js > Collection > Collection.eachPrimaryKey() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js offers the `Collection.eachPrimaryKey()` method, which iterates over the primary keys of all records in the collection. This is useful when you need to perform operations that only require the primary key, such as deleting records in bulk or logging keys. The callback function receives the primary key as an argument, and the method returns a Promise that resolves once all keys have been processed. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/TableSchema + +Dexie.js offers a `WhereClause` object that enables flexible querying of data. The `WhereClause` provides a variety of methods for specifying query conditions, including comparisons like `above()`, `below()`, `between()`, `equals()`, and `notEqual()`. It also supports case-insensitive comparisons (`equalsIgnoreCase()`, `startsWithIgnoreCase()`) and range-based queries (`inAnyRange()`, `anyOf()`). This allows for powerful and precise data retrieval. + +-------------------------------- + +### API Reference > POST and DELETE > DELETE + +Source: https://dexie.org/docs/cloud/rest-api + +The DELETE method is used to remove objects from a table based on their primary key. For compound primary keys, a JSON representation of the key must be provided and URL-encoded. The difference between deleting from `/all` and `/public` is that `/public` will only delete the object if its `realmId` is set to `rlm-public`. Deleting personal data using the `/my` endpoint does not require the `GLOBAL_WRITE` scope but will fail if the user lacks permissions within the object's realm. + +-------------------------------- + +### Dexie.js > Table + +Source: https://dexie.org/docs/safari-issues + +The `Table` object in Dexie.js represents a collection of objects within your database. It provides methods for querying, adding, updating, and deleting data. You can access table-specific operations through the `db.table('tableName')` syntax. For instance, `table.get(key)` retrieves a single object by its primary key, while `table.toArray()` fetches all objects in the table. Methods like `where()` allow for complex querying based on specific criteria. + +-------------------------------- + +### Docs Home > Typescript + +Source: https://dexie.org/docs/DBCore/DBCoreGetManyRequest + +Dexie.js includes comprehensive support for TypeScript, providing strong typing for database schemas, tables, and queries. This enhances developer productivity by offering autocompletion, type checking, and improved code maintainability. The TypeScript integration helps catch errors early in the development process and makes it easier to understand and refactor code. + +-------------------------------- + +### Table > Table.toArray() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers several methods for retrieving collections of data from your tables. `Table.toArray()` retrieves all records from a table into an array. `Collection.toArray()` does the same but operates on a filtered or ordered collection. `Table.keys()` and `Table.primaryKeys()` are more efficient if you only need the keys, and `Table.uniqueKeys()` retrieves unique values from a specific index. These methods are essential for fetching and processing data. + +-------------------------------- + +### WhereClause > WhereClause.noneOf() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.noneOf()` method filters out records where a property's value is present in a given array of values. This is the inverse of `anyOf()`, allowing you to exclude multiple specific values. + +-------------------------------- + +### API Reference > ExportImport + +Source: https://dexie.org/docs/Collection/Collection + +Exporting and importing data from your Dexie.js database is a crucial feature for backups, migrations, and data sharing. Dexie.js provides utilities to serialize your database content into a portable format and then deserialize it back into the database. This process ensures that your data can be safely moved between environments. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Releasing-Dexie + +The `WhereClause` object in Dexie.js is used to build complex queries for filtering records. It offers a rich set of methods for specifying conditions. You can use methods like `above()`, `below()`, `between()`, `equals()`, and `notEqual()` for range and equality checks. For string matching, methods like `startsWith()`, `equalsIgnoreCase()`, and `startsWithAnyOfIgnoreCase()` provide flexible options. `anyOf()`, `noneOf()`, and `inAnyRange()` allow for checking against multiple values. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +Getting started with Dexie.js is straightforward. The library offers various integration options for popular frameworks like React, Svelte, and Vue, making it easy to incorporate into your existing projects. Whether you are building a new application or adding offline capabilities to an existing one, Dexie.js provides the tools to manage your data efficiently. + +-------------------------------- + +### Cloud > db.cloud.schema + +Source: https://dexie.org/docs/cloud/limits + +The `db.cloud.schema` property provides access to the schema definition used by Dexie Cloud for synchronization. This schema dictates how data is structured and synchronized across clients and the server, ensuring data integrity and consistency. + +-------------------------------- + +### Dexie > Dexie.open() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers a `Dexie.open()` method for establishing a connection to your IndexedDB database. This method takes the database name and a schema definition callback, where you specify your tables and indexes. It returns a promise that resolves with the database instance once it's ready for use. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.anyOf() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause.anyOf()` method selects records where a specific index matches any of the values in the provided array. This is a convenient way to query for multiple possible values in a single condition. It significantly simplifies queries involving multiple OR conditions. + +-------------------------------- + +### Cloud > db.cloud.schema + +Source: https://dexie.org/docs/cloud/Member + +The `db.cloud.schema` property reflects the database schema as configured for Dexie Cloud. It provides a way to programmatically inspect the structure of your synchronized database, including tables and their indexes. + +-------------------------------- + +### >n limitations of IndexedDB + +Source: https://dexie.org/docs/Tutorial/Svelte + +When working with Dexie.js, it's important to be aware of the **limitations of IndexedDB** itself. These include limitations on data types that can be stored (though Dexie helps with cloning), potential performance bottlenecks with very large datasets, and browser-specific behaviors or bugs. Understanding these underlying constraints will help you design your database schema and queries more effectively. + +-------------------------------- + +### Dexie.js > Table > Table.defineClass() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides a feature for defining class structures for your tables. Using `Table.defineClass()`, you can create JavaScript classes that represent the shape of your data within a table. Instances of these classes can then be added to the table, and Dexie.js will automatically handle the mapping between the class properties and the database schema. This promotes better code organization and type safety, allowing you to work with your data using object-oriented principles. + +-------------------------------- + +### Collection > Collection.sortBy() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.sortBy()` method sorts the records in the collection by one or more properties. You provide the property name(s) as arguments. This is an efficient way to order your query results directly within the database. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +The `Table` object in Dexie.js represents a database table and provides a rich API for interacting with its data. You can perform operations like adding, retrieving, updating, and deleting records. Furthermore, the `Table` object offers methods for more advanced querying and data manipulation, such as limiting results, offsetting, ordering, and transforming data into specific classes or collections. + +-------------------------------- + +### safari-issues + +Source: https://dexie.org/docs/cloud/web-hooks + +Safari browsers have historically had some specific issues or quirks when dealing with IndexedDB. The 'safari-issues' section likely details these known problems and provides workarounds or explanations on how Dexie.js handles or mitigates them to ensure a consistent experience across different browsers. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause` is used to define filtering conditions for database queries. It allows you to specify criteria for selecting records based on the values in their properties. This is a core component for building efficient and targeted data retrieval operations. + +-------------------------------- + +### Dexie.js > API Reference > Compound Index + +Source: https://dexie.org/docs/safari-issues + +Dexie.js supports the creation of compound indexes, which are indexes defined over multiple properties of an object. This is particularly useful when you frequently query or sort data based on combinations of fields. Compound indexes can significantly improve the performance of such queries. When defining your schema, you can specify compound indexes by listing the property names in the desired order, separated by dots. The order of properties in a compound index is important as it affects the types of queries that can be efficiently executed. + +-------------------------------- + +### Y.js + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +The `Y.js` library is a CRDT (Conflict-free Replicated Data Type) framework for building collaborative applications. `y-dexie` is an integration layer that allows Y.js to use Dexie.js as its persistence layer. This combination enables robust offline support and real-time synchronization for collaborative editing and other real-time features within web applications. + +-------------------------------- + +### MultiEntry Index + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +MultiEntry indexes in Dexie.js allow you to index array properties within your objects. When you define a `multiEntry` index, Dexie will create an index entry for each element within the array property. This enables efficient querying for records that contain specific values within their arrays. For example, indexing a `tags` array property. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.above()` method creates a query condition to select records where a specific indexed property is strictly greater than a given value. This is useful for range queries where you need to exclude the boundary value. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/MultiEntry-Index + +Dexie.js builds on top of the IndexedDB specification to provide a more robust, developer-friendly API. It aims to simplify common IndexedDB operations, making it easier to work with structured data in the browser. This includes features like automatic schema versioning, improved transaction handling, and a more intuitive query API. + +-------------------------------- + +### 4. Play Around + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `CreateAnimal` component provides a form for adding new animals to the database. It uses React's `useState` hook to manage the input values for the animal's name and age. Upon form submission, it prevents the default form behavior, validates that both name and age are provided, and then calls `db.animals.add({ name, age: Number(age) })` to insert the new animal record. After adding the animal, the input fields are cleared. + +-------------------------------- + +### Dexie.js API > Table + +Source: https://dexie.org/docs/cloud/authentication + +The `Table` object in Dexie.js provides methods for interacting with database tables. You can perform operations such as mapping table rows to JavaScript classes using `mapToClass()`, retrieving table names with `name`, setting the starting offset for queries with `offset()`, ordering results with `orderBy()`, adding or updating records with `put()`, reversing query results with `reverse()`, accessing table schema information via `schema`, fetching all records as an array with `toArray()`, converting records into a collection for further processing with `toCollection()`, updating existing records with `update()`, inserting or updating records with `upsert()`, and creating complex queries with `where()`. + +-------------------------------- + +### Dexie.js > The Table Class + +Source: https://dexie.org/docs/Tutorial/Design + +The `Table` class represents an object store in Dexie.js. You get direct access to `Table` instances for each object store defined in your schema on your Dexie instance. For example, if you define `friends` and `pets` as object stores, `db.friends` and `db.pets` will be `Table` instances. The `Table` class is the primary interface for performing all operations on your object stores, including querying, adding, putting, deleting, clearing, and modifying data. + +-------------------------------- + +### Table > Table.clear() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.clear()` method removes all records from the table, effectively resetting it to an empty state. It returns a Promise that resolves when all records have been deleted. Use this method with caution as it is a destructive operation. + +-------------------------------- + +### Cloud > db.cloud.options + +Source: https://dexie.org/docs/cloud/consistency + +The `db.cloud.options` property provides access to the configuration options that were used to initialize Dexie Cloud. You can inspect these options to understand how the cloud service is set up. + +-------------------------------- + +### WhereClause > WhereClause.belowOrEqual() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.belowOrEqual()` method filters records where a property's value is less than or equal to a given value. This provides an inclusive boundary for range queries. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/index + +Dexie.js aims to simplify the use of IndexedDB by providing a more intuitive and developer-friendly API. It abstracts away much of the complexity inherent in the native IndexedDB API, allowing developers to focus on their application logic rather than low-level database operations. Key features include automatic schema versioning and upgrades, transactional operations, and support for complex queries. + +-------------------------------- + +### Cloud > db.cloud.currentUser + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `db.cloud.currentUser` property provides access to the currently logged-in user's information. This object typically contains details such as the user's ID, email, and any custom properties associated with their profile. It's a convenient way to access user data within your application. + +-------------------------------- + +### Dexie.js > 4. Create a component that adds some data + +Source: https://dexie.org/docs/Tutorial/React + +Writing to the database can be done using Table.add(), Table.put(), Table.update() and Collection.modify(). Here we're gonna create a simple React component that allows the user to add friends into the database using Table.add(). + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Dexie.js provides a set of powerful tools for querying data. The `WhereClause` object allows you to build complex queries with various operators like `equals`, `above`, `below`, `between`, `startsWith`, and more. These can be combined to filter data efficiently based on your specific needs. + +-------------------------------- + +### API Reference > Collection > Collection.distinct() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.distinct()` method returns a collection containing only the unique values found in a specific index across all records. This is useful for generating lists of distinct items, such as unique tags or categories, without retrieving the full records. + +-------------------------------- + +### Version > Version.upgrade() + +Source: https://dexie.org/docs/Download + +The `Version.upgrade()` method is used to define the logic for upgrading your database schema. This is where you can add new tables, modify existing ones, or perform any data migrations needed when a user's database version is older than the one defined in your code. It ensures data integrity during schema changes. + +-------------------------------- + +### Getting Started + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +Dexie.js is a powerful wrapper for the IndexedDB database, making it easier to work with in web applications. It provides a more intuitive and feature-rich API compared to the native IndexedDB API, simplifying common database operations and offering advanced functionalities. Whether you're dealing with simple data storage or complex querying needs, Dexie.js aims to streamline your development process. + +-------------------------------- + +### EntityTable + +Source: https://dexie.org/docs/EntityTable + +`EntityTable` is new in Dexie 4 and provides syntactic sugar on top of `Table`: + 1. It defines the TInsertType where primary key is optional and any class methods are omitted (so that plain javascript objects can be provided to Table.add(), instead of having to construct using new()) + 2. It extracts the TKey type from T[KeyPropName] + +-------------------------------- + +### Docs Home > Cloud > db.cloud.persistedSyncState + +Source: https://dexie.org/docs/Dexie/Dexie.on + +`db.cloud.persistedSyncState` provides access to the state of ongoing synchronization processes. This can be useful for monitoring and debugging sync issues. + +-------------------------------- + +### Collection > Collection.distinct() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.distinct()` method retrieves unique values from a collection based on a specified key path. This is useful for getting a list of unique values for a particular field across a set of records. + +-------------------------------- + +### Dexie Cloud Best Practices + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Dexie Cloud offers best practices for managing your cloud-connected database. These guidelines cover aspects like data modeling, synchronization strategies, and security to ensure a scalable and reliable application. + +-------------------------------- + +### Dexie.js + +Source: https://dexie.org/docs/safari-issues + +Dexie.js aims to make working with IndexedDB more manageable and less error-prone. It provides a Promise-based API, which aligns with modern JavaScript development practices. The library handles many of the complexities of IndexedDB, such as schema versioning and transaction management, allowing developers to focus on their application logic. Additionally, Dexie.js offers features like automatic schema upgrades, making database evolution smoother. It also provides a more expressive query language and utility functions to simplify common database operations. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.equalsIgnoreCase()` method performs a case-insensitive comparison to select records where an indexed property matches a given value. This is particularly useful for text fields where the exact casing of the stored data might vary. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/cloud/best-practices + +The `Version` object in Dexie.js is central to managing your database schema evolution. Each version of your database schema is represented by a `Version` object, which you define using `db.version(versionNumber)`. Within a version, you specify the `stores()` that will be created or modified, including their primary keys and indexes. The `upgrade()` method is crucial for defining migration logic to transform data from a previous version to the current one, ensuring backward compatibility and smooth upgrades. + +-------------------------------- + +### Docs Home > Y.js + +Source: https://dexie.org/docs/inbound + +Y.js is a framework for building collaborative applications that allows different clients to edit shared data in real-time. The `y-dexie` library acts as a connector, enabling Y.js to use Dexie.js (and thus IndexedDB) as a persistent storage backend for its collaborative data structures. This combination facilitates the creation of offline-first collaborative features. + +-------------------------------- + +### DBCore + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie's `DBCore` API provides a lower-level interface to IndexedDB operations. It exposes methods that map more directly to the native IndexedDB specifications, offering more control but also requiring a deeper understanding of IndexedDB internals. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Typescript-old + +Dexie.js aims to simplify the use of IndexedDB by providing a more intuitive and robust API. It addresses many of the complexities and limitations inherent in the native IndexedDB API, making it easier for developers to work with client-side databases. Key features include a promise-based interface, automatic schema management, and advanced querying capabilities. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +The `Version` object in Dexie.js is central to managing database schema evolution. When you need to change your database schema, such as adding new tables or modifying existing ones, you do so by creating new versions. The `Version.stores()` method is used to define the schema for a particular version, specifying the tables and their indexes. The `Version.upgrade()` method allows you to define migration logic that runs when the database is upgraded from a previous version to the current one, ensuring data is correctly transformed during schema changes. + +-------------------------------- + +### Cloud > db.cloud.schema + +Source: https://dexie.org/docs/DerivedWork + +Dexie Cloud's schema definition (`db.cloud.schema`) is crucial for understanding how your data is structured and synchronized. It defines the collections and their properties that are managed by the cloud service. + +-------------------------------- + +### Docs Home > Inbound + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The 'Inbound' section likely refers to data or requests coming into your application or system. In the context of Dexie.js, this could pertain to how data is imported, received from external sources, or processed upon arrival into the database. It's about the flow of data into your Dexie-managed storage. + +-------------------------------- + +### Roadmap + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +Dexie.js has a well-defined roadmap, with significant development efforts focused on version 5.0. This upcoming version aims to introduce major enhancements and potentially new features that will further improve the library's performance, developer experience, and capabilities. Keeping an eye on the roadmap provides insights into the future direction of Dexie.js and its evolving ecosystem. + +-------------------------------- + +### Cloud > db.cloud.permissions() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `db.cloud.permissions()` method is used to retrieve the permissions associated with the current user or a specific role. This information is crucial for implementing role-based access control within your application. + +-------------------------------- + +### Collection > Collection.offset() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Collection.offset()` method skips a specified number of records from the beginning of a collection before returning the results. It takes a single argument, `numRows`, indicating how many records to skip. This method is typically used in conjunction with `limit()` for implementing pagination, allowing you to fetch records in chunks. It should generally be applied after `where()` or `filter()` clauses. + +Example: +`db.friends.offset(20).limit(10).toArray();` This would retrieve records 21 through 30. + +-------------------------------- + +### Cloud > db.cloud.syncState + +Source: https://dexie.org/docs/cloud/consistency + +The `db.cloud.syncState` property provides real-time information about the current synchronization status, including whether data is being synced, if there are conflicts, or if the sync is complete. + +-------------------------------- + +### Workers + +Source: https://dexie.org/docs/StorageManager + +Web Workers and Service Workers can access the storage API in the same manner as web pages, by utilizing `navigator.storage`. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Table/Table + +Dexie.js is a wrapper for IndexedDB that provides a more convenient and powerful API. It simplifies common IndexedDB operations such as opening a database, defining schemas, and performing CRUD operations. Dexie.js also introduces features like observable queries and transaction management, making it a popular choice for modern web applications that require robust offline data storage. + +-------------------------------- + +### Promise > Promise.finally() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Promise.finally()` method registers a callback that will be executed when a Promise is settled, regardless of whether it was fulfilled or rejected. This is useful for cleanup operations. + +-------------------------------- + +### Tutorial > Getting Started with Dexie.js + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie.js is a powerful JavaScript library designed to simplify interactions with IndexedDB. It offers a promise-based API, making asynchronous database operations more manageable and readable compared to the native IndexedDB API. Key features include easy schema definition and migration, efficient querying capabilities with a fluent API, and support for transactions. Its design prioritizes developer experience and performance, making it a popular choice for building offline-first web applications. + +-------------------------------- + +### Docs Home > Y.js + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Y.js is a framework for building collaborative applications, and `y-dexie` is an integration that allows Y.js to use Dexie.js as its persistence layer. This combination enables robust offline support and synchronization for real-time collaborative features. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/cloud/limits + +Dexie Cloud provides best practices and guidelines for building scalable and maintainable cloud-connected applications. Following these recommendations can help you optimize performance, handle data synchronization efficiently, and ensure a smooth user experience, especially in collaborative environments. + +-------------------------------- + +### Dexie > Dexie.addons + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js provides a `Dexie.addons` property that allows you to register and manage add-ons for your database. Add-ons can extend Dexie's functionality or integrate with other libraries. By using the `use()` method, you can attach these add-ons to your Dexie instance. + +-------------------------------- + +### Collection > Collection.limit() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Collection.limit()` method restricts the number of records returned from a collection. You specify the maximum number of records you want to retrieve. This is often used in conjunction with `offset()` for pagination. For example, `db.friends.limit(10).toArray()` would retrieve at most the first 10 friends. + +-------------------------------- + +### Dexie.js > API Reference > Table + +Source: https://dexie.org/docs/safari-issues + +The `Table` object in Dexie.js represents a single data store (similar to a table in SQL databases) within your IndexedDB. It provides a set of methods for performing common operations on the records within that table. You can add new records using `add()` or `bulkAdd()`, retrieve records with `get()` or `bulkGet()`, update existing records using `put()` or `bulkPut()`, and delete records with `delete()` or `bulkDelete()`. The `Table` object also offers methods for querying like `count()`, `each()`, and `filter()`. + +-------------------------------- + +### API Reference > MultiEntry Index + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +A `MultiEntry` index in Dexie.js allows you to index array values within a specific key path. When you define a `MultiEntry` index, Dexie.js will create a separate index entry for each element in the array stored at that key path. This is extremely useful for querying data based on individual elements within an array, such as searching for items that contain a specific tag in a list of tags. It significantly enhances the searchability of array-based data. + +-------------------------------- + +### WriteableTable and WriteableCollection + +Source: https://dexie.org/docs/Deprecations + +For most applications, the deprecation of `WriteableTable` and `WriteableCollection` will not introduce any complications. However, if you are developing an addon that previously extended `WriteableTable` or `WriteableCollection`, you will need to update your code to extend `Table` and `Collection` instead. This adjusted approach will ensure compatibility with older versions of Dexie.js. + +-------------------------------- + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie offers `shallowClone()` and `deepClone()` methods which can be useful for creating copies of data structures. `shallowClone()` copies only the top-level properties + +-------------------------------- + +### API Reference > Collection > Collection.first() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.first()` and `Collection.last()` methods in Dexie.js retrieve the first or last record from a collection, respectively, based on the current order. These are efficient methods when you only need one of the boundary records, often used after applying sorting or filtering criteria. + +-------------------------------- + +### API Reference > Classes > Promise + +Source: https://dexie.org/docs/API-Reference + +Dexie heavily utilizes Promises to handle asynchronous database operations. The `Promise` class here likely refers to the standard JavaScript Promise object or Dexie's internal handling of them. Understanding promises is crucial for correctly managing the flow of operations like reading, writing, and querying data. + +-------------------------------- + +### Road Map: Dexie 5.0 > Representing Classes instead of Interfaces + +Source: https://dexie.org/docs/roadmap/dexie5 + +In dexie@4 and earlier, we've always had the Table.mapToClass() method to connect a table to its model class. In dexie@5 this will be done simply by declaring the schema with `Table(MyClass)` instead of `Table`. This change allows for a more object-oriented approach to data modeling, where your database tables are directly associated with their corresponding class definitions. This integration simplifies the mapping process and enables you to leverage class methods directly within your data operations. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DerivedWork + +Dexie.js is a robust wrapper for the browser's IndexedDB database. It simplifies common operations and provides a more developer-friendly API, making it easier to manage client-side data. Dexie handles many of the complexities of IndexedDB, such as schema management and transaction handling, allowing developers to focus on their application logic. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/inbound + +Dexie.js has evolved significantly over its versions. Dexie 5.0, for instance, introduced various improvements and new features. It's important to consult the roadmap and changelogs to understand the latest developments, breaking changes, and future directions of the library. This ensures you are utilizing the most efficient and up-to-date features available. + +-------------------------------- + +### Transaction > Transaction.abort() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Transaction.abort()` method is used to explicitly abort a transaction. When a transaction is aborted, all changes made within that transaction are discarded, and the database remains in its state prior to the transaction. This is useful for scenarios where an error occurs during the transaction, and you want to ensure data integrity by rolling back any partial changes. Aborting a transaction also triggers the `on.abort` event. + +Example: +`db.transaction('friends', 'rw', () => { /* ... */ }).catch(err => { if (err.name === 'AbortError') { console.log('Transaction aborted.'); } });` + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Version` object in Dexie.js represents a database schema version. It provides methods like `stores()` to define the object stores (tables) and their indexes for a given version, and `upgrade()` to define the logic for migrating data when the database version changes. This is crucial for managing database schema evolution over time. + +-------------------------------- + +### useLiveQuery() + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +The `useLiveQuery` hook is used to observe IndexedDB data within a React component, automatically re-rendering the component when the data changes. This functionality allows Dexie to act as a persistent and memory-efficient state manager for React applications, eliminating the need to load the entire database into RAM. Modifications made to the data through Dexie methods such as `Table.add()`, `Table.update()`, or `Table.delete()` will trigger an automatic re-render in any component observing the affected data. + +-------------------------------- + +### API Reference > Classes > WhereClause + +Source: https://dexie.org/docs/API-Reference + +The `WhereClause` class represents a query condition used for filtering records in a table. You typically obtain a `WhereClause` instance by calling methods like `table.where('propertyName')`. It provides a fluent API for specifying various types of query predicates. + +-------------------------------- + +### WhereClause > WhereClause.below() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.below()` method filters records where a property's value is strictly less than a given value. This is useful for range-based queries on numerical or date properties. + +-------------------------------- + +### WhereClause > WhereClause.belowOrEqual() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.belowOrEqual()` method filters records where a specific property's value is less than or equal to a given value. This is inclusive of the specified value, useful for range queries that include the upper boundary. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie.js offers a `WhereClause` object that represents a condition used for filtering data. The `WhereClause` provides a fluent API for constructing complex query conditions. Methods like `equals()`, `equalsIgnoreCase()`, `above()`, `below()`, `between()`, `startsWith()`, `startsWithIgnoreCase()`, `anyOf()`, `anyOfIgnoreCase()`, `noneOf()`, and `notEqual()` allow developers to specify precise filtering criteria for retrieving data from Dexie.js tables. These methods can be chained together to build sophisticated queries that precisely target the desired records. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The `db.cloud.options` property holds the configuration settings for Dexie Cloud, as defined during initialization with `db.cloud.configure()`. Accessing this can be useful for inspecting the current cloud-related settings. + +-------------------------------- + +### Cloud > db.cloud.invites + +Source: https://dexie.org/docs/cloud/Member + +The `db.cloud.invites` collection provides access to invitation-related data within Dexie Cloud. You can use this to manage invitations sent to users, track their status, and programmatically interact with the invitation system. + +-------------------------------- + +### Dexie.js > Migrating by exporting and importing + +Source: https://dexie.org/docs/cloud/best-practices + +Migrating a database can be done by exporting the current database to a JSON file, then writing a node script to migrate the JSON file and produce a new file, and finally importing the new file to another database. This process allows for more complex data transformations that might not be feasible with ad-hoc migration. + +-------------------------------- + +### Docs Home > Cloud > Sharding and Scalability + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +This section discusses strategies for sharding and scaling your Dexie Cloud application. It covers techniques for distributing data across multiple servers and optimizing performance as your user base and data volume grow. Effective scaling is key to handling increased load. + +-------------------------------- + +### Dexie.js > Collection > Collection.primaryKeys() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides the `Collection.primaryKeys()` method, which returns a Promise that resolves to an array containing the primary keys of all records in the collection. This is an efficient way to get a list of identifiers for the matching records, often used before performing bulk operations or for reference purposes. + +-------------------------------- + +### Cloud > db.cloud.persistedSyncState + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `db.cloud.persistedSyncState` property provides access to the state of the last successful synchronization. This information can be useful for understanding synchronization history or for implementing custom synchronization logic. + +-------------------------------- + +### Docs Home > Compound Index > How Compound Index Works + +Source: https://dexie.org/docs/Compound-Index + +A compound index can be viewed as the index of a concatenation of two properties. They are expressed as "[prop1+prop2]" both when declaring them and when referring to them in `where()` clauses. However, when expecting a compound value, an array is expected, as compound keys are represented by arrays in IndexedDB. For instance, to query a person with `firstName` 'foo' and `lastName` 'bar' using a compound index, you would use `db.people.where({firstName: 'foo', lastName: 'bar'}).first()`. + +-------------------------------- + +### Dexie.js > Collection > Collection.raw() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides the `Collection.raw()` method, which returns a collection of records in their raw IndexedDB format. This can be useful for interoperability with other libraries or for debugging purposes when you need to inspect the underlying data structure as stored by IndexedDB. It returns a Promise that resolves with an array of raw records. + +-------------------------------- + +### Export and Import Database > Install + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +To use the export and import functionalities, you first need to install the `dexie` and `dexie-export-import` npm packages. After installation, you can import the necessary functions from `dexie-export-import`. The basic usage involves calling `importDB` with a Blob and optionally an options object to import data into a Dexie instance, or `exportDB` with a Dexie instance to export the database to a Blob. The `importInto` function is useful for merging data into an already existing database, while `peakImportFile` lets you preview the contents of an import file before committing to the import process. + +-------------------------------- + +### Understanding the basics > Declarative Schema + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +The database schema is declarative, not imperative. +```javascript +var db = new Dexie('dbname'); +db.version(1).stores({ + friends: 'id, name, age' +}); +db.open().then(function (db) { + // Database opened successfully +}).catch (function (err) { + // Error occurred +}); +``` + +-------------------------------- + +### Table > Table.bulkGet() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.bulkGet()` method retrieves multiple records from a table based on an array of primary keys. It returns a Promise that resolves with an array of the found records, maintaining the order of the provided keys. Records not found will result in `undefined` at their corresponding position. + +-------------------------------- + +### Libs > dexie-react-hooks > useObservable() + +Source: https://dexie.org/docs/dexie-react-hooks/useObservable%28%29 + +Variables that observableFactory is dependent on (similar to the `deps` argument in `useEffect()`). + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +The `Table` object in Dexie.js represents a database table and provides a comprehensive set of methods for interacting with its data. You can perform operations like deleting records, iterating through them, filtering based on specific criteria, retrieving individual records, and updating or inserting new data. The `Table` object also exposes properties like `name` and `schema` for inspecting the table's structure. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.above() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.above()` method is used to filter records where the indexed property's value is strictly greater than the specified value. This is useful for querying data within a specific range, excluding the lower bound. + +-------------------------------- + +### API Reference > Classes > Version + +Source: https://dexie.org/docs/API-Reference + +The `Version` class is used to define and manage schema versions of your Dexie database. You create new versions using `db.version(newVersionNumber).stores(...)`. This allows you to evolve your database schema over time, and Dexie handles the necessary upgrades automatically. + +-------------------------------- + +### DexieError + +Source: https://dexie.org/docs/DexieErrors/DexieError + +The `DexieError` object, and its subclasses, possess key properties that aid in understanding and resolving errors. The `name` property indicates the type of error that occurred (e.g., 'ConstraintError', 'UpgradeError'). The `message` property provides a detailed textual description of the error, offering more context. For certain errors, an `inner` property may be present, containing the original exception if the Dexie error was a wrapper around another error. If the error was thrown, a `stack` property, containing the call stack, might also be available, which is invaluable for debugging. These properties collectively provide comprehensive information to diagnose and fix issues. + +-------------------------------- + +### Dexie.js + +Source: https://dexie.org/docs/Releasing-Dexie + +Dexie.js is a popular wrapper library for IndexedDB, aiming to simplify its usage and add powerful features. It offers a more intuitive API for database operations, including querying, schema management, and transaction handling. Dexie.js also addresses some of the inherent limitations of IndexedDB, making it easier to build robust web applications with local data storage. + +-------------------------------- + +### Docs Home > Typescript + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie.js offers robust support for TypeScript, providing type safety and improved developer experience. This includes type definitions for database schemas, queries, and operations, which help catch errors at compile time and enhance code maintainability. The library's TypeScript integration ensures that your database interactions are type-checked, leading to more reliable applications. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The `db.cloud.version` property provides information about the current version of the Dexie Cloud addon being used. This can be helpful for compatibility checks and understanding feature availability. + +-------------------------------- + +### Tutorial + +Source: https://dexie.org/docs/cloud/web-hooks + +Similarly, getting started with Dexie.js in Angular involves setting up the database and integrating it into Angular components and services. Tutorials would typically demonstrate how to use Dexie's promise-based API within the Angular ecosystem, potentially leveraging RxJS for observable-based data streams. + +-------------------------------- + +### WhereClause > WhereClause.above() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.above()` method filters records where a specific property's value is strictly greater than a given value. This is useful for range queries where you want to find all items that fall above a certain threshold. + +-------------------------------- + +### Collection > Collection.limit() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Collection.limit()` method restricts the number of records returned from a collection. It takes a single argument, `numRows`, which specifies the maximum number of records to retrieve. This is useful for pagination or when you only need a subset of the matching records. The `limit()` method should typically be used after `where()` or `filter()` clauses to limit the results of a query. + +Example: +`db.friends.limit(10).toArray();` This will retrieve at most 10 friends from the table. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `WhereClause` object in Dexie.js is used to define query criteria for retrieving data from tables. It provides a rich set of methods for specifying conditions, such as `above()`, `below()`, `between()`, `equals()`, `equalsIgnoreCase()`, `anyOf()`, `noneOf()`, `startsWith()`, and `startsWithIgnoreCase()`. These methods allow for flexible and precise data filtering. + +-------------------------------- + +### Cloud > db.cloud.version + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `db.cloud.version` property provides information about the current version of the Dexie Cloud configuration or schema being used. This can be helpful for managing database migrations or understanding compatibility. + +-------------------------------- + +### Realms > Default Access Control > Example: Zero config Access Control + +Source: https://dexie.org/docs/cloud/access-control + +Let's say you write a ToDo app where you don't care at all about collaboration. You just want each user to get their IndexedDB synced with the cloud so that they can have their same ToDo list on multiple devices and have them in sync. No user should access another user's ToDo list - they are 100% private for each user. The sample below is almost identical to how it would be declared in a plain Dexie.js app. The differences are simply that the dexieCloud addon has been enabled, it has connected to a Dexie Cloud database, and it uses the '@' sign to generate universal IDs. +``` +import { Dexie } from 'dexie' +import dexieCloud from 'dexie-cloud-addon' + +const db = new Dexie('mySyncedDB', { addons: [dexieCloud] }) +db.version(1).stores({ + todoLists: '@id, title', + todoItems: '@id, title, done, todoListId', +}) + +db.cloud.configure({ + databaseUrl: '', + requireAuth: true, +}) + +``` +_In this sample, we are only declaring application tables 'todoLists' and 'todoItems'. This is ok. Sync will work for each user, but users will not be able to share their lists with others_ + +-------------------------------- + +### API Reference > Collection + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `Collection` object in Dexie.js provides a set of methods for querying and manipulating data within a table. You can perform operations like adding (`.add()`), filtering (`.filter()`), counting (`.count()`), deleting (`.delete()`), and retrieving data in various formats (`.toArray()`, `.keys()`, `.primaryKeys()`). It also supports sorting (`.sortBy()`), limiting results (`.limit()`), and offsetting (`.offset()`), along with methods for iterating through collections (`.each()`, `.eachKey()`, `.eachPrimaryKey()`). Advanced features include using `.or()` for OR queries, `.and()` for AND queries, and `.distinct()` to get unique values. + +-------------------------------- + +### Docs Home > Tutorial > Migrating existing DB to Dexie + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Migrating an existing database to Dexie.js involves transitioning your current data and schema to be managed by Dexie. This tutorial likely provides strategies and code examples for exporting data from your old database system, defining a corresponding schema in Dexie, and importing the data. It addresses the challenges of data transformation and ensuring data integrity during the migration process. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The `WhereClause.between()` method allows you to filter records where a property's value falls within a specified range, inclusive of the start and end values. This is particularly useful for querying date ranges or numerical intervals. + +-------------------------------- + +### Collection + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie offers a `Dexie.Collection` object that represents a set of records retrieved from a table, often as a result of a query. It provides a fluent API for further filtering, sorting, and manipulating the results before fetching them into an array or iterating over them. Methods like `filter()`, `limit()`, `offset()`, `sortBy()`, and `reverse()` are available on the `Collection`. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +Dexie.js is a popular wrapper library for IndexedDB, designed to simplify database operations in web applications. It offers a more intuitive and developer-friendly API compared to the native IndexedDB API, making it easier to work with client-side data storage. Dexie.js handles many of the complexities of IndexedDB, such as transaction management, cursors, and error handling, allowing developers to focus on their application logic. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Dexie Cloud provides best practices for developing and deploying cloud-connected applications. These guidelines cover aspects like schema design, data synchronization strategies, security considerations, and performance optimization. Adhering to these best practices helps ensure the reliability, scalability, and maintainability of your application. + +-------------------------------- + +### Dexie.js > 5. Create a component that queries data + +Source: https://dexie.org/docs/Tutorial/React + +Write a simple component that just renders all friends in the database. The function passed to `useLiveQuery()` queries Dexie for all friends. The result will be undefined momentarily before the very initial result arrives - which explains why we refer it as `friends?` rather than `friends`. + +-------------------------------- + +### Table > Table.limit() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.limit()` method restricts the number of records returned by a query. It takes an integer argument specifying the maximum number of records to include in the result set. This is often used in conjunction with `offset()` for pagination, especially when combined with `orderBy()`. + +-------------------------------- + +### Inbound + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +The 'Inbound' section likely refers to data or messages coming into the application or system. In the context of Dexie.js, this could relate to data synchronization from a remote source or the processing of incoming requests. Understanding inbound data flows is crucial for managing data integrity and application logic. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +The `WhereClause.equalsIgnoreCase()` method performs a case-insensitive equality check. This is helpful when you need to match string values without regard to whether they are uppercase or lowercase, providing more flexible search capabilities. + +-------------------------------- + +### Compound Index + +Source: https://dexie.org/docs/Tutorial/Getting-started + +A `Compound Index` in Dexie.js is an index that consists of multiple properties. When defining an index in your schema, you can list multiple property names separated by commas to create a compound index. Dexie will then create an index that can be efficiently queried using combinations of these properties in the specified order. Compound indexes are crucial for optimizing queries that involve multiple criteria. + +Example: +`db.version(1).stores({ + friends: '[name+age], address' +});` Here, `[name+age]` defines a compound index on the `name` and `age` properties. + +-------------------------------- + +### Getting Started with Dexie.js + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Getting started with Dexie.js is straightforward. You can install it via npm or yarn and then import it into your project. The basic setup involves creating a Dexie instance and defining your database schema using the `stores()` method. This allows you to specify your object stores (tables) and their indexes. + +-------------------------------- + +### Docs Home > Typescript + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +Dexie.js offers robust support for TypeScript, enabling better code maintainability and reducing runtime errors. By leveraging TypeScript, developers can benefit from static typing, autocompletion, and improved tooling when working with Dexie.js databases. This section likely covers how to define your database schema and interact with it using TypeScript for a more type-safe development experience. + +-------------------------------- + +### NPM and webpack + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +When using NPM and webpack, you can manage your project's versions and dependencies efficiently. This setup is ideal for working with CommonJS modules. After installing Node.js, which includes npm, you can initialize a new npm package in a dedicated directory. Install Dexie and webpack as dependencies using npm commands. Then, create a JavaScript file (e.g., index.js) to interact with Dexie, defining your database schema and performing operations. To bundle your JavaScript code for the browser, use webpack. Finally, create an HTML file to load the bundled JavaScript. For testing, especially on browsers like Edge that might block IndexedDB from the file system, using a local web server like `http-server` is recommended. You can then access your application via `http://localhost:8080/` and inspect the console logs by pressing F12. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/cloud/Member + +The `Version` object in Dexie.js is central to managing your database schema over time. When you define your database structure using `db.version(x).stores({...})`, you are creating a new version. The `Version.upgrade()` method is crucial for defining the schema migrations that occur when a user's database is updated to a new version. This allows you to add tables, modify indexes, or change schemas gracefully without data loss. + +-------------------------------- + +### Table > Table.bulkPut() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers `Table.bulkPut()` for efficiently inserting or updating multiple records. If a record with the same primary key exists, it's updated; otherwise, it's inserted. This method is ideal for synchronizing data or ensuring a set of records exists in the database. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +The `Version` API in Dexie.js is crucial for managing database schema evolution. When you need to add, remove, or modify tables and indexes, you do so within a `Version` object. The `Version.stores()` method defines the structure of your object stores (tables), and `Version.upgrade()` provides a hook to perform data migrations when the database version changes. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +Dexie.js is a robust wrapper for the IndexedDB API, designed to simplify database interactions in web applications. It offers a promise-based API, making asynchronous operations more manageable and readable. Key features include automatic database schema management, including versioning and upgrades, and observable queries that automatically update your UI when data changes. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Dexie.js offers excellent support for TypeScript, providing a type-safe experience for database interactions. This includes typed database instances, schemas, and query results, which significantly improves code quality and reduces runtime errors. The TypeScript integration allows developers to leverage the full power of static typing when working with IndexedDB. + +-------------------------------- + +### Dexie Cloud CLI > create + +Source: https://dexie.org/docs/cloud/cli + +Creates a database in the cloud. +**cd** to the root directory of your web app and write: +npx dexie-cloud create [--service ] +This command creates a new database in the cloud. You will be prompted for your email address and receive an email with the one-time password (OTP) to enter into the next prompt. Once the database has been created, your will also get two files stored in the same directory as you stand in. +| +---|--- +dexie-cloud.json| Contains the URL to your new database +dexie-cloud.key| Contains the client ID and secret for further CLI commands +Neither of these files should be added to git as they represent environment rather than source. It is especially important to not add the .key file as it contains the secret. The files are not needed for the web app to work - they are only useful if you want to run other CLI commands, like white-listing new apps etc. They can also be used to access the Dexie Cloud REST API from a server. +Your email will be stored in the database as the database owner. + +-------------------------------- + +### Collection > Collection.offset() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Collection.offset()` method is used to skip a specified number of records from the beginning of a collection. This is commonly used for implementing pagination, allowing you to fetch data in chunks. For instance, `db.friends.offset(20).limit(10).toArray()` would retrieve friends from the 21st to the 30th. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/web-hooks + +Dexie.js is a powerful wrapper for IndexedDB, designed to make client-side database operations more intuitive and efficient. It abstracts away much of the complexity inherent in the native IndexedDB API, providing a cleaner, more developer-friendly interface. This allows developers to focus on building features rather than wrestling with low-level database details. Dexie.js offers features like promise-based operations, automatic schema versioning, and simplified CRUD (Create, Read, Update, Delete) operations, making it a popular choice for modern web applications requiring robust offline capabilities. + +-------------------------------- + +### WhereClause > WhereClause.above() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.above()` method filters records where a property's value is strictly greater than a given value. This is the counterpart to `below()` for defining upper bounds in range queries. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Dexie.js offers a robust solution for managing data in web applications, abstracting away the complexities of the native IndexedDB API. It provides a promise-based interface for all asynchronous operations, making code cleaner and easier to reason about. With Dexie, you can define database schemas, perform CRUD operations, and handle transactions with significantly less boilerplate code. Its focus on developer experience makes it a popular choice for building modern, data-intensive web applications. + +-------------------------------- + +### Cloud > Invite + +Source: https://dexie.org/docs/cloud/Invite + +An invite is member from the members table with attached properties `realm`, `accept()` and `reject()` properties. `realm` is a lookup from member.realmId to the actual realm object. `accept()` and `reject()` are methods / callbacks that can be used to accept or reject the realm. A user will only get the desired access after accepting the invite. + +-------------------------------- + +### Understanding the basics > Creating Database vs opening existing + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +IndexedDB (and Dexie) has a built-in system for db installation and schema upgrades. Many people think they will have to check if the database needs to be created, and then run different code depending on whether or not the database was installed on the client. This is not needed. Your Dexie code can be declarative (you declare what tables and schemas you have in current and previously released versions and you let Dexie / indexedDB handle the situation where a database wasn't created yet, needs upgrading, or is already on latest version). +IndexedDB is designed for handling database creation and upgrades through the `onupgradeneeded` event, and defines the schema there. There is no native method for checking whether or not a database exists. Dexie adds a declarative schema syntax on top of that so that you don't need to subscribe to the `onupgradeneeded` event either. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The Dexie Cloud API Limits section details the constraints and quotas associated with using the Dexie Cloud service. This includes information on rate limits for API requests, data storage limits, and other usage restrictions to ensure fair usage and service stability. + +-------------------------------- + +### Dexie > Dexie.open() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Dexie.open()` static method is used to open an existing Dexie database or create a new one if it doesn't exist. It takes the database name, version, and a schema definition as arguments. This is the primary way to get a reference to your database instance, which you'll use for all subsequent operations. + +-------------------------------- + +### Tutorial > Building Addons + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Building add-ons for Dexie.js allows you to extend its functionality and tailor it to specific needs. This involves understanding Dexie's internal structure and utilizing its extension points. Common areas for add-ons include custom data synchronization, integration with other libraries, or providing framework-specific enhancements. The process typically involves creating a class that implements the desired interface and registering it with Dexie. + +-------------------------------- + +### Dexie.js > ExportImport > Export and Import Database + +Source: https://dexie.org/docs/safari-issues + +Dexie.js offers robust support for exporting and importing database data, which is invaluable for tasks such as backups, migrations, or sharing data. The `Export and Import Database` feature allows you to serialize your entire database or specific tables into a format that can be easily stored or transferred. This process typically involves iterating through tables and their records, and then re-importing them into a new or existing database instance. This capability is essential for data management and ensures data integrity during various operations. + +-------------------------------- + +### API Reference > Compound Index + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js supports defining **compound indexes**, which are indexes that span across multiple properties of a table. This is crucial for optimizing queries that filter or sort based on a combination of fields. When defining a compound index, you specify an array of property names in the desired order. Dexie will then create an index that efficiently supports queries involving these properties in that specific order. + +-------------------------------- + +### Libs > dexie-react-hooks > useObservable() + +Source: https://dexie.org/docs/dexie-react-hooks/useObservable%28%29 + +Function that returns an observable. This function will be re-executed if deps change. If the new observable does not have a current value, the last current value will persist until new observable emits a value. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Transactions are the foundation of all operations in IndexedDB, ensuring data integrity and atomicity. Dexie.js provides a robust transaction API that allows you to group multiple operations together. If any operation within a transaction fails, the entire transaction is rolled back, leaving your database in a consistent state. You can manage transactions using `Transaction.abort()`, `Transaction.on.abort`, `Transaction.on.complete`, and `Transaction.on.error` events. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/Promise/Promise.on + +The `Version` object in Dexie represents a specific version of your database schema. It is used during database initialization and upgrades. You can define the structure of your object stores and indexes for a given version using methods like `Version.stores()`. Additionally, the `Version.upgrade()` method allows you to define the logic for migrating data from a previous version to the current one, ensuring a smooth transition as your database schema evolves. + +-------------------------------- + +### Docs Home > Y.js + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +Y.js is a collaborative framework that enables real-time multi-user collaboration on shared data. It provides conflict-free replicated data types (CRDTs) that can be merged automatically. This section discusses the integration of Y.js with Dexie.js for building collaborative applications. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `Version` object in Dexie.js is central to managing database schema changes and upgrades. When you define your database schema using `db.version(X).stores({...})`, you are creating a specific version of your database. The `Version.upgrade()` method is crucial for defining the logic that runs when migrating from an older schema version to a newer one. This method allows you to perform complex data migrations, such as adding new tables, modifying existing ones, or populating initial data, ensuring a smooth transition for your users as your database evolves. + +-------------------------------- + +### Dexie > Dexie.verno + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.verno` property indicates the current version number of the database schema. This is useful for checking the database version or for implementing version-specific logic. + +-------------------------------- + +### Table > Table.bulkPut() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.bulkPut()` method inserts or updates multiple records in a table in a single operation. It takes an array of record objects. For each object in the array, `bulkPut` will either insert it as a new record or update an existing record if a record with the same primary key is found. This is highly efficient for synchronizing data or when processing lists of items. Like `bulkAdd`, it returns a Promise and can throw a `BulkError` on failure. + +Example: +`db.friends.bulkPut([{id: 1, name: 'Alice Updated'}, {id: 2, name: 'Bob New'}]).then(() => console.log('Bulk put operation complete.'));` + +-------------------------------- + +### API Reference > Sync > REST + +Source: https://dexie.org/docs/API-Reference + +The `REST` section likely pertains to the REST API provided by Dexie Cloud for interacting with your synchronized data. This API allows you to access and manipulate your data programmatically from external applications or services, complementing the direct database access provided by Dexie. + +-------------------------------- + +### Docs Home > Version > Version.stores() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Version.stores()` method is used to define the structure of your database, including its object stores (tables) and their respective indexes. This is a crucial step in setting up your Dexie.js database. You specify the names of the stores and the indexes within each store, which enables efficient querying of your data. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.notEqual()` method creates a query condition to select records where an indexed property does not match a given value. This is useful for excluding records that have a specific value in an indexed field. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/Releasing-Dexie + +The `Version` API in Dexie.js is central to managing database schema migrations. `Version.stores(schema)` is used to define the structure of your database tables and indexes for a specific version. `Version.upgrade(upgradeFunction)` allows you to provide a function that will be executed when migrating from a previous version to the current one, enabling you to perform data transformations or add new tables and indexes. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/Realm + +Dexie.js is a popular wrapper for IndexedDB, designed to make working with the browser's native database significantly easier and more pleasant. It abstracts away much of the complexity of the raw IndexedDB API, offering a more intuitive and feature-rich experience. This includes features like automatic schema management, promise-based operations, and enhanced querying capabilities. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/cloud/limits + +The `WhereClause` in Dexie.js is used for creating complex queries. Methods like `equals()`, `below()`, `above()`, `between()`, `startsWith()`, and their case-insensitive variants, allow you to define precise conditions for filtering data. You can also combine multiple `WhereClause` conditions using logical operators for more sophisticated filtering. + +-------------------------------- + +### Dexie.js > Dexie.extend() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides `Dexie.extend()` which is a utility for extending the capabilities of Dexie.js, potentially by adding new methods to the `Dexie` instance, `Table` objects, or `Collection` objects. This allows developers to create custom extensions or integrate third-party libraries seamlessly with Dexie.js. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/best-practices + +The Dexie.js library provides a convenient way to interact with IndexedDB, simplifying common database operations and offering a more intuitive API. It aims to abstract away the complexities of the native IndexedDB API, allowing developers to focus on their application logic rather than low-level database management. This includes features like simplified CRUD operations, automatic schema versioning, and robust transaction handling. + +-------------------------------- + +### Dexie.js > Collection > Collection.desc() + +Source: https://dexie.org/docs/safari-issues + +The `Collection.desc()` method in Dexie.js allows you to specify that the sorting order for a collection should be descending. This is typically used in conjunction with `sortBy()` or when defining index order. For example, `collection.sortBy('name').desc()` would sort the collection by name in descending order. + +-------------------------------- + +### Table > Table.defineClass() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie allows you to define custom classes for your tables using `Table.defineClass()`. This enables you to work with your data as objects of your own classes, complete with methods and properties, making your code more object-oriented and maintainable. + +-------------------------------- + +### Table > Table.where() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.where()` method is a powerful tool for querying data within a specific table. It allows you to define criteria for selecting records based on their properties. You can chain multiple `where()` clauses to build complex queries. The result of `Table.where()` is a `Collection` object, which represents a set of records matching the query criteria. This `Collection` object then provides further methods for filtering, sorting, and retrieving the data. + +Example: +`db.friends.where('age').above(25).toArray();` This query retrieves all friends whose age is greater than 25. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Tutorial + +Dexie.js is a powerful wrapper library for IndexedDB that significantly simplifies database operations in web applications. It aims to provide a more intuitive and developer-friendly API compared to the native IndexedDB API, which can be verbose and complex. By offering promise-based operations and automatic handling of many low-level details, Dexie.js allows developers to focus on their application logic rather than database intricacies. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Accessing the current authenticated user is done through `db.cloud.currentUser`. This property provides information about the user who is currently logged in, allowing you to personalize the application or enforce permissions. + +-------------------------------- + +### Dexie.js > Deprecations + +Source: https://dexie.org/docs/safari-issues + +Dexie.js includes a set of `Deprecations` which outlines features or methods that are no longer recommended for use or have been removed in newer versions. This section is crucial for developers migrating older codebases to newer Dexie.js versions, helping them identify and update deprecated API calls to their modern equivalents, ensuring compatibility and leveraging the latest features. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/Typescript-old + +The `WhereClause` object in Dexie.js represents a set of criteria used for querying data within a table. It offers a rich set of methods for defining complex conditions, such as `above()`, `belowOrEqual()`, `anyOf()`, `between()`, `equals()`, and `startsWith()`. These methods allow for flexible and precise data retrieval based on specific field values and ranges. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The `WhereClause` API in Dexie.js provides a powerful way to query data within your IndexedDB. It allows you to define complex filtering conditions using a fluent and readable syntax. Methods like `equals()`, `equalsIgnoreCase()`, `above()`, `below()`, `between()`, `inAnyRange()`, `startsWith()`, `startsWithIgnoreCase()`, `anyOf()`, `anyOfIgnoreCase()`, and `noneOf()` enable precise data retrieval based on various criteria. This makes querying flexible and efficient. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud API Limits + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section details the usage limits and quotas for the Dexie Cloud API. Understanding these limits is important for designing scalable applications and avoiding unexpected throttling or service interruptions. + +-------------------------------- + +### Example: Sharable ToDo list > Table "members" + +Source: https://dexie.org/docs/cloud/access-control + +The `members` table contains the edges between a realm and its members. Each member must have at least a `realmId` and an `email` property. Members can be added before the target user even has any user account in the system. The primary key for this table is `@id`. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie.js aims to make IndexedDB easier to use by providing a well-structured API. It handles many of the complexities and boilerplate code associated with direct IndexedDB operations, allowing developers to focus on their application logic. The library supports promises, making asynchronous database operations more manageable and readable. It also offers features like schema migrations, object store management, and transaction handling. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +The `Version` object in Dexie.js is crucial for managing database schema changes over time. When you define your database schema, you do so within a `Version`. The `Version.stores()` method is used to define the object stores (tables) and their indexes, while the `Version.upgrade()` method allows you to specify the logic for migrating data when the database schema is updated. + +-------------------------------- + +### Tutorial > Migrating existing DB to Dexie + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Migrating existing databases to Dexie.js can be a common requirement when adopting the library. This tutorial likely covers strategies for importing data from other sources or existing IndexedDB instances into a Dexie-managed database. It would involve defining the Dexie schema and then populating it with the existing data. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/Promise/Promise + +Dexie.js supports defining custom classes for your table objects. This allows you to add methods and properties directly to your data objects, making them behave like instances of your custom classes. Use `table.defineClass()` to register a class with a table, and then use `table.mapToClass()` to ensure that objects retrieved from the table are instances of that class. This enhances the object-oriented approach to data management. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.above() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause.above()` method filters records where a specific index is strictly greater than the provided value. This is useful for range queries where you want to exclude the boundary value. It's commonly used in conjunction with indexed properties. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/TableSchema + +IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files/blobs. IndexedDB is a transactional database system, meaning that all operations are performed within transactions. Transactions can be used to ensure data integrity and consistency. However, IndexedDB can be complex to use directly due to its asynchronous nature and verbose API. Dexie.js aims to simplify these aspects. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/cloud/web-hooks + +Modern TypeScript support in Dexie.js provides enhanced type safety and autocompletion for database operations. This section would cover how to set up TypeScript with Dexie, define database schemas with types, and leverage the type information for more robust and maintainable code. + +-------------------------------- + +### Dexie > Dexie.open() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.open()` method is the primary way to open or create a Dexie database. It takes the database name and a configuration object, including schema definitions. Dexie handles versioning and schema migrations automatically. It returns a Promise that resolves with the database instance once it's ready. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/cloud/limits + +The `Version` object in Dexie.js represents a specific version of your database schema. The `stores()` method is used to define the object stores (tables) and their indexes for that version. The `upgrade()` method allows you to specify migration logic for transitioning from a previous version to the current one, ensuring data consistency during schema changes. + +-------------------------------- + +### Table > Table.toCollection() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Table.toCollection()` method converts a table or a query result into a `Collection` object. This allows you to chain further collection manipulation methods like `filter()`, `sortBy()`, `limit()`, and `offset()` before retrieving the final data. For example, `db.friends.toCollection().filter(f => f.age > 18)`. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +The `WhereClause` object in Dexie.js is used to define complex query conditions. It offers a variety of methods for filtering data, including comparisons like `above()`, `below()`, `equals()`, and `notEqual()`. You can also perform range-based queries with `between()` and `inAnyRange()`, as well as string matching operations like `startsWith()` and `equalsIgnoreCase()`. These methods allow for precise and efficient data retrieval. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The `db.cloud.currentUser` property provides access to the currently logged-in user's profile information. This allows your application to display user-specific data or personalize the user experience based on the authenticated user. + +-------------------------------- + +### Access Control Tables + +Source: https://dexie.org/docs/cloud/access-control + +Access control is defined using the Dexie tables `realms`, `members` and `roles`. To take advantage of these, just add them to your schema declaration. The server end-point will know how to handle these special tables if they are present. + +-------------------------------- + +### API Reference > Table + +Source: https://dexie.org/docs/Collection/Collection + +The `Table` object in Dexie.js represents a specific table within your database. It offers methods for performing CRUD (Create, Read, Update, Delete) operations on records. You can use methods like `add()`, `put()`, `get()`, `delete()`, and `update()` to interact with the data in a table. `Table.where()` is used to create queryable collections. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.below() + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `WhereClause.below()` method filters records where a specific index is strictly less than the provided value. This is useful for range queries where you want to exclude the upper boundary value. It helps in defining exclusive upper bounds for your searches. + +-------------------------------- + +### Table > Table.add() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.add()` method inserts a new record into the table. It returns a Promise that resolves with the new record's primary key. If a record with the same primary key already exists, a `ConstraintError` will be thrown unless you are using an auto-incrementing key. + +-------------------------------- + +### Transaction > Transaction + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers a `Dexie.transaction()` method that simplifies the process of managing database transactions. It allows you to group multiple operations into a single atomic unit, ensuring data consistency. You can specify the tables involved and the transaction mode (e.g., 'readonly', 'readwrite'). Dexie handles the transaction lifecycle, including commits and rollbacks. + +-------------------------------- + +### Collection > Collection.primaryKeys() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js offers `Collection.primaryKeys()` which is similar to `keys()` but specifically designed to retrieve primary keys, ensuring correct handling even with compound primary keys. It returns a Promise resolving to an array of primary keys. + +-------------------------------- + +### API Reference > Table + +Source: https://dexie.org/docs/cloud/consistency + +The `Table.where()` method is the entry point for creating queries on a specific table in Dexie.js. It returns a `WhereClause` instance that allows you to define criteria for selecting records based on their indexed properties. This is the foundation for filtering data and retrieving specific subsets of records from your database. + +-------------------------------- + +### Inbound + +Source: https://dexie.org/docs/inbound + +A primary key is considered inbound if it's included in the stored objects. This means that when you add or put an object into the table, the primary key value is part of the object itself. + +Examples of Inbound Primary Key: +```javascript +db.version(1).stores({ + friends: "id" +}); +``` + +```javascript +db.version(1).stores({ + friends: "id,name" +}); +``` + +```javascript +db.version(1).stores({ + friends: "++id,name" +}); +``` + +Adding / Updating Inbound Values: +```javascript +await db.friends.add({id: "fooId", name: "Foo"}); + +await db.friends.put({id: "fooId", name: "Foo"}); + +await db.friends.bulkAdd([{id: "id1", name: "Friend1"}, {id: "id2", name: "Friend2"}]); + +await db.friends.bulkPut([{id: "id1", name: "Friend1"}, {id: "id2", name: "Friend2"}]); +``` + +-------------------------------- + +### Releasing Dexie > Releasing + +Source: https://dexie.org/docs/Releasing-Dexie + +To perform the release, navigate to your dedicated 'dexie-release' directory and execute the `tools/release.sh` script. You will be prompted to enter the new version number; for pre-releases, use a format like "2.0.0-beta.10". If addons have version bumps, you'll be asked whether to release them as well. The script will run tests via karma, including the full suite on BrowserStack. It will then publish the new version to npm and commit the built distribution files to the `github/releases` branch. After the script completes, browse to `https://github.com/dexie/Dexie.js/releases` to edit the new tag and write release notes based on the commit history. + +-------------------------------- + +### WhereClause > WhereClause.aboveOrEqual() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.aboveOrEqual()` method filters records where a specific property's value is greater than or equal to a given value. This is inclusive of the specified value, making it suitable for range queries that include the boundary. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +Dexie.js is a powerful wrapper library for IndexedDB, designed to simplify database operations and provide a more developer-friendly experience. It abstracts away much of the complexity of the native IndexedDB API, offering a cleaner, more intuitive interface for creating, querying, and managing your data. This makes it an excellent choice for web applications that require robust client-side data storage. + +-------------------------------- + +### Dexie > Dexie.version() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie provides a `Dexie.version()` method to define and manage database schema versions. Each version can have its own set of tables and indexes. When the database version changes, Dexie's `on.populate` event is triggered, allowing you to perform schema migrations. This versioning system is crucial for evolving your database structure over time without data loss. + +-------------------------------- + +### Primary Keys > Auto-generated IDs + +Source: https://dexie.org/docs/cloud/best-practices + +When using `@` as the primary key definition in your Dexie stores, the library automatically generates unique IDs for your records. These IDs are prefixed with a three-letter abbreviation derived from the table name (e.g., 'itm' for 'items', 'frn' for 'friends'). This prefix ensures that IDs are recognizable and helps maintain data integrity, especially when tables are renamed later, as the prefix remains consistent throughout the database's lifetime. Dexie will enforce this policy and reject any manually provided keys that do not match the expected prefix. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.where()` method is the entry point for performing queries on a table in Dexie.js. It takes a criteria object or a function that defines the conditions for filtering records. The method returns a `WhereClause` object, which provides a fluent API for building complex queries using various operators like `equals()`, `above()`, `below()`, `startsWith()`, and more. This allows for powerful and flexible data retrieval. + +-------------------------------- + +### Dexie-react-hooks > usePermissions() + +Source: https://dexie.org/docs/dexie-react-hooks/usePermissions%28%29 + +Observe security permissions for a table and individual objects managed by Dexie Cloud. Use this hook in order to know whether to render certain action buttons depending on what permission the user has to modify the object or add / remove objects. + +-------------------------------- + +### Cloud > db.cloud.currentUser + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `db.cloud.currentUser` property provides access to the currently logged-in user's information. This object contains details about the authenticated user, allowing you to personalize the application experience or enforce user-specific permissions. + +-------------------------------- + +### Dexie.js API > WhereClause + +Source: https://dexie.org/docs/cloud/authentication + +The `WhereClause` in Dexie.js is used to define filter criteria for queries. It offers a rich set of methods for specifying conditions, including comparisons like `above()`, `aboveOrEqual()`, `below()`, `belowOrEqual()`, `between()`, and `equals()`. You can also perform case-insensitive comparisons using methods like `equalsIgnoreCase()`. For checking membership within a set of values, `anyOf()` and `noneOf()` are available, along with `inAnyRange()` for checking if a value falls within any of multiple ranges. `notEqual()` excludes specific values, while `startsWith()`, `startsWithAnyOf()`, and `startsWithIgnoreCase()` are useful for string matching. + +-------------------------------- + +### Cloud > db.cloud.permissions() + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `db.cloud.permissions()` method is used to retrieve the permissions associated with the current user or a specified user. This allows your application to dynamically adjust behavior or UI elements based on the user's access rights. + +-------------------------------- + +### Promise + +Source: https://dexie.org/docs/Promise/Promise + +Dexie.js provides its own implementation of ECMAScript 6 compliant Promise/A+. All methods in Dexie that are designed to return a Promise will instead return a `Dexie.Promise`. This implementation is crucial for maintaining transaction zones and ensuring proper interaction with native Promises, especially when dealing with IndexedDB. + +-------------------------------- + +### Dexie > Dexie.tables + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.tables` property is an object that contains references to all the tables defined in the database schema. You can access tables directly using their names, like `db.tables.friends`. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/cloud/web-hooks + +Dexie.js offers a robust mechanism for handling database schema changes over time through its `Version` API. When you need to modify your database structure, such as adding new tables, indexes, or changing existing ones, you define these changes within a `Version` object. The `upgrade()` method within a version is crucial, as it allows you to write the imperative code needed to migrate your existing data to the new schema. This ensures data integrity and smooth transitions as your application evolves. + +-------------------------------- + +### Quick Reference > Class Binding + +Source: https://dexie.org/docs/API-Reference + +Dexie allows you to map JavaScript classes to your database tables, enabling you to work with objects that have prototype methods and properties. You use the `table.mapToClass(YourClass)` method for this. This feature enhances code organization and allows you to encapsulate data-related logic within your class definitions. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `Version` object in Dexie.js represents a specific schema version of your database. You use it to define the structure of your database, including tables, indexes, and relationships. The `Version.stores()` method is used to declare the object stores (tables) and their respective indexes for a given version. `Version.upgrade()` allows you to define migration logic when the database version changes. + +-------------------------------- + +### Dexie > Dexie.getDatabaseNames() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.getDatabaseNames()` method returns a Promise that resolves to an array of strings, where each string is the name of a Dexie database currently available in the browser's IndexedDB storage. This can be useful for managing multiple databases or for inspection purposes. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Tutorial + +The `WhereClause` object in Dexie.js provides a fluent API for querying data. It exposes various methods for filtering records based on different criteria. For instance, `where('name').startsWithIgnoreCase('john')` allows you to find all records where the 'name' field begins with 'john', ignoring case. + +-------------------------------- + +### Dexie > Dexie.open() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers a `Dexie.open()` method for initializing and opening your database connection. This method takes the database name and a `version()` callback where you define your database schema. It returns a promise that resolves with the database instance once it's open and ready for use. Handling potential errors during database opening, such as `Dexie.OpenFailedError`, is essential for robust applications. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/Promise/Promise + +The `Version` object in Dexie.js is used to manage database schema migrations. Each version represents a specific state of your database schema. You use `db.version(versionNumber).stores(schemaDefinition)` to define the tables and indexes for that version. The `upgrade()` method within a version can be used to perform data migrations when the database is upgraded to a new version. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +The `WhereClause` object in Dexie.js is used for constructing complex queries. It provides a fluent API for specifying conditions on your data. Methods like `equals()`, `equalsIgnoreCase()`, `above()`, `below()`, `between()`, `startsWith()`, and `startsWithIgnoreCase()` allow you to build precise filters for your data retrieval operations. You can also use `anyOf()`, `noneOf()`, and `inAnyRange()` for more flexible matching. + +-------------------------------- + +### Table > Table.where() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js's `Table.where()` method is the primary way to query data based on specific criteria. You use it to specify conditions on table properties, often combined with operators like `equals()`, `above()`, `below()`, `startsWith()`, etc. You can also chain multiple `where()` clauses or use `and()` and `or()` to build complex queries. This method returns a `Collection` object that can then be further manipulated. + +-------------------------------- + +### Table > Table.defineClass() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js offers a way to define custom classes for your tables, enabling you to add methods and custom logic directly to your data objects. Using `table.defineClass()` or `db.Table.prototype.mapToClass()`, you can associate a JavaScript class with a table. Instances of this class will then be automatically created when you retrieve data from the table, providing an object-oriented interface to your database. + +-------------------------------- + +### Primary Keys > Compose primary keys from referred keys and other properties + +Source: https://dexie.org/docs/cloud/best-practices + +Dexie allows you to compose primary keys from multiple properties, including referred keys from other tables and additional fields. This is useful for creating unique composite keys that represent complex relationships. For instance, in a `friendRelations` table, a primary key can be defined as a composite of `friend1Id`, `friend2Id`, and `label`. This ensures that each relationship between two friends with a specific label is unique within the database. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `WhereClause` API in Dexie.js provides a flexible way to define complex query conditions. You can use methods like `equals()`, `notEqual()`, `above()`, `below()`, `between()`, `inAnyRange()`, and `startsWith()` to specify precise filtering criteria. For case-insensitive searches, methods like `equalsIgnoreCase()` and `startsWithIgnoreCase()` are available. `anyOf()` and `noneOf()` allow for matching against multiple values. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.anyOf() + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `WhereClause` object in Dexie.js provides methods for constructing sophisticated queries. `anyOf()` and `anyOfIgnoreCase()` allow you to query for records where a property matches any value in a given array, with the latter performing a case-insensitive comparison. These are useful for searching across multiple possible values for a single field. + +-------------------------------- + +### Collection + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie's `Collection` object represents a set of records retrieved from a table, often as a result of a query. It offers a fluent API for further filtering, sorting, and manipulating the results before fetching them into an array or iterating over them. Methods like `filter()`, `limit()`, `offset()`, `sortBy()`, and `reverse()` are available on the `Collection`. + +-------------------------------- + +### Cloud > Dexie Cloud CLI + +Source: https://dexie.org/docs/cloud/consistency + +The Dexie Cloud CLI (Command Line Interface) provides tools for managing your Dexie Cloud project, such as deploying your backend, managing users, and configuring your application. This section covers how to install and use the CLI. + +-------------------------------- + +### Collection > Collection.or() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie's `Collection.or()` method allows you to combine multiple conditions using a logical OR. For example, `where('name').equals('John').or('name').equals('Jane')` would find records where the name is either 'John' or 'Jane'. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud CLI + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +Dexie Cloud provides a CLI tool that simplifies common tasks related to managing your cloud deployment. This includes setting up new projects, deploying updates, and managing user accounts. The CLI streamlines the development and deployment workflow, making it easier to manage your Dexie Cloud-powered applications. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/SyncState + +Dexie.js is a popular wrapper library for IndexedDB. It simplifies the process of interacting with IndexedDB by providing a more intuitive and feature-rich API. This makes it easier to manage databases, tables, and data operations, especially in modern web applications. + +-------------------------------- + +### Docs Home > safari-issues + +Source: https://dexie.org/docs/cloud/UserLogin + +This section addresses specific issues or workarounds related to Safari browser compatibility with Dexie.js. It provides solutions and guidance for common problems encountered when using Dexie.js in the Safari environment. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Promise/Promise.on + +Dexie.js is a popular JavaScript library that acts as a wrapper for IndexedDB, making it easier to interact with this client-side database. It simplifies common IndexedDB operations, offers a more intuitive API, and provides additional features that enhance developer productivity. Dexie aims to abstract away the complexities of the native IndexedDB API, allowing developers to focus on building applications rather than managing low-level database details. + +-------------------------------- + +### API Reference > Classes > Table + +Source: https://dexie.org/docs/API-Reference + +A `Table` in Dexie represents a collection of objects with a defined schema. You access tables through the `Dexie` instance (e.g., `db.friends`). The `Table` class provides methods for CRUD operations (add, put, get, delete), querying, and manipulating records within that table. + +-------------------------------- + +### Dexie > Dexie.addons + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js provides `Dexie.addons` which is an array where you can register custom addons. Addons can extend Dexie's functionality, add new methods, or modify existing behavior. This promotes modularity and allows for code reuse across different projects. + +-------------------------------- + +### Dexie > Dexie.table() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers a `Dexie.table()` method to access a specific table within your database. This method returns a `Table` object, which provides access to all table-level operations like `get()`, `add()`, `put()`, `delete()`, `where()`, etc. It's the primary way to interact with the data stored in your tables. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Download + +Dexie.js simplifies IndexedDB by offering a promise-based API, automatic schema upgrades, and query capabilities that go beyond the basic IndexedDB API. It aims to make database operations more developer-friendly and less error-prone. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table` object in Dexie.js represents a collection of objects within your database, analogous to a table in a relational database. It provides a rich set of methods for performing operations on the data stored within that collection. You can add, retrieve, update, and delete individual records, as well as perform bulk operations for efficiency. Furthermore, the `Table` object allows you to define custom class mappings, set up hooks for data modification events, and query your data using methods like `where()`, `orderBy()`, and `filter()`. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.schema + +Source: https://dexie.org/docs/cloud/UserLogin + +The `db.cloud.schema` property represents the database schema configured for Dexie Cloud. It defines the structure of your data, including tables, primary keys, and indexes, as managed by the cloud synchronization service. Understanding this schema is crucial for interacting with your data. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Dexie.js is a lightweight wrapper for the IndexedDB API, designed to simplify database operations in web applications. It provides a more intuitive and developer-friendly interface compared to the native IndexedDB API, offering features like promises, simpler transaction management, and improved querying capabilities. This makes it easier to work with structured data in the browser, enabling richer offline experiences and faster data access. + +-------------------------------- + +### Summary + +Source: https://dexie.org/docs/StorageManager + +If you are storing critical data with Dexie (or in IndexedDB generally), you might consider using StorageManager to ensure the data can be persistently stored, and not just "best-effort". For user experience, some apps may want to wait with enabling the persistent mode until the user seems to be repeatedly using the application, or maybe using certain parts of the application where persisted storage is critical. + +-------------------------------- + +### Dexie > Dexie.defineClass() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Dexie.defineClass()` static method provides a way to create a new JavaScript class that can be used with Dexie tables. It's a convenient factory function for defining classes that are compatible with Dexie's object mapping. + +-------------------------------- + +### Docs Home > ...arted with Dexie in Svelte + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +Explore how to get started with Dexie.js in Svelte applications. This section provides practical examples and best practices for using Dexie with Svelte components, including managing state and performing asynchronous database operations. Optimize your Svelte app's data handling with Dexie. + +-------------------------------- + +### Collection > Collection.modify() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.modify()` method allows you to update multiple records in a collection based on a modification function. This function receives each record and should return the modified record or `undefined` to delete it. It's a powerful way to perform bulk updates. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +The `WhereClause` object in Dexie.js provides a rich API for querying data. Methods like `equals()`, `equalsIgnoreCase()`, `below()`, `aboveOrEqual()`, `between()`, and `inAnyRange()` allow for precise filtering of records based on various conditions. These methods can be chained to build complex queries. + +-------------------------------- + +### API Reference > Table + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +The `Table` object in Dexie.js represents a collection of records within your database. It provides methods for CRUD (Create, Read, Update, Delete) operations such as `Table.add()`, `Table.get()`, `Table.put()`, and `Table.delete()`. You can also perform bulk operations like `Table.bulkAdd()`, `Table.bulkPut()`, and `Table.bulkDelete()` for efficiency. Methods like `Table.count()`, `Table.toArray()`, `Table.filter()`, and `Table.orderBy()` allow for querying and retrieving data, while `Table.hook()` enables you to intercept and modify operations at various stages (creating, reading, updating, deleting). + +-------------------------------- + +### Dexie > Dexie.on() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.on()` method is used to subscribe to various events emitted by a Dexie database instance. It provides a unified interface for event handling, allowing you to attach callbacks to lifecycle events like `ready`, `error`, `close`, and `populate`. You can also subscribe to table-specific events using `db.friends.on('creating', callback)`. + +Example: +`db.on('populate', (trans) => { /* ... */ });` + +-------------------------------- + +### Dexie.js > Automatic use of IndexedDBShim + +Source: https://dexie.org/docs/Deprecations + +If you want the previous behavior regarding IndexedDBShim, call `shimIndexedDB.__useShim();` before including dexie. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/TableSchema + +Dexie.js is a popular wrapper for IndexedDB that simplifies its usage by providing a more intuitive API. It aims to abstract away the complexities of IndexedDB, making it easier for developers to work with client-side databases. Dexie.js offers features like observable queries, automatic schema upgrades, and transaction management, which significantly enhance the developer experience when using IndexedDB. + +-------------------------------- + +### Dexie > Dexie.addons + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.addons` property allows you to register and manage add-ons for Dexie.js. Add-ons can extend Dexie's functionality, providing features like automatic schema migration, enhanced logging, or integration with other libraries. You can use `Dexie.addons.add()` to register a new add-on, passing it a function that receives the Dexie instance as an argument. This function can then modify the Dexie instance or hook into its events. + +Example: +`Dexie.addons.add({ name: 'MyAddon', activate: (db) => { /* ... */ } });` + +-------------------------------- + +### Docs Home > Cloud > db.cloud.currentUser + +Source: https://dexie.org/docs/cloud/PersistedSyncState + +The `db.cloud.currentUser` property provides access to the currently logged-in user's information. This object contains details about the authenticated user, which can be used to personalize the application interface or enforce user-specific logic. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Dexie.js provides a robust set of features for interacting with IndexedDB, including transactional operations, table management, and advanced querying capabilities. It aims to make client-side data storage more accessible and efficient for web developers. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +Dexie Cloud offers a set of best practices to ensure optimal performance, security, and scalability. These include strategies for schema design, efficient querying, managing user roles, and handling synchronization conflicts. Following these guidelines will help you build robust and maintainable cloud-enabled applications. + +-------------------------------- + +### Dexie.js > WhereClause + +Source: https://dexie.org/docs/safari-issues + +The `WhereClause` object is central to performing filtered queries in Dexie.js. It is accessed via the `table.where()` method and provides a fluent API for specifying conditions. You can use methods like `equals()`, `above()`, `below()`, `between()`, `startsWith()`, and `anyOf()` to construct complex query predicates. These methods allow you to efficiently retrieve subsets of data based on various criteria. + +-------------------------------- + +### EntityTable + +Source: https://dexie.org/docs/EntityTable + +EntityTable is useful when any of the following criterias are true: + * Primary key is auto-generated (`++id`) + * The type is represented by a class with methods. + +Else, if you are using method-less entities or primary key is not auto-generated, you can use Table instead. EntityTable is a helper type that provides typings for Table based on supplied entity type and it's primary key property. Methods such as Table.add(), Table.put() etc will expect plain javascript objects that corresponds to the provided entity type where the primary key is optional. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +The `Transaction` object in Dexie.js represents a unit of work that is performed against the database. Transactions ensure data integrity by allowing multiple operations to be grouped together, either all succeeding or all failing. Key methods associated with `Transaction` include `abort()`, which cancels the transaction, and event handlers like `on.abort`, `on.complete`, and `on.error` that allow you to react to the transaction's lifecycle. The `table()` method provides access to a specific table within the transaction context. + +-------------------------------- + +### API Reference > /public/... endpoint + +Source: https://dexie.org/docs/cloud/rest-api + +The `/public/...` endpoint provides access to public data residing in the `rlm-public` realm. Unlike other endpoints, it does not require authorization for GET requests. This means any user can retrieve data from this endpoint without needing to authenticate. + +-------------------------------- + +### ...n limitations of IndexedDB + +Source: https://dexie.org/docs/cloud/web-hooks + +IndexedDB, the underlying technology for Dexie.js, has certain limitations that developers should be aware of. These can include transaction scope, potential performance bottlenecks with large datasets or complex queries, and browser-specific inconsistencies. Dexie.js aims to mitigate many of these limitations by providing a more robust and user-friendly API, but understanding the core constraints of IndexedDB is still beneficial for advanced usage and troubleshooting. + +-------------------------------- + +### API Reference > Collection + +Source: https://dexie.org/docs/roadmap/dexie5 + +The `Collection` object in Dexie provides methods for querying and manipulating data within a table. You can perform operations like filtering, sorting, limiting results, counting items, and retrieving specific data. Methods such as `filter()`, `sortBy()`, `limit()`, `count()`, and `toArray()` allow for flexible data retrieval and manipulation. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js simplifies database **transactions** by providing a higher-level API. Transactions ensure data integrity by grouping operations. You can define the tables involved and the mode (read-only or read-write). Dexie automatically handles transaction management, including commits and rollbacks, making it easier to write reliable database code. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.equals() + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `WhereClause` object in Dexie.js offers methods for precise querying. `equals()` and `equalsIgnoreCase()` allow you to find records where a property exactly matches a specified value. The `equalsIgnoreCase()` variant provides a case-insensitive comparison, which is helpful for scenarios where user input might have varying capitalization. + +-------------------------------- + +### add() operator > Array addition + +Source: https://dexie.org/docs/PropModification/add%28%29 + +When the argument to `add()` is an array of primitives, the operator adds the items from the argument array to the target array and then sorts the target array in ascending order using `Array.prototype.sort()`. If the target property does not exist, is null, undefined, or not an array, a new target array will be created. + +-------------------------------- + +### Dexie > Dexie.extend() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js allows you to extend its core functionality or add new methods using `Dexie.extend()`. This method enables you to augment the Dexie instance or its prototypes with your own custom logic, making Dexie more adaptable to your project's specific needs. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.orderBy()` method in Dexie.js is used to specify the sorting order for queries. You provide the name of the index or property by which to sort. It returns a `WhereClause` instance, allowing you to chain further query conditions or sorting modifiers like `reverse()`. This method is essential for retrieving data in a predictable and organized manner. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Dexie.js is a powerful wrapper library for IndexedDB that aims to simplify database operations in web applications. It offers a more intuitive API compared to the native IndexedDB, providing features like promise-based operations, automatic schema upgrades, and powerful querying capabilities. This makes it easier for developers to work with browser-based storage for offline data, caching, and more. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.toArray()` method in Dexie.js retrieves all records from a table and returns them as an array. It returns a promise that resolves with an array containing all the objects in the table. This is a convenient way to fetch all data from a collection, but be mindful of performance implications when dealing with very large tables. + +-------------------------------- + +### Cloud > db.cloud.currentUser + +Source: https://dexie.org/docs/cloud/Member + +The `db.cloud.currentUser` property provides access to the currently logged-in user's information. This object contains details about the authenticated user, which can be used to personalize the application or enforce user-specific logic. + +-------------------------------- + +### Dexie.js > Promises + +Source: https://dexie.org/docs/Tutorial/Design + +Dexie incorporates its own Promise implementation, built upon promise-light by Taylor Hakes, which adheres to Promise/A+ and ECMAScript 6 standards. A Promise object features a `then()` method, which is executed upon successful completion or failure of an operation. The `then()` method accepts two arguments: a `complete` callback for success and a `fail` callback for errors. ECMAScript 6 introduces the `catch()` method as a convenient shorthand for `then(null, fn)`, allowing for separate handling of success and error scenarios, thereby enhancing code readability. Dexie's Promise implementation also includes a `finally()` method that executes irrespective of whether the operation succeeds or fails. All asynchronous methods in Dexie return a Promise instance, simplifying API usage and improving the robustness of error handling. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +Dexie.js provides a robust API for interacting with IndexedDB, offering features beyond the native IndexedDB API. It simplifies database operations, enhances transaction management, and supports schema evolution. The library aims to make working with client-side data storage more intuitive and efficient. + +-------------------------------- + +### Docs Home > Version + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The `Version` object in Dexie.js represents a database schema version. It is used to define and manage database structure changes over time. The `stores()` method is crucial for defining the object stores (tables) within a given version, specifying their schemas and primary keys. The `upgrade()` method allows you to define migration logic that runs when the database version is incremented, enabling you to perform data transformations or add new stores. + +-------------------------------- + +### Dexie.js > Automatic use of IndexedDBShim + +Source: https://dexie.org/docs/Deprecations + +The deprecation of `Transaction.table()` and `Transaction[table]` is taken back (un-deprecated) and will be continuously maintained in 2.0.0-beta.5 and forward. There are no plans to ever deprecated them. + +-------------------------------- + +### Summary > How to use it from your app + +Source: https://dexie.org/docs/StorageManager + +If the result of `tryPersistWithoutPromtingUser()` was "prompt", you have the option to show your own user interface. This UI can explain the benefits of persistence and include a button. When the user clicks this button, you would then call `navigator.storage.persist()` to initiate the persistence process. + +-------------------------------- + +### Table > Table.bulkDelete() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.bulkDelete()` method removes multiple records from a table in a single operation. It takes an array of primary key values as input. This is an efficient way to delete multiple items at once compared to calling `delete()` in a loop. If a specified key does not exist in the table, that particular deletion is skipped without causing the entire operation to fail. It returns a Promise that resolves when all deletions are attempted. + +Example: +`db.friends.bulkDelete([1, 5, 10]).then(() => console.log('Deleted multiple friends.'));` + +-------------------------------- + +### Do this instead + +Source: https://dexie.org/docs/cloud/best-practices + +This example formulates the condition of the deletion in a where-clause. The condition is persisted on the cloud and re-executed in case the data has changed from what it was on the client when it performed the operation. Any added todoItem will also be deleted. Also, if another offline client would add items to that list and sync later on, some time after we made our sync, the persisted where-clause will be applied onto the other client's added items (because the server sees that the other client's data was based on a snapshot before we did our sync). Thus the added items from that client won't be added and the other client would instead get their local data updated and all these items deleted along with the list in its sync response. + +-------------------------------- + +### Table > Table.mapToClass() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Table.mapToClass()` method allows you to associate a JavaScript class with a table in Dexie.js. When you retrieve records from this table, they will be instances of the specified class, inheriting its methods and properties. This is a powerful feature for implementing object-oriented patterns and encapsulating logic within your data models. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie Cloud provides a CLI tool, `Dexie Cloud CLI`, which likely assists developers in managing their Dexie Cloud projects. This could include commands for deploying configurations, managing environments, or performing other administrative tasks related to the cloud service, streamlining the development and deployment workflow. + +-------------------------------- + +### EntityTable + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `EntityTable` in Dexie.js represents a table where records are treated as entities, often associated with a JavaScript class. This allows for more structured data management and the addition of methods to your data objects, providing an object-oriented interface to your database tables. + +-------------------------------- + +### What is "storage" and how does it apply to Dexie? + +Source: https://dexie.org/docs/StorageManager + +Dexie is a JavaScript library that acts as a wrapper for IndexedDB, enabling the creation and access of client-side databases within a web browser. The StorageManager is an API that allows developers to configure how IndexedDB stores data for any database associated with a website or application. + +-------------------------------- + +### API Reference > Version + +Source: https://dexie.org/docs/cloud/consistency + +The `Version` API in Dexie.js is used to define and manage database schemas and their evolution over time. Each version can have its own set of store configurations and upgrade functions, allowing you to migrate your database schema safely as your application evolves. + +-------------------------------- + +### Promise > Promise.catch() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Promise.catch()` method is used to handle errors that occur during the execution of a Promise chain. It takes a callback function that will be executed if any preceding Promise in the chain rejects. + +-------------------------------- + +### Dexie.js > Examples: Consistent Operations > Avoid this + +Source: https://dexie.org/docs/cloud/best-practices + +The example of deleting a todo list by first retrieving all item IDs and then performing a `bulkDelete`, followed by deleting the todo list itself, has a potential issue. This approach retrieves the primary keys of the items to delete as they were at the time on the client. This might not be accurate if the client is offline or if other offline clients have added items that haven't synced yet. In such cases, some items might be forgotten and left in the database, pointing to a non-existent todo list ID. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `WhereClause` API in Dexie.js provides a powerful and flexible way to construct complex queries. It allows you to filter data based on various criteria, including equality, inequality, ranges, and string matching. Methods like `equals()`, `equalsIgnoreCase()`, `below()`, `aboveOrEqual()`, `between()`, `startsWith()`, `startsWithIgnoreCase()`, and `inAnyRange()` offer granular control over your data retrieval. This rich set of operators enables you to write precise queries that fetch exactly the data you need, optimizing performance and simplifying data access logic. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +The `WhereClause` API in Dexie.js provides a flexible way to query data based on various conditions. You can perform equality checks, range queries, and case-insensitive searches. Methods like `equals()`, `above()`, `below()`, `between()`, `anyOf()`, and `startsWith()` allow you to construct complex queries to retrieve exactly the data you need from your IndexedDB tables. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `WhereClause` object in Dexie.js is used to build complex queries for filtering records in your database. Methods like `above()`, `aboveOrEqual()`, `below()`, `belowOrEqual()`, and `between()` allow you to specify range conditions for indexed properties. These methods are essential for efficiently retrieving subsets of data based on numerical or date ranges. + +-------------------------------- + +### Dexie > Dexie.addons + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Dexie.addons` property allows you to register and manage third-party add-ons for Dexie. These add-ons can extend Dexie's functionality, providing features like real-time synchronization, advanced querying capabilities, or integration with other libraries. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/Download + +The `WhereClause` object in Dexie.js provides a powerful way to filter and query data. It allows you to specify conditions for matching records in your tables. Methods like `equals()`, `above()`, `below()`, `between()`, and `startsWith()` enable flexible data retrieval based on various criteria. + +-------------------------------- + +### Table > Table.modify() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.modify()` method allows you to update multiple records in a table based on a modification function. This function receives each record and should return the modified record or `undefined` to delete it. It's a powerful way to perform bulk updates on an entire table or a filtered subset. + +-------------------------------- + +### Home + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js is a robust and developer-friendly wrapper around the IndexedDB API. It simplifies database operations by providing a more intuitive API, reducing boilerplate code, and offering features like promises, observable streams, and automatic schema upgrades. Dexie aims to make working with client-side databases a much more pleasant experience. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreQueryResponse + +Dexie.js is a powerful wrapper for IndexedDB that simplifies database operations. It enhances the native IndexedDB API with Promises, making asynchronous operations more manageable and readable. Beyond basic CRUD operations, Dexie.js introduces features like `liveQuery` which allows you to subscribe to changes in your database and automatically update your UI. This makes it an excellent choice for building dynamic and responsive web applications. + +-------------------------------- + +### PropModification > replacePrefix() operator + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `replacePrefix()` operator within `PropModification` is designed for updating string properties by replacing a specified prefix with a new string. This is useful for tasks like renaming keys or modifying paths within string values. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +Dexie Cloud Best Practices provide recommendations for optimizing performance, security, and scalability when using the Dexie Cloud service. This guidance helps developers build robust and efficient real-time applications. + +-------------------------------- + +### Derived Work > Known Addons + +Source: https://dexie.org/docs/DerivedWork + +This section lists various addons and middleware developed for Dexie.js, extending its functionality. Examples include `dexie-logger` for monitoring operations, `dexie-encrypted` for adding encryption, and `dexie-relationships` for managing foreign key constraints. + +-------------------------------- + +### Cloud > db.cloud.permissions() + +Source: https://dexie.org/docs/DerivedWork + +The `db.cloud.permissions()` method allows you to retrieve the permission set for the current user. This is essential for implementing role-based access control within your application, enabling you to dynamically adjust UI elements or restrict actions based on the user's granted permissions. It provides a way to query what the current user is allowed to do. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +Dexie.js Cloud offers best practices for building scalable and maintainable cloud-synced applications. This includes guidance on schema design, data synchronization strategies, and optimizing performance. Adhering to these practices can help ensure your application remains robust as it grows. + +-------------------------------- + +### Motivation + +Source: https://dexie.org/docs/Simplify-with-yield + +Dexie.js includes its own Promise implementation because Promises from other libraries, like Q or Task.js, can be incompatible with IndexedDB transactions in some browsers. This custom Promise implementation is crucial for ensuring reliable transaction handling. Furthermore, Dexie's Promises support Promise-Specific Data (PSD), which is analogous to thread-specific data in other programming contexts. This feature is utilized to maintain transaction scopes and manage reentrant transaction locks effectively, providing a more robust and predictable asynchronous experience when working with IndexedDB. + +-------------------------------- + +### WhereClause > WhereClause.between() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.between()` method filters records where a property's value falls within a specified range (inclusive). You provide a lower and upper bound to define the desired interval. + +-------------------------------- + +### API Reference > ExportImport > Export and Import Database + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +Dexie.js supports exporting and importing database content, which is invaluable for backup, migration, or data sharing purposes. This feature allows you to serialize the entire database or specific tables into a format that can be easily stored or transferred. Subsequently, the exported data can be imported back into a Dexie.js database, effectively restoring its state or merging data. This is particularly useful when dealing with large datasets or when performing complex database updates. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/cloud/index + +The `Version` object in Dexie.js represents a database schema version. The `Version.stores()` method is used to define the object stores (tables) and their indexes for that version. The `Version.upgrade()` method is where you define the logic for migrating data from a previous version to the current one, ensuring data integrity during schema changes. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `WhereClause` object is used to construct queries for filtering data in Dexie.js. It provides a rich set of methods for defining conditions, such as `equals()`, `notEqual()`, `above()`, `below()`, `between()`, and range-based queries like `inAnyRange()`. It also supports case-insensitive comparisons with methods like `equalsIgnoreCase()` and `startsWithIgnoreCase()`. + +-------------------------------- + +### Cloud > Dexie Cloud API Limits + +Source: https://dexie.org/docs/cloud/consistency + +This section details the API limits imposed by Dexie Cloud. Understanding these limits is important for designing scalable applications and avoiding potential issues related to rate limiting or resource constraints. + +-------------------------------- + +### 2. Be wise when catching promises! + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Event handlers or other root-level scopes are the correct places to catch promises. This is because these scopes are not returning promises, meaning there's no caller expecting a promise. Consequently, the responsibility for catching and handling errors falls solely on these top-level scopes, including informing the user. If errors are not caught at this level, they will eventually trigger the standard `unhandledrejection` event. + +-------------------------------- + +### Dexie.js > Collection > Collection.until() + +Source: https://dexie.org/docs/safari-issues + +The `Collection.until()` method in Dexie.js allows you to specify a condition to stop iteration early. When used with methods like `each()`, `until()` will halt the iteration as soon as the provided predicate function returns `true`. This is useful for finding the first occurrence of a specific condition or for optimizing iterations where you don't need to process the entire collection. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/cloud/Member + +The `Version` object in Dexie.js represents a specific version of your database schema. It is used to manage schema changes and migrations. You can define tables, indexes, and constraints within a `Version` object. This allows for controlled evolution of your database structure over time. + +-------------------------------- + +### Richer Queries + +Source: https://dexie.org/docs/roadmap/dexie5 + +Dexie.js aims to enhance query capabilities by supporting combinations of criteria within the same collection and a subset of MongoDB-style queries. Previously, Dexie only supported queries that fully utilized at least one index, with `where()` clauses limited to indexed fields and `orderBy()` requiring an index for ordering, often making it impossible to combine with other criteria unless they used the same index. While `filter()` allowed combining index-based and manual filtering, it placed the burden on the developer to discern which parts of the query should use an index. Dexie 5.0 will eliminate this limitation, allowing any combination of criteria within a single query, with the engine automatically determining index utilization. The `orderBy()` method will be available on `Collection` regardless of whether the current query already 'occupies' an index. It will support multiple fields, including non-indexed ones, and allow for specifying collation. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +The `WhereClause` in Dexie.js is used to build complex queries. It allows you to specify conditions for filtering records in your database. You can use methods like `equals()`, `equalsIgnoreCase()`, `startsWith()`, `startsWithIgnoreCase()`, `below()`, `belowOrEqual()`, `above()`, `aboveOrEqual()`, `between()`, `inAnyRange()`, `noneOf()`, and `notEqual()` to construct precise queries. This provides powerful and flexible ways to retrieve specific data subsets. + +-------------------------------- + +### WhereClause > WhereClause.noneOf() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.noneOf()` method filters records where a specific property's value does not match any of the values provided in an array. This is useful for excluding records that contain certain values. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/inbound + +The `WhereClause` object in Dexie.js is used to construct complex queries based on specific criteria. It's returned by the `Table.where()` method. You can chain various methods to define your query conditions, such as `equals()`, `below()`, `above()`, `between()`, `startsWith()`, and `anyOf()`. These methods allow you to filter data based on equality, range, string patterns, and multiple values, providing a flexible way to retrieve the exact data you need. + +-------------------------------- + +### Dexie.js > AND and OR + +Source: https://dexie.org/docs/Tutorial/Design + +Dexie provides enhanced capabilities for logical AND and OR operations, which are not natively supported by indexedDB. Logical OR is implemented by executing two separate requests concurrently and then combining their results. Logical AND is achieved using a combination of the `where()` method with a suitable index and the `and()` method, which acts as a JavaScript filter. This approach is preferred for AND operations as it leverages the efficiency of JavaScript filtering after an initial indexed query. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Dexie.js provides support for TypeScript, allowing you to benefit from static typing for enhanced code quality and maintainability. By defining your database schema with TypeScript, you can get compile-time checks for your database operations, reducing the likelihood of runtime errors. This integration makes Dexie a robust choice for large-scale applications developed with TypeScript. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.equals() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.equals()` method is used to retrieve records where the indexed property's value exactly matches the specified value. This is the most basic form of filtering and is equivalent to a direct equality check. + +-------------------------------- + +### Cloud > Dexie Cloud API Limits + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The Dexie Cloud API Limits section details the constraints and quotas associated with using the Dexie Cloud services. Understanding these limits is crucial for building scalable applications and avoiding unexpected issues related to rate limiting or resource exhaustion. This includes information on request limits, data storage, and bandwidth. + +-------------------------------- + +### ExportImport > Export and Import Database + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Exporting and importing your Dexie.js database is a valuable feature for backups, data migration, or sharing data. Dexie provides methods to serialize your database content into a format (like JSON) that can be stored externally. Subsequently, you can use a corresponding import mechanism to restore the data back into a Dexie.js database. This process ensures data persistence beyond the browser's local storage. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud CLI + +Source: https://dexie.org/docs/Dexie/Dexie.on + +The Dexie Cloud CLI (Command Line Interface) provides tools for managing your Dexie Cloud projects, such as deploying schema changes and managing users. It streamlines common administrative tasks. + +-------------------------------- + +### Version > Version.stores() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +Dexie.js's `Version.stores()` method is used to define the schema of your database. You specify the tables (object stores) and their indexes within this method. This is a crucial step when creating or upgrading your database to ensure the correct structure is in place. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +The `Version` object in Dexie.js represents a specific version of your database schema. It's used during database initialization and upgrades. The `stores()` method is called on a `Version` object to define the object stores (tables) and their indexes for that particular version. The `upgrade()` method is used to define the logic that runs when migrating the database from a previous version to the current one, allowing for schema changes and data migrations. + +-------------------------------- + +### Table > Table.put() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.put()` method inserts or updates a record in the table. If a record with the same primary key exists, it will be updated with the new values; otherwise, it will be inserted. This is a versatile method for handling both new entries and modifications. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud API Limits + +Source: https://dexie.org/docs/Dexie/Dexie.on + +The Dexie Cloud API Limits section details the restrictions and quotas on API usage. Understanding these limits is crucial for designing scalable applications and avoiding service disruptions. + +-------------------------------- + +### Import file example for sealing the schema + +Source: https://dexie.org/docs/cloud/cli + +Sealing the schema means locking the schema from letting clients add new tables as a step in a sync call. To seal the schema, set the `sealed` property to `true` in the import file. This prevents clients from adding new tables without an explicit schema update. + +-------------------------------- + +### Ajax Populate Sample > Same Sample with Comments And Logging + +Source: https://dexie.org/docs/Dexie/Dexie.on + +When populating a database from an AJAX call using the `on('ready')` event, it's crucial to manage the asynchronous nature of the AJAX request and subsequent database transactions. First, you check if the database is already populated by querying the count of records in a relevant table. If the count is zero, indicating an empty database, you initiate an AJAX call. This call should be wrapped in a `Dexie.Promise` to allow Dexie.js to track its completion. Upon successful retrieval of data, you resolve the Promise with the data. Subsequently, you initiate a Dexie.js transaction (`db.transaction('rw', ...)`). Within this transaction, you iterate through the received data and add each item to the appropriate table. Returning the Promise generated by `db.transaction()` ensures that Dexie.js waits for the transaction to commit before proceeding with any other queued database operations. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.noneOf()` method allows you to query records where an indexed property does not match any of the values provided in an array. This is useful for excluding specific records based on a set of criteria. + +-------------------------------- + +### Collection > Collection.distinct() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Collection.distinct()` method allows you to retrieve unique values from a specific property within a collection of records. This is useful when you want to get a list of all unique values for a certain field, for example, a list of all unique categories in a product table. It operates on an existing collection, which might be the result of a query. + +-------------------------------- + +### Docs Home > Cloud > Dexie Cloud REST API + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section describes the REST API provided by Dexie Cloud. It allows you to interact with Dexie Cloud services programmatically using standard HTTP requests, which can be useful for backend integrations or custom tooling. + +-------------------------------- + +### Y.js + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Y.js is a framework for building collaborative applications that synchronize shared data. `y-dexie` is an integration that allows Y.js to use Dexie.js as its persistence layer, enabling offline support and efficient data synchronization for real-time collaborative experiences. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.userInteraction + +Source: https://dexie.org/docs/cloud/UserLogin + +The `db.cloud.userInteraction` property relates to managing user-initiated actions and ensuring that certain operations, like critical data mutations or re-authentication, prompt for explicit user confirmation. This helps prevent accidental data loss or unauthorized changes. + +-------------------------------- + +### Dexie.js > Collection > Collection.and() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides the `Collection.and()` method to combine multiple criteria using a logical AND operator. This allows you to create more specific queries by requiring all conditions to be met. For example, `table.where('status').equals('active').and(person => person.age > 18)` would find records where the status is 'active' AND the age is greater than 18. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The `WhereClause` API in Dexie.js provides powerful tools for querying data. It allows you to define complex filtering conditions on your database tables. Methods like `equals()`, `equalsIgnoreCase()`, `below()`, `aboveOrEqual()`, and `between()` enable precise data retrieval based on various comparison operators. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Dexie Cloud introduces a comprehensive set of features for building real-time, collaborative applications with synchronized data. It handles authentication, authorization, conflict resolution, and offline support, significantly simplifying the development of such applications. Key components include DBPermissionSet, DexieCloudOptions, Invite, Member, PersistedSyncState, Realm, Role, and SyncState. + +-------------------------------- + +### Dexie.js > Version + +Source: https://dexie.org/docs/safari-issues + +The `Version` API in Dexie.js is used for managing database schema changes over time. When you create or upgrade your database, you define its structure using `db.version(versionNumber).stores({...})`. The `upgrade` method allows you to define data migrations when a new version of the database is introduced, ensuring that existing data is handled correctly when the schema evolves. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/Tutorial + +Dexie Cloud offers several best practices to ensure optimal performance and scalability. This includes strategies for handling data consistency, implementing efficient syncing mechanisms, and understanding API limits. Proper schema design and judicious use of indexing are also key to maintaining a responsive application. + +-------------------------------- + +### Dexie.js > Dexie Constructor + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides a mechanism for defining and managing database schema versions and upgrades through its `version()` and `stores()` methods. When you open a database, Dexie.js checks the current version against the defined schema. If the database version is lower than the requested version, an upgrade process is initiated. During the upgrade, you can define schema changes, such as creating new tables, adding indexes, or deleting old ones. The `populate` event is triggered during the initial creation of the database or when upgrading to a new version, allowing you to seed initial data or perform complex migrations. + +-------------------------------- + +### Dexie.js > Collection > Collection.offset() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides a `Collection.offset()` method that allows you to skip a specified number of records from the beginning of a collection. This is commonly used in conjunction with `limit()` for implementing pagination, enabling you to fetch data in chunks. For example, to get the second page of results with 10 items per page, you would use `offset(10).limit(10)`. + +-------------------------------- + +### Docs Home > Cloud > Add demo users + +Source: https://dexie.org/docs/Dexie/Dexie.on + +Adding demo users and public data is a common step when setting up and testing Dexie Cloud applications. This helps in simulating real-world usage scenarios and verifying synchronization. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.events.syncComplete + +Source: https://dexie.org/docs/Dexie/Dexie.on + +`db.cloud.events.syncComplete` is an event that fires when a synchronization cycle has successfully completed. You can use this event to trigger actions after data has been synced. + +-------------------------------- + +### Cloud > Dexie Cloud Best Practices + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +Dexie Cloud Best Practices focus on optimizing performance, ensuring data consistency, and managing security effectively. This includes recommendations on schema design, efficient querying, handling synchronization conflicts, and leveraging features like sharding and scalability for larger applications. Adhering to these practices helps in building robust and maintainable cloud-synced applications. + +-------------------------------- + +### Docs Home > Cloud > Authentication in Dexie Cloud + +Source: https://dexie.org/docs/cloud/UserLogin + +Dexie.js Cloud offers integrated authentication features, simplifying the process of managing user sign-ups, logins, and sessions. This section covers how to implement authentication in your application, including handling user credentials, JWTs, and user roles. Securely managing user identities is crucial for most applications. + +-------------------------------- + +### Dexie.js > Calling Sub Functions + +Source: https://dexie.org/docs/Simplify-with-yield + +There are two primary methods for structuring code with sub-functions in Dexie.js when dealing with asynchronous operations. Method 1 involves declaring each function with Dexie.async(). This approach is more declarative but requires using `var` declarations with `function*` expressions. Method 2 involves declaring functions simply as `function* myFunc(){ ... }`. This method results in cleaner code but necessitates using JSDoc comments to clarify how these functions are intended to be consumed, as generator functions are not exclusively used for emulating async/await and their calling mechanism (e.g., via `spawn()` or `yield*`) cannot always be assumed. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.below() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.below()` method filters records where the indexed property's value is strictly less than the specified value. This is useful for querying data within a specific range, excluding the upper bound. + +-------------------------------- + +### replacePrefix() operator > Consistency use cases + +Source: https://dexie.org/docs/PropModification/replacePrefix%28%29 + +Client A and Client B shares a copy of a Dexie Cloud database with a tree structure. The tree structure is defined using the indexed `filePath` property. A network outage happens for both clients. At the time of the network outage both clients have identical copies of the tree. +Now both clients are off-line for a while and while they are offline they perform different actions: + * Client A adds `item4` with filePath `foo/`. + * Client B renames filepath `foo/` to `bar/` using `replacePrefix()` the same way as in the sample from syntax above. + +Network is then repaired for both clients. +If Client A syncs first: + 1. Client A syncs. The canonical data is now: +`foo/ + item1 + item2 + item3 + item4 +` + 2. Client B syncs. The consistent `replacePrefix` operation is executed server-side. Result: +`bar/ + item1 + item2 + item3 + item4 +` +If instead Client B would have synced first: + 1. Client B syncs. The consistent `replacePrefix` operation is executed server-side and also persisted in the change log, in case another client based on previous revision will sync things later. +`bar/ + item1 + item2 + item3 +` + 2. Client A syncs the addition of `{filePath: 'foo/', name: 'item4'}` (based on an earlier state of the data). Since the base revision number is part of the sync request, server detects that a consistent operation has to be executed onto the data that client A wants to add to the database. The new object `{filePath: 'foo/', name: 'item4'}` is therefore transformed into `{filePath: 'bar/', name: 'item4'}`. Result: +`bar/ + item1 + item2 + item3 + item4 +` + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.belowOrEqual()` method creates a query condition to select records where a specific indexed property is less than or equal to a given value. This is commonly used for range queries, including the boundary value. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.userInteraction + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +The `db.cloud.userInteraction` property likely relates to managing user interactions or prompts required during the cloud synchronization process. This could involve handling user consent for certain operations or displaying notifications related to sync activities, ensuring a smooth user experience. + +-------------------------------- + +### Dexie.js > Compound indexes > Matching Multiple Values + +Source: https://dexie.org/docs/Compound-Index + +To query for specific people based on multiple criteria within a compound index, such as both first and last name, you can utilize the `WhereClause.anyOf()` method. This method allows you to specify an array of criteria, where each criterion is itself an array representing the values for the properties in the compound index. For example, `db.people.where('[firstName+lastName]').anyOf([["Foo", "Bar"], ["Baz", "Qux"]]).toArray()` would retrieve records for both "Foo Bar" and "Baz Qux". + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Promise/unhandledrejection-event + +Dexie.js aims to make IndexedDB development more enjoyable and productive. It achieves this by providing a promise-based API, simplifying transaction management, and offering automatic database schema versioning and upgrades. This allows developers to focus on their application logic rather than the intricacies of the IndexedDB specification. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/DerivedWork + +Dexie.js provides robust support for TypeScript, enabling type-safe database interactions. This includes defining your database schema with TypeScript interfaces and classes, which allows for compile-time checking of your database operations. While there might be older versions of TypeScript support, the current TypeScript integration is highly recommended for new projects to leverage the benefits of static typing, improving code quality and maintainability. + +-------------------------------- + +### Customizing login GUI > Example login dialog + +Source: https://dexie.org/docs/cloud/authentication + +The `MyLoginGUI` component utilizes the `useObservable` hook to subscribe to `db.cloud.userInteraction`. If the `ui` observable is undefined, it means no user interaction is currently needed, and the component returns null. Otherwise, it renders the `MyLoginDialog` component, passing the `ui` object as a prop to handle the display and interaction logic for the login process. + +-------------------------------- + +### safari-issues + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Safari issues related to IndexedDB might require specific workarounds or configurations when using Dexie.js. This section likely details known problems and provides guidance on how to address them to ensure consistent behavior across different browsers. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie.js is a popular JavaScript library that provides a convenient and powerful API for working with IndexedDB, the browser's built-in NoSQL database. It simplifies many of the complexities associated with native IndexedDB operations, offering a promise-based interface, automatic schema versioning, and enhanced querying capabilities. Dexie.js is widely used in modern web development to enable offline data storage, improve application performance, and enhance user experience by providing rich data management features directly in the browser. + +-------------------------------- + +### Docs Home > Version + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +The `Version` object in Dexie.js represents a database schema version. You can use it to define and manage your database structure. The `stores()` method is crucial for defining your object stores (tables) and their indexes. The `upgrade()` method allows you to perform schema migrations when the database version changes, ensuring data integrity during updates. + +-------------------------------- + +### useLiveQuery() + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +The `useLiveQuery()` hook observes IndexedDB data and causes your React component to re-render whenever the observed data changes. This enables Dexie to function as a persistent, RAM-efficient state manager for your React applications, as it avoids loading the entire database into memory. When data is added, updated, or deleted using Dexie's methods (e.g., `Table.add()`, `Table.update()`, `Table.delete()`), any component observing that data will automatically update. + +-------------------------------- + +### systemjs + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +System.js, similar to requirejs, requires explicit configuration for module locations and types. You need to inform System.js where to find the Dexie module and specify its format. This is done within the `System.config` object. You'll map the module name 'dexie' to its corresponding file path (e.g., in `node_modules/dexie/dist/dexie.js`). Additionally, within the `packages` configuration, you specify the module format for Dexie, such as 'amd' or 'cjs'. The process begins with installing Dexie via npm. + +-------------------------------- + +### Simplify with yield + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js integrates seamlessly with modern JavaScript features, including `async/await` syntax. This allows you to write asynchronous database operations in a more synchronous and readable style. Instead of chaining `.then()` callbacks, you can use `await` to pause execution until a Promise resolves, making your database logic cleaner and easier to follow. For example, `const items = await db.items.toArray();`. + +-------------------------------- + +### Database Versioning + +Source: https://dexie.org/docs/Tutorial/Design + +Database versioning is essential when working with indexedDB. Dexie offers an upgrading framework that simplifies this process. For instance, if you start with a schema defining friends with an auto-incremented 'id' and an index on 'name', you can later add an index for 'shoeSize' by simply increasing the version number and updating the stores definition. This allows you to query based on the new index in subsequent versions. + +-------------------------------- + +### Dexie > Dexie Constructor + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Dexie.js` constructor is used to create an instance of the Dexie database. You typically pass the database name as an argument. This instance is then used to define the database schema, open the connection, and perform all database operations. + +-------------------------------- + +### Table > Table.toArray() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js's `Table.toArray()` method is used to retrieve all records from a table (or a filtered collection) into a JavaScript array. This is a common operation when you need to process or display multiple records. For very large tables, consider using `each()` for better memory efficiency. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.inAnyRange() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.inAnyRange()` method allows you to specify multiple ranges and retrieve records where the indexed property falls within any of those ranges. This provides a flexible way to query data across several non-contiguous intervals. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/cloud/Member + +Dexie.js provides a flexible `WhereClause` object for building complex queries. The `WhereClause` methods allow you to specify conditions for filtering data based on various criteria. You can use methods like `WhereClause.equals()`, `WhereClause.above()`, `WhereClause.below()`, `WhereClause.between()`, `WhereClause.startsWith()`, and `WhereClause.anyOf()` to define precise filters. There are also case-insensitive variants like `equalsIgnoreCase()` and `anyOfIgnoreCase()` for more flexible matching. + +-------------------------------- + +### Dexie > Dexie.defineClass() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.defineClass()` method is used to define a JavaScript class that will be associated with a specific table. Instances of this class will be automatically created when you retrieve data from that table, allowing you to add methods and custom logic to your data objects. This promotes an object-oriented approach to database interaction. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/MultiEntry-Index + +The `Version` object in Dexie manages database schema versions and upgrades. Each version can define its own set of object stores and indexes using `Version.stores()`. The `Version.upgrade()` method allows you to define migration logic when moving from an older schema version to a new one, ensuring data integrity during schema changes. + +-------------------------------- + +### Table > Hooks + +Source: https://dexie.org/docs/cloud/index + +Dexie.js provides a hook system for tables, allowing you to intercept and modify operations at various stages. The available hooks are: `creating` (before a new object is created), `reading` (before an object is read), `updating` (before an object is updated), and `deleting` (before an object is deleted). These hooks are useful for implementing logic such as data validation, default value assignment, or custom side effects. + +-------------------------------- + +### Building Addons > Understanding where Dexie classes reside + +Source: https://dexie.org/docs/Tutorial/Building-Addons + +Dexie classes such as `Collection` and `Table` are created within the closure scope of the `Dexie` constructor. To extend the prototypes of these classes, you need to work with an instance of `Dexie`. This involves accessing the class prototypes through a `Dexie` instance to make modifications. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/WhereClause/WhereClause + +Dexie.js is a powerful wrapper for IndexedDB that provides a more intuitive and developer-friendly API. It simplifies common IndexedDB operations, making it easier to work with and manage your client-side data. Whether you're building complex applications or simple offline-first experiences, Dexie.js streamlines the process of interacting with the browser's database capabilities. + +-------------------------------- + +### Dexie.js + +Source: https://dexie.org/docs/cloud/custom-emails + +Dexie.js is a popular JavaScript library that acts as a wrapper for the IndexedDB API, making it significantly easier and more intuitive to work with browser-based databases. It addresses many of the complexities and verbosities of the native IndexedDB, offering a more developer-friendly experience. Key features include a Promise-based API, simplified transaction management, automatic schema upgrades, and robust error handling. Dexie.js also provides extensions and utilities to enhance functionality, such as live queries for real-time data updates and support for various frontend frameworks. + +-------------------------------- + +### Typescript + +Source: https://dexie.org/docs/cloud/index + +Dexie.js supports TypeScript, providing type definitions for enhanced development experience and compile-time checks. This allows developers to leverage the benefits of static typing when working with Dexie.js, leading to more robust and maintainable code. Ensure you have the appropriate TypeScript configuration and types installed to utilize this feature effectively. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/cloud/Realm + +The `WhereClause` object in Dexie.js is central to performing advanced queries. It allows you to specify various conditions for filtering data, including equality, inequality, range checks (e.g., `above`, `below`, `between`), and pattern matching (e.g., `startsWith`, `equalsIgnoreCase`). This significantly enhances the querying power compared to the native IndexedDB API. + +-------------------------------- + +### Docs Home > safari-issues + +Source: https://dexie.org/docs/DBCore/DBCoreDeleteRequest + +This section addresses specific issues or workarounds related to using Dexie.js with Safari browsers. It might cover known bugs, performance considerations, or best practices for ensuring compatibility and optimal performance when Dexie.js is used in the Safari environment. + +-------------------------------- + +### Roadmap > safari-issues + +Source: https://dexie.org/docs/cloud/Member + +This section addresses specific issues or workarounds related to Safari browser compatibility with Dexie.js. It may detail known limitations or provide solutions for problems encountered when using Dexie.js in the Safari environment. + +-------------------------------- + +### Table + +Source: https://dexie.org/docs/cloud/web-hooks + +The `Table.count()` method in Dexie.js returns the total number of records present in a table. It returns a promise that resolves with an integer representing the count. This method is useful for obtaining statistics about your data or for simple checks on whether a table is empty. + +-------------------------------- + +### Docs Home > Compound Index + +Source: https://dexie.org/docs/Compound-Index + +A compound (or composite) index is an index based on several keypaths. It can be used to efficiently index multiple properties in one index to easily find the existence of the combination of two keys and their values. In Dexie, a compound index must be specified when defining the schema. For example, `db.version(1).stores({ people: 'id, [firstName+lastName]' });` will create a compound index on `firstName` and `lastName`. Records containing valid keys in these properties will be indexed. If having stored an object with properties `{firstName: 'foo', lastName: 'bar'}`, it can be efficiently looked up using `db.people.where('[firstName+lastName]').equals(['foo', 'bar'])`. This can also be expressed as `db.people.where({firstName: 'foo', lastName: 'bar'})`, which is a special case that only works in Dexie >=2.0 and can match by multiple properties, regardless of browser support for compound queries. + +-------------------------------- + +### Libs > dexie-react-hooks > useObservable() + +Source: https://dexie.org/docs/dexie-react-hooks/useObservable%28%29 + +import React from 'react'; +import { BehaviorSubject } from 'rxjs'; +import { useObservable } from 'dexie-react-hooks'; + +const counter = new BehaviorSubject(1); + +// +// React component +// +export function SimpleCounter() { + const currentCount = useObservable(counter); + + return ( + <> +

Current Count is {currentCount}

+ + + ); +} + +-------------------------------- + +### Docs Home > Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCoreGetManyRequest + +Dexie.js has a roadmap for future development, with version 5.0 being a significant upcoming release. This new version is expected to introduce new features, performance improvements, and potentially breaking changes. Developers should consult the roadmap to stay informed about upcoming changes and plan their upgrades accordingly. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Tutorial/Consuming-dexie-as-a-module + +Dexie.js is a powerful wrapper for IndexedDB that simplifies database operations in web applications. It provides a more intuitive and convenient API compared to the native IndexedDB API, making it easier to work with databases in JavaScript. Dexie.js handles many of the complexities of IndexedDB, such as transaction management and cursor operations, allowing developers to focus on their application logic. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.equals()` method creates a query condition to select records where an indexed property exactly matches a given value. This is the most straightforward way to query for a specific record based on an indexed field. + +-------------------------------- + +### Collection > Collection.or() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js provides a `Collection.or()` method that allows you to combine multiple query conditions with a logical OR. This means a record will be included in the result if it matches *any* of the specified conditions. For example, `db.friends.where('city').equals('New York').or('city').equals('London')` would return friends from either New York or London. + +-------------------------------- + +### Code complexity + +Source: https://dexie.org/docs/The-Main-Limitations-of-IndexedDB + +Without a wrapper library like Dexie, your application code could become unnecessarily complex. You would need to write significantly more lines of code, and if correct error handling is a priority, your code will soon become very complex and difficult to read and maintain. + +-------------------------------- + +### Dexie.js export-import addon > Interface + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +Importing the dexie-export-import module extends the Dexie interface and `Dexie.prototype` directly, meaning there's no separate addon instance to manage. The extended interface adds `export()` and `import()` methods to `Dexie` instances, and an `import()` method to the `Dexie` constructor. The `export()` method, when called on a `Dexie` instance, returns a Promise that resolves to a Blob representing the exported database, with optional `ExportOptions`. The `Dexie.import()` static method and `Dexie.prototype.import()` instance method both accept a Blob and optional `StaticImportOptions` or `ImportOptions` respectively, to manage the import process. + +-------------------------------- + +### WhereClause > WhereClause.aboveOrEqual() + +Source: https://dexie.org/docs/cloud/Member + +The `WhereClause.aboveOrEqual()` method filters records where a property's value is greater than or equal to a given value. This provides an inclusive lower bound for range queries. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `WhereClause` object in Dexie.js provides a fluent API for building complex queries. It allows you to specify conditions for filtering data within an object store. Methods like `equals()`, `equalsIgnoreCase()`, `above()`, `below()`, `between()`, and `startsWith()` enable precise data retrieval based on various criteria. + +-------------------------------- + +### Version + +Source: https://dexie.org/docs/DerivedWork + +The `Version` object in Dexie.js represents a specific version of your database schema. When you need to make changes to your database structure, such as adding or removing tables, or modifying indexes, you do so within a `Version` upgrade function. The `Version.stores()` method is used to define the schema for that specific version, and `Version.upgrade()` allows you to write migration logic to transition data from the previous version to the new one. + +-------------------------------- + +### Summary > Handy functions > isStoragePersisted + +Source: https://dexie.org/docs/StorageManager + +This function checks if storage is already persisted. It returns a promise resolved with `true` if the current origin is using persistent storage, `false` if not, and `undefined` if the API is not present. + +-------------------------------- + +### Modify Schema + +Source: https://dexie.org/docs/Tutorial/Understanding-the-basics + +In older versions of Dexie (prior to 3.0), when modifying a schema, it was a requirement to keep all previous version declarations alongside the new one. This ensured backward compatibility and allowed Dexie to manage schema evolution correctly across different versions. + +-------------------------------- + +### Dexie.js > Things to play with > Make query parameters editable + +Source: https://dexie.org/docs/Tutorial/React + +Add a new component that allows the user to specify `minAge` and `maxAge` and pass those into the props to ``. You will notice that updating the props will also be instantly reflected in the query results of your app. + +-------------------------------- + +### Dexie.js > Versioning + +Source: https://dexie.org/docs/Tutorial/Design + +Dexie handles database versioning by filtering the differences between existing and new versions, sequentially adding or removing stores and indexes. A key feature in Dexie 3 is its reliance on the installed schema rather than the declared schema for computing these differences. This means Dexie compares the actual installed schema with the next version's schema, rather than the declared schema of the current version with the next version. Consequently, discrepancies between the declared and actual installed schema of the current version do not matter. Furthermore, Dexie can open a new version of a database even if the old version is not present in the schema declaration on the device. + +-------------------------------- + +### Dexie.js + +Source: https://dexie.org/docs/DexieErrors/Dexie + +It's also OK to run several different database transactions in parallel. Transactions are maintained using zones. + +-------------------------------- + +### Export and Import Database + +Source: https://dexie.org/docs/ExportImport/dexie-export-import + +The `dexie-export-import` npm package extends Dexie with the capability to export and import databases to and from Blobs. This functionality is crucial for tasks such as backing up your database, migrating data between different versions or environments, or transferring data to another application. + +The package offers several functions to facilitate these operations: + +- `importDB(blob, [options])`: Imports data from a Blob or File into a Dexie instance. +- `exportDB(db, [options])`: Exports a Dexie database to a Blob. +- `importInto(db, blob, [options])`: Imports data from a Blob or File into an existing Dexie instance, merging the data. +- `peakImportFile(blob)`: Allows you to inspect the metadata of an import file (like database name, version, and table information) without actually performing an import operation. + +These functions can be imported directly from the `dexie-export-import` module. Alternatively, when using Dexie v2.x with TypeScript, you can import the package to enable static methods directly on the `Dexie` class and instance methods on a `db` object, providing a more integrated feel. + +-------------------------------- + +### export + +Source: https://dexie.org/docs/cloud/cli + +The `npx dexie-cloud export` command allows you to export schema, data, roles, or demo users to a JSON file. The export format is compatible with the import format. You can specify options to export only specific parts of the database, such as `--schema`, `--data`, `--roles`, or `--demoUsers`. You can also filter exports by `realmId` or `table`. Re-importing export files is generally additive, except for explicitly nullified objects. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/cloud/index + +The `WhereClause` object in Dexie.js is used to construct complex query conditions for filtering data. It provides a rich set of methods for various comparison operators, including equality (`equals`, `equalsIgnoreCase`), inequality (`notEqual`), range comparisons (`above`, `aboveOrEqual`, `below`, `belowOrEqual`, `between`), and set operations (`anyOf`, `noneOf`, `inAnyRange`). It also supports string-specific operations like `startsWith`, `startsWithAnyOf`, `startsWithIgnoreCase`, and `startsWithAnyOfIgnoreCase` for prefix matching. + +-------------------------------- + +### API Reference > Collection + +Source: https://dexie.org/docs/Collection/Collection + +The `Collection` object in Dexie.js represents a set of records within a table. It provides a rich set of methods for filtering, sorting, and retrieving data. You can chain these methods to build complex queries. For example, you can use `filter()`, `orderBy()`, `limit()`, and `toArray()` to fetch specific subsets of your data. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.version + +Source: https://dexie.org/docs/Dexie/Dexie.on + +`db.cloud.version` provides information about the current version of the Dexie Cloud addon being used. + +-------------------------------- + +### Cloud > db.cloud.invites + +Source: https://dexie.org/docs/DBCore/DBCorePutRequest + +The `db.cloud.invites` collection provides access to invitation data within Dexie Cloud. This allows you to manage user invitations, such as sending invitations to new users or tracking the status of existing invitations. You can use this to build features for inviting collaborators or sharing access to specific data within your application. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/Tutorial/Best-Practices + +Dexie.js is a powerful wrapper for IndexedDB that simplifies database operations and provides a more developer-friendly API. It offers features like live queries, automatic schema versioning, and transaction management, making it easier to build robust web applications with local storage capabilities. + +-------------------------------- + +### Docs Home > WhereClause + +Source: https://dexie.org/docs/cloud/index + +The `WhereClause` API in Dexie provides a powerful way to filter and query data. It allows you to specify conditions for retrieving records based on various operators, such as equality, range comparisons (`above`, `below`, `between`), and pattern matching (`startsWith`, `equalsIgnoreCase`). This enables flexible and efficient data retrieval from your IndexedDB stores. + +-------------------------------- + +### Simplify with yield + +Source: https://dexie.org/docs/Simplify-with-yield + +Dexie.js provides a simplified way to use IndexedDB with modern browsers by leveraging the `yield` keyword for a synchronous-like programming style. This feature is available in Dexie version 1.3 and later. By using `Dexie.spawn()` or `Dexie.async()`, you can write code that looks and feels synchronous, making it easier to manage asynchronous operations. Each promise-returning method can be `yield`ed, similar to how `async/await` works in ES7, but without the need for transpilation in modern browsers. + +-------------------------------- + +### Dexie.js > Dexie.events() + +Source: https://dexie.org/docs/safari-issues + +Dexie.js provides `Dexie.events()` which is likely related to managing event listeners for various Dexie.js occurrences, such as database connection changes, transaction events, or data mutations. This allows developers to react to specific database activities by registering callback functions that are executed when the corresponding events are fired. + +-------------------------------- + +### Table > Table.bulkAdd() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.bulkAdd()` method allows you to insert multiple records into a table in a single operation. It takes an array of record objects as input. This method is significantly more efficient than calling `add()` in a loop for multiple records. If any of the records violate constraints (e.g., duplicate primary keys), the entire operation will fail by default, and a `BulkError` will be thrown. However, you can configure Dexie to allow partial success. + +Example: +`db.friends.bulkAdd([{name: 'David'}, {name: 'Eve'}]).then(() => console.log('Added multiple friends.'));` + +-------------------------------- + +### Collection + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Collection` object in Dexie.js represents a set of records retrieved from a table, often as the result of a query. It provides methods for further manipulation and retrieval of these records. You can chain methods like `filter()`, `sortBy()`, `limit()`, and `offset()` to refine your collection. Finally, you can retrieve the data as an array using `toArray()` or iterate through it using `each()`. + +-------------------------------- + +### Dexie > Dexie.version() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.version()` method is used to define or access database schema versions. You chain `.version(x).stores({...})` to define the schema for a specific version during database initialization. You can also query the current version using `db.verno`. + +-------------------------------- + +### IndexSpec > Properties > auto + +Source: https://dexie.org/docs/IndexSpec + +The `auto` property in `IndexSpec` is specifically applicable to primary keys. When set to `true`, it signifies that the primary key will automatically increment its value for each new record inserted into the table. This is a common requirement for generating unique identifiers for records. + +-------------------------------- + +### Exception Handling + +Source: https://dexie.org/docs/API-Reference + +With Dexie, unlike standard IndexedDB, exceptions are consistently handled through the `Promise.catch()` method. This approach simplifies error management by providing a single, unified mechanism. When working with transactions, this benefit is amplified, allowing you to catch all errors in one place—at the end of the transaction—rather than managing individual `catch()` calls for each database operation. Any uncaught error, whether an error event, an exception, or even a typo in your code, will abort the ongoing transaction and cause its returned Promise to reject, activating any `catch()` clause attached to the transaction scope. + +-------------------------------- + +### Cloud > db.cloud.options + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `db.cloud.options` property allows you to access and potentially modify the configuration options for Dexie Cloud. This can be useful for dynamically adjusting settings or inspecting the current configuration. + +-------------------------------- + +### Docs Home > Version > Version.stores() + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +The `Version` class in Dexie.js represents a specific version of your database schema. The `Version.stores()` method is used to define the object stores (tables) and their indexes for that particular version. This is a core part of database schema management, allowing you to declare the structure of your data when you create or upgrade your database. + +-------------------------------- + +### Docs Home > WhereClause > WhereClause.noneOf() + +Source: https://dexie.org/docs/cloud/UserLogin + +The `WhereClause.noneOf()` method retrieves records where the indexed property does not match any of the values provided in an array. This is useful for excluding specific values from your query results. + +-------------------------------- + +### Table > Table.add() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js provides `Table.add()` to insert a new record into a table. It returns a promise that resolves with the primary key of the newly added record. If the table has an auto-incrementing primary key, Dexie handles its generation automatically. + +-------------------------------- + +### ExportImport > Export and Import Database + +Source: https://dexie.org/docs/Tutorial/Svelte + +Exporting and importing your Dexie.js database can be crucial for backup, migration, or data sharing purposes. Dexie provides utilities to serialize your database into a format that can be easily stored and later rehydrated. This process typically involves iterating through your tables, extracting the data, and then using `bulkPut` or similar methods to populate a new database instance. + +-------------------------------- + +### Dexie.js > Collection > Collection.toArray() + +Source: https://dexie.org/docs/safari-issues + +The `Collection.toArray()` method in Dexie.js is used to retrieve all records from a collection as a JavaScript array. This is a common operation when you need to process a set of records in memory or display them in a list. When you call `collection.toArray()`, it returns a Promise that resolves with an array containing all the records that match the collection's criteria. This is often used after applying filters, sorts, or limits to narrow down the desired dataset. + +-------------------------------- + +### Collection > Collection.last() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Similarly, `Collection.last()` retrieves the last record from a collection, typically after sorting. It returns a Promise that resolves with the record object or `undefined` if the collection is empty. For instance, `const lastFriend = await db.friends.orderBy('name').reverse().first();` effectively gets the last friend by name. + +-------------------------------- + +### Docs Home > safari-issues + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +This section addresses specific issues encountered when using Dexie.js with the Safari browser. It might include workarounds, explanations of browser-specific behaviors, or patches for known compatibility problems. If you're developing for Safari, this information is crucial for ensuring your Dexie-powered application functions correctly. + +-------------------------------- + +### Dexie.js > API Reference > Promise + +Source: https://dexie.org/docs/safari-issues + +Dexie.js integrates with Promises to handle asynchronous operations, making it easier to manage sequences of database actions. All operations that return a Dexie.js `Promise` can be chained using `.then()` and `.catch()` for error handling. This Promise-based approach simplifies asynchronous code flow compared to traditional callbacks. Furthermore, Dexie.js provides features like `Promise.spawn()` which allows you to write asynchronous code that looks synchronous using generators, simplifying complex asynchronous logic. + +-------------------------------- + +### Fine grained observation + +Source: https://dexie.org/docs/liveQuery%28%29 + +The observation is as fine-grained as it can possibly be - queries that would be affected by a modification will rerender - others not (with some exceptions - false positives happen but never false negatives). This is also true if your querier callback performs a series of awaited queries or multiple in parallel using Promise.all(). It can even contain if-statements or other conditional paths within it, determining additional queries to make before returning a final result - still, observation will function and never miss an update. No matter how simple or complex the query is - it will be monitored in detail so that if a single part of the query is affected by a change, the querier will be executed and the component will rerender. + +Once again, the rule is that: +__**If a database change would affect the result of your querier, your querier callback will be re-executed and your observable will emit the new result.** + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.between()` method allows you to query records where an indexed property falls within a specified range, inclusive of the boundary values. You provide a lower bound and an upper bound, and Dexie.js retrieves all records that satisfy this condition. + +-------------------------------- + +### API Reference > WhereClause + +Source: https://dexie.org/docs/cloud/consistency + +The `WhereClause.aboveOrEqual()` method creates a query condition to select records where a specific indexed property is greater than or equal to a given value. This is commonly used for range queries, including the boundary value. + +-------------------------------- + +### Dexie Cloud > Customize Authentication (optional) + +Source: https://dexie.org/docs/Tutorial/Dexie-Cloud + +Choose between keeping the default authentication but customizing the GUI, or replacing authentication entirely with a custom solution. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +Sharding and Scalability in the context of Dexie Cloud addresses how the service handles large amounts of data and a high number of concurrent users. This section would likely discuss strategies for distributing data and load to ensure performance and availability as the application grows. + +-------------------------------- + +### Eviction Limits + +Source: https://dexie.org/docs/StorageManager + +Browser-specific limits govern data storage. If these limits are exceeded, non-persistent data may be evicted, or attempts to write new data might fail. When an operation would surpass the storage quota, the browser typically throws a `DOMException` with an error like `QuotaExceededError`. Detailed information on browser storage limits and eviction criteria can be found on the Mozilla Developer Network. + +-------------------------------- + +### Properties > Consuming Observable + +Source: https://dexie.org/docs/cloud/dexie-cloud-addon + +The `db.cloud.invites` property is an Observable that emits an array of `Invite` objects. This can be used to display current invites for a user and automatically update the UI when invites are added, updated, or removed. For example, a React component can use the `useObservable` hook from `dexie-react-hooks` to subscribe to these changes and render the list of invites dynamically. + +-------------------------------- + +### Dexie Cloud API > List users > Paging + +Source: https://dexie.org/docs/cloud/rest-api + +Paging through user lists is handled by the `pagingKey`. When the `hasMore` field in the response is `true`, a `pagingKey` is provided. To fetch the next set of results, repeat the original GET request to `/users` but include the `pagingKey` as a query parameter. + +-------------------------------- + +### Example: A Simple Project Management Model > removeComment + +Source: https://dexie.org/docs/cloud/access-control + +The `removeComment()` function deletes a comment from the database based on its ID. It uses the `db.comments.delete()` method to remove the specified comment record. + +-------------------------------- + +### Dexie > Dexie.events() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.events()` method is used to subscribe to various events emitted by Dexie.js. This allows you to react to specific database occurrences, such as the database being blocked, closed, or an error occurring. You can use `Dexie.on('eventName').subscribe(callback)` to register your event handlers. This is crucial for building responsive applications and handling lifecycle events gracefully. + +Example: +`db.on('error', (error) => { console.error('Dexie error:', error); });` + +-------------------------------- + +### How To Use the StorageManager API > Controlling Persistence + +Source: https://dexie.org/docs/StorageManager + +To check whether your IndexedDB database is successfully persisted, inspect the promise returned by `persist()`, or use the following function to query it without trying to persist: +```javascript +async function isStoragePersisted() { + return await navigator.storage && navigator.storage.persisted && + navigator.storage.persisted(); +} +``` +Example of use: +```javascript +isStoragePersisted().then(async isPersisted => { + if (isPersisted) { + console.log(":) Storage is successfully persisted."); + } else { + console.log(":( Storage is not persisted."); + console.log("Trying to persist..:"); + if (await persist()) { + console.log(":) We successfully turned the storage to be persisted."); + } else { + console.log(":( Failed to make storage persisted"); + } + } +}) +``` + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/limits + +Dexie.js provides a convenient API for IndexedDB, offering a promise-based interface and simplifying common database operations. It abstracts away much of the complexity of the native IndexedDB API, making it easier to interact with the database in web applications. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/Realm + +IndexedDB, while powerful, has several limitations that can make direct usage cumbersome. These limitations include a verbose API, lack of direct support for complex queries (like range queries or case-insensitive searches), and the need for manual transaction management. Dexie.js aims to overcome these challenges by providing a higher-level abstraction that simplifies development and reduces the potential for errors. + +-------------------------------- + +### Table > Table.bulkUpdate() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Table.bulkUpdate()` method updates multiple existing records in a table based on their primary keys. It accepts an array of objects, where each object contains the primary key of the record to update and the properties to modify. If a record with a specified primary key does not exist, that particular update operation will be skipped without failing the entire bulk operation. This is useful for applying batch updates to specific records. + +Example: +`db.friends.bulkUpdate([{ key: 1, changes: { age: 32 } }, { key: 3, changes: { name: 'Eve Updated' } }]).then(() => console.log('Bulk update finished.'));` + +-------------------------------- + +### Dexie.js > Typescript + +Source: https://dexie.org/docs/safari-issues + +Dexie.js offers comprehensive support for TypeScript, enabling type-safe database operations. By defining your database schema with TypeScript, you gain autocompletion, compile-time error checking, and improved code maintainability. This integration helps prevent common errors related to data structure mismatches and ensures that your database interactions are robust. + +-------------------------------- + +### Limitations + +Source: https://dexie.org/docs/dexie-react-hooks/useLiveQuery%28%29 + +IndexedDB is a per-origin database, meaning that offline data stored for one website cannot read data for another website unless they share the same origin. useLiveQuery() will naturally have the same boundary between origins. Syncing data between origins, clients, and different browsers or devices requires another solution and can be accomplished using our addon dexie-cloud-addon and our commercial service Dexie Cloud. + +-------------------------------- + +### Table > Table.bulkPut() + +Source: https://dexie.org/docs/Tutorial/Svelte + +Dexie.js offers `Table.bulkPut()` for efficiently inserting or updating multiple records in a table. Similar to `bulkAdd()`, it takes an array of objects. However, `bulkPut()` will update existing records if their primary keys match, and insert them if they don't. This makes it a versatile method for synchronizing data or ensuring records exist. + +-------------------------------- + +### Dexie > Dexie.version() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.version()` method is used to define a specific version of your database schema. It returns a `Version` object that allows you to specify the schema for that version using the `stores()` method. This is the foundation for managing database schema upgrades and migrations over time. Each call to `version()` should represent a distinct version number. + +Example: +`db.version(1).stores({ + friends: '++id, name' +});` + +-------------------------------- + +### Derived Work > Known Addons > Dexie-mongoify + +Source: https://dexie.org/docs/DerivedWork + +Dexie-mongoify provides a MongoDB-style API for Dexie.js, allowing developers familiar with MongoDB syntax to interact with IndexedDB using similar commands and patterns. + +-------------------------------- + +### Table > Table.bulkPut() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Table.bulkPut()` method inserts or updates multiple records in a table in a single atomic operation. It returns a Promise that resolves with an array of the primary keys for the affected records. This is more efficient than calling `put()` multiple times. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/cloud/web-hooks + +The `db.cloud.login()` method initiates the user login process in Dexie Cloud. It typically takes authentication credentials or token information and handles the communication with the authentication server. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/cloud/DBPermissionSet + +Dexie.js is a popular JavaScript library that acts as a wrapper for the native IndexedDB API. It significantly simplifies the development process by providing a more intuitive and developer-friendly interface for interacting with the browser's IndexedDB. This means you can leverage the power of client-side NoSQL databases without the complexities often associated with the raw IndexedDB API. + +-------------------------------- + +### Docs Home > Y.js > y-dexie + +Source: https://dexie.org/docs/DBCore/DBCoreQuery + +Y.js is a framework for building collaborative applications, and `y-dexie` is an adapter that integrates Y.js with Dexie.js. This integration allows you to leverage Dexie.js as a persistent storage backend for Y.js, enabling real-time data synchronization and conflict resolution across multiple clients. It's a powerful combination for building collaborative features into your web applications. + +-------------------------------- + +### Dexie Cloud Import > Import file format + +Source: https://dexie.org/docs/cloud/cli + +The import functionality allows you to manage your Dexie Cloud database schema, permissions, and data. You can create a JSON file specifying the schema, whether the schema is locked, demo users, roles with associated permissions, and the actual data to be imported. The `schema` property defines the Dexie.js schema for your tables. The `sealed` property, if set to `true`, prevents further schema extensions. `demoUsers` can be used to create placeholder users for showcasing your application. The `roles` property enables the definition of custom roles with specific permissions, such as managing data, adding friends, or read-only access. The `data` property allows for the import of structured data organized by realm, table, and primary key, enabling both creation/updates and deletions of records. + +-------------------------------- + +### Limitations of IndexedDB + +Source: https://dexie.org/docs/cloud/consistency + +IndexedDB, the underlying browser storage API that Dexie.js wraps, has certain limitations. These can include transaction scope, storage limits imposed by browsers, and potential performance considerations for very large datasets or complex operations. Understanding these limitations helps in designing efficient and scalable applications using Dexie.js. + +-------------------------------- + +### Releasing Dexie > Before Releasing + +Source: https://dexie.org/docs/Releasing-Dexie + +Before releasing, ensure you have a dedicated 'dexie-release' clone of the master branch. Navigate to this directory, check that your working directory is clean (`git status`), checkout the `master` branch (or `master-1` for maintenance releases), pull the latest changes, and install dependencies (`npm install`). If you are releasing addons along with Dexie, make sure their versions are bumped in their respective `package.json` files and committed. The release script will handle releasing addons if their versions differ from their published versions on npm. Additionally, ensure that `BROWSER_STACK_USERNAME` and `BROWSER_STACK_ACCESS_KEY` environment variables are set for the full test suite to run, and that the BrowserStack Tunnel is killed on your system. + +-------------------------------- + +### Cloud > Dexie Cloud CLI + +Source: https://dexie.org/docs/cloud/index + +Dexie Cloud offers a Command Line Interface (CLI) tool for managing your cloud database. The `Dexie Cloud CLI` allows you to perform various administrative tasks, such as deploying schema changes, managing users, and configuring your cloud environment. This tool streamlines the development and deployment workflow for applications using Dexie Cloud. + +-------------------------------- + +### Docs Home > Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +The `db.cloud.invites` property provides access to the Dexie Cloud invites collection. This allows you to manage invitations for new users to join your application or specific realms. + +-------------------------------- + +### Cloud + +Source: https://dexie.org/docs/DBCore/DBCoreMutateRequest + +Dexie Cloud includes functionalities for managing database permissions and schema definitions. The `db.cloud.permissions()` method likely allows programmatic access to permission settings, while `db.cloud.schema` would provide information about the structure of your synchronized database. This is essential for ensuring that data access is appropriately controlled and that the database schema is correctly defined for synchronization. + +-------------------------------- + +### Dexie > Dexie.debug + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +The `Dexie.debug` property allows you to enable or disable debug logging for Dexie.js operations. Setting `Dexie.debug = true;` will log detailed information about database operations, including queries, schema changes, and errors, which can be invaluable for troubleshooting. + +-------------------------------- + +### Dexie > Dexie.events() + +Source: https://dexie.org/docs/DBCore/DBCoreGetRequest + +Dexie.js provides `Dexie.events()` which is a mechanism for emitting and listening to custom events within your Dexie instance. This allows for decoupled communication between different parts of your application that interact with the database. + +-------------------------------- + +### Docs Home + +Source: https://dexie.org/docs/DBCore/DBCoreTransaction + +This section covers how to integrate Dexie.js with popular JavaScript frameworks like React, Svelte, and Vue. It provides guidance on setting up Dexie.js within these frameworks, enabling developers to leverage its capabilities in their preferred development environment. + +-------------------------------- + +### Collection > Collection.filter() + +Source: https://dexie.org/docs/DBCore/DBCoreIndex + +The `Collection.filter()` method allows you to apply additional client-side filtering to a collection of records. While Dexie's `where()` clause performs server-side filtering (using indexes), `filter()` is useful for more complex filtering logic that cannot be expressed through indexes. + +-------------------------------- + +### API Reference > Table + +Source: https://dexie.org/docs/cloud/consistency + +The `Table.toArray()` method in Dexie.js is used to retrieve all records from a table and return them as a JavaScript array. This is a convenient way to fetch all data when you need to process it in memory or display it in a list. It simplifies the process of getting all entries from a table, making it easier to work with the entire dataset at once. + +-------------------------------- + +### WhereClause + +Source: https://dexie.org/docs/cloud/custom-emails + +The `WhereClause` object in Dexie.js enables sophisticated querying capabilities. It is returned by the `Table.where()` method and provides a fluent API for defining complex filter conditions. You can specify equality (`equals`), range comparisons (`below`, `above`, `between`), and multiple value matches (`anyOf`, `noneOf`). The `IgnoreCase` variants of these methods offer case-insensitive comparisons, making your queries more flexible. + +-------------------------------- + +### Simplify with yield + +Source: https://dexie.org/docs/cloud/web-hooks + +Dexie.js includes features to simplify working with JavaScript Promises and asynchronous operations. By default, Dexie operations return Promises, allowing you to use `async/await` syntax for cleaner asynchronous code. Additionally, Dexie provides features like `yield` (in older versions or specific contexts) that can further simplify iteration over asynchronous results, making complex data handling more manageable. + +-------------------------------- + +### WhereClause > WhereClause.inAnyRange() + +Source: https://dexie.org/docs/DBCore/DBCoreAddRequest + +The `WhereClause.inAnyRange()` method allows you to specify multiple range conditions for a property. It filters records where the property's value falls within any of the specified ranges, providing flexibility in defining complex search criteria. + +-------------------------------- + +### Dexie.js API > Version + +Source: https://dexie.org/docs/cloud/authentication + +The `Version` object in Dexie.js represents a database schema version. It is primarily used with the `Version.stores()` method to define the object stores (tables) and their indexes for a given version. The `Version.upgrade()` method is crucial for defining the schema migration logic when upgrading from a previous version to the current one, allowing you to add, remove, or modify tables and their structures. + +-------------------------------- + +### Exception Handling > Working With Transactions + +Source: https://dexie.org/docs/API-Reference + +Transactions in Dexie simplify code when performing multiple database operations. They offer several advantages: if any error occurs during modification operations (like `add`, `put`, `update`, `delete`), the entire transaction is aborted, and all modifications are rolled back. You don't need to individually handle promises for each operation within the transaction; error handling is encapsulated. Write operations can be performed synchronously without waiting for completion before starting the next. Even read operations can occur immediately after write operations, and the results will reflect all modifications because operations are queued during pending write operations within the transaction. Crucially, no errors will be missed; they are all caught by the final `catch()` method, encompassing both error events and standard exceptions. + +-------------------------------- + +### API Reference > Collection > Collection.filter() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Collection.filter()` method allows you to create a subset of a collection based on a predicate function. This function is executed for each item, and only items for which the predicate returns `true` are included in the resulting collection. This is a powerful tool for refining your data set before performing other operations. + +-------------------------------- + +### Dexie > Dexie.open() + +Source: https://dexie.org/docs/Tutorial/Getting-started + +The `Dexie.open()` method is used to open a connection to your Dexie.js database. If the database does not exist, it will be created. If the database exists and the version specified in the `Dexie` constructor is higher than the current version, an upgrade process will be triggered. This method returns a Promise that resolves with the `Dexie` instance when the database is successfully opened and ready for use. + +It's crucial to handle the Promise returned by `Dexie.open()` to ensure your application interacts with the database only after it's fully initialized. You can also chain `.then()` and `.catch()` to handle success and error scenarios, respectively. + +Example: +`Dexie.open('myDatabase', 1, db => { db.createObjectStore('friends'); });` + +-------------------------------- + +### EntityTable + +Source: https://dexie.org/docs/EntityTable + +Dexie also exports a generic `Table` that could be used instead of EntityTable if preferring so. `Table` is the building block for `EntityTable`. It allows an optional 3rd argument `TInsertType` that is expected from Table.add(), Table.put() etc. That's where we want to provide a version of our type where the primary key is optional (as it can be auto-generated). + +-------------------------------- + +### Docs Home > Version > Version.stores() + +Source: https://dexie.org/docs/DBCore/DBCoreGetManyRequest + +The `Version.stores()` method in Dexie.js is used to define the structure of your database. You specify the object stores (tables) and their primary keys. This method is typically called during database initialization or upgrades. For example, `db.version(1).stores({ friends: '++id,name' })` defines a 'friends' store with an auto-incrementing 'id' as the primary key and an index on the 'name' property. + +-------------------------------- + +### Transaction + +Source: https://dexie.org/docs/WhereClause/WhereClause + +The `Transaction.table()` method in Dexie.js provides access to a specific table within the current transaction. This allows you to perform operations like adding, getting, updating, or deleting records from that particular table. It's a crucial part of managing data within the context of a transaction, ensuring that all related operations are handled correctly. + +-------------------------------- + +### Docs Home > Cloud > db.cloud.options + +Source: https://dexie.org/docs/Dexie/Dexie.on + +`db.cloud.options` provides access to the configuration options set for Dexie Cloud. This allows you to inspect or dynamically modify certain settings. + +-------------------------------- + +### Roadmap > Road Map: Dexie 5.0 + +Source: https://dexie.org/docs/DBCore/DBCoreCountRequest + +Dexie 5.0 is a planned major release of the Dexie.js library, likely introducing significant new features, performance improvements, and potentially breaking changes. The roadmap for this version would outline the key initiatives and goals, such as enhanced API capabilities, better TypeScript integration, or improved support for new web platform features. Staying informed about the roadmap helps users prepare for the upgrade and leverage the latest advancements. + +-------------------------------- + +### Table > Table.toArray() + +Source: https://dexie.org/docs/Tutorial/Svelte + +The `Table.toArray()` method in Dexie.js retrieves all records from a table that satisfy the current query criteria and returns them as a JavaScript array. If no criteria have been applied, it will return all records in the table. This is a common method used to fetch data for display or further processing in the application. \ No newline at end of file diff --git a/packages/web/README.md b/packages/web/README.md index 97517be30..78b844b01 100644 --- a/packages/web/README.md +++ b/packages/web/README.md @@ -96,13 +96,20 @@ VITE_GOOGLE_CLIENT_ID # OAuth client ID (public) ### IndexedDB Databases -The app uses 5 separate IndexedDB databases: - -1. **`corates-query-cache`** - TanStack Query offline cache (projects, orgs, subscriptions) -2. **`corates-auth-cache`** - Better Auth session and avatar cache -3. **`corates-pdf-cache`** - PDF file cache for offline access -4. **`corates-form-state`** - Form state persistence (auto-save) -5. **`y-indexeddb-${projectId}`** - Per-project Yjs document storage +The app uses a unified Dexie database (`corates`) for all client-side storage: + +| Table | Purpose | +| -------------------- | ---------------------------------------------- | +| `projects` | Y.Doc persistence via y-dexie | +| `pdfs` | PDF file cache with LRU eviction (200MB limit) | +| `avatars` | User avatar cache with 30-day expiry | +| `formStates` | Form auto-save across OAuth redirects | +| `queryCache` | TanStack Query offline persistence | +| `localChecklists` | Offline practice checklists | +| `localChecklistPdfs` | PDFs associated with local checklists | +| `ops` | Operation queue for offline mutations (future) | + +Additionally, `y-indexeddb-${projectId}` databases are used for per-project Yjs document storage. ## Architecture diff --git a/packages/web/package.json b/packages/web/package.json index 13b8e6d8e..eaec2769b 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -52,12 +52,12 @@ "@tanstack/solid-query": "^5.90.19", "better-auth": "^1.4.10", "d3": "^7.9.0", - "idb": "^8.0.3", + "dexie": "^4.2.1", "preact": "^10.28.1", "solid-icons": "^1.1.0", "solid-js": "^1.9.10", "tailwind-merge": "^3.4.0", - "y-indexeddb": "^9.0.12", + "y-dexie": "^4.2.2", "y-websocket": "^3.0.0", "yjs": "^13.6.29" }, @@ -67,6 +67,7 @@ "@tailwindcss/vite": "^4.1.18", "@testing-library/jest-dom": "^6.9.1", "@vitest/ui": "^4.0.16", + "fake-indexeddb": "^6.2.5", "jsdom": "^27.4.0", "prettier": "^3.7.4", "puppeteer": "^24.34.0", diff --git a/packages/web/src/api/better-auth-store.js b/packages/web/src/api/better-auth-store.js index f4fdd218a..0c0bdd602 100644 --- a/packages/web/src/api/better-auth-store.js +++ b/packages/web/src/api/better-auth-store.js @@ -48,6 +48,7 @@ import { clearAvatarCache, pruneExpiredAvatars, } from '@/primitives/avatarCache.js'; +import { clearAllData } from '@/primitives/db.js'; // LocalStorage keys for offline caching const AUTH_CACHE_KEY = 'corates-auth-cache'; @@ -439,8 +440,9 @@ function createBetterAuthStore() { setCachedUser(null); setCachedAvatarUrl(null); - // Clear cached avatar from IndexedDB - clearAvatarCache(); + // Clear all local data from unified Dexie database + // This includes avatars, PDFs, query cache, form states, and ops queue + await clearAllData(); // Clear all in-memory query cache queryClient.clear(); @@ -824,6 +826,9 @@ function createBetterAuthStore() { // Clear pending email from localStorage (account-specific) localStorage.removeItem('pendingEmail'); + // Sign out from Better Auth session + await authClient.signOut(); + // Use shared cleanup (clears caches, resets state, notifies tabs) await _performSignoutCleanup(); diff --git a/packages/web/src/lib/__tests__/error-utils.test.js b/packages/web/src/lib/__tests__/error-utils.test.js index 55e6f43a7..00975053e 100644 --- a/packages/web/src/lib/__tests__/error-utils.test.js +++ b/packages/web/src/lib/__tests__/error-utils.test.js @@ -139,7 +139,7 @@ describe('handleDomainError', () => { await handleDomainError(error, { setError, showToast: false }); - expect(setError).toHaveBeenCalledWith('Project not found'); + expect(setError).toHaveBeenCalledWith('This project could not be found'); }); it('should navigate on auth errors', async () => { diff --git a/packages/web/src/lib/__tests__/formStatePersistence.test.js b/packages/web/src/lib/__tests__/formStatePersistence.test.js new file mode 100644 index 000000000..b802973c3 --- /dev/null +++ b/packages/web/src/lib/__tests__/formStatePersistence.test.js @@ -0,0 +1,131 @@ +import { beforeEach, describe, expect, it } from 'vitest'; +import 'fake-indexeddb/auto'; +import { db } from '@primitives/db.js'; +import { + saveFormState, + getFormState, + clearFormState, + hasPendingFormState, + cleanupExpiredStates, +} from '../formStatePersistence.js'; + +describe('formStatePersistence', () => { + beforeEach(async () => { + await db.formStates.clear(); + }); + + describe('saveFormState and getFormState', () => { + it('saves and retrieves form state', async () => { + const data = { name: 'Test Project', description: 'A description' }; + + await saveFormState('createProject', data); + + const result = await getFormState('createProject'); + expect(result).toEqual(data); + }); + + it('saves and retrieves form state with projectId', async () => { + const data = { studies: ['study-1', 'study-2'] }; + + await saveFormState('addStudies', data, 'project-123'); + + const result = await getFormState('addStudies', 'project-123'); + expect(result).toEqual(data); + }); + + it('returns null for non-existent form state', async () => { + const result = await getFormState('createProject'); + expect(result).toBeNull(); + }); + + it('overwrites existing form state', async () => { + await saveFormState('createProject', { name: 'Old' }); + await saveFormState('createProject', { name: 'New' }); + + const result = await getFormState('createProject'); + expect(result).toEqual({ name: 'New' }); + }); + + it('keeps separate states for different projectIds', async () => { + await saveFormState('addStudies', { data: 'a' }, 'project-1'); + await saveFormState('addStudies', { data: 'b' }, 'project-2'); + + expect(await getFormState('addStudies', 'project-1')).toEqual({ data: 'a' }); + expect(await getFormState('addStudies', 'project-2')).toEqual({ data: 'b' }); + }); + }); + + describe('clearFormState', () => { + it('clears specific form state', async () => { + await saveFormState('createProject', { name: 'Test' }); + + await clearFormState('createProject'); + + const result = await getFormState('createProject'); + expect(result).toBeNull(); + }); + + it('clears form state with projectId', async () => { + await saveFormState('addStudies', { data: 'test' }, 'project-123'); + + await clearFormState('addStudies', 'project-123'); + + expect(await getFormState('addStudies', 'project-123')).toBeNull(); + }); + }); + + describe('hasPendingFormState', () => { + it('returns true when form state exists', async () => { + await saveFormState('createProject', { name: 'Test' }); + + const result = await hasPendingFormState('createProject'); + expect(result).toBe(true); + }); + + it('returns false when form state does not exist', async () => { + const result = await hasPendingFormState('createProject'); + expect(result).toBe(false); + }); + }); + + describe('cleanupExpiredStates', () => { + it('removes expired form states', async () => { + // Insert an expired state directly (25 hours ago) + const expiredTimestamp = Date.now() - 25 * 60 * 60 * 1000; + await db.formStates.put({ + key: 'createProject', + type: 'createProject', + projectId: null, + data: { name: 'Expired' }, + timestamp: expiredTimestamp, + }); + + // Insert a fresh state + await saveFormState('addStudies', { data: 'Fresh' }, 'project-1'); + + await cleanupExpiredStates(); + + // Expired state should be gone (or return null due to expiry check in getFormState) + expect(await getFormState('createProject')).toBeNull(); + // Fresh state should remain + expect(await getFormState('addStudies', 'project-1')).toEqual({ data: 'Fresh' }); + }); + }); + + describe('expiry behavior', () => { + it('returns null for expired form state', async () => { + // Insert an expired state directly + const expiredTimestamp = Date.now() - 25 * 60 * 60 * 1000; + await db.formStates.put({ + key: 'createProject', + type: 'createProject', + projectId: null, + data: { name: 'Expired' }, + timestamp: expiredTimestamp, + }); + + const result = await getFormState('createProject'); + expect(result).toBeNull(); + }); + }); +}); diff --git a/packages/web/src/lib/__tests__/queryPersister.test.js b/packages/web/src/lib/__tests__/queryPersister.test.js new file mode 100644 index 000000000..3a98475af --- /dev/null +++ b/packages/web/src/lib/__tests__/queryPersister.test.js @@ -0,0 +1,78 @@ +import { beforeEach, describe, expect, it } from 'vitest'; +import 'fake-indexeddb/auto'; +import { db } from '@primitives/db.js'; +import { createIDBPersister } from '../queryPersister.js'; + +describe('queryPersister', () => { + beforeEach(async () => { + await db.queryCache.clear(); + }); + + describe('createIDBPersister', () => { + it('returns persister with required methods', () => { + const persister = createIDBPersister(); + + expect(persister).toHaveProperty('persistClient'); + expect(persister).toHaveProperty('restoreClient'); + expect(persister).toHaveProperty('removeClient'); + expect(typeof persister.persistClient).toBe('function'); + expect(typeof persister.restoreClient).toBe('function'); + expect(typeof persister.removeClient).toBe('function'); + }); + }); + + describe('persistClient', () => { + it('persists client state', async () => { + const persister = createIDBPersister(); + const clientState = { + timestamp: Date.now(), + buster: 'test', + clientState: { + queries: [{ queryKey: ['test'], state: { data: 'hello' } }], + mutations: [], + }, + }; + + await persister.persistClient(clientState); + + const record = await db.queryCache.get('queryClient'); + expect(record).toBeDefined(); + expect(record.data).toEqual(clientState); + }); + }); + + describe('restoreClient', () => { + it('restores persisted client state', async () => { + const persister = createIDBPersister(); + const clientState = { + timestamp: Date.now(), + clientState: { queries: [], mutations: [] }, + }; + + await persister.persistClient(clientState); + const restored = await persister.restoreClient(); + + expect(restored).toEqual(clientState); + }); + + it('returns null when no state persisted', async () => { + const persister = createIDBPersister(); + + const restored = await persister.restoreClient(); + + expect(restored).toBeNull(); + }); + }); + + describe('removeClient', () => { + it('removes persisted client state', async () => { + const persister = createIDBPersister(); + await persister.persistClient({ test: 'data' }); + + await persister.removeClient(); + + const restored = await persister.restoreClient(); + expect(restored).toBeNull(); + }); + }); +}); diff --git a/packages/web/src/lib/formStatePersistence.js b/packages/web/src/lib/formStatePersistence.js index 1d6b7082f..c0093279f 100644 --- a/packages/web/src/lib/formStatePersistence.js +++ b/packages/web/src/lib/formStatePersistence.js @@ -1,33 +1,12 @@ /** * Form State Persistence - * Saves and restores form state across OAuth redirects using IndexedDB. + * Saves and restores form state across OAuth redirects using Dexie. * Handles File/ArrayBuffer serialization for PDF uploads. */ -const DB_NAME = 'corates-form-state'; -const DB_VERSION = 1; -const STORE_NAME = 'pendingForms'; -const MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours - -/** - * Open the IndexedDB database - * @returns {Promise} - */ -function openDB() { - return new Promise((resolve, reject) => { - const request = indexedDB.open(DB_NAME, DB_VERSION); - - request.onerror = () => reject(request.error); - request.onsuccess = () => resolve(request.result); +import { db } from '@primitives/db.js'; - request.onupgradeneeded = event => { - const db = event.target.result; - if (!db.objectStoreNames.contains(STORE_NAME)) { - db.createObjectStore(STORE_NAME, { keyPath: 'key' }); - } - }; - }); -} +const MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours /** * Generate a storage key based on form type and optional project ID @@ -40,128 +19,53 @@ function getKey(type, projectId) { } /** - * Save form state to IndexedDB + * Save form state to Dexie * @param {'createProject' | 'addStudies'} type - Form type * @param {Object} data - Form state data (should already be serializable) * @param {string} [projectId] - Project ID for add-studies form * @returns {Promise} */ export async function saveFormState(type, data, projectId) { - const db = await openDB(); const key = getKey(type, projectId); - return new Promise((resolve, reject) => { - const tx = db.transaction(STORE_NAME, 'readwrite'); - const store = tx.objectStore(STORE_NAME); - - const record = { - key, - type, - projectId: projectId ?? null, - data, - timestamp: Date.now(), - }; - - store.put(record); - - tx.oncomplete = () => { - db.close(); - resolve(); - }; - - tx.onerror = () => { - db.close(); - reject(tx.error); - }; - - tx.onabort = () => { - db.close(); - reject(tx.error); - }; + await db.formStates.put({ + key, + type, + projectId: projectId ?? null, + data, + timestamp: Date.now(), }); } /** - * Get saved form state from IndexedDB + * Get saved form state from Dexie * @param {'createProject' | 'addStudies'} type - Form type * @param {string} [projectId] - Project ID for add-studies form * @returns {Promise} - The saved data or null if not found/expired */ export async function getFormState(type, projectId) { - const db = await openDB(); const key = getKey(type, projectId); + const record = await db.formStates.get(key); - return new Promise((resolve, reject) => { - const tx = db.transaction(STORE_NAME, 'readonly'); - const store = tx.objectStore(STORE_NAME); - - let result = null; - - const request = store.get(key); - request.onerror = () => { - tx.abort(); - }; - request.onsuccess = () => { - const record = request.result; - - if (!record || Date.now() - record.timestamp > MAX_AGE_MS) { - if (record) { - clearFormState(type, projectId).catch(() => {}); - } - result = null; - } else { - result = record.data; - } - }; + if (!record) return null; - tx.oncomplete = () => { - db.close(); - resolve(result); - }; - - tx.onerror = () => { - db.close(); - reject(tx.error); - }; + if (Date.now() - record.timestamp > MAX_AGE_MS) { + clearFormState(type, projectId).catch(() => {}); + return null; + } - tx.onabort = () => { - db.close(); - reject(tx.error); - }; - }); + return record.data; } /** - * Clear saved form state from IndexedDB + * Clear saved form state from Dexie * @param {'createProject' | 'addStudies'} type - Form type * @param {string} [projectId] - Project ID for add-studies form * @returns {Promise} */ export async function clearFormState(type, projectId) { - const db = await openDB(); const key = getKey(type, projectId); - - return new Promise((resolve, reject) => { - const tx = db.transaction(STORE_NAME, 'readwrite'); - const store = tx.objectStore(STORE_NAME); - - store.delete(key); - - tx.oncomplete = () => { - db.close(); - resolve(); - }; - - tx.onerror = () => { - db.close(); - reject(tx.error); - }; - - tx.onabort = () => { - db.close(); - reject(tx.error); - }; - }); + await db.formStates.delete(key); } /** @@ -230,43 +134,6 @@ export function clearRestoreParamsFromUrl() { * @returns {Promise} */ export async function cleanupExpiredStates() { - const db = await openDB(); - - return new Promise((resolve, reject) => { - const tx = db.transaction(STORE_NAME, 'readwrite'); - const store = tx.objectStore(STORE_NAME); - - const now = Date.now(); - const request = store.openCursor(); - - request.onerror = () => { - tx.abort(); - }; - - request.onsuccess = event => { - const cursor = event.target.result; - if (cursor) { - const record = cursor.value; - if (now - record.timestamp > MAX_AGE_MS) { - cursor.delete(); - } - cursor.continue(); - } - }; - - tx.oncomplete = () => { - db.close(); - resolve(); - }; - - tx.onerror = () => { - db.close(); - reject(tx.error); - }; - - tx.onabort = () => { - db.close(); - reject(tx.error); - }; - }); + const expiryThreshold = Date.now() - MAX_AGE_MS; + await db.formStates.where('timestamp').below(expiryThreshold).delete(); } diff --git a/packages/web/src/lib/queryPersister.js b/packages/web/src/lib/queryPersister.js index 9a37cedb0..75d734712 100644 --- a/packages/web/src/lib/queryPersister.js +++ b/packages/web/src/lib/queryPersister.js @@ -1,79 +1,54 @@ /** - * TanStack Query IndexedDB Persister + * TanStack Query Dexie Persister * - * Persists query cache to IndexedDB for local-first offline support. + * Persists query cache to Dexie for local-first offline support. */ -import { openDB } from 'idb'; +import { db } from '@primitives/db.js'; -const DB_NAME = 'corates-query-cache'; -const DB_VERSION = 1; -const STORE_NAME = 'queryCache'; const CACHE_KEY = 'queryClient'; -// Shared database instance promise -let dbPromise = null; - -/** - * Get or create the IndexedDB database - */ -function getDB() { - if (!dbPromise) { - dbPromise = openDB(DB_NAME, DB_VERSION, { - upgrade(db) { - if (!db.objectStoreNames.contains(STORE_NAME)) { - db.createObjectStore(STORE_NAME); - } - }, - }); - } - return dbPromise; -} - /** - * Create an IndexedDB persister for TanStack Query + * Create a Dexie persister for TanStack Query * Implements the persister interface expected by TanStack Query * @returns {Object} Persister object with persistClient, restoreClient, removeClient methods */ export function createIDBPersister() { return { /** - * Persist query client state to IndexedDB + * Persist query client state to Dexie * @param {Object} client - The persisted client state */ persistClient: async client => { try { - const db = await getDB(); - await db.put(STORE_NAME, client, CACHE_KEY); + await db.queryCache.put({ key: CACHE_KEY, data: client }); } catch (error) { - console.error('Failed to persist query client to IndexedDB:', error); + console.error('Failed to persist query client to Dexie:', error); } }, /** - * Restore query client state from IndexedDB + * Restore query client state from Dexie * @returns {Promise} The persisted client state or null */ restoreClient: async () => { try { - const db = await getDB(); - const client = await db.get(STORE_NAME, CACHE_KEY); - return client || null; + const record = await db.queryCache.get(CACHE_KEY); + return record?.data || null; } catch (error) { - console.error('Failed to restore query client from IndexedDB:', error); + console.error('Failed to restore query client from Dexie:', error); return null; } }, /** - * Remove persisted query client state from IndexedDB + * Remove persisted query client state from Dexie */ removeClient: async () => { try { - const db = await getDB(); - await db.delete(STORE_NAME, CACHE_KEY); + await db.queryCache.delete(CACHE_KEY); } catch (error) { - console.error('Failed to remove query client from IndexedDB:', error); + console.error('Failed to remove query client from Dexie:', error); } }, }; diff --git a/packages/web/src/primitives/__tests__/avatarCache.test.js b/packages/web/src/primitives/__tests__/avatarCache.test.js new file mode 100644 index 000000000..d1fde4db7 --- /dev/null +++ b/packages/web/src/primitives/__tests__/avatarCache.test.js @@ -0,0 +1,92 @@ +import { beforeEach, describe, expect, it } from 'vitest'; +import 'fake-indexeddb/auto'; +import { db } from '../db.js'; +import { + getCachedAvatar, + cacheAvatar, + removeCachedAvatar, + clearAvatarCache, + pruneExpiredAvatars, +} from '../avatarCache.js'; + +describe('avatarCache', () => { + beforeEach(async () => { + await db.avatars.clear(); + }); + + describe('cacheAvatar and getCachedAvatar', () => { + it('caches and retrieves avatar', async () => { + const dataUrl = 'data:image/png;base64,abc123'; + + await cacheAvatar('user-1', dataUrl); + + const result = await getCachedAvatar('user-1'); + expect(result).toBe(dataUrl); + }); + + it('returns null for non-existent user', async () => { + const result = await getCachedAvatar('nonexistent'); + expect(result).toBeNull(); + }); + + it('returns null for null/undefined userId', async () => { + expect(await getCachedAvatar(null)).toBeNull(); + expect(await getCachedAvatar(undefined)).toBeNull(); + }); + + it('overwrites existing avatar', async () => { + await cacheAvatar('user-1', 'data:image/png;base64,old'); + await cacheAvatar('user-1', 'data:image/png;base64,new'); + + const result = await getCachedAvatar('user-1'); + expect(result).toBe('data:image/png;base64,new'); + }); + }); + + describe('removeCachedAvatar', () => { + it('removes a cached avatar', async () => { + await cacheAvatar('user-1', 'data:image/png;base64,abc'); + + await removeCachedAvatar('user-1'); + + const result = await getCachedAvatar('user-1'); + expect(result).toBeNull(); + }); + + it('handles removing non-existent avatar gracefully', async () => { + await removeCachedAvatar('nonexistent'); + }); + }); + + describe('clearAvatarCache', () => { + it('clears all cached avatars', async () => { + await cacheAvatar('user-1', 'data:image/png;base64,a'); + await cacheAvatar('user-2', 'data:image/png;base64,b'); + + await clearAvatarCache(); + + expect(await getCachedAvatar('user-1')).toBeNull(); + expect(await getCachedAvatar('user-2')).toBeNull(); + }); + }); + + describe('pruneExpiredAvatars', () => { + it('removes expired avatars', async () => { + // Insert an "expired" avatar directly + const thirtyOneDaysAgo = Date.now() - 31 * 24 * 60 * 60 * 1000; + await db.avatars.put({ + userId: 'old-user', + dataUrl: 'data:image/png;base64,old', + cachedAt: thirtyOneDaysAgo, + }); + + // Insert a fresh avatar + await cacheAvatar('new-user', 'data:image/png;base64,new'); + + await pruneExpiredAvatars(); + + expect(await getCachedAvatar('old-user')).toBeNull(); + expect(await getCachedAvatar('new-user')).toBe('data:image/png;base64,new'); + }); + }); +}); diff --git a/packages/web/src/primitives/__tests__/db.test.js b/packages/web/src/primitives/__tests__/db.test.js new file mode 100644 index 000000000..8577abf2f --- /dev/null +++ b/packages/web/src/primitives/__tests__/db.test.js @@ -0,0 +1,374 @@ +/** + * Tests for db.js - Unified Dexie database + * + * Phase 1 of Dexie migration: Verify database schema and basic operations + */ + +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import 'fake-indexeddb/auto'; + +// Reset the database before importing to get a fresh instance +let db, deleteProjectData, clearAllData; + +describe('db.js - Unified Dexie Database', () => { + beforeEach(async () => { + // Import db instance and helper functions + // Test isolation achieved via afterEach cleanup (deleteProjectData/clearAllData) + const module = await import('../db.js'); + db = module.db; + deleteProjectData = module.deleteProjectData; + clearAllData = module.clearAllData; + + // Ensure database is open + if (!db.isOpen()) { + await db.open(); + } + }); + + afterEach(async () => { + // Clear all data between tests + if (db.isOpen()) { + await db.projects.clear(); + await db.pdfs.clear(); + await db.ops.clear(); + await db.avatars.clear(); + await db.formStates.clear(); + await db.localChecklists.clear(); + await db.localChecklistPdfs.clear(); + await db.queryCache.clear(); + } + }); + + describe('Database Initialization', () => { + it('should open database successfully', () => { + expect(db.isOpen()).toBe(true); + expect(db.name).toBe('corates'); + }); + + it('should have all expected tables', () => { + // y-dexie creates internal tables for Y.Doc updates (prefixed with $) + const userTables = db.tables + .map(t => t.name) + .filter(n => !n.startsWith('$')) + .sort(); + expect(userTables).toEqual([ + 'avatars', + 'formStates', + 'localChecklistPdfs', + 'localChecklists', + 'ops', + 'pdfs', + 'projects', + 'queryCache', + ]); + }); + + it('should be at version 1', () => { + expect(db.verno).toBe(1); + }); + }); + + describe('Projects Table', () => { + it('should add and retrieve a project', async () => { + const project = { + id: 'proj-123', + orgId: 'org-456', + updatedAt: Date.now(), + }; + + await db.projects.add(project); + const retrieved = await db.projects.get('proj-123'); + + expect(retrieved.id).toBe('proj-123'); + expect(retrieved.orgId).toBe('org-456'); + }); + + it('should query projects by orgId', async () => { + await db.projects.bulkAdd([ + { id: 'proj-1', orgId: 'org-A', updatedAt: 1 }, + { id: 'proj-2', orgId: 'org-A', updatedAt: 2 }, + { id: 'proj-3', orgId: 'org-B', updatedAt: 3 }, + ]); + + const orgAProjects = await db.projects.where('orgId').equals('org-A').toArray(); + + expect(orgAProjects).toHaveLength(2); + expect(orgAProjects.map(p => p.id).sort()).toEqual(['proj-1', 'proj-2']); + }); + }); + + describe('PDFs Table', () => { + it('should add and retrieve a PDF cache entry', async () => { + const pdfEntry = { + id: 'proj-1:study-1:test.pdf', + projectId: 'proj-1', + studyId: 'study-1', + fileName: 'test.pdf', + data: new ArrayBuffer(100), + size: 100, + cachedAt: Date.now(), + }; + + await db.pdfs.add(pdfEntry); + const retrieved = await db.pdfs.get('proj-1:study-1:test.pdf'); + + expect(retrieved.projectId).toBe('proj-1'); + expect(retrieved.studyId).toBe('study-1'); + expect(retrieved.fileName).toBe('test.pdf'); + expect(retrieved.size).toBe(100); + }); + + it('should query PDFs by projectId', async () => { + await db.pdfs.bulkAdd([ + { + id: 'proj-1:study-1:a.pdf', + projectId: 'proj-1', + studyId: 'study-1', + fileName: 'a.pdf', + data: new ArrayBuffer(10), + size: 10, + cachedAt: 1, + }, + { + id: 'proj-1:study-2:b.pdf', + projectId: 'proj-1', + studyId: 'study-2', + fileName: 'b.pdf', + data: new ArrayBuffer(20), + size: 20, + cachedAt: 2, + }, + { + id: 'proj-2:study-1:c.pdf', + projectId: 'proj-2', + studyId: 'study-1', + fileName: 'c.pdf', + data: new ArrayBuffer(30), + size: 30, + cachedAt: 3, + }, + ]); + + const proj1Pdfs = await db.pdfs.where('projectId').equals('proj-1').toArray(); + + expect(proj1Pdfs).toHaveLength(2); + expect(proj1Pdfs.map(p => p.fileName).sort()).toEqual(['a.pdf', 'b.pdf']); + }); + + it('should order PDFs by cachedAt for LRU eviction', async () => { + await db.pdfs.bulkAdd([ + { + id: 'p:s:newest.pdf', + projectId: 'p', + studyId: 's', + fileName: 'newest.pdf', + data: new ArrayBuffer(10), + size: 10, + cachedAt: 3000, + }, + { + id: 'p:s:oldest.pdf', + projectId: 'p', + studyId: 's', + fileName: 'oldest.pdf', + data: new ArrayBuffer(10), + size: 10, + cachedAt: 1000, + }, + { + id: 'p:s:middle.pdf', + projectId: 'p', + studyId: 's', + fileName: 'middle.pdf', + data: new ArrayBuffer(10), + size: 10, + cachedAt: 2000, + }, + ]); + + const ordered = await db.pdfs.orderBy('cachedAt').toArray(); + + expect(ordered.map(p => p.fileName)).toEqual(['oldest.pdf', 'middle.pdf', 'newest.pdf']); + }); + }); + + describe('Ops Table (Operation Queue)', () => { + it('should add operation with auto-increment id', async () => { + const op = { + idempotencyKey: 'key-123', + endpoint: '/api/projects', + payload: { name: 'Test' }, + status: 'pending', + createdAt: Date.now(), + attempts: 0, + }; + + const id = await db.ops.add(op); + const retrieved = await db.ops.get(id); + + expect(retrieved.id).toBe(id); + expect(retrieved.idempotencyKey).toBe('key-123'); + expect(retrieved.status).toBe('pending'); + }); + + it('should query pending operations', async () => { + await db.ops.bulkAdd([ + { + idempotencyKey: 'k1', + endpoint: '/api/a', + payload: {}, + status: 'pending', + createdAt: 1, + attempts: 0, + }, + { + idempotencyKey: 'k2', + endpoint: '/api/b', + payload: {}, + status: 'applied', + createdAt: 2, + attempts: 1, + }, + { + idempotencyKey: 'k3', + endpoint: '/api/c', + payload: {}, + status: 'pending', + createdAt: 3, + attempts: 0, + }, + ]); + + const pending = await db.ops.where('status').equals('pending').toArray(); + + expect(pending).toHaveLength(2); + expect(pending.map(o => o.idempotencyKey).sort()).toEqual(['k1', 'k3']); + }); + + it('should query pending ops sorted by createdAt using compound index', async () => { + await db.ops.bulkAdd([ + { + idempotencyKey: 'k3', + endpoint: '/api/c', + payload: {}, + status: 'pending', + createdAt: 3000, + attempts: 0, + }, + { + idempotencyKey: 'k1', + endpoint: '/api/a', + payload: {}, + status: 'pending', + createdAt: 1000, + attempts: 0, + }, + { + idempotencyKey: 'k2', + endpoint: '/api/b', + payload: {}, + status: 'pending', + createdAt: 2000, + attempts: 0, + }, + ]); + + const pending = await db.ops.where('status').equals('pending').sortBy('createdAt'); + + expect(pending.map(o => o.idempotencyKey)).toEqual(['k1', 'k2', 'k3']); + }); + + it('should update operation status', async () => { + const id = await db.ops.add({ + idempotencyKey: 'k1', + endpoint: '/api/test', + payload: {}, + status: 'pending', + createdAt: Date.now(), + attempts: 0, + }); + + await db.ops.update(id, { status: 'syncing', attempts: 1 }); + const updated = await db.ops.get(id); + + expect(updated.status).toBe('syncing'); + expect(updated.attempts).toBe(1); + }); + }); + + describe('deleteProjectData', () => { + it('should delete project and associated PDFs', async () => { + await db.projects.add({ id: 'proj-to-delete', orgId: 'org-1', updatedAt: 1 }); + await db.projects.add({ id: 'proj-to-keep', orgId: 'org-1', updatedAt: 2 }); + + await db.pdfs.bulkAdd([ + { + id: 'proj-to-delete:s1:a.pdf', + projectId: 'proj-to-delete', + studyId: 's1', + fileName: 'a.pdf', + data: new ArrayBuffer(10), + size: 10, + cachedAt: 1, + }, + { + id: 'proj-to-delete:s2:b.pdf', + projectId: 'proj-to-delete', + studyId: 's2', + fileName: 'b.pdf', + data: new ArrayBuffer(10), + size: 10, + cachedAt: 2, + }, + { + id: 'proj-to-keep:s1:c.pdf', + projectId: 'proj-to-keep', + studyId: 's1', + fileName: 'c.pdf', + data: new ArrayBuffer(10), + size: 10, + cachedAt: 3, + }, + ]); + + await deleteProjectData('proj-to-delete'); + + const projects = await db.projects.toArray(); + expect(projects).toHaveLength(1); + expect(projects[0].id).toBe('proj-to-keep'); + + const pdfs = await db.pdfs.toArray(); + expect(pdfs).toHaveLength(1); + expect(pdfs[0].projectId).toBe('proj-to-keep'); + }); + }); + + describe('clearAllData', () => { + it('should clear all tables', async () => { + await db.projects.add({ id: 'p1', orgId: 'o1', updatedAt: 1 }); + await db.pdfs.add({ + id: 'p1:s1:a.pdf', + projectId: 'p1', + studyId: 's1', + fileName: 'a.pdf', + data: new ArrayBuffer(10), + size: 10, + cachedAt: 1, + }); + await db.ops.add({ + idempotencyKey: 'k1', + endpoint: '/api/test', + payload: {}, + status: 'pending', + createdAt: 1, + attempts: 0, + }); + + await clearAllData(); + + expect(await db.projects.count()).toBe(0); + expect(await db.pdfs.count()).toBe(0); + expect(await db.ops.count()).toBe(0); + }); + }); +}); diff --git a/packages/web/src/primitives/__tests__/pdfCache.test.js b/packages/web/src/primitives/__tests__/pdfCache.test.js new file mode 100644 index 000000000..c29374d48 --- /dev/null +++ b/packages/web/src/primitives/__tests__/pdfCache.test.js @@ -0,0 +1,153 @@ +import { beforeEach, describe, expect, it } from 'vitest'; +import 'fake-indexeddb/auto'; +import { db } from '../db.js'; +import { + cachePdf, + getCachedPdf, + removeCachedPdf, + clearStudyCache, + clearProjectCache, + getCacheSize, +} from '../pdfCache.js'; + +describe('pdfCache', () => { + beforeEach(async () => { + await db.pdfs.clear(); + }); + + describe('cachePdf and getCachedPdf', () => { + it('caches and retrieves PDF data', async () => { + const data = new ArrayBuffer(100); + new Uint8Array(data).fill(42); + + const result = await cachePdf('project-1', 'study-1', 'test.pdf', data); + expect(result).toBe(true); + + const retrieved = await getCachedPdf('project-1', 'study-1', 'test.pdf'); + expect(retrieved).not.toBeNull(); + expect(retrieved.byteLength).toBe(100); + expect(new Uint8Array(retrieved)[0]).toBe(42); + }); + + it('returns null for non-existent cache entry', async () => { + const result = await getCachedPdf('project-1', 'study-1', 'nonexistent.pdf'); + expect(result).toBeNull(); + }); + + it('overwrites existing cache entry', async () => { + const data1 = new ArrayBuffer(100); + new Uint8Array(data1).fill(1); + + const data2 = new ArrayBuffer(200); + new Uint8Array(data2).fill(2); + + await cachePdf('project-1', 'study-1', 'test.pdf', data1); + await cachePdf('project-1', 'study-1', 'test.pdf', data2); + + const retrieved = await getCachedPdf('project-1', 'study-1', 'test.pdf'); + expect(retrieved.byteLength).toBe(200); + expect(new Uint8Array(retrieved)[0]).toBe(2); + }); + + it('rejects files exceeding single file limit', async () => { + const largeData = new ArrayBuffer(51 * 1024 * 1024); // 51MB + + const result = await cachePdf('project-1', 'study-1', 'huge.pdf', largeData); + expect(result).toBe(false); + + const retrieved = await getCachedPdf('project-1', 'study-1', 'huge.pdf'); + expect(retrieved).toBeNull(); + }); + }); + + describe('removeCachedPdf', () => { + it('removes a cached PDF', async () => { + const data = new ArrayBuffer(100); + + await cachePdf('project-1', 'study-1', 'test.pdf', data); + const result = await removeCachedPdf('project-1', 'study-1', 'test.pdf'); + expect(result).toBe(true); + + const retrieved = await getCachedPdf('project-1', 'study-1', 'test.pdf'); + expect(retrieved).toBeNull(); + }); + + it('returns true even when entry does not exist', async () => { + const result = await removeCachedPdf('project-1', 'study-1', 'nonexistent.pdf'); + expect(result).toBe(true); + }); + }); + + describe('clearStudyCache', () => { + it('clears all PDFs for a specific study', async () => { + const data = new ArrayBuffer(100); + + await cachePdf('project-1', 'study-1', 'file1.pdf', data); + await cachePdf('project-1', 'study-1', 'file2.pdf', data); + await cachePdf('project-1', 'study-2', 'file3.pdf', data); + + const deleted = await clearStudyCache('project-1', 'study-1'); + expect(deleted).toBe(2); + + expect(await getCachedPdf('project-1', 'study-1', 'file1.pdf')).toBeNull(); + expect(await getCachedPdf('project-1', 'study-1', 'file2.pdf')).toBeNull(); + expect(await getCachedPdf('project-1', 'study-2', 'file3.pdf')).not.toBeNull(); + }); + }); + + describe('clearProjectCache', () => { + it('clears all PDFs for a specific project', async () => { + const data = new ArrayBuffer(100); + + await cachePdf('project-1', 'study-1', 'file1.pdf', data); + await cachePdf('project-1', 'study-2', 'file2.pdf', data); + await cachePdf('project-2', 'study-1', 'file3.pdf', data); + + const deleted = await clearProjectCache('project-1'); + expect(deleted).toBe(2); + + expect(await getCachedPdf('project-1', 'study-1', 'file1.pdf')).toBeNull(); + expect(await getCachedPdf('project-1', 'study-2', 'file2.pdf')).toBeNull(); + expect(await getCachedPdf('project-2', 'study-1', 'file3.pdf')).not.toBeNull(); + }); + }); + + describe('getCacheSize', () => { + it('returns 0 for empty cache', async () => { + const size = await getCacheSize(); + expect(size).toBe(0); + }); + + it('returns total size of all cached PDFs', async () => { + const data1 = new ArrayBuffer(1000); + const data2 = new ArrayBuffer(2000); + + await cachePdf('project-1', 'study-1', 'file1.pdf', data1); + await cachePdf('project-1', 'study-2', 'file2.pdf', data2); + + const size = await getCacheSize(); + expect(size).toBe(3000); + }); + }); + + describe('LRU eviction', () => { + it('evicts oldest entries when cache limit exceeded', async () => { + // Cache limit is 200MB, so we test with smaller files but verify ordering + const data = new ArrayBuffer(1000); + + // Cache multiple entries with different timestamps + await cachePdf('project-1', 'study-1', 'old.pdf', data); + await new Promise(r => setTimeout(r, 10)); // Small delay for cachedAt difference + await cachePdf('project-1', 'study-2', 'newer.pdf', data); + + // Verify both are cached + expect(await getCachedPdf('project-1', 'study-1', 'old.pdf')).not.toBeNull(); + expect(await getCachedPdf('project-1', 'study-2', 'newer.pdf')).not.toBeNull(); + + // Verify ordering by cachedAt + const entries = await db.pdfs.orderBy('cachedAt').toArray(); + expect(entries[0].fileName).toBe('old.pdf'); + expect(entries[1].fileName).toBe('newer.pdf'); + }); + }); +}); diff --git a/packages/web/src/primitives/avatarCache.js b/packages/web/src/primitives/avatarCache.js index 72848fe41..198d667a0 100644 --- a/packages/web/src/primitives/avatarCache.js +++ b/packages/web/src/primitives/avatarCache.js @@ -1,17 +1,14 @@ /** * avatarCache - Local caching layer for user avatars * - * This provides offline access to avatar images by storing them in IndexedDB. + * This provides offline access to avatar images by storing them in Dexie. * When online, avatars are fetched from the API and cached locally. * When offline, the cached version is used. */ import { API_BASE } from '@config/api.js'; import { compressImageBlob } from '@lib/imageUtils.js'; - -const DB_NAME = 'corates-avatar-cache'; -const DB_VERSION = 1; -const AVATAR_STORE_NAME = 'avatars'; +import { db } from './db.js'; // Cache expiry: 30 days in milliseconds const CACHE_EXPIRY_MS = 30 * 24 * 60 * 60 * 1000; @@ -25,50 +22,6 @@ const externalFetchFailures = new Map(); // url -> { failedAt, retryAfter } const EXTERNAL_RETRY_DELAY_MS = 60 * 1000; // Wait 1 minute before retrying failed external fetches const MAX_RETRY_DELAY_MS = 5 * 60 * 1000; // Max 5 minutes between retries -// Shared database instance and initialization promise -let dbInstance = null; -let dbInitPromise = null; - -/** - * Open the IndexedDB database (singleton pattern) - */ -function openDatabase() { - if (dbInitPromise) return dbInitPromise; - - dbInitPromise = new Promise((resolve, reject) => { - if (typeof indexedDB === 'undefined') { - reject(new Error('IndexedDB not available')); - return; - } - - const request = indexedDB.open(DB_NAME, DB_VERSION); - - request.onerror = () => reject(request.error); - request.onsuccess = () => { - dbInstance = request.result; - resolve(dbInstance); - }; - - request.onupgradeneeded = event => { - const db = event.target.result; - if (!db.objectStoreNames.contains(AVATAR_STORE_NAME)) { - const store = db.createObjectStore(AVATAR_STORE_NAME, { keyPath: 'userId' }); - store.createIndex('cachedAt', 'cachedAt', { unique: false }); - } - }; - }); - - return dbInitPromise; -} - -/** - * Get database instance - */ -async function getDb() { - if (dbInstance) return dbInstance; - return openDatabase(); -} - /** * Convert a blob to a base64 data URL */ @@ -90,22 +43,8 @@ export async function getCachedAvatar(userId) { if (!userId) return null; try { - const db = await getDb(); - const tx = db.transaction(AVATAR_STORE_NAME, 'readonly'); - const store = tx.objectStore(AVATAR_STORE_NAME); - - return new Promise((resolve, reject) => { - const request = store.get(userId); - request.onsuccess = () => { - const result = request.result; - if (result?.dataUrl) { - resolve(result.dataUrl); - } else { - resolve(null); - } - }; - request.onerror = () => reject(request.error); - }); + const record = await db.avatars.get(userId); + return record?.dataUrl ?? null; } catch (err) { console.error('Error getting cached avatar:', err); return null; @@ -121,18 +60,10 @@ export async function cacheAvatar(userId, dataUrl) { if (!userId || !dataUrl) return; try { - const db = await getDb(); - const tx = db.transaction(AVATAR_STORE_NAME, 'readwrite'); - const store = tx.objectStore(AVATAR_STORE_NAME); - - await new Promise((resolve, reject) => { - const request = store.put({ - userId, - dataUrl, - cachedAt: Date.now(), - }); - request.onsuccess = () => resolve(); - request.onerror = () => reject(request.error); + await db.avatars.put({ + userId, + dataUrl, + cachedAt: Date.now(), }); } catch (err) { console.error('Error caching avatar:', err); @@ -147,15 +78,7 @@ export async function removeCachedAvatar(userId) { if (!userId) return; try { - const db = await getDb(); - const tx = db.transaction(AVATAR_STORE_NAME, 'readwrite'); - const store = tx.objectStore(AVATAR_STORE_NAME); - - await new Promise((resolve, reject) => { - const request = store.delete(userId); - request.onsuccess = () => resolve(); - request.onerror = () => reject(request.error); - }); + await db.avatars.delete(userId); } catch (err) { console.error('Error removing cached avatar:', err); } @@ -311,15 +234,7 @@ export async function getAvatarWithCache(userId, imageUrl) { */ export async function clearAvatarCache() { try { - const db = await getDb(); - const tx = db.transaction(AVATAR_STORE_NAME, 'readwrite'); - const store = tx.objectStore(AVATAR_STORE_NAME); - - await new Promise((resolve, reject) => { - const request = store.clear(); - request.onsuccess = () => resolve(); - request.onerror = () => reject(request.error); - }); + await db.avatars.clear(); } catch (err) { console.error('Error clearing avatar cache:', err); } @@ -331,30 +246,8 @@ export async function clearAvatarCache() { */ export async function pruneExpiredAvatars() { try { - const db = await getDb(); - const tx = db.transaction(AVATAR_STORE_NAME, 'readwrite'); - const store = tx.objectStore(AVATAR_STORE_NAME); - const index = store.index('cachedAt'); - const expiryThreshold = Date.now() - CACHE_EXPIRY_MS; - - // Get all entries older than the threshold using the cachedAt index - // eslint-disable-next-line no-undef - const range = IDBKeyRange.upperBound(expiryThreshold); - - await new Promise((resolve, reject) => { - const request = index.openCursor(range); - request.onsuccess = event => { - const cursor = event.target.result; - if (cursor) { - cursor.delete(); - cursor.continue(); - } else { - resolve(); - } - }; - request.onerror = () => reject(request.error); - }); + await db.avatars.where('cachedAt').below(expiryThreshold).delete(); } catch (err) { console.error('Error pruning expired avatars:', err); } diff --git a/packages/web/src/primitives/db.js b/packages/web/src/primitives/db.js new file mode 100644 index 000000000..bb6ef44f1 --- /dev/null +++ b/packages/web/src/primitives/db.js @@ -0,0 +1,188 @@ +/** + * Unified Dexie database for CoRATES client-side storage + * + * This module provides a single IndexedDB database for all local data: + * - Project Y.Doc persistence (via y-dexie) + * - PDF cache for offline access + * - Operation queue for offline mutations + * + * @see packages/docs/plans/dexie-migration.md + */ + +import Dexie from 'dexie'; +import yDexie from 'y-dexie'; + +/** + * @typedef {import('yjs').Doc} YDoc + */ + +/** + * Project row with Y.Doc for collaborative data + * @typedef {Object} ProjectRow + * @property {string} id - Project ID (primary key) + * @property {string} orgId - Organization ID + * @property {number} updatedAt - Last update timestamp + * @property {YDoc} ydoc - Y.Doc for project collaborative data + */ + +/** + * PDF cache entry + * @typedef {Object} PdfCacheRow + * @property {string} id - Composite key: projectId:studyId:fileName + * @property {string} projectId - Project ID + * @property {string} studyId - Study ID + * @property {string} fileName - PDF file name + * @property {ArrayBuffer} data - PDF binary data + * @property {number} size - Size in bytes + * @property {number} cachedAt - Cache timestamp + */ + +/** + * Operation queue entry for offline mutations + * @typedef {Object} OpQueueRow + * @property {number} [id] - Auto-incremented ID + * @property {string} idempotencyKey - Unique key for server replay + * @property {string} endpoint - API endpoint + * @property {unknown} payload - Operation payload + * @property {'pending'|'syncing'|'applied'|'failed'} status - Operation status + * @property {number} createdAt - Creation timestamp + * @property {number} attempts - Number of sync attempts + * @property {number} [lastAttempt] - Last attempt timestamp + * @property {string} [error] - Error message if failed + */ + +/** + * Avatar cache entry + * @typedef {Object} AvatarRow + * @property {string} userId - User ID (primary key) + * @property {string} dataUrl - Base64 data URL of avatar image + * @property {number} cachedAt - Cache timestamp + */ + +/** + * Form state persistence entry (for OAuth redirect preservation) + * @typedef {Object} FormStateRow + * @property {string} key - Storage key (type or type:projectId) + * @property {'createProject'|'addStudies'} type - Form type + * @property {string|null} projectId - Associated project ID (for addStudies) + * @property {unknown} data - Serialized form data + * @property {number} timestamp - Save timestamp + */ + +/** + * Local checklist entry (for offline practice mode) + * @typedef {Object} LocalChecklistRow + * @property {string} id - Checklist ID (local-{uuid}) + * @property {string} name - Checklist name + * @property {string} type - Checklist type (AMSTAR2, ROBINS-I, etc.) + * @property {Object} data - Checklist data + * @property {number} createdAt - Creation timestamp + * @property {number} updatedAt - Last update timestamp + */ + +/** + * Local checklist PDF entry + * @typedef {Object} LocalChecklistPdfRow + * @property {string} checklistId - Associated checklist ID (primary key) + * @property {ArrayBuffer} data - PDF binary data + * @property {string} fileName - Original file name + * @property {number} updatedAt - Last update timestamp + */ + +/** + * TanStack Query cache entry + * @typedef {Object} QueryCacheRow + * @property {string} key - Cache key (primary key) + * @property {unknown} data - Serialized query client state + */ + +/** + * CoRATES unified database + * @extends Dexie + */ +class CoratesDB extends Dexie { + /** @type {Dexie.Table} */ + projects; + + /** @type {Dexie.Table} */ + pdfs; + + /** @type {Dexie.Table} */ + ops; + + /** @type {Dexie.Table} */ + avatars; + + /** @type {Dexie.Table} */ + formStates; + + /** @type {Dexie.Table} */ + localChecklists; + + /** @type {Dexie.Table} */ + localChecklistPdfs; + + /** @type {Dexie.Table} */ + queryCache; + + constructor() { + super('corates', { addons: [yDexie] }); + + this.version(1).stores({ + // Y.Doc stored as 'ydoc' property via y-dexie + projects: 'id, orgId, updatedAt, ydoc: Y.Doc', + // PDF cache with LRU eviction by cachedAt + pdfs: 'id, projectId, studyId, cachedAt', + // Operation queue with compound index for efficient pending queries + ops: '++id, idempotencyKey, status, createdAt, [status+createdAt]', + // Avatar cache with expiry by cachedAt + avatars: 'userId, cachedAt', + // Form state persistence for OAuth redirects + formStates: 'key, type, timestamp', + // Local checklists for offline practice + localChecklists: 'id, createdAt, updatedAt', + // PDFs associated with local checklists + localChecklistPdfs: 'checklistId, updatedAt', + // TanStack Query cache persistence + queryCache: 'key', + }); + } +} + +/** + * Singleton database instance + * @type {CoratesDB} + */ +export const db = new CoratesDB(); + +/** + * Delete all data for a specific project + * Used when user is removed from a project or project is deleted + * @param {string} projectId - Project ID to clean up + */ +export async function deleteProjectData(projectId) { + await db.transaction('rw', [db.projects, db.pdfs], async () => { + await db.projects.delete(projectId); + await db.pdfs.where('projectId').equals(projectId).delete(); + }); +} + +/** + * Clear all local data (e.g., on logout) + * Note: localChecklists and localChecklistPdfs are intentionally NOT cleared + * as they are user's local practice data not tied to authentication + */ +export async function clearAllData() { + await db.transaction( + 'rw', + [db.projects, db.pdfs, db.ops, db.avatars, db.formStates, db.queryCache], + async () => { + await db.projects.clear(); + await db.pdfs.clear(); + await db.ops.clear(); + await db.avatars.clear(); + await db.formStates.clear(); + await db.queryCache.clear(); + }, + ); +} diff --git a/packages/web/src/primitives/pdfCache.js b/packages/web/src/primitives/pdfCache.js index a1dd31f01..51d7c11bb 100644 --- a/packages/web/src/primitives/pdfCache.js +++ b/packages/web/src/primitives/pdfCache.js @@ -1,5 +1,5 @@ /** - * pdfCache - Local-first PDF caching layer using IndexedDB + * pdfCache - Local-first PDF caching layer using Dexie * * This provides a cache for PDFs stored in cloud (R2) to enable: * - Fast loading from local cache @@ -9,68 +9,18 @@ * The cloud (R2) remains the source of truth. This is just a cache. */ -const DB_NAME = 'corates-pdf-cache'; -const DB_VERSION = 1; -const PDF_STORE_NAME = 'pdfs'; +import { db } from './db.js'; // LRU cache limits const MAX_CACHE_SIZE_BYTES = 200 * 1024 * 1024; // 200 MB total cache limit const MAX_SINGLE_FILE_SIZE = 50 * 1024 * 1024; // 50 MB per file (matches PDF_LIMITS.MAX_SIZE) -// Shared database instance and initialization promise -let dbInstance = null; -let dbInitPromise = null; - -/** - * Open the IndexedDB database (singleton pattern) - */ -function openDatabase() { - if (dbInitPromise) { - return dbInitPromise; - } - - if (dbInstance) { - return Promise.resolve(dbInstance); - } - - dbInitPromise = new Promise((resolve, reject) => { - const request = indexedDB.open(DB_NAME, DB_VERSION); - - request.onerror = () => { - dbInitPromise = null; - reject(request.error); - }; - - request.onsuccess = () => { - dbInstance = request.result; - resolve(dbInstance); - }; - - request.onupgradeneeded = event => { - const db = event.target.result; - - if (!db.objectStoreNames.contains(PDF_STORE_NAME)) { - // Key is a composite: projectId:studyId:fileName - const store = db.createObjectStore(PDF_STORE_NAME, { keyPath: 'id' }); - store.createIndex('projectId', 'projectId', { unique: false }); - store.createIndex('studyId', 'studyId', { unique: false }); - store.createIndex('cachedAt', 'cachedAt', { unique: false }); - } - }; - }); - - return dbInitPromise; -} - -/** - * Get database instance - */ -async function getDb() { - return openDatabase(); -} - /** * Generate cache key for a PDF + * @param {string} projectId + * @param {string} studyId + * @param {string} fileName + * @returns {string} */ function getCacheKey(projectId, studyId, fileName) { return `${projectId}:${studyId}:${fileName}`; @@ -85,20 +35,9 @@ function getCacheKey(projectId, studyId, fileName) { */ export async function getCachedPdf(projectId, studyId, fileName) { try { - const db = await getDb(); const id = getCacheKey(projectId, studyId, fileName); - - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readonly'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.get(id); - - request.onsuccess = () => { - const result = request.result; - resolve(result ? result.data : null); - }; - request.onerror = () => reject(request.error); - }); + const record = await db.pdfs.get(id); + return record?.data ?? null; } catch (err) { console.warn('Failed to read from PDF cache:', err); return null; @@ -106,39 +45,12 @@ export async function getCachedPdf(projectId, studyId, fileName) { } /** - * Get total cache size and list of entries sorted by cachedAt (oldest first) - * @returns {Promise<{totalSize: number, entries: Array<{id: string, size: number, cachedAt: number}>}>} + * Get total cache size + * @returns {Promise} */ -async function getCacheStats() { - try { - const db = await getDb(); - - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readonly'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.openCursor(); - const entries = []; - let totalSize = 0; - - request.onsuccess = event => { - const cursor = event.target.result; - if (cursor) { - const { id, size, cachedAt } = cursor.value; - entries.push({ id, size, cachedAt }); - totalSize += size || 0; - cursor.continue(); - } else { - // Sort by cachedAt ascending (oldest first for LRU eviction) - entries.sort((a, b) => a.cachedAt - b.cachedAt); - resolve({ totalSize, entries }); - } - }; - request.onerror = () => reject(request.error); - }); - } catch (err) { - console.warn('Failed to get cache stats:', err); - return { totalSize: 0, entries: [] }; - } +async function getTotalCacheSize() { + const all = await db.pdfs.toArray(); + return all.reduce((sum, entry) => sum + (entry.size || 0), 0); } /** @@ -147,29 +59,23 @@ async function getCacheStats() { */ async function evictIfNeeded(requiredSpace) { try { - const { totalSize, entries } = await getCacheStats(); - let currentSize = totalSize; + const all = await db.pdfs.orderBy('cachedAt').toArray(); + let totalSize = all.reduce((sum, entry) => sum + (entry.size || 0), 0); const targetSize = MAX_CACHE_SIZE_BYTES - requiredSpace; - if (currentSize <= targetSize) { - return; // No eviction needed + if (totalSize <= targetSize) { + return; } - const db = await getDb(); - - // Evict oldest entries until we're under the limit - for (const entry of entries) { - if (currentSize <= targetSize) break; - - await new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readwrite'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.delete(entry.id); - request.onsuccess = () => resolve(); - request.onerror = () => reject(request.error); - }); + const toDelete = []; + for (const entry of all) { + if (totalSize <= targetSize) break; + toDelete.push(entry.id); + totalSize -= entry.size || 0; + } - currentSize -= entry.size; + if (toDelete.length > 0) { + await db.pdfs.bulkDelete(toDelete); } } catch (err) { console.warn('Failed to evict from PDF cache:', err); @@ -182,44 +88,32 @@ async function evictIfNeeded(requiredSpace) { * @param {string} studyId * @param {string} fileName * @param {ArrayBuffer} data + * @returns {Promise} */ export async function cachePdf(projectId, studyId, fileName, data) { try { const fileSize = data.byteLength; - // Skip caching if file exceeds single-file limit if (fileSize > MAX_SINGLE_FILE_SIZE) { console.warn(`PDF too large to cache: ${fileSize} bytes (limit: ${MAX_SINGLE_FILE_SIZE})`); return false; } - // Evict old entries if needed to make room await evictIfNeeded(fileSize); - const db = await getDb(); - const id = getCacheKey(projectId, studyId, fileName); - - const record = { - id, + await db.pdfs.put({ + id: getCacheKey(projectId, studyId, fileName), projectId, studyId, fileName, data, size: fileSize, cachedAt: Date.now(), - }; - - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readwrite'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.put(record); - - request.onsuccess = () => resolve(true); - request.onerror = () => reject(request.error); }); + + return true; } catch (err) { console.warn('Failed to write to PDF cache:', err); - // Don't throw - caching failure shouldn't break the app return false; } } @@ -229,23 +123,16 @@ export async function cachePdf(projectId, studyId, fileName, data) { * @param {string} projectId * @param {string} studyId * @param {string} fileName + * @returns {Promise} */ export async function removeCachedPdf(projectId, studyId, fileName) { try { - const db = await getDb(); const id = getCacheKey(projectId, studyId, fileName); - - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readwrite'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.delete(id); - - request.onsuccess = () => resolve(true); - request.onerror = () => reject(request.error); - }); + await db.pdfs.delete(id); + return true; } catch (err) { console.warn('Failed to remove from PDF cache:', err); - // Don't throw - cache cleanup failure shouldn't break the app + return false; } } @@ -253,67 +140,32 @@ export async function removeCachedPdf(projectId, studyId, fileName) { * Clear all cached PDFs for a study * @param {string} projectId * @param {string} studyId + * @returns {Promise} Number of entries deleted */ export async function clearStudyCache(projectId, studyId) { try { - const db = await getDb(); const keyPrefix = `${projectId}:${studyId}:`; - - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readwrite'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.openCursor(); - let deleted = 0; - - request.onsuccess = event => { - const cursor = event.target.result; - if (cursor) { - if (cursor.key.startsWith(keyPrefix)) { - cursor.delete(); - deleted++; - } - cursor.continue(); - } else { - resolve(deleted); - } - }; - request.onerror = () => reject(request.error); - }); + const toDelete = await db.pdfs.filter(entry => entry.id.startsWith(keyPrefix)).primaryKeys(); + await db.pdfs.bulkDelete(toDelete); + return toDelete.length; } catch (err) { console.warn('Failed to clear study cache:', err); + return 0; } } /** * Clear all cached PDFs for a project * @param {string} projectId + * @returns {Promise} Number of entries deleted */ export async function clearProjectCache(projectId) { try { - const db = await getDb(); - - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readwrite'); - const store = transaction.objectStore(PDF_STORE_NAME); - const index = store.index('projectId'); - const keyRange = globalThis.IDBKeyRange.only(projectId); - const request = index.openCursor(keyRange); - let deleted = 0; - - request.onsuccess = event => { - const cursor = event.target.result; - if (cursor) { - cursor.delete(); - deleted++; - cursor.continue(); - } else { - resolve(deleted); - } - }; - request.onerror = () => reject(request.error); - }); + const count = await db.pdfs.where('projectId').equals(projectId).delete(); + return count; } catch (err) { console.warn('Failed to clear project cache:', err); + return 0; } } @@ -322,8 +174,12 @@ export async function clearProjectCache(projectId) { * @returns {Promise} */ export async function getCacheSize() { - const { totalSize } = await getCacheStats(); - return totalSize; + try { + return await getTotalCacheSize(); + } catch (err) { + console.warn('Failed to get cache size:', err); + return 0; + } } export default { diff --git a/packages/web/src/primitives/useProject/index.js b/packages/web/src/primitives/useProject/index.js index 1b29b17fe..d9a763405 100644 --- a/packages/web/src/primitives/useProject/index.js +++ b/packages/web/src/primitives/useProject/index.js @@ -6,7 +6,7 @@ import { createEffect, onCleanup, createMemo } from 'solid-js'; import * as Y from 'yjs'; -import { IndexeddbPersistence } from 'y-indexeddb'; +import { DexieYProvider } from 'y-dexie'; import projectStore from '@/stores/projectStore.js'; import { queryClient } from '@lib/queryClient.js'; import { queryKeys } from '@lib/queryKeys.js'; @@ -18,6 +18,7 @@ import { createStudyOperations } from './studies.js'; import { createChecklistOperations } from './checklists/index.js'; import { createPdfOperations } from './pdfs.js'; import { createReconciliationOperations } from './reconciliation.js'; +import { db, deleteProjectData } from '../db.js'; /** * Global connection registry to prevent multiple connections to the same project. @@ -25,12 +26,6 @@ import { createReconciliationOperations } from './reconciliation.js'; */ const connectionRegistry = new Map(); -/** - * IndexedDB database name prefix for Y.js persistence - * Must match the pattern used in the IndexeddbPersistence initialization - */ -const INDEXEDDB_PREFIX = 'corates-project-'; - /** * Get or create a shared connection for a project * @param {string} projectId - The project ID @@ -48,7 +43,7 @@ function getOrCreateConnection(projectId) { // Create new connection entry const entry = { ydoc: new Y.Doc(), - indexeddbProvider: null, + dexieProvider: null, connectionManager: null, syncManager: null, studyOps: null, @@ -78,8 +73,8 @@ function releaseConnection(projectId) { if (entry.connectionManager) { entry.connectionManager.destroy(); } - if (entry.indexeddbProvider) { - entry.indexeddbProvider.destroy(); + if (entry.dexieProvider) { + DexieYProvider.release(entry.ydoc); } if (entry.ydoc) { entry.ydoc.destroy(); @@ -106,8 +101,8 @@ export async function cleanupProjectLocalData(projectId) { if (entry.connectionManager) { entry.connectionManager.destroy(); } - if (entry.indexeddbProvider) { - entry.indexeddbProvider.destroy(); + if (entry.dexieProvider) { + DexieYProvider.release(entry.ydoc); } if (entry.ydoc) { entry.ydoc.destroy(); @@ -117,20 +112,11 @@ export async function cleanupProjectLocalData(projectId) { projectStore.setConnectionState(projectId, { connected: false, synced: false }); } - // 2. Delete IndexedDB storage (y-indexeddb uses this naming pattern) + // 2. Clear from unified Dexie database (project Y.Doc, PDF cache, etc.) try { - const dbName = `${INDEXEDDB_PREFIX}${projectId}`; - await new Promise((resolve, reject) => { - const request = indexedDB.deleteDatabase(dbName); - request.onsuccess = () => resolve(); - request.onerror = () => reject(request.error); - request.onblocked = () => { - console.warn('IndexedDB deletion blocked for project:', projectId); - resolve(); // Continue anyway - }; - }); + await deleteProjectData(projectId); } catch (err) { - console.error('Failed to delete IndexedDB for project:', projectId, err); + console.error('Failed to clear Dexie data for project:', projectId, err); } // 3. Clear from projectStore (in-memory cache) @@ -236,25 +222,47 @@ export function useProject(projectId) { connectionEntry.syncManager?.syncFromYDoc(); }); - // Set up IndexedDB persistence for offline support - connectionEntry.indexeddbProvider = new IndexeddbPersistence( - `corates-project-${projectId}`, - ydoc, - ); - - connectionEntry.indexeddbProvider.whenSynced.then(() => { - // Sync UI from locally persisted data immediately - connectionEntry.syncManager.syncFromYDoc(); - - // For local projects, we're "connected" and "synced" once IndexedDB is synced - if (isLocalProject()) { - projectStore.setConnectionState(projectId, { - connecting: false, - connected: true, - synced: true, - }); + // Set up Dexie persistence for offline support using y-dexie + // First ensure the project row exists in Dexie, then load the Y.Doc + db.projects.get(projectId).then(async existingProject => { + if (!existingProject) { + // Create a project row if it doesn't exist + await db.projects.put({ id: projectId, updatedAt: Date.now() }); } - // For online projects, synced: true is set when WebSocket syncs (in onSync callback) + + // Get the project row (which includes the ydoc property via y-dexie) + const project = await db.projects.get(projectId); + + // Load the Dexie Y.Doc and apply its state to our ydoc + connectionEntry.dexieProvider = DexieYProvider.load(project.ydoc); + + connectionEntry.dexieProvider.whenLoaded.then(() => { + // Apply persisted state from Dexie Y.Doc to our Y.Doc + const persistedState = Y.encodeStateAsUpdate(project.ydoc); + Y.applyUpdate(ydoc, persistedState); + + // Subscribe to our ydoc updates to persist them to Dexie + const updateHandler = (update, origin) => { + // Don't persist updates that came from the Dexie doc itself + if (origin !== 'dexie-sync') { + Y.applyUpdate(project.ydoc, update, 'dexie-sync'); + } + }; + ydoc.on('update', updateHandler); + + // Sync UI from locally persisted data immediately + connectionEntry.syncManager.syncFromYDoc(); + + // For local projects, we're "connected" and "synced" once Dexie is loaded + if (isLocalProject()) { + projectStore.setConnectionState(projectId, { + connecting: false, + connected: true, + synced: true, + }); + } + // For online projects, synced: true is set when WebSocket syncs (in onSync callback) + }); }); // For local projects, don't connect to WebSocket diff --git a/packages/web/src/stores/localChecklistsStore.js b/packages/web/src/stores/localChecklistsStore.js index 879e77139..b1be2615b 100644 --- a/packages/web/src/stores/localChecklistsStore.js +++ b/packages/web/src/stores/localChecklistsStore.js @@ -1,84 +1,26 @@ /** - * localChecklistsStore - Shared store for local checklists (IndexedDB) + * localChecklistsStore - Shared store for local checklists (Dexie) * Exports reactive accessors and methods for managing local-only checklists. */ import { createSignal } from 'solid-js'; import { createChecklistOfType, DEFAULT_CHECKLIST_TYPE } from '@/checklist-registry'; - -const DB_NAME = 'corates-local-checklists'; -const DB_VERSION = 2; // Bumped for PDF store -const STORE_NAME = 'checklists'; -const PDF_STORE_NAME = 'pdfs'; - -let dbInstance = null; -let dbInitPromise = null; - -function openDatabase() { - if (dbInitPromise) return dbInitPromise; - if (dbInstance) return Promise.resolve(dbInstance); - - dbInitPromise = new Promise((resolve, reject) => { - const request = indexedDB.open(DB_NAME, DB_VERSION); - - request.onerror = () => { - dbInitPromise = null; - reject(request.error); - }; - - request.onsuccess = () => { - dbInstance = request.result; - resolve(dbInstance); - }; - - request.onupgradeneeded = event => { - const db = event.target.result; - if (!db.objectStoreNames.contains(STORE_NAME)) { - const store = db.createObjectStore(STORE_NAME, { keyPath: 'id' }); - store.createIndex('createdAt', 'createdAt', { unique: false }); - store.createIndex('updatedAt', 'updatedAt', { unique: false }); - } - if (!db.objectStoreNames.contains(PDF_STORE_NAME)) { - const pdfStore = db.createObjectStore(PDF_STORE_NAME, { keyPath: 'checklistId' }); - pdfStore.createIndex('updatedAt', 'updatedAt', { unique: false }); - } - }; - }); - - return dbInitPromise; -} +import { db } from '@primitives/db.js'; // Reactive state const [checklists, setChecklists] = createSignal([]); const [loading, setLoading] = createSignal(true); const [error, setError] = createSignal(null); -async function getDb() { - return openDatabase(); -} - async function loadChecklists() { - const db = await getDb(); - - return new Promise((resolve, reject) => { - const transaction = db.transaction(STORE_NAME, 'readonly'); - const store = transaction.objectStore(STORE_NAME); - const request = store.getAll(); - - request.onsuccess = () => { - const checklistsList = request.result || []; - checklistsList.sort((a, b) => (b.updatedAt || b.createdAt) - (a.updatedAt || a.createdAt)); - setChecklists(checklistsList); - resolve(checklistsList); - }; - request.onerror = () => reject(request.error); - }); + const checklistsList = await db.localChecklists.orderBy('updatedAt').reverse().toArray(); + setChecklists(checklistsList); + return checklistsList; } async function init() { try { setLoading(true); - await getDb(); await loadChecklists(); } catch (err) { console.error('Error initializing local checklists:', err); @@ -89,7 +31,6 @@ async function init() { } async function createChecklist(name = 'Untitled Checklist', type = DEFAULT_CHECKLIST_TYPE) { - const db = await getDb(); const now = Date.now(); const id = `local-${crypto.randomUUID()}`; @@ -110,100 +51,47 @@ async function createChecklist(name = 'Untitled Checklist', type = DEFAULT_CHECK isLocal: true, }; - return new Promise((resolve, reject) => { - const transaction = db.transaction(STORE_NAME, 'readwrite'); - const store = transaction.objectStore(STORE_NAME); - const request = store.add(checklist); - - request.onsuccess = () => { - setChecklists(prev => [checklist, ...prev]); - resolve(checklist); - }; - - request.onerror = () => reject(request.error); - }); + await db.localChecklists.add(checklist); + setChecklists(prev => [checklist, ...prev]); + return checklist; } async function getChecklist(checklistId) { - const db = await getDb(); - return new Promise((resolve, reject) => { - const transaction = db.transaction(STORE_NAME, 'readonly'); - const store = transaction.objectStore(STORE_NAME); - const request = store.get(checklistId); - request.onsuccess = () => resolve(request.result || null); - request.onerror = () => reject(request.error); - }); + return (await db.localChecklists.get(checklistId)) || null; } async function updateChecklist(checklistId, updates) { - const db = await getDb(); const existing = await getChecklist(checklistId); if (!existing) return null; const updatedChecklist = { ...existing, ...updates, updatedAt: Date.now() }; - - return new Promise((resolve, reject) => { - const transaction = db.transaction(STORE_NAME, 'readwrite'); - const store = transaction.objectStore(STORE_NAME); - const request = store.put(updatedChecklist); - request.onsuccess = () => { - setChecklists(prev => prev.map(c => (c.id === checklistId ? updatedChecklist : c))); - resolve(updatedChecklist); - }; - request.onerror = () => reject(request.error); - }); + await db.localChecklists.put(updatedChecklist); + setChecklists(prev => prev.map(c => (c.id === checklistId ? updatedChecklist : c))); + return updatedChecklist; } async function deleteChecklist(checklistId) { - const db = await getDb(); - return new Promise((resolve, reject) => { - const transaction = db.transaction([STORE_NAME, PDF_STORE_NAME], 'readwrite'); - const checklistStore = transaction.objectStore(STORE_NAME); - const pdfStore = transaction.objectStore(PDF_STORE_NAME); - - checklistStore.delete(checklistId); - pdfStore.delete(checklistId); - - transaction.oncomplete = () => { - setChecklists(prev => prev.filter(c => c.id !== checklistId)); - resolve(true); - }; - transaction.onerror = () => reject(transaction.error); + await db.transaction('rw', [db.localChecklists, db.localChecklistPdfs], async () => { + await db.localChecklists.delete(checklistId); + await db.localChecklistPdfs.delete(checklistId); }); + setChecklists(prev => prev.filter(c => c.id !== checklistId)); + return true; } async function savePdf(checklistId, pdfData, fileName = 'document.pdf') { - const db = await getDb(); const pdfRecord = { checklistId, data: pdfData, fileName, updatedAt: Date.now() }; - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readwrite'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.put(pdfRecord); - request.onsuccess = () => resolve(pdfRecord); - request.onerror = () => reject(request.error); - }); + await db.localChecklistPdfs.put(pdfRecord); + return pdfRecord; } async function getPdf(checklistId) { - const db = await getDb(); - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readonly'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.get(checklistId); - request.onsuccess = () => resolve(request.result || null); - request.onerror = () => reject(request.error); - }); + return (await db.localChecklistPdfs.get(checklistId)) || null; } async function deletePdf(checklistId) { - const db = await getDb(); - return new Promise((resolve, reject) => { - const transaction = db.transaction(PDF_STORE_NAME, 'readwrite'); - const store = transaction.objectStore(PDF_STORE_NAME); - const request = store.delete(checklistId); - request.onsuccess = () => resolve(true); - request.onerror = () => reject(request.error); - }); + await db.localChecklistPdfs.delete(checklistId); + return true; } // Initialize immediately diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 93cd74bcf..9667117d4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -274,9 +274,9 @@ importers: d3: specifier: ^7.9.0 version: 7.9.0 - idb: - specifier: ^8.0.3 - version: 8.0.3 + dexie: + specifier: ^4.2.1 + version: 4.2.1 preact: specifier: ^10.28.1 version: 10.28.1 @@ -289,9 +289,9 @@ importers: tailwind-merge: specifier: ^3.4.0 version: 3.4.0 - y-indexeddb: - specifier: ^9.0.12 - version: 9.0.12(yjs@13.6.29) + y-dexie: + specifier: ^4.2.2 + version: 4.2.2(dexie@4.2.1)(yjs@13.6.29) y-websocket: specifier: ^3.0.0 version: 3.0.0(yjs@13.6.29) @@ -314,6 +314,9 @@ importers: '@vitest/ui': specifier: ^4.0.16 version: 4.0.16(vitest@4.0.16) + fake-indexeddb: + specifier: ^6.2.5 + version: 6.2.5 jsdom: specifier: ^27.4.0 version: 27.4.0 @@ -6892,6 +6895,12 @@ packages: integrity: sha512-26T91cV5dbOYnXdJi5qQHoTtUoNEqwkHcAyu/IKtjIAxiEqPMrDiRkDOPWVsGfNZGmlQVHQbZRSjD8sxagWVsQ==, } + dexie@4.2.1: + resolution: + { + integrity: sha512-Ckej0NS6jxQ4Po3OrSQBFddayRhTCic2DoCAG5zacOfOVB9P2Q5Xc5uL/nVa7ZVs+HdMnvUPzLFCB/JwpB6Csg==, + } + diff@8.0.2: resolution: { @@ -7559,6 +7568,13 @@ packages: engines: { node: '>= 10.17.0' } hasBin: true + fake-indexeddb@6.2.5: + resolution: + { + integrity: sha512-CGnyrvbhPlWYMngksqrSSUT1BAVP49dZocrHuK0SvtR0D5TMs5wP0o3j7jexDJW01KSadjBp1M/71o/KR3nD1w==, + } + engines: { node: '>=18' } + fast-deep-equal@3.1.3: resolution: { @@ -8102,12 +8118,6 @@ packages: } engines: { node: '>=0.10.0' } - idb@8.0.3: - resolution: - { - integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==, - } - ieee754@1.2.1: resolution: { @@ -11801,14 +11811,15 @@ packages: integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==, } - y-indexeddb@9.0.12: + y-dexie@4.2.2: resolution: { - integrity: sha512-9oCFRSPPzBK7/w5vOkJBaVCQZKHXB/v6SIT+WYhnJxlEC61juqG0hBrAf+y3gmSMLFLwICNH9nQ53uscuse6Hg==, + integrity: sha512-nbUbIc8iL3Fpyyu13HkzU0djU4dUxI/SyySvTKQYd6wfSaodoiVKbf5ZqW7RAlXHg5nrtVLhjR7E7RZohrZ7lg==, } - engines: { node: '>=16.0.0', npm: '>=8.0.0' } + engines: { node: '>=18' } peerDependencies: - yjs: ^13.0.0 + dexie: '>=4.2.0-alpha.1 <5.0.0' + yjs: ^13.6.27 y-protocols@1.0.7: resolution: @@ -16116,6 +16127,8 @@ snapshots: devtools-protocol@0.0.1534754: {} + dexie@4.2.1: {} + diff@8.0.2: {} dom-accessibility-api@0.5.16: {} @@ -16625,6 +16638,8 @@ snapshots: transitivePeerDependencies: - supports-color + fake-indexeddb@6.2.5: {} + fast-deep-equal@3.1.3: {} fast-fifo@1.3.2: {} @@ -16968,8 +16983,6 @@ snapshots: dependencies: safer-buffer: 2.1.2 - idb@8.0.3: {} - ieee754@1.2.1: {} ignore@5.3.2: {} @@ -19339,9 +19352,9 @@ snapshots: xmlchars@2.2.0: {} - y-indexeddb@9.0.12(yjs@13.6.29): + y-dexie@4.2.2(dexie@4.2.1)(yjs@13.6.29): dependencies: - lib0: 0.2.117 + dexie: 4.2.1 yjs: 13.6.29 y-protocols@1.0.7(yjs@13.6.29):