[]
The database adapter (IDatabaseAdapter) is a key point of the server-side functionality, responsible for the persistent storage of document snapshots and operations.
The database adapter defines the interaction with the underlying storage. Operations (op) are continuously stored to record history, while snapshots only retain the latest version, updated by accumulated operations.
This document explains how to use and implement a database adapter and integrate it into DocumentServices.
Store and read document snapshots and operations
Support historical data queries and submissions
Applicable Scenarios: Persistent storage in production environments, custom storage solutions
Built-in Adapters: MemoryDb (in-memory storage), Postgres Adapter, and SQLite3 Adapter
/**
* Defines the interface for a database adapter in operational transformation.
* @template S - The type of snapshot data.
* @template T - The type of operation data.
* @public
*/
export interface IDatabaseAdapter<S = unknown, T = unknown> {
/**
* Retrieves operations between two versions (inclusive of 'from', exclusive of 'to').
* @param {string} id - The document ID.
* @param {number} from - The starting version.
* @param {number} [to] - The ending version (optional).
* @param {unknown} [options] - Additional options (optional).
* @returns {Promise<IOp<T>[]>} A promise resolving to an array of operations.
*/
getOps(id: string, from: number, to?: number, options?: unknown): Promise<IOp<T>[]>;
/**
* Retrieves document information by ID.
* @param {string} id - The document ID.
* @param {unknown} [options] - Additional options (optional).
* @returns {Promise<IDocument | null>} A promise resolving to the document info or null if not found.
*/
getDocument(id: string, options?: unknown): Promise<IDocument | null>;
/**
* Retrieves the snapshot of a document by ID.
* @param {string} id - The document ID.
* @param {unknown} [options] - Additional options (optional).
* @returns {Promise<ISnapshot<S> | null>} A promise resolving to the snapshot or null if not found.
*/
getSnapshot(id: string, options?: unknown): Promise<ISnapshot<S> | null>;
/**
* Retrieves a specific fragment of a document by ID.
* @param {string} id - The document ID.
* @param {string} fragmentId - The ID of the fragment.
* @param {unknown} [options] - Additional options (optional).
* @returns {Promise<{ version: number, data: S | null } | null>} Resolves to an object with fragment version and data, or null if the document does not exist. If the document exists but the fragment does not, data is null.
*/
getFragment(id: string, fragmentId: string, options?: unknown): Promise<{ version: number, data: S | null } | null>;
/**
* Commits an operation to the database.
* @param {string} id - The document ID.
* @param {IOp<T>} op - The operation to commit.
* @param {IDocument} document - The document metadata.
* @param {unknown} [options] - Additional options (optional).
* @returns {Promise<boolean>} A promise resolving to true if the operation was committed, false otherwise.
*/
commitOp(id: string, op: IOp<T>, document: IDocument, options?: unknown): Promise<boolean>;
/**
* Commits a snapshot to the database.
* @param {string} id - The document ID.
* @param {ICommitSnapshot<S>} snapshot - The snapshot to commit.
* @param {unknown} [options] - Additional options (optional).
* @returns {Promise<boolean>} A promise resolving to true if the snapshot was committed, false otherwise.
*/
commitSnapshot(id: string, snapshot: ICommitSnapshot<S>, options?: unknown): Promise<boolean>;
/**
* Retrieves the committed version of an operation, if it exists.
* @param {string} id - The document ID.
* @param {number} to - The ending version to check up to.
* @param {IOp<T>} op - The operation to verify.
* @returns {Promise<number | null>} A promise resolving to the committed version or null if not committed.
*/
getCommittedOpVersion(id: string, to: number, op: IOp): Promise<number | null>;
/**
* Closes the database connection.
* @returns {Promise<void>} A promise that resolves when the database is closed.
*/
close(): Promise<void>;
}Pass the database adapter into the configuration of DocumentServices:
import { DocumentServices, IDatabaseAdapter, MemoryDb } from '@mescius/js-collaboration-ot';
const dbAdapter: IDatabaseAdapter = new MemoryDb();
const docService = new DocumentServices({ db: dbAdapter });Description: An in-memory adapter, with data stored in RAM.
Use Case: Development and testing.
Limitations: Data is lost after the server restarts, not suitable for production environments.
Notes: When creating DocumentServices, MemoryDb is the default data base adapter.
import { MemoryDb } from '@mescius/js-collaboration-ot';
const dbAdapter = new MemoryDb();Description: A persistent adapter based on PostgreSQL.
Use Case: Production environments, supporting persistent storage.
import pg from 'pg';
import { PostgresDb } from '@mescius/js-collaboration-ot-postgres';
const config = {
host: 'localhost',
database: 'your_database',
user: 'your_user_name',
password: 'your_password',
port: 5432, // default port
};
const dbInstance = new pg.Pool(config);
const dbAdapter = new PostgresDb(dbInstance);Description: A persistent adapter based on SQLite3.
Use Case: Development and testing environments, supporting persistent storage.
import sqlite3 from 'sqlite3';
import { SqliteDb } from '@mescius/js-collaboration-ot-sqlite';
const dbInstance = new sqlite3.Database("./sample.db");
const dbAdapter = new SqliteDb(dbInstance);If the built-in adapters do not meet your needs, you can create a custom database adapter by implementing the IDatabaseAdapter interface. Please refer to Custom Database Adapter.