Skip to content

Commit 5b3afbc

Browse files
authored
Merge pull request #912 from streamich/arr-update-operation
Introduce "upd_arr" operation
2 parents cac7b9c + 82026c8 commit 5b3afbc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+823
-418
lines changed

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,13 @@
124124
"react": "^18.3.1",
125125
"react-dom": "^18.3.1",
126126
"rxjs": "^7.8.2",
127-
"ts-jest": "^29.1.2",
128-
"ts-loader": "^9.5.1",
127+
"ts-jest": "^29.4.0",
128+
"ts-loader": "^9.5.2",
129129
"ts-node": "^10.9.2",
130-
"tslib": "^2.6.2",
130+
"tslib": "^2.8.1",
131131
"tslint": "^6.1.3",
132132
"tslint-config-common": "^1.6.2",
133-
"typescript": "^5.4.5",
133+
"typescript": "^5.8.3",
134134
"use-t": "^1.6.3",
135135
"webpack": "^5.95.0",
136136
"webpack-cli": "^5.1.4",

src/json-crdt-extensions/ModelWithExt.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {Extensions} from '../json-crdt/extensions/Extensions';
44
import {Model} from '../json-crdt/model';
55
import type {NodeBuilder} from '../json-crdt-patch';
66
import type {SchemaToJsonNode} from '../json-crdt/schema/types';
7-
import type {JsonNode} from '../json-crdt/nodes';
87

98
const extensions = new Extensions();
109

@@ -21,7 +20,7 @@ export class ModelWithExt {
2120
public static readonly create = <S extends NodeBuilder | unknown>(
2221
schema?: S,
2322
sidOrClock: clock.ClockVector | number = Model.sid(),
24-
): Model<S extends NodeBuilder ? SchemaToJsonNode<S> : JsonNode> => {
23+
) => {
2524
const model = Model.create(schema, sidOrClock);
2625
model.ext = extensions;
2726
return model;

src/json-crdt-extensions/mval/__tests__/MvalExt.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ test('view should preserve identity', () => {
88
mv: mval.new(1),
99
}),
1010
);
11-
expect(model.s.mv.toView()).toBe(model.s.mv.toView());
11+
expect(model.s.mv.$.view()).toBe(model.s.mv.$.view());
1212
});
1313

1414
test('can set new values in single fork', () => {

src/json-crdt-extensions/peritext/__tests__/extension.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const schema = s.obj({
1616

1717
test('view should preserve identity', () => {
1818
const model = ModelWithExt.create(schema);
19-
expect(model.s.nested.obj.text.toView()).toBe(model.s.nested.obj.text.toView());
19+
expect(model.s.nested.obj.text.$.view()).toBe(model.s.nested.obj.text.$.view());
2020
});
2121

2222
describe('non-typed access', () => {
@@ -94,7 +94,7 @@ describe('typed access', () => {
9494

9595
test('can access PeritextApi using parent proxy selector', () => {
9696
const model = ModelWithExt.create(schema);
97-
const api = model.s.nested.obj.text.toApi();
97+
const api = model.s.nested.obj.text.$;
9898
expect(api).toBeInstanceOf(VecApi);
9999
let node = api.node.ext();
100100
expect(node).toBeInstanceOf(PeritextNode);

src/json-crdt-extensions/quill-delta/__tests__/extension.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const schema = s.obj({
1515

1616
test('view should preserve identity', () => {
1717
const model = ModelWithExt.create(schema);
18-
expect(model.s.nested.obj.text.toView()).toBe(model.s.nested.obj.text.toView());
18+
expect(model.s.nested.obj.text.$.view()).toBe(model.s.nested.obj.text.$.view());
1919
});
2020

2121
describe('typed access', () => {
@@ -43,7 +43,7 @@ describe('typed access', () => {
4343

4444
test('can access Quill Delta node using parent proxy selector', () => {
4545
const model = ModelWithExt.create(schema);
46-
const api = model.s.nested.obj.text.toApi();
46+
const api = model.s.nested.obj.text.$;
4747
expect(api).toBeInstanceOf(VecApi);
4848
let node = api.node.ext();
4949
expect(node).toBeInstanceOf(QuillDeltaNode);

src/json-crdt-patch/Patch.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export type JsonCrdtPatchOperation =
2121
| operations.InsStrOp
2222
| operations.InsBinOp
2323
| operations.InsArrOp
24+
| operations.UpdArrOp
2425
| operations.DelOp
2526
| operations.NopOp;
2627

@@ -130,6 +131,8 @@ export class Patch implements Printable {
130131
else if (op instanceof operations.NewArrOp) patchOps.push(new operations.NewArrOp(ts(op.id)));
131132
else if (op instanceof operations.InsArrOp)
132133
patchOps.push(new operations.InsArrOp(ts(op.id), ts(op.obj), ts(op.ref), op.data.map(ts)));
134+
else if (op instanceof operations.UpdArrOp)
135+
patchOps.push(new operations.UpdArrOp(ts(op.id), ts(op.obj), ts(op.ref), ts(op.val)));
133136
else if (op instanceof operations.InsStrOp)
134137
patchOps.push(new operations.InsStrOp(ts(op.id), ts(op.obj), ts(op.ref), op.data));
135138
else if (op instanceof operations.InsBinOp)

src/json-crdt-patch/PatchBuilder.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ export class PatchBuilder {
160160
* @returns ID of the new operation.
161161
*/
162162
public insObj(obj: ITimestampStruct, data: [key: string, value: ITimestampStruct][]): ITimestampStruct {
163-
this.pad();
164163
if (!data.length) throw new Error('EMPTY_TUPLES');
164+
this.pad();
165165
const id = this.clock.tick(1);
166166
const op = new operations.InsObjOp(id, obj, data);
167167
const span = op.span();
@@ -176,8 +176,8 @@ export class PatchBuilder {
176176
* @returns ID of the new operation.
177177
*/
178178
public insVec(obj: ITimestampStruct, data: [index: number, value: ITimestampStruct][]): ITimestampStruct {
179-
this.pad();
180179
if (!data.length) throw new Error('EMPTY_TUPLES');
180+
this.pad();
181181
const id = this.clock.tick(1);
182182
const op = new operations.InsVecOp(id, obj, data);
183183
const span = op.span();
@@ -206,8 +206,8 @@ export class PatchBuilder {
206206
* @returns ID of the new operation.
207207
*/
208208
public insStr(obj: ITimestampStruct, ref: ITimestampStruct, data: string): ITimestampStruct {
209-
this.pad();
210209
if (!data.length) throw new Error('EMPTY_STRING');
210+
this.pad();
211211
const id = this.clock.tick(1);
212212
const op = new operations.InsStrOp(id, obj, ref, data);
213213
const span = op.span();
@@ -222,8 +222,8 @@ export class PatchBuilder {
222222
* @returns ID of the new operation.
223223
*/
224224
public insBin(obj: ITimestampStruct, ref: ITimestampStruct, data: Uint8Array): ITimestampStruct {
225-
this.pad();
226225
if (!data.length) throw new Error('EMPTY_BINARY');
226+
this.pad();
227227
const id = this.clock.tick(1);
228228
const op = new operations.InsBinOp(id, obj, ref, data);
229229
const span = op.span();
@@ -247,6 +247,19 @@ export class PatchBuilder {
247247
return id;
248248
}
249249

250+
/**
251+
* Update an element in an "arr" object.
252+
*
253+
* @returns ID of the new operation.
254+
*/
255+
public updArr(arr: ITimestampStruct, ref: ITimestampStruct, val: ITimestampStruct): ITimestampStruct {
256+
this.pad();
257+
const id = this.clock.tick(1);
258+
const op = new operations.UpdArrOp(id, arr, ref, val);
259+
this.patch.ops.push(op);
260+
return id;
261+
}
262+
250263
/**
251264
* Delete a span of operations.
252265
*

src/json-crdt-patch/codec/binary/Decoder.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,13 @@ export class Decoder extends CborDecoder<CrdtReader> {
165165
builder.insArr(obj, after, elements);
166166
break;
167167
}
168+
case JsonCrdtPatchOpcode.upd_arr: {
169+
const obj = this.decodeId();
170+
const ref = this.decodeId();
171+
const val = this.decodeId();
172+
builder.updArr(obj, ref, val);
173+
break;
174+
}
168175
case JsonCrdtPatchOpcode.del: {
169176
const length = octet & 0b111 || reader.vu57();
170177
const obj = this.decodeId();

src/json-crdt-patch/codec/binary/Encoder.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,14 @@ export class Encoder extends CborEncoder<CrdtWriter> {
205205
for (let i = 0; i < length; i++) this.encodeId(elements[i]);
206206
break;
207207
}
208+
case operations.UpdArrOp: {
209+
const operation = <operations.UpdArrOp>op;
210+
writer.u8(JsonCrdtPatchOpcodeOverlay.upd_arr);
211+
this.encodeId(operation.obj);
212+
this.encodeId(operation.ref);
213+
this.encodeId(operation.val);
214+
break;
215+
}
208216
case operations.DelOp: {
209217
const operation = <operations.DelOp>op;
210218
const what = operation.what;

src/json-crdt-patch/codec/binary/__tests__/codec.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ test('encodes a patch with all operation types', () => {
104104
assertCodec();
105105
builder.arr();
106106
assertCodec();
107+
builder.updArr(ts(1, 1), ts(2, 2), ts(3, 3));
108+
assertCodec();
109+
builder.nop(1);
110+
assertCodec();
107111
});
108112

109113
test('supports consts with undefined value', () => {

0 commit comments

Comments
 (0)