UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

146 lines (145 loc) 7.22 kB
import { Model } from '../model'; import { type ITimestampStruct, type Patch } from '../../json-crdt-patch'; import type { Printable } from 'tree-dump/lib/types'; import type { JsonNode } from '../nodes/types'; /** * The `Log` represents a history of patches applied to a JSON CRDT model. It * consists of: (1) a starting {@link Model} instance, (2) a list of {@link Patch} instances, * that can be applied to the starting model to reach the current state of the * document, and (3) the current state of the document, the `end` {@link Model}. * * The log can be used to replay the history of patches to any point in time, * from the "start" to the "end" of the log, and return the resulting {@link Model} * state. * * @todo Make this implement UILifecycle (start, stop) interface. */ export declare class Log<N extends JsonNode = JsonNode<any>> implements Printable { /** * Model factory function that creates a new JSON CRDT model instance, which * is used as the starting point of the log. It is called every time a new * model is needed to replay the log. * * @readonly Internally this function may be updated, but externally it is * read-only. * * @todo Rename to something else to give way to a `start()` in UILifecycle. * Call "snapshot". Maybe introduce `type Snapshot<N> = () => Model<N>;`. */ start: () => Model<N>; /** * The end of the log, the current state of the document. It is the model * instance that is used to apply new patches to the log. * * @readonly */ readonly end: Model<N>; /** * Creates a `PatchLog` instance from a newly JSON CRDT model. Checks if * the model API buffer has any initial operations applied, if yes, it * uses them to create the initial state of the log. * * @param model A new JSON CRDT model, just created with * `Model.withLogicalClock()` or `Model.withServerClock()`. * @returns A new `PatchLog` instance. */ static fromNewModel<N extends JsonNode = JsonNode<any>>(model: Model<N>): Log<N>; static from<N extends JsonNode = JsonNode<any>>(model: Model<N>): Log<N>; /** * The collection of patches which are applied to the `start()` model to reach * the `end` model. The patches in the log, stored in an AVL tree for * efficient replaying. The patches are sorted by their logical timestamps * and applied in causal order. * * @readonly */ readonly patches: { min: import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch> | undefined; root: import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch> | undefined; max: import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch> | undefined; readonly comparator: import("sonic-forest/lib/types").Comparator<ITimestampStruct>; set(k: ITimestampStruct, v: Patch): import("sonic-forest/lib/types").SonicNodePublicReference<import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch>>; find(k: ITimestampStruct): import("sonic-forest/lib/types").SonicNodePublicReference<import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch>> | undefined; get(k: ITimestampStruct): Patch | undefined; del(k: ITimestampStruct): boolean; clear(): void; has(k: ITimestampStruct): boolean; _size: number; size(): number; isEmpty(): boolean; getOrNextLower(k: ITimestampStruct): import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch> | undefined; forEach(fn: (node: import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch>) => void): void; first(): import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch> | undefined; last(): import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch> | undefined; readonly next: <N_1 extends import("sonic-forest/lib/types").HeadlessNode>(curr: N_1) => N_1 | undefined; iterator0(): () => import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch> | undefined; iterator(): Iterator<import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch>, any, any>; entries(): IterableIterator<import("sonic-forest/lib/types").ITreeNode<ITimestampStruct, Patch>>; toString(tab: string): string; }; private __onPatch; private __onFlush; constructor( /** * Model factory function that creates a new JSON CRDT model instance, which * is used as the starting point of the log. It is called every time a new * model is needed to replay the log. * * @readonly Internally this function may be updated, but externally it is * read-only. * * @todo Rename to something else to give way to a `start()` in UILifecycle. * Call "snapshot". Maybe introduce `type Snapshot<N> = () => Model<N>;`. */ start: () => Model<N>, /** * The end of the log, the current state of the document. It is the model * instance that is used to apply new patches to the log. * * @readonly */ end?: Model<N>); /** * Call this method to destroy the {@link Log} instance. It unsubscribes patch * and flush listeners from the `end` model and clears the patch log. */ destroy(): void; /** * Creates a new model instance using the `start()` factory function and * replays all patches in the log to reach the current state of the document. * * @returns A new model instance with all patches replayed. */ replayToEnd(): Model<N>; /** * Replays the patch log until a specified timestamp, including the patch * at the given timestamp. The model returned is a new instance of `start()` * with patches replayed up to the given timestamp. * * @param ts Timestamp ID of the patch to replay to. * @param inclusive If `true`, the patch at the given timestamp `ts` is included, * otherwise replays up to the patch before the given timestamp. Default is `true`. * @returns A new model instance with patches replayed up to the given timestamp. */ replayTo(ts: ITimestampStruct, inclusive?: boolean): Model<N>; /** * Advance the start of the log to a specified timestamp, excluding the patch * at the given timestamp. This method removes all patches from the log that * are older than the given timestamp and updates the `start()` factory * function to replay the log from the new start. * * @param ts Timestamp ID of the patch to advance to. */ advanceTo(ts: ITimestampStruct): void; /** * Creates a patch which reverts the given patch. The RGA insertion operations * are reversed just by deleting the inserted values. All other operations * require time travel to the state just before the patch was applied, so that * a copy of a mutated object can be created and inserted back into the model. * * @param patch The patch to undo * @returns A new patch that undoes the given patch */ undo(patch: Patch): Patch; toString(tab?: string): string; }