json-joy
Version:
Collection of libraries for building collaborative editing apps.
146 lines (145 loc) • 7.22 kB
TypeScript
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;
}