@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
  }
@@ -48,14 +48,11 @@ class AbstractCrdt {
48
48
  /**
49
49
  * INTERNAL
50
50
  */
51
- _apply(op) {
51
+ _apply(op, isLocal) {
52
52
  switch (op.type) {
53
53
  case live_1.OpType.DeleteCrdt: {
54
54
  if (this._parent != null && this._parentKey != null) {
55
- const parent = this._parent;
56
- const reverse = this._serialize(this._parent._id, this._parentKey);
57
- this._parent._detachChild(this);
58
- return { modified: parent, reverse };
55
+ return this._parent._detachChild(this);
59
56
  }
60
57
  return { modified: false };
61
58
  }
@@ -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).
@@ -54,7 +54,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
54
54
  /**
55
55
  * INTERNAL
56
56
  */
57
- _serialize(parentId, parentKey) {
57
+ _serialize(parentId, parentKey, doc) {
58
58
  if (this._id == null) {
59
59
  throw new Error("Cannot serialize item is not attached");
60
60
  }
@@ -64,16 +64,20 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
64
64
  const ops = [];
65
65
  const op = {
66
66
  id: this._id,
67
+ opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
67
68
  type: live_1.OpType.CreateList,
68
69
  parentId,
69
70
  parentKey,
70
71
  };
71
72
  ops.push(op);
72
73
  for (const [value, key] of __classPrivateFieldGet(this, _LiveList_items, "f")) {
73
- ops.push(...value._serialize(this._id, key));
74
+ ops.push(...value._serialize(this._id, key, doc));
74
75
  }
75
76
  return ops;
76
77
  }
78
+ _indexOfPosition(position) {
79
+ return __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((item) => item[1] === position);
80
+ }
77
81
  /**
78
82
  * INTERNAL
79
83
  */
@@ -95,7 +99,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
95
99
  /**
96
100
  * INTERNAL
97
101
  */
98
- _attachChild(id, key, child) {
102
+ _attachChild(id, key, child, isLocal) {
99
103
  var _a;
100
104
  if (this._doc == null) {
101
105
  throw new Error("Can't attach child if doc is not present");
@@ -103,28 +107,57 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
103
107
  child._attach(id, this._doc);
104
108
  child._setParentLink(this, key);
105
109
  const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
106
- // Assign a temporary position until we get the fix from the backend
110
+ let newKey = key;
111
+ // If there is a conflict
107
112
  if (index !== -1) {
108
- __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] = (0, position_1.makePosition)(key, (_a = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]) === null || _a === void 0 ? void 0 : _a[1]);
113
+ if (isLocal) {
114
+ // If change is local => assign a temporary position to newly attached child
115
+ let before = __classPrivateFieldGet(this, _LiveList_items, "f")[index] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] : undefined;
116
+ let after = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]
117
+ ? __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1][1]
118
+ : undefined;
119
+ newKey = (0, position_1.makePosition)(before, after);
120
+ child._setParentLink(this, newKey);
121
+ }
122
+ else {
123
+ // If change is remote => assign a temporary position to existing child until we get the fix from the backend
124
+ __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] = (0, position_1.makePosition)(key, (_a = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]) === null || _a === void 0 ? void 0 : _a[1]);
125
+ }
109
126
  }
110
- __classPrivateFieldGet(this, _LiveList_items, "f").push([child, key]);
127
+ __classPrivateFieldGet(this, _LiveList_items, "f").push([child, newKey]);
111
128
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
112
- return { reverse: [{ type: live_1.OpType.DeleteCrdt, id }], modified: this };
129
+ const newIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === newKey);
130
+ return {
131
+ reverse: [{ type: live_1.OpType.DeleteCrdt, id }],
132
+ modified: {
133
+ node: this,
134
+ type: "LiveList",
135
+ updates: [{ index: newIndex, type: "insert" }],
136
+ },
137
+ };
113
138
  }
114
139
  /**
115
140
  * INTERNAL
116
141
  */
117
142
  _detachChild(child) {
118
- const indexToDelete = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((item) => item[0] === child);
119
- __classPrivateFieldGet(this, _LiveList_items, "f").splice(indexToDelete, 1);
120
143
  if (child) {
144
+ const reverse = this._serialize(this._id, child._parentKey, this._doc);
145
+ const indexToDelete = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((item) => item[0] === child);
146
+ __classPrivateFieldGet(this, _LiveList_items, "f").splice(indexToDelete, 1);
121
147
  child._detach();
148
+ const storageUpdate = {
149
+ node: this,
150
+ type: "LiveList",
151
+ updates: [{ index: indexToDelete, type: "delete" }],
152
+ };
153
+ return { modified: storageUpdate, reverse };
122
154
  }
155
+ return { modified: false };
123
156
  }
124
157
  /**
125
158
  * INTERNAL
126
159
  */
127
- _setChildKey(key, child) {
160
+ _setChildKey(key, child, previousKey) {
128
161
  var _a;
129
162
  child._setParentLink(this, key);
130
163
  const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
@@ -137,12 +170,44 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
137
170
  item[1] = key;
138
171
  }
139
172
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
173
+ const newIndex = this._indexOfPosition(key);
174
+ return {
175
+ modified: {
176
+ node: this,
177
+ type: "LiveList",
178
+ updates: [{ index: newIndex, type: "insert" }],
179
+ },
180
+ reverse: [
181
+ {
182
+ type: live_1.OpType.SetParentKey,
183
+ id: item === null || item === void 0 ? void 0 : item[0]._id,
184
+ parentKey: previousKey,
185
+ },
186
+ ],
187
+ };
188
+ }
189
+ /**
190
+ * INTERNAL
191
+ */
192
+ _apply(op, isLocal) {
193
+ return super._apply(op, isLocal);
194
+ }
195
+ /**
196
+ * INTERNAL
197
+ */
198
+ _getType() {
199
+ return "LiveList";
140
200
  }
141
201
  /**
142
202
  * INTERNAL
143
203
  */
144
- _apply(op) {
145
- return super._apply(op);
204
+ _toSerializedCrdt() {
205
+ var _a;
206
+ return {
207
+ type: live_1.CrdtType.List,
208
+ parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
209
+ parentKey: this._parentKey,
210
+ };
146
211
  }
147
212
  /**
148
213
  * Returns the number of elements.
@@ -173,10 +238,17 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
173
238
  value._setParentLink(this, position);
174
239
  __classPrivateFieldGet(this, _LiveList_items, "f").push([value, position]);
175
240
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
241
+ const newIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === position);
176
242
  if (this._doc && this._id) {
177
243
  const id = this._doc.generateId();
178
244
  value._attach(id, this._doc);
179
- this._doc.dispatch(value._serialize(this._id, position), [{ type: live_1.OpType.DeleteCrdt, id }], [this]);
245
+ const storageUpdates = new Map();
246
+ storageUpdates.set(this._id, {
247
+ node: this,
248
+ type: "LiveList",
249
+ updates: [{ index: newIndex, type: "insert" }],
250
+ });
251
+ this._doc.dispatch(value._serialize(this._id, position, this._doc), [{ type: live_1.OpType.DeleteCrdt, id }], storageUpdates);
180
252
  }
181
253
  }
182
254
  /**
@@ -217,11 +289,22 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
217
289
  item[1] = position;
218
290
  item[0]._setParentLink(this, position);
219
291
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
292
+ const newIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === position);
220
293
  if (this._doc && this._id) {
294
+ const storageUpdates = new Map();
295
+ storageUpdates.set(this._id, {
296
+ node: this,
297
+ type: "LiveList",
298
+ updates: [
299
+ { index: index, type: "delete" },
300
+ { index: newIndex, type: "insert" },
301
+ ],
302
+ });
221
303
  this._doc.dispatch([
222
304
  {
223
305
  type: live_1.OpType.SetParentKey,
224
306
  id: item[0]._id,
307
+ opId: this._doc.generateOpId(),
225
308
  parentKey: position,
226
309
  },
227
310
  ], [
@@ -230,7 +313,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
230
313
  id: item[0]._id,
231
314
  parentKey: previousPosition,
232
315
  },
233
- ], [this]);
316
+ ], storageUpdates);
234
317
  }
235
318
  }
236
319
  /**
@@ -247,21 +330,63 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
247
330
  if (this._doc) {
248
331
  const childRecordId = item[0]._id;
249
332
  if (childRecordId) {
333
+ const storageUpdates = new Map();
334
+ storageUpdates.set(this._id, {
335
+ node: this,
336
+ type: "LiveList",
337
+ updates: [{ index: index, type: "delete" }],
338
+ });
250
339
  this._doc.dispatch([
251
340
  {
252
341
  id: childRecordId,
342
+ opId: this._doc.generateOpId(),
253
343
  type: live_1.OpType.DeleteCrdt,
254
344
  },
255
- ], item[0]._serialize(this._id, item[1]), [this]);
345
+ ], item[0]._serialize(this._id, item[1]), storageUpdates);
256
346
  }
257
347
  }
258
348
  }
349
+ clear() {
350
+ if (this._doc) {
351
+ let ops = [];
352
+ let reverseOps = [];
353
+ let updateDelta = [];
354
+ let i = 0;
355
+ for (const item of __classPrivateFieldGet(this, _LiveList_items, "f")) {
356
+ item[0]._detach();
357
+ const childId = item[0]._id;
358
+ if (childId) {
359
+ ops.push({ id: childId, type: live_1.OpType.DeleteCrdt });
360
+ reverseOps.push(...item[0]._serialize(this._id, item[1]));
361
+ updateDelta.push({ index: i, type: "delete" });
362
+ }
363
+ i++;
364
+ }
365
+ __classPrivateFieldSet(this, _LiveList_items, [], "f");
366
+ const storageUpdates = new Map();
367
+ storageUpdates.set(this._id, {
368
+ node: this,
369
+ type: "LiveList",
370
+ updates: updateDelta,
371
+ });
372
+ this._doc.dispatch(ops, reverseOps, storageUpdates);
373
+ }
374
+ else {
375
+ for (const item of __classPrivateFieldGet(this, _LiveList_items, "f")) {
376
+ item[0]._detach();
377
+ }
378
+ __classPrivateFieldSet(this, _LiveList_items, [], "f");
379
+ }
380
+ }
259
381
  /**
260
382
  * Returns an Array of all the elements in the LiveList.
261
383
  */
262
384
  toArray() {
263
385
  return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry) => (0, utils_1.selfOrRegisterValue)(entry[0]));
264
386
  }
387
+ toCrdtArray() {
388
+ return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry) => entry[0]);
389
+ }
265
390
  /**
266
391
  * Tests whether all elements pass the test implemented by the provided function.
267
392
  * @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.
@@ -41,7 +41,7 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
41
41
  /**
42
42
  * INTERNAL
43
43
  */
44
- _serialize(parentId, parentKey) {
44
+ _serialize(parentId, parentKey, doc) {
45
45
  if (this._id == null) {
46
46
  throw new Error("Cannot serialize item is not attached");
47
47
  }
@@ -51,13 +51,14 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
51
51
  const ops = [];
52
52
  const op = {
53
53
  id: this._id,
54
+ opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
54
55
  type: live_1.OpType.CreateMap,
55
56
  parentId,
56
57
  parentKey,
57
58
  };
58
59
  ops.push(op);
59
60
  for (const [key, value] of __classPrivateFieldGet(this, _LiveMap_map, "f")) {
60
- ops.push(...value._serialize(this._id, key));
61
+ ops.push(...value._serialize(this._id, key, doc));
61
62
  }
62
63
  return ops;
63
64
  }
@@ -99,7 +100,7 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
99
100
  /**
100
101
  * INTERNAL
101
102
  */
102
- _attachChild(id, key, child) {
103
+ _attachChild(id, key, child, isLocal) {
103
104
  if (this._doc == null) {
104
105
  throw new Error("Can't attach child if doc is not present");
105
106
  }
@@ -115,7 +116,14 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
115
116
  child._setParentLink(this, key);
116
117
  child._attach(id, this._doc);
117
118
  __classPrivateFieldGet(this, _LiveMap_map, "f").set(key, child);
118
- return { modified: this, reverse };
119
+ return {
120
+ modified: {
121
+ node: this,
122
+ type: "LiveMap",
123
+ updates: { [key]: { type: "update" } },
124
+ },
125
+ reverse,
126
+ };
119
127
  }
120
128
  /**
121
129
  * INTERNAL
@@ -130,12 +138,36 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
130
138
  * INTERNAL
131
139
  */
132
140
  _detachChild(child) {
141
+ const reverse = this._serialize(this._id, child._parentKey, this._doc);
133
142
  for (const [key, value] of __classPrivateFieldGet(this, _LiveMap_map, "f")) {
134
143
  if (value === child) {
135
144
  __classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
136
145
  }
137
146
  }
138
147
  child._detach();
148
+ const storageUpdate = {
149
+ node: this,
150
+ type: "LiveMap",
151
+ updates: { [child._parentKey]: { type: "delete" } },
152
+ };
153
+ return { modified: storageUpdate, reverse };
154
+ }
155
+ /**
156
+ * INTERNAL
157
+ */
158
+ _getType() {
159
+ return "LiveMap";
160
+ }
161
+ /**
162
+ * INTERNAL
163
+ */
164
+ _toSerializedCrdt() {
165
+ var _a;
166
+ return {
167
+ type: live_1.CrdtType.Map,
168
+ parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
169
+ parentKey: this._parentKey,
170
+ };
139
171
  }
140
172
  /**
141
173
  * Returns a specified element from the LiveMap.
@@ -165,9 +197,15 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
165
197
  if (this._doc && this._id) {
166
198
  const id = this._doc.generateId();
167
199
  item._attach(id, this._doc);
168
- this._doc.dispatch(item._serialize(this._id, key), oldValue
200
+ const storageUpdates = new Map();
201
+ storageUpdates.set(this._id, {
202
+ node: this,
203
+ type: "LiveMap",
204
+ updates: { [key]: { type: "update" } },
205
+ });
206
+ this._doc.dispatch(item._serialize(this._id, key, this._doc), oldValue
169
207
  ? oldValue._serialize(this._id, key)
170
- : [{ type: live_1.OpType.DeleteCrdt, id }], [this]);
208
+ : [{ type: live_1.OpType.DeleteCrdt, id }], storageUpdates);
171
209
  }
172
210
  }
173
211
  /**
@@ -195,7 +233,19 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
195
233
  }
196
234
  item._detach();
197
235
  if (this._doc && item._id) {
198
- this._doc.dispatch([{ type: live_1.OpType.DeleteCrdt, id: item._id }], item._serialize(this._id, key), [this]);
236
+ const storageUpdates = new Map();
237
+ storageUpdates.set(this._id, {
238
+ node: this,
239
+ type: "LiveMap",
240
+ updates: { [key]: { type: "delete" } },
241
+ });
242
+ this._doc.dispatch([
243
+ {
244
+ type: live_1.OpType.DeleteCrdt,
245
+ id: item._id,
246
+ opId: this._doc.generateOpId(),
247
+ },
248
+ ], item._serialize(this._id, key), storageUpdates);
199
249
  }
200
250
  __classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
201
251
  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
  */