Skip to content

Commit 9aa5923

Browse files
authored
Merge pull request #608 from streamich/log-types
JSON CRDT `Log` inner typing support
2 parents dbdb619 + 6ae8b30 commit 9aa5923

File tree

3 files changed

+23
-11
lines changed

3 files changed

+23
-11
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/CHANGELOG*

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@
7676
"lib/"
7777
],
7878
"scripts": {
79-
"prettier": "npx prettier@3.2.5 --ignore-path .gitignore --write .",
80-
"prettier:check": "npx prettier@3.2.5 --ignore-path .gitignore --check .",
79+
"prettier": "npx prettier@3.2.5 --write .",
80+
"prettier:check": "npx prettier@3.2.5 --check .",
8181
"lint": "yarn tslint",
8282
"lint:fix": "yarn tslint --fix",
8383
"tslint": "tslint 'src/**/*.{js,jsx,ts,tsx}' -t verbose --project .",

src/json-crdt/log/Log.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,19 @@ import {AvlMap} from 'sonic-forest/lib/avl/AvlMap';
55
import {Model} from '../model';
66
import {first, next} from 'sonic-forest/lib/util';
77
import type {Printable} from '../../util/print/types';
8+
import type {JsonNode} from '../nodes/types';
89

9-
export class Log implements Printable {
10+
/**
11+
* The `Log` represents a history of patches applied to a JSON CRDT model. It
12+
* consists of: (1) a starting {@link Model} instance, (2) a list of {@link Patch} instances,
13+
* that can be applied to the starting model to reach the current state of the
14+
* document, and (3) the current state of the document, the `end` {@link Model}.
15+
*
16+
* The log can be used to replay the history of patches to any point in time,
17+
* from the "start" to the "end" of the log, and return the resulting {@link Model}
18+
* state.
19+
*/
20+
export class Log<N extends JsonNode = JsonNode<any>> implements Printable {
1021
/**
1122
* Creates a `PatchLog` instance from a newly JSON CRDT model. Checks if
1223
* the model API buffer has any initial operations applied, if yes, it
@@ -16,9 +27,9 @@ export class Log implements Printable {
1627
* `Model.withLogicalClock()` or `Model.withServerClock()`.
1728
* @returns A new `PatchLog` instance.
1829
*/
19-
public static fromNewModel(model: Model<any>): Log {
30+
public static fromNewModel<N extends JsonNode = JsonNode<any>>(model: Model<N>): Log<N> {
2031
const clock = model.clock.clone();
21-
const log = new Log(() => new Model(clock));
32+
const log = new Log<N>(() => new Model(clock));
2233
const api = model.api;
2334
if (api.builder.patch.ops.length) log.end.applyPatch(api.flush());
2435
return log;
@@ -32,15 +43,15 @@ export class Log implements Printable {
3243
* @readonly Internally this function may be updated, but externally it is
3344
* read-only.
3445
*/
35-
public start: () => Model;
46+
public start: () => Model<N>;
3647

3748
/**
3849
* The end of the log, the current state of the document. It is the model
3950
* instance that is used to apply new patches to the log.
4051
*
4152
* @readonly
4253
*/
43-
public readonly end: Model;
54+
public readonly end: Model<N>;
4455

4556
/**
4657
* The collection of patches which are applied to the `start()` model to reach
@@ -55,7 +66,7 @@ export class Log implements Printable {
5566
private __onPatch: FanOutUnsubscribe;
5667
private __onFlush: FanOutUnsubscribe;
5768

58-
constructor(start: () => Model) {
69+
constructor(start: () => Model<N>) {
5970
this.start = start;
6071
const end = (this.end = start());
6172
const onPatch = (patch: Patch) => {
@@ -84,7 +95,7 @@ export class Log implements Printable {
8495
*
8596
* @returns A new model instance with all patches replayed.
8697
*/
87-
public replayToEnd(): Model {
98+
public replayToEnd(): Model<N> {
8899
const clone = this.start().clone();
89100
for (let node = first(this.patches.root); node; node = next(node)) clone.applyPatch(node.v);
90101
return clone;
@@ -98,7 +109,7 @@ export class Log implements Printable {
98109
* @param ts Timestamp ID of the patch to replay to.
99110
* @returns A new model instance with patches replayed up to the given timestamp.
100111
*/
101-
public replayTo(ts: ITimestampStruct): Model {
112+
public replayTo(ts: ITimestampStruct): Model<N> {
102113
const clone = this.start().clone();
103114
for (let node = first(this.patches.root); node && compare(ts, node.k) >= 0; node = next(node))
104115
clone.applyPatch(node.v);
@@ -119,7 +130,7 @@ export class Log implements Printable {
119130
for (; node && compare(ts, node.k) >= 0; node = next(node)) newStartPatches.push(node.v);
120131
for (const patch of newStartPatches) this.patches.del(patch.getId()!);
121132
const oldStart = this.start;
122-
this.start = (): Model => {
133+
this.start = (): Model<N> => {
123134
const model = oldStart();
124135
for (const patch of newStartPatches) model.applyPatch(patch);
125136
return model;

0 commit comments

Comments
 (0)