MongoDB Adapter for livedb / sharedb

0.4.1 · active · verified Wed Apr 22

livedb-mongo is a database adapter for `livedb` and its successor, `sharedb`, providing persistent storage and an oplog implementation using MongoDB. While historically named `livedb-mongo`, the project's development has transitioned to primarily support `sharedb`, with its GitHub repository now `sharedb-mongo`. The package is currently at v5.1.0 and maintains an active release cadence, frequently updating to support newer Node.js and MongoDB versions. It stores document snapshots directly in named collections and operations in `COLLECTION_ops`, enabling direct MongoDB queries against the unwrapped JSON documents, which include internal versioning fields (`_v`, `_type`). This adapter is crucial for enabling real-time collaborative applications built with `livedb` or `sharedb`, ensuring operational transformation (OT) works correctly with MongoDB as the backend. It explicitly warns against direct database manipulation outside of the `livedb`/`sharedb` API to prevent data corruption.

Common errors

Warnings

Install

Imports

Quickstart

Initializes `livedb-mongo` as an adapter for `livedb`, then fetches or creates a document and applies an update operation.

const ShareDbMongo = require('livedb-mongo'); // Or import ShareDbMongo from 'livedb-mongo'; for ESM
const livedb = require('livedb'); // This adapter is for livedb (and sharedb)

// MongoDB connection string. Ensure MongoDB is running locally.
// Replace with your actual MongoDB connection string in production.
const mongoUrl = process.env.MONGO_URL || 'mongodb://localhost:27017/livedb_test_db';

// Initialize the livedb-mongo adapter (also known as sharedb-mongo)
// The second argument is for MongoDB driver options.
const mongoAdapter = new ShareDbMongo(mongoUrl, {
  // Modern driver options, crucial for recent MongoDB versions
  useUnifiedTopology: true,
  // replicaSet can be important for change streams if using sharedb's oplog features
  // replicaSet: 'rs0'
});

// Initialize livedb client with the mongo adapter
const db = livedb.client(mongoAdapter);

const collection = 'documents';
const docId = 'exampleDoc';

console.log(`Attempting to connect to MongoDB at ${mongoUrl} via livedb-mongo...`);

// Try to fetch a document. If it doesn't exist, create it.
db.fetch(collection, docId, (err, snapshot) => {
  if (err) {
    console.error('Error fetching document:', err);
    mongoAdapter.close(); // Ensure connection is closed on error
    return;
  }

  if (snapshot.v === 0) { // Document does not exist (version is 0)
    console.log(`Document '${docId}' not found. Creating it...`);
    const initialData = { title: 'Hello World', content: 'This is the initial version.', counter: 0 };
    db.create(collection, docId, 'json0', initialData, (createErr) => {
      if (createErr) {
        console.error('Error creating document:', createErr);
      } else {
        console.log(`Document '${docId}' created successfully with data:`, initialData);
      }
      mongoAdapter.close(); // Close connection after operation
    });
  } else {
    console.log(`Document '${docId}' found (v${snapshot.v}):`, snapshot.data);
    // Example: Apply an operation to update the document (e.g., increment counter)
    const op = { p: ['counter'], na: 1 }; // Operational Transform: Increment 'counter' by 1
    db.apply(collection, docId, op, { source: 'example_script', version: snapshot.v + 1 }, (applyErr) => {
      if (applyErr) {
        console.error('Error applying operation:', applyErr);
      } else {
        console.log('Operation applied successfully: counter incremented.');
        // Fetch again to see the updated state
        db.fetch(collection, docId, (fetchUpdatedErr, updatedSnapshot) => {
          if (fetchUpdatedErr) console.error('Error fetching updated document:', fetchUpdatedErr);
          else console.log('Updated document data:', updatedSnapshot.data);
          mongoAdapter.close();
        });
      }
    });
  }
});

view raw JSON →