ShareDB Documentation

repository·master·Indexed 27 days ago

https://github.com/share/sharedb

ShareDB is a realtime JSON OT (Operational Transformation) database backend enabling multi-user collaboration and real-time synchronization. It supports various database adapters (MemoryDB, MongoDB, PostgreSQL), pub/sub integrations for horizontal scaling, and milestone adapters for document history snapshots. The API provides a Backend class for managing client connections, middleware registration, and document operations across browser and server environments.

Tokens
14.5K
Snippets
27
Records
104
Agent score
91%

What's inside ShareDB

  1. Introduction to ShareDB

    master

    ShareDB is a full-stack library designed for real-time JSON document collaboration. It consists of two main components:

    1. Node.js Server: Coordinates and commits edits from multiple clients.
    2. JavaScript Client: Manipulates documents; compatible with both Node.js and browser environments.

    Conflict management is handled via Operational Transformation (OT), with specific strategies implemented through ShareDB's type plugins.

  2. Overview of ShareDB

    master
    ShareDB is a realtime database backend that uses Operational Transformation (OT) to synchronize JSON documents. It enables concurrent multi-user collaboration and provides a synchronous editing API with asynchronous eventual consistency. It is designed for both browser and server environments and can be horizontally scaled using pub/sub integration.
  3. Choose a ShareDB database adapter

    master

    ShareDB uses database adapters to persist document contents and operations (ops). Choose an adapter based on your persistence and query requirements:

    • MemoryDB: An in-memory, non-persistent database. Best for testing. It has no query support and data is lost on app restart. Not suitable for production.
    • ShareDBMongo (sharedb-mongo): Backed by MongoDB. Provides full query support.
    • ShareDBMingoMemory (sharedb-mingo-memory): An in-memory database that implements a subset of MongoDB operations, including queries. Useful for testing against a MongoDB-like environment.
    • ShareDBPostgres (sharedb-postgres): Backed by PostgreSQL. It has no query support.
  4. Core features of ShareDB

    master

    ShareDB provides the following capabilities for building collaborative applications:

    • Real-time Synchronization: Syncs any JSON document across clients.
    • Concurrency: Supports multi-user collaboration.
    • Consistency Model: Provides a synchronous editing API with asynchronous eventual consistency.
    • Querying: Supports realtime query subscriptions.
    • Scalability: Horizontally scalable via pub/sub integration.
    • Data Access: Supports projections to select specific fields from documents and operations.
    • Extensibility: Middleware for access control and custom extensions.
    • Resilience: Offline change syncing upon reconnection.
    • Versioning: Access to historic document versions.
    • Presence: Realtime user presence syncing.
    • Testing: Includes in-memory implementations of database and pub/sub for unit testing.
  5. Register OT types on the Server and Client

    master

    ShareDB delegates the implementation of operational transformation to OT types. To use a custom OT type, you must register it on both the server and the client.

    Note: Failure to register the type on both sides will result in errors when attempting to synchronize operations.

    // Server-side registration
    const Backend = require('sharedb')
    const richText = require('rich-text')
    Backend.types.register(richText.type)
    
    // Client-side registration
    const Client = require('sharedb/lib/client')
    const richText = require('rich-text')
    Client.types.register(richText.type)
  6. Configure Pub/Sub for multi-instance communication

    master
    To enable communication between multiple ShareDB instances, you must configure a [pub/sub adapter]({{ site.baseurl }}{% link adapters/pub-sub.md %}). This allows different ShareDB processes to synchronize state and broadcast updates to one another.
  7. Use untyped presence for transient information

    master

    You can use untyped presence to share transient information (like mouse coordinates) independently of a specific document.

    1. Subscribe: Use connection.getPresence(channel) to get a Presence instance and call .subscribe().
    2. Listen: Listen for the 'receive' event. An update of null indicates the remote client is no longer present.
    3. Submit: To send data, create a LocalPresence instance via presence.create() and call .submit(value). The value can be any arbitrary shape.

    Note: You can create multiple LocalPresence instances from a single Presence instance to represent multiple cursors or inputs.

    const presence = connection.getPresence('my-channel')
    presence.subscribe()
    
    presence.on('receive', (presenceId, update) => {
      if (update === null) {
        // The remote client is no longer present in the document
      } else {
        // Handle the new value by updating UI, etc.
      }
    })
    
    const localPresence = presence.create()
    // The presence value can take any shape
    localPresence.submit({foo: 'bar'})
  8. Use typed presence for document-coupled information

    master

    To couple presence to a specific document and ensure synchronization with document operations (preventing issues like cursor jitter), use DocPresence.

    1. Subscribe: Use connection.getDocPresence(collection, id) to get a DocPresence instance and call .subscribe().
    2. Listen: Listen for the 'receive' event. An update of null indicates the remote client is no longer present.
    3. Submit: Create a LocalPresence via presence.create() and call .submit(value). The shape of the value is determined by the document type.

    Note: Currently, only the rich-text type supports presence information.

    const presence = connection.getDocPresence(collection, id)
    presence.subscribe()
    
    presence.on('receive', (presenceId, update) => {
      if (update === null) {
        // The remote client is no longer present in the document
      } else {
        // Handle the new value by updating UI, etc.
      }
    })
    
    const localPresence = presence.create()
    // The presence value depends on the type
    localPresence.submit(value)