[]
If the built-in adapters do not meet your needs, you can implement the IDatabaseAdapter interface to create a custom adapter.
Below is an example.
import { IOp, ISnapshot, IDocument, ICommitSnapshot, IDatabaseAdapter, Db } from '@mescius/js-collaboration-ot';
export class SampleDb<S = unknown, T = unknown> extends Db<S, T> implements IDatabaseAdapter<S, T> {
private ops: Map<string, IOp<T>[]> = new Map();
private documents: Map<string, IDocument> = new Map();
private fragments: Map<string, Map<string, S>> = new Map();
async getOps(id: string, from: number, to?: number): Promise<IOp<T>[]> {
const allOps = this.ops.get(id) || [];
const toVersion = to ?? Number.MAX_SAFE_INTEGER;
return allOps.filter(op => op.v >= from && op.v < toVersion);
}
async getDocument(id: string): Promise<IDocument | undefined> {
return this.documents.get(id);
}
async getSnapshot(id: string): Promise<ISnapshot<S> | undefined> {
const doc = this.documents.get(id);
if (!doc) return;
const fragments = await this.getFragments(id);
return {
id,
v: doc.snapshotVersion,
type: doc.type,
fragments
};
}
async getFragment(id: string, fragmentId: string): Promise<S | undefined> {
return this.fragments.get(id)?.get(fragmentId);
}
async getFragments(id: string, fragmentIds?: string[]): Promise<{ [id: string]: S }> {
const allFragments = this.fragments.get(id) || new Map();
const result: { [id: string]: S } = {};
if (fragmentIds) {
fragmentIds.forEach(id => {
const fragment = allFragments.get(id);
if (fragment) result[id] = fragment;
});
} else {
allFragments.forEach((value, key) => {
result[key] = value;
});
}
return result;
}
async commitOp(id: string, op: IOp<T>, document: IDocument): Promise<boolean> {
if (op.create) {
if (this.documents.has(id)) return false;
this.documents.set(id, document);
this.ops.set(id, [op]);
this.fragments.set(id, new Map());
return true;
}
const currentOps = this.ops.get(id) || [];
currentOps.push(op);
this.ops.set(id, currentOps);
this.documents.set(id, document);
return true;
}
async commitSnapshot(id: string, snapshot: ICommitSnapshot<S>): Promise<boolean> {
const doc = this.documents.get(id);
if (!doc) return false;
doc.snapshotVersion = snapshot.v;
const fragments = this.fragments.get(id) || new Map();
if (snapshot.fragmentsChanges) {
const { createFragments, updateFragments, deleteFragments } = snapshot.fragmentsChanges;
// Handle creates and updates
Object.entries({ ...createFragments, ...updateFragments }).forEach(([key, value]) => {
fragments.set(key, value as S);
});
// Handle deletes
deleteFragments?.forEach(key => fragments.delete(key));
}
return true;
}
async close(): Promise<void> {
// Nothing to do for in-memory Database
}
}
import { DocumentServices, IDatabaseAdapter, MemoryDb } from '@mescius/js-collaboration-ot';
const dbAdapter: IDatabaseAdapter = new SampleDb();
const docService = new DocumentServices({ db: dbAdapter });