Dexie Observable Addon

raw JSON →
4.0.1-beta.13 verified Thu Apr 23 auth: no javascript

Dexie.Observable is an addon for Dexie.js that significantly enhances IndexedDB functionality by enabling cross-window and cross-instance database change observation. It introduces an event mechanism, similar to `localStorage`'s `onstorage`, specifically for IndexedDB, allowing web applications to react in real-time to data modifications, irrespective of the originating tab or worker. This ensures views remain synchronized and up-to-date across all connected clients. The package is an integral part of the Dexie.js ecosystem, fully compatible with Dexie v4.x, and typically releases in alignment with Dexie.js's maintenance and feature updates. Although the package version provided is `4.0.1-beta.13`, it functions within the broader stable Dexie v4 environment. Furthermore, it forms the foundational layer for `Dexie.Syncable.js`, which provides robust two-way data replication capabilities with remote servers.

error TypeError: db.on is not a function
cause `dexie-observable` has not been correctly imported and initialized, or the `db.on` method is being called before the addon has extended the Dexie prototype.
fix
Ensure import Dexie from 'dexie'; is followed by import 'dexie-observable'; in your module. Also, make sure you are calling db.on() on an instance of Dexie created *after* the import.
error Changes not propagating across browser windows/tabs.
cause The required schema upgrade for `dexie-observable` to create its internal tables was not performed, or the browser's IndexedDB implementation is not firing the necessary events.
fix
If using an existing database, ensure you have added a new, empty version to your schema definition (db.version(X).stores({});) to trigger the addon's installation. Verify browser compatibility with cross-window IndexedDB events.
breaking When integrating `dexie-observable` with an existing Dexie database, a schema upgrade is mandatory to allow the addon to install its internal tables. Failing to do so will prevent `dexie-observable` from functioning correctly.
fix Add a new version to your database schema, even if it's an empty `db.version(X).stores({});` entry, after your existing schema. This triggers the necessary upgrade logic.
gotcha The `dexie-observable` package is primarily imported for its side-effects, meaning it extends the Dexie prototype directly. There are no named exports from 'dexie-observable' itself that you would typically import and use directly.
fix Use `import 'dexie-observable';` after `import Dexie from 'dexie';`. Any functionality, like `db.on('changes')`, will then be available on your Dexie database instance.
gotcha The package version `4.0.1-beta.13` indicates it is a beta release. While generally stable for use with Dexie v4, users should be aware that it's not a final major release and could potentially introduce minor changes before a stable 4.x version of the addon is officially released.
fix Monitor the Dexie.js GitHub releases for a stable `dexie-observable` v4.x release, or use with caution in production environments, ensuring thorough testing.
gotcha The `$$` prefix for a primary key (e.g., `$$uuid`) is a special syntax introduced by `dexie-observable` to automatically generate UUID strings for that key. If you need a custom UUID generation logic, you can override `Dexie.createUUID`.
fix To use a custom UUID generator, assign your function to `Dexie.createUUID = myCustomUUIDFunction;` before initializing your database. Ensure your custom function returns a unique string suitable for primary keys.
npm install dexie-observable
yarn add dexie-observable
pnpm add dexie-observable

This example demonstrates how to initialize Dexie with the observable addon, define a store using UUID primary keys, and subscribe to the `db.on('changes')` event to react to database modifications, including those from other browser windows.

import Dexie from 'dexie';
import 'dexie-observable'; // Enables db.on('changes')

const db = new Dexie('ObservableTestDB');
db.version(1).stores({
  friends: '$$uuid,name,age'
});

// Subscribe to database changes across all windows/instances
db.on('changes', (changes) => {
  console.log('Database changes detected:');
  changes.forEach((change) => {
    switch (change.type) {
      case 1: // CREATED
        console.log(`CREATED: ${JSON.stringify(change.obj)}`);
        break;
      case 2: // UPDATED
        console.log(`UPDATED: Old: ${JSON.stringify(change.oldObj)}, New: ${JSON.stringify(change.obj)}`);
        break;
      case 3: // DELETED
        console.log(`DELETED: ${JSON.stringify(change.oldObj)}`);
        break;
    }
  });
});

async function addFriend() {
  await db.friends.add({ name: 'Alice', age: 30 });
  console.log('Added Alice. Check other browser tabs!');
  await db.friends.add({ name: 'Bob', age: 25 });
  console.log('Added Bob. Check other browser tabs!');
}

addFriend();