@liveblocks/client 0.13.2 → 0.15.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/lib/cjs/AbstractCrdt.d.ts +13 -7
  2. package/lib/cjs/AbstractCrdt.js +2 -5
  3. package/lib/cjs/LiveList.d.ts +17 -6
  4. package/lib/cjs/LiveList.js +140 -15
  5. package/lib/cjs/LiveMap.d.ts +12 -4
  6. package/lib/cjs/LiveMap.js +57 -7
  7. package/lib/cjs/LiveObject.d.ts +22 -8
  8. package/lib/cjs/LiveObject.js +109 -24
  9. package/lib/cjs/LiveRegister.d.ts +13 -5
  10. package/lib/cjs/LiveRegister.js +23 -4
  11. package/lib/cjs/{immutable/index.d.ts → immutable.d.ts} +5 -3
  12. package/lib/cjs/{immutable/index.js → immutable.js} +77 -19
  13. package/lib/cjs/index.d.ts +2 -1
  14. package/lib/cjs/index.js +8 -1
  15. package/lib/cjs/live.d.ts +7 -0
  16. package/lib/cjs/room.d.ts +11 -3
  17. package/lib/cjs/room.js +150 -76
  18. package/lib/cjs/types.d.ts +33 -1
  19. package/lib/cjs/utils.d.ts +4 -1
  20. package/lib/cjs/utils.js +101 -1
  21. package/lib/esm/AbstractCrdt.d.ts +13 -7
  22. package/lib/esm/AbstractCrdt.js +2 -5
  23. package/lib/esm/LiveList.d.ts +17 -6
  24. package/lib/esm/LiveList.js +141 -16
  25. package/lib/esm/LiveMap.d.ts +12 -4
  26. package/lib/esm/LiveMap.js +57 -7
  27. package/lib/esm/LiveObject.d.ts +22 -8
  28. package/lib/esm/LiveObject.js +109 -24
  29. package/lib/esm/LiveRegister.d.ts +13 -5
  30. package/lib/esm/LiveRegister.js +24 -5
  31. package/lib/esm/{immutable/index.d.ts → immutable.d.ts} +5 -3
  32. package/lib/esm/{immutable/index.js → immutable.js} +75 -19
  33. package/lib/esm/index.d.ts +2 -1
  34. package/lib/esm/index.js +1 -0
  35. package/lib/esm/live.d.ts +7 -0
  36. package/lib/esm/room.d.ts +11 -3
  37. package/lib/esm/room.js +151 -77
  38. package/lib/esm/types.d.ts +33 -1
  39. package/lib/esm/utils.d.ts +4 -1
  40. package/lib/esm/utils.js +99 -1
  41. package/package.json +1 -1
@@ -1,7 +1,8 @@
1
- import { Op } from "./live";
1
+ import { Op, SerializedCrdt } from "./live";
2
+ import { StorageUpdate } from "./types";
2
3
  export declare type ApplyResult = {
3
4
  reverse: Op[];
4
- modified: AbstractCrdt;
5
+ modified: StorageUpdate;
5
6
  } | {
6
7
  modified: false;
7
8
  };
@@ -10,7 +11,7 @@ export interface Doc {
10
11
  generateOpId: () => string;
11
12
  addItem: (id: string, item: AbstractCrdt) => void;
12
13
  deleteItem: (id: string) => void;
13
- dispatch: (ops: Op[], reverseOps: Op[], modified: AbstractCrdt[]) => void;
14
+ dispatch: (ops: Op[], reverseOps: Op[], storageUpdates: Map<string, StorageUpdate>) => void;
14
15
  }
15
16
  export declare abstract class AbstractCrdt {
16
17
  #private;
@@ -33,7 +34,7 @@ export declare abstract class AbstractCrdt {
33
34
  /**
34
35
  * INTERNAL
35
36
  */
36
- _apply(op: Op): ApplyResult;
37
+ _apply(op: Op, isLocal: boolean): ApplyResult;
37
38
  /**
38
39
  * INTERNAL
39
40
  */
@@ -45,7 +46,7 @@ export declare abstract class AbstractCrdt {
45
46
  /**
46
47
  * INTERNAL
47
48
  */
48
- abstract _attachChild(id: string, key: string, crdt: AbstractCrdt): ApplyResult;
49
+ abstract _attachChild(id: string, key: string, crdt: AbstractCrdt, isLocal: boolean): ApplyResult;
49
50
  /**
50
51
  * INTERNAL
51
52
  */
@@ -53,9 +54,14 @@ export declare abstract class AbstractCrdt {
53
54
  /**
54
55
  * INTERNAL
55
56
  */
56
- abstract _detachChild(crdt: AbstractCrdt): void;
57
+ abstract _detachChild(crdt: AbstractCrdt): ApplyResult;
57
58
  /**
58
59
  * INTERNAL
59
60
  */
60
- abstract _serialize(parentId: string, parentKey: string): Op[];
61
+ abstract _serialize(parentId: string, parentKey: string, doc?: Doc): Op[];
62
+ /**
63
+ * INTERNAL
64
+ */
65
+ abstract _toSerializedCrdt(): SerializedCrdt;
66
+ abstract _getType(): string;
61
67
  }
@@ -45,14 +45,11 @@ export class AbstractCrdt {
45
45
  /**
46
46
  * INTERNAL
47
47
  */
48
- _apply(op) {
48
+ _apply(op, isLocal) {
49
49
  switch (op.type) {
50
50
  case OpType.DeleteCrdt: {
51
51
  if (this._parent != null && this._parentKey != null) {
52
- const parent = this._parent;
53
- const reverse = this._serialize(this._parent._id, this._parentKey);
54
- this._parent._detachChild(this);
55
- return { modified: parent, reverse };
52
+ return this._parent._detachChild(this);
56
53
  }
57
54
  return { modified: false };
58
55
  }
@@ -1,5 +1,5 @@
1
1
  import { AbstractCrdt, Doc, ApplyResult } from "./AbstractCrdt";
2
- import { SerializedList, SerializedCrdtWithId, Op } from "./live";
2
+ import { SerializedList, SerializedCrdtWithId, Op, SerializedCrdt } from "./live";
3
3
  /**
4
4
  * The LiveList class represents an ordered collection of items that is synchorinized across clients.
5
5
  */
@@ -13,7 +13,8 @@ export declare class LiveList<T> extends AbstractCrdt {
13
13
  /**
14
14
  * INTERNAL
15
15
  */
16
- _serialize(parentId?: string, parentKey?: string): Op[];
16
+ _serialize(parentId?: string, parentKey?: string, doc?: Doc): Op[];
17
+ _indexOfPosition(position: string): number;
17
18
  /**
18
19
  * INTERNAL
19
20
  */
@@ -25,19 +26,27 @@ export declare class LiveList<T> extends AbstractCrdt {
25
26
  /**
26
27
  * INTERNAL
27
28
  */
28
- _attachChild(id: string, key: string, child: AbstractCrdt): ApplyResult;
29
+ _attachChild(id: string, key: string, child: AbstractCrdt, isLocal: boolean): ApplyResult;
29
30
  /**
30
31
  * INTERNAL
31
32
  */
32
- _detachChild(child: AbstractCrdt): void;
33
+ _detachChild(child: AbstractCrdt): ApplyResult;
33
34
  /**
34
35
  * INTERNAL
35
36
  */
36
- _setChildKey(key: string, child: AbstractCrdt): void;
37
+ _setChildKey(key: string, child: AbstractCrdt, previousKey: string): ApplyResult;
37
38
  /**
38
39
  * INTERNAL
39
40
  */
40
- _apply(op: Op): ApplyResult;
41
+ _apply(op: Op, isLocal: boolean): ApplyResult;
42
+ /**
43
+ * INTERNAL
44
+ */
45
+ _getType(): string;
46
+ /**
47
+ * INTERNAL
48
+ */
49
+ _toSerializedCrdt(): SerializedCrdt;
41
50
  /**
42
51
  * Returns the number of elements.
43
52
  */
@@ -64,10 +73,12 @@ export declare class LiveList<T> extends AbstractCrdt {
64
73
  * @param index The index of the element to delete
65
74
  */
66
75
  delete(index: number): void;
76
+ clear(): void;
67
77
  /**
68
78
  * Returns an Array of all the elements in the LiveList.
69
79
  */
70
80
  toArray(): T[];
81
+ toCrdtArray(): AbstractCrdt[];
71
82
  /**
72
83
  * Tests whether all elements pass the test implemented by the provided function.
73
84
  * @param predicate Function to test for each element, taking two arguments (the element and its index).
@@ -12,7 +12,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
12
12
  var _LiveList_items, _LiveListIterator_innerIterator;
13
13
  import { AbstractCrdt } from "./AbstractCrdt";
14
14
  import { deserialize, selfOrRegister, selfOrRegisterValue } from "./utils";
15
- import { OpType, } from "./live";
15
+ import { OpType, CrdtType, } from "./live";
16
16
  import { makePosition, compare } from "./position";
17
17
  /**
18
18
  * The LiveList class represents an ordered collection of items that is synchorinized across clients.
@@ -51,7 +51,7 @@ export class LiveList extends AbstractCrdt {
51
51
  /**
52
52
  * INTERNAL
53
53
  */
54
- _serialize(parentId, parentKey) {
54
+ _serialize(parentId, parentKey, doc) {
55
55
  if (this._id == null) {
56
56
  throw new Error("Cannot serialize item is not attached");
57
57
  }
@@ -61,16 +61,20 @@ export class LiveList extends AbstractCrdt {
61
61
  const ops = [];
62
62
  const op = {
63
63
  id: this._id,
64
+ opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
64
65
  type: OpType.CreateList,
65
66
  parentId,
66
67
  parentKey,
67
68
  };
68
69
  ops.push(op);
69
70
  for (const [value, key] of __classPrivateFieldGet(this, _LiveList_items, "f")) {
70
- ops.push(...value._serialize(this._id, key));
71
+ ops.push(...value._serialize(this._id, key, doc));
71
72
  }
72
73
  return ops;
73
74
  }
75
+ _indexOfPosition(position) {
76
+ return __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((item) => item[1] === position);
77
+ }
74
78
  /**
75
79
  * INTERNAL
76
80
  */
@@ -92,7 +96,7 @@ export class LiveList extends AbstractCrdt {
92
96
  /**
93
97
  * INTERNAL
94
98
  */
95
- _attachChild(id, key, child) {
99
+ _attachChild(id, key, child, isLocal) {
96
100
  var _a;
97
101
  if (this._doc == null) {
98
102
  throw new Error("Can't attach child if doc is not present");
@@ -100,28 +104,57 @@ export class LiveList extends AbstractCrdt {
100
104
  child._attach(id, this._doc);
101
105
  child._setParentLink(this, key);
102
106
  const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
103
- // Assign a temporary position until we get the fix from the backend
107
+ let newKey = key;
108
+ // If there is a conflict
104
109
  if (index !== -1) {
105
- __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] = makePosition(key, (_a = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]) === null || _a === void 0 ? void 0 : _a[1]);
110
+ if (isLocal) {
111
+ // If change is local => assign a temporary position to newly attached child
112
+ let before = __classPrivateFieldGet(this, _LiveList_items, "f")[index] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] : undefined;
113
+ let after = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]
114
+ ? __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1][1]
115
+ : undefined;
116
+ newKey = makePosition(before, after);
117
+ child._setParentLink(this, newKey);
118
+ }
119
+ else {
120
+ // If change is remote => assign a temporary position to existing child until we get the fix from the backend
121
+ __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] = makePosition(key, (_a = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]) === null || _a === void 0 ? void 0 : _a[1]);
122
+ }
106
123
  }
107
- __classPrivateFieldGet(this, _LiveList_items, "f").push([child, key]);
124
+ __classPrivateFieldGet(this, _LiveList_items, "f").push([child, newKey]);
108
125
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
109
- return { reverse: [{ type: OpType.DeleteCrdt, id }], modified: this };
126
+ const newIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === newKey);
127
+ return {
128
+ reverse: [{ type: OpType.DeleteCrdt, id }],
129
+ modified: {
130
+ node: this,
131
+ type: "LiveList",
132
+ updates: [{ index: newIndex, type: "insert" }],
133
+ },
134
+ };
110
135
  }
111
136
  /**
112
137
  * INTERNAL
113
138
  */
114
139
  _detachChild(child) {
115
- const indexToDelete = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((item) => item[0] === child);
116
- __classPrivateFieldGet(this, _LiveList_items, "f").splice(indexToDelete, 1);
117
140
  if (child) {
141
+ const reverse = this._serialize(this._id, child._parentKey, this._doc);
142
+ const indexToDelete = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((item) => item[0] === child);
143
+ __classPrivateFieldGet(this, _LiveList_items, "f").splice(indexToDelete, 1);
118
144
  child._detach();
145
+ const storageUpdate = {
146
+ node: this,
147
+ type: "LiveList",
148
+ updates: [{ index: indexToDelete, type: "delete" }],
149
+ };
150
+ return { modified: storageUpdate, reverse };
119
151
  }
152
+ return { modified: false };
120
153
  }
121
154
  /**
122
155
  * INTERNAL
123
156
  */
124
- _setChildKey(key, child) {
157
+ _setChildKey(key, child, previousKey) {
125
158
  var _a;
126
159
  child._setParentLink(this, key);
127
160
  const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
@@ -134,12 +167,44 @@ export class LiveList extends AbstractCrdt {
134
167
  item[1] = key;
135
168
  }
136
169
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
170
+ const newIndex = this._indexOfPosition(key);
171
+ return {
172
+ modified: {
173
+ node: this,
174
+ type: "LiveList",
175
+ updates: [{ index: newIndex, type: "insert" }],
176
+ },
177
+ reverse: [
178
+ {
179
+ type: OpType.SetParentKey,
180
+ id: item === null || item === void 0 ? void 0 : item[0]._id,
181
+ parentKey: previousKey,
182
+ },
183
+ ],
184
+ };
185
+ }
186
+ /**
187
+ * INTERNAL
188
+ */
189
+ _apply(op, isLocal) {
190
+ return super._apply(op, isLocal);
191
+ }
192
+ /**
193
+ * INTERNAL
194
+ */
195
+ _getType() {
196
+ return "LiveList";
137
197
  }
138
198
  /**
139
199
  * INTERNAL
140
200
  */
141
- _apply(op) {
142
- return super._apply(op);
201
+ _toSerializedCrdt() {
202
+ var _a;
203
+ return {
204
+ type: CrdtType.List,
205
+ parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
206
+ parentKey: this._parentKey,
207
+ };
143
208
  }
144
209
  /**
145
210
  * Returns the number of elements.
@@ -170,10 +235,17 @@ export class LiveList extends AbstractCrdt {
170
235
  value._setParentLink(this, position);
171
236
  __classPrivateFieldGet(this, _LiveList_items, "f").push([value, position]);
172
237
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
238
+ const newIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === position);
173
239
  if (this._doc && this._id) {
174
240
  const id = this._doc.generateId();
175
241
  value._attach(id, this._doc);
176
- this._doc.dispatch(value._serialize(this._id, position), [{ type: OpType.DeleteCrdt, id }], [this]);
242
+ const storageUpdates = new Map();
243
+ storageUpdates.set(this._id, {
244
+ node: this,
245
+ type: "LiveList",
246
+ updates: [{ index: newIndex, type: "insert" }],
247
+ });
248
+ this._doc.dispatch(value._serialize(this._id, position, this._doc), [{ type: OpType.DeleteCrdt, id }], storageUpdates);
177
249
  }
178
250
  }
179
251
  /**
@@ -214,11 +286,22 @@ export class LiveList extends AbstractCrdt {
214
286
  item[1] = position;
215
287
  item[0]._setParentLink(this, position);
216
288
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
289
+ const newIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === position);
217
290
  if (this._doc && this._id) {
291
+ const storageUpdates = new Map();
292
+ storageUpdates.set(this._id, {
293
+ node: this,
294
+ type: "LiveList",
295
+ updates: [
296
+ { index: index, type: "delete" },
297
+ { index: newIndex, type: "insert" },
298
+ ],
299
+ });
218
300
  this._doc.dispatch([
219
301
  {
220
302
  type: OpType.SetParentKey,
221
303
  id: item[0]._id,
304
+ opId: this._doc.generateOpId(),
222
305
  parentKey: position,
223
306
  },
224
307
  ], [
@@ -227,7 +310,7 @@ export class LiveList extends AbstractCrdt {
227
310
  id: item[0]._id,
228
311
  parentKey: previousPosition,
229
312
  },
230
- ], [this]);
313
+ ], storageUpdates);
231
314
  }
232
315
  }
233
316
  /**
@@ -244,21 +327,63 @@ export class LiveList extends AbstractCrdt {
244
327
  if (this._doc) {
245
328
  const childRecordId = item[0]._id;
246
329
  if (childRecordId) {
330
+ const storageUpdates = new Map();
331
+ storageUpdates.set(this._id, {
332
+ node: this,
333
+ type: "LiveList",
334
+ updates: [{ index: index, type: "delete" }],
335
+ });
247
336
  this._doc.dispatch([
248
337
  {
249
338
  id: childRecordId,
339
+ opId: this._doc.generateOpId(),
250
340
  type: OpType.DeleteCrdt,
251
341
  },
252
- ], item[0]._serialize(this._id, item[1]), [this]);
342
+ ], item[0]._serialize(this._id, item[1]), storageUpdates);
253
343
  }
254
344
  }
255
345
  }
346
+ clear() {
347
+ if (this._doc) {
348
+ let ops = [];
349
+ let reverseOps = [];
350
+ let updateDelta = [];
351
+ let i = 0;
352
+ for (const item of __classPrivateFieldGet(this, _LiveList_items, "f")) {
353
+ item[0]._detach();
354
+ const childId = item[0]._id;
355
+ if (childId) {
356
+ ops.push({ id: childId, type: OpType.DeleteCrdt });
357
+ reverseOps.push(...item[0]._serialize(this._id, item[1]));
358
+ updateDelta.push({ index: i, type: "delete" });
359
+ }
360
+ i++;
361
+ }
362
+ __classPrivateFieldSet(this, _LiveList_items, [], "f");
363
+ const storageUpdates = new Map();
364
+ storageUpdates.set(this._id, {
365
+ node: this,
366
+ type: "LiveList",
367
+ updates: updateDelta,
368
+ });
369
+ this._doc.dispatch(ops, reverseOps, storageUpdates);
370
+ }
371
+ else {
372
+ for (const item of __classPrivateFieldGet(this, _LiveList_items, "f")) {
373
+ item[0]._detach();
374
+ }
375
+ __classPrivateFieldSet(this, _LiveList_items, [], "f");
376
+ }
377
+ }
256
378
  /**
257
379
  * Returns an Array of all the elements in the LiveList.
258
380
  */
259
381
  toArray() {
260
382
  return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry) => selfOrRegisterValue(entry[0]));
261
383
  }
384
+ toCrdtArray() {
385
+ return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry) => entry[0]);
386
+ }
262
387
  /**
263
388
  * Tests whether all elements pass the test implemented by the provided function.
264
389
  * @param predicate Function to test for each element, taking two arguments (the element and its index).
@@ -1,5 +1,5 @@
1
1
  import { AbstractCrdt, Doc, ApplyResult } from "./AbstractCrdt";
2
- import { Op, SerializedCrdtWithId } from "./live";
2
+ import { Op, SerializedCrdtWithId, SerializedCrdt } from "./live";
3
3
  /**
4
4
  * The LiveMap class is similar to a JavaScript Map that is synchronized on all clients.
5
5
  * Keys should be a string, and values should be serializable to JSON.
@@ -11,7 +11,7 @@ export declare class LiveMap<TKey extends string, TValue> extends AbstractCrdt {
11
11
  /**
12
12
  * INTERNAL
13
13
  */
14
- _serialize(parentId?: string, parentKey?: string): Op[];
14
+ _serialize(parentId?: string, parentKey?: string, doc?: Doc): Op[];
15
15
  /**
16
16
  * INTERNAL
17
17
  */
@@ -23,7 +23,7 @@ export declare class LiveMap<TKey extends string, TValue> extends AbstractCrdt {
23
23
  /**
24
24
  * INTERNAL
25
25
  */
26
- _attachChild(id: string, key: TKey, child: AbstractCrdt): ApplyResult;
26
+ _attachChild(id: string, key: TKey, child: AbstractCrdt, isLocal: boolean): ApplyResult;
27
27
  /**
28
28
  * INTERNAL
29
29
  */
@@ -31,7 +31,15 @@ export declare class LiveMap<TKey extends string, TValue> extends AbstractCrdt {
31
31
  /**
32
32
  * INTERNAL
33
33
  */
34
- _detachChild(child: AbstractCrdt): void;
34
+ _detachChild(child: AbstractCrdt): ApplyResult;
35
+ /**
36
+ * INTERNAL
37
+ */
38
+ _getType(): string;
39
+ /**
40
+ * INTERNAL
41
+ */
42
+ _toSerializedCrdt(): SerializedCrdt;
35
43
  /**
36
44
  * Returns a specified element from the LiveMap.
37
45
  * @param key The key of the element to return.
@@ -38,7 +38,7 @@ export class LiveMap extends AbstractCrdt {
38
38
  /**
39
39
  * INTERNAL
40
40
  */
41
- _serialize(parentId, parentKey) {
41
+ _serialize(parentId, parentKey, doc) {
42
42
  if (this._id == null) {
43
43
  throw new Error("Cannot serialize item is not attached");
44
44
  }
@@ -48,13 +48,14 @@ export class LiveMap extends AbstractCrdt {
48
48
  const ops = [];
49
49
  const op = {
50
50
  id: this._id,
51
+ opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
51
52
  type: OpType.CreateMap,
52
53
  parentId,
53
54
  parentKey,
54
55
  };
55
56
  ops.push(op);
56
57
  for (const [key, value] of __classPrivateFieldGet(this, _LiveMap_map, "f")) {
57
- ops.push(...value._serialize(this._id, key));
58
+ ops.push(...value._serialize(this._id, key, doc));
58
59
  }
59
60
  return ops;
60
61
  }
@@ -96,7 +97,7 @@ export class LiveMap extends AbstractCrdt {
96
97
  /**
97
98
  * INTERNAL
98
99
  */
99
- _attachChild(id, key, child) {
100
+ _attachChild(id, key, child, isLocal) {
100
101
  if (this._doc == null) {
101
102
  throw new Error("Can't attach child if doc is not present");
102
103
  }
@@ -112,7 +113,14 @@ export class LiveMap extends AbstractCrdt {
112
113
  child._setParentLink(this, key);
113
114
  child._attach(id, this._doc);
114
115
  __classPrivateFieldGet(this, _LiveMap_map, "f").set(key, child);
115
- return { modified: this, reverse };
116
+ return {
117
+ modified: {
118
+ node: this,
119
+ type: "LiveMap",
120
+ updates: { [key]: { type: "update" } },
121
+ },
122
+ reverse,
123
+ };
116
124
  }
117
125
  /**
118
126
  * INTERNAL
@@ -127,12 +135,36 @@ export class LiveMap extends AbstractCrdt {
127
135
  * INTERNAL
128
136
  */
129
137
  _detachChild(child) {
138
+ const reverse = this._serialize(this._id, child._parentKey, this._doc);
130
139
  for (const [key, value] of __classPrivateFieldGet(this, _LiveMap_map, "f")) {
131
140
  if (value === child) {
132
141
  __classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
133
142
  }
134
143
  }
135
144
  child._detach();
145
+ const storageUpdate = {
146
+ node: this,
147
+ type: "LiveMap",
148
+ updates: { [child._parentKey]: { type: "delete" } },
149
+ };
150
+ return { modified: storageUpdate, reverse };
151
+ }
152
+ /**
153
+ * INTERNAL
154
+ */
155
+ _getType() {
156
+ return "LiveMap";
157
+ }
158
+ /**
159
+ * INTERNAL
160
+ */
161
+ _toSerializedCrdt() {
162
+ var _a;
163
+ return {
164
+ type: CrdtType.Map,
165
+ parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
166
+ parentKey: this._parentKey,
167
+ };
136
168
  }
137
169
  /**
138
170
  * Returns a specified element from the LiveMap.
@@ -162,9 +194,15 @@ export class LiveMap extends AbstractCrdt {
162
194
  if (this._doc && this._id) {
163
195
  const id = this._doc.generateId();
164
196
  item._attach(id, this._doc);
165
- this._doc.dispatch(item._serialize(this._id, key), oldValue
197
+ const storageUpdates = new Map();
198
+ storageUpdates.set(this._id, {
199
+ node: this,
200
+ type: "LiveMap",
201
+ updates: { [key]: { type: "update" } },
202
+ });
203
+ this._doc.dispatch(item._serialize(this._id, key, this._doc), oldValue
166
204
  ? oldValue._serialize(this._id, key)
167
- : [{ type: OpType.DeleteCrdt, id }], [this]);
205
+ : [{ type: OpType.DeleteCrdt, id }], storageUpdates);
168
206
  }
169
207
  }
170
208
  /**
@@ -192,7 +230,19 @@ export class LiveMap extends AbstractCrdt {
192
230
  }
193
231
  item._detach();
194
232
  if (this._doc && item._id) {
195
- this._doc.dispatch([{ type: OpType.DeleteCrdt, id: item._id }], item._serialize(this._id, key), [this]);
233
+ const storageUpdates = new Map();
234
+ storageUpdates.set(this._id, {
235
+ node: this,
236
+ type: "LiveMap",
237
+ updates: { [key]: { type: "delete" } },
238
+ });
239
+ this._doc.dispatch([
240
+ {
241
+ type: OpType.DeleteCrdt,
242
+ id: item._id,
243
+ opId: this._doc.generateOpId(),
244
+ },
245
+ ], item._serialize(this._id, key), storageUpdates);
196
246
  }
197
247
  __classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
198
248
  return true;
@@ -1,5 +1,5 @@
1
1
  import { AbstractCrdt, Doc, ApplyResult } from "./AbstractCrdt";
2
- import { Op, SerializedCrdtWithId } from "./live";
2
+ import { Op, SerializedCrdt, SerializedCrdtWithId } from "./live";
3
3
  /**
4
4
  * The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
5
5
  * Keys should be a string, and values should be serializable to JSON.
@@ -11,13 +11,15 @@ export declare class LiveObject<T extends Record<string, any> = Record<string, a
11
11
  /**
12
12
  * INTERNAL
13
13
  */
14
- _serialize(parentId?: string, parentKey?: string): Op[];
14
+ _serialize(parentId?: string, parentKey?: string, doc?: Doc): Op[];
15
15
  /**
16
16
  * INTERNAL
17
17
  */
18
- static _deserialize([id, item]: SerializedCrdtWithId, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): LiveObject<{
19
- [key: string]: any;
20
- }>;
18
+ static _deserialize([id, item]: SerializedCrdtWithId, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): LiveObject<Record<string, any>>;
19
+ /**
20
+ * INTERNAL
21
+ */
22
+ static _deserializeChildren(object: LiveObject, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): LiveObject<Record<string, any>>;
21
23
  /**
22
24
  * INTERNAL
23
25
  */
@@ -25,11 +27,15 @@ export declare class LiveObject<T extends Record<string, any> = Record<string, a
25
27
  /**
26
28
  * INTERNAL
27
29
  */
28
- _attachChild(id: string, key: keyof T, child: AbstractCrdt): ApplyResult;
30
+ _attachChild(id: string, key: keyof T, child: AbstractCrdt, isLocal: boolean): ApplyResult;
31
+ /**
32
+ * INTERNAL
33
+ */
34
+ _detachChild(child: AbstractCrdt): ApplyResult;
29
35
  /**
30
36
  * INTERNAL
31
37
  */
32
- _detachChild(child: AbstractCrdt): void;
38
+ _detachChildren(): void;
33
39
  /**
34
40
  * INTERNAL
35
41
  */
@@ -37,7 +43,15 @@ export declare class LiveObject<T extends Record<string, any> = Record<string, a
37
43
  /**
38
44
  * INTERNAL
39
45
  */
40
- _apply(op: Op): ApplyResult;
46
+ _apply(op: Op, isLocal: boolean): ApplyResult;
47
+ /**
48
+ * INTERNAL
49
+ */
50
+ _toSerializedCrdt(): SerializedCrdt;
51
+ /**
52
+ * INTERNAL
53
+ */
54
+ _getType(): string;
41
55
  /**
42
56
  * Transform the LiveObject into a javascript object
43
57
  */