Skip to content

Commit d0036aa

Browse files
committed
feat(json-crdt): 🎸 add ability for file to sync to model
1 parent 891b259 commit d0036aa

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/json-crdt/file/File.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ export class File implements Printable {
7676
this.log.push(patch);
7777
}
7878

79+
public sync(): (() => void) {
80+
const {model, log} = this;
81+
const api = model.api;
82+
const onPatchUnsubscribe = api.onPatch.listen((patch) => {
83+
log.push(patch);
84+
});
85+
const onLocalChangeUnsubscribe = api.onLocalChange.listen(() => {
86+
const patch = api.flush();
87+
if (patch.ops.length) this.log.push(patch);
88+
});
89+
return () => {
90+
onPatchUnsubscribe();
91+
onLocalChangeUnsubscribe();
92+
};
93+
}
94+
7995
public serialize(params: types.FileSerializeParams = {}): types.FileWriteSequence {
8096
if (params.noView && params.model === 'sidecar') throw new Error('SIDECAR_MODEL_WITHOUT_VIEW');
8197
const metadata: types.FileMetadata = [{}, FileModelEncoding.Auto];

src/json-crdt/file/__tests__/File.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,28 @@ describe('.unserialize()', () => {
119119
expect(file2.model.view()).toEqual({foo: 'bar', xyz: 123});
120120
});
121121
});
122+
123+
describe('.sync()', () => {
124+
test('keeps track of local changes', async () => {
125+
const {file, model} = setup({foo: 'bar'});
126+
file.sync();
127+
model.api.obj([]).set({x: 1});
128+
await Promise.resolve();
129+
expect(file.model.view()).toEqual({foo: 'bar', x: 1});
130+
expect(file.log.replayToEnd().view()).toEqual({foo: 'bar', x: 1});
131+
});
132+
133+
test('keeps track of remote changes', async () => {
134+
const {file, model} = setup({foo: 'bar'});
135+
const clone = model.clone();
136+
file.sync();
137+
clone.api.obj([]).set({x: 1});
138+
expect(clone.view()).toEqual({foo: 'bar', x: 1});
139+
expect(file.model.view()).toEqual({foo: 'bar'});
140+
const patch = clone.api.flush();
141+
file.model.applyPatch(patch);
142+
await Promise.resolve();
143+
expect(file.model.view()).toEqual({foo: 'bar', x: 1});
144+
expect(file.log.replayToEnd().view()).toEqual({foo: 'bar', x: 1});
145+
});
146+
});

0 commit comments

Comments
 (0)