@liveblocks/client 0.12.0-beta.8 → 0.12.2

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.
package/lib/cjs/doc.js CHANGED
@@ -10,21 +10,25 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _Doc_instances, _Doc_clock, _Doc_items, _Doc_root, _Doc_actor, _Doc_dispatch, _Doc_applyCreateRegister, _Doc_applyDeleteRecordKey, _Doc_applyUpdateRecord, _Doc_applyCreateMap, _Doc_applyCreateList, _Doc_applyCreateObject, _Doc_applyDeleteRecord, _Doc_applySetParentKey, _AbstractCrdt_listeners, _AbstractCrdt_deepListeners, _AbstractCrdt_parent, _AbstractCrdt_doc, _AbstractCrdt_id, _LiveObject_map, _LiveMap_map, _LiveRegister_data, _LiveList_items, _LiveListIterator_innerIterator;
13
+ var _Doc_instances, _Doc_clock, _Doc_opClock, _Doc_items, _Doc_root, _Doc_actor, _Doc_dispatch, _Doc_undoStack, _Doc_redoStack, _Doc_applyOp, _AbstractCrdt_instances, _AbstractCrdt_listeners, _AbstractCrdt_deepListeners, _AbstractCrdt_parent, _AbstractCrdt_doc, _AbstractCrdt_id, _AbstractCrdt_parentKey, _AbstractCrdt_applySetParentKey, _AbstractCrdt_applyRegister, _AbstractCrdt_applyCreateObject, _AbstractCrdt_applyCreateMap, _AbstractCrdt_applyCreateList, _LiveObject_instances, _LiveObject_map, _LiveObject_propToLastUpdate, _LiveObject_applyDeleteObjectKey, _LiveMap_map, _LiveRegister_data, _LiveList_items, _LiveListIterator_innerIterator;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.LiveList = exports.LiveMap = exports.LiveObject = exports.Doc = void 0;
16
16
  const utils_1 = require("./utils");
17
17
  const live_1 = require("./live");
18
18
  const position_1 = require("./position");
19
19
  function noOp() { }
20
+ const MAX_UNDO_STACK = 50;
20
21
  class Doc {
21
22
  constructor(root, actor = 0, dispatch = noOp) {
22
23
  _Doc_instances.add(this);
23
24
  _Doc_clock.set(this, 0);
25
+ _Doc_opClock.set(this, 0);
24
26
  _Doc_items.set(this, new Map());
25
27
  _Doc_root.set(this, void 0);
26
28
  _Doc_actor.set(this, void 0);
27
29
  _Doc_dispatch.set(this, void 0);
30
+ _Doc_undoStack.set(this, []);
31
+ _Doc_redoStack.set(this, []);
28
32
  __classPrivateFieldSet(this, _Doc_root, root, "f");
29
33
  __classPrivateFieldSet(this, _Doc_actor, actor, "f");
30
34
  __classPrivateFieldSet(this, _Doc_dispatch, dispatch, "f");
@@ -65,6 +69,7 @@ class Doc {
65
69
  return doc;
66
70
  }
67
71
  dispatch(ops) {
72
+ __classPrivateFieldSet(this, _Doc_redoStack, [], "f");
68
73
  __classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);
69
74
  }
70
75
  addItem(id, item) {
@@ -76,45 +81,38 @@ class Doc {
76
81
  getItem(id) {
77
82
  return __classPrivateFieldGet(this, _Doc_items, "f").get(id);
78
83
  }
79
- apply(op) {
80
- switch (op.type) {
81
- case live_1.OpType.UpdateObject: {
82
- __classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyUpdateRecord).call(this, op);
83
- break;
84
- }
85
- case live_1.OpType.CreateObject: {
86
- __classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateObject).call(this, op);
87
- break;
88
- }
89
- case live_1.OpType.CreateMap: {
90
- __classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateMap).call(this, op);
91
- break;
92
- }
93
- case live_1.OpType.CreateList: {
94
- __classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateList).call(this, op);
95
- break;
96
- }
97
- case live_1.OpType.DeleteCrdt: {
98
- __classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyDeleteRecord).call(this, op);
99
- break;
100
- }
101
- case live_1.OpType.SetParentKey: {
102
- __classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applySetParentKey).call(this, op);
103
- break;
104
- }
105
- case live_1.OpType.DeleteObjectKey: {
106
- __classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyDeleteRecordKey).call(this, op);
107
- break;
108
- }
109
- case live_1.OpType.CreateRegister: {
110
- __classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateRegister).call(this, op);
111
- break;
112
- }
84
+ apply(ops) {
85
+ const reverse = [];
86
+ for (const op of ops) {
87
+ reverse.push(...__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyOp).call(this, op));
113
88
  }
89
+ return reverse;
114
90
  }
115
91
  get root() {
116
92
  return __classPrivateFieldGet(this, _Doc_root, "f");
117
93
  }
94
+ addToUndoStack(ops) {
95
+ if (__classPrivateFieldGet(this, _Doc_undoStack, "f").length >= MAX_UNDO_STACK) {
96
+ __classPrivateFieldGet(this, _Doc_undoStack, "f").shift();
97
+ }
98
+ __classPrivateFieldGet(this, _Doc_undoStack, "f").push(ops);
99
+ }
100
+ undo() {
101
+ const ops = __classPrivateFieldGet(this, _Doc_undoStack, "f").pop();
102
+ if (ops == null) {
103
+ return;
104
+ }
105
+ __classPrivateFieldGet(this, _Doc_redoStack, "f").push(this.apply(ops));
106
+ __classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);
107
+ }
108
+ redo() {
109
+ const ops = __classPrivateFieldGet(this, _Doc_redoStack, "f").pop();
110
+ if (ops == null) {
111
+ return;
112
+ }
113
+ __classPrivateFieldGet(this, _Doc_undoStack, "f").push(this.apply(ops));
114
+ __classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);
115
+ }
118
116
  count() {
119
117
  return __classPrivateFieldGet(this, _Doc_items, "f").size;
120
118
  }
@@ -122,82 +120,48 @@ class Doc {
122
120
  var _a, _b;
123
121
  return `${__classPrivateFieldGet(this, _Doc_actor, "f")}:${__classPrivateFieldSet(this, _Doc_clock, (_b = __classPrivateFieldGet(this, _Doc_clock, "f"), _a = _b++, _b), "f"), _a}`;
124
122
  }
123
+ generateOpId() {
124
+ var _a, _b;
125
+ return `${__classPrivateFieldGet(this, _Doc_actor, "f")}:${__classPrivateFieldSet(this, _Doc_opClock, (_b = __classPrivateFieldGet(this, _Doc_opClock, "f"), _a = _b++, _b), "f"), _a}`;
126
+ }
125
127
  }
126
128
  exports.Doc = Doc;
127
- _Doc_clock = new WeakMap(), _Doc_items = new WeakMap(), _Doc_root = new WeakMap(), _Doc_actor = new WeakMap(), _Doc_dispatch = new WeakMap(), _Doc_instances = new WeakSet(), _Doc_applyCreateRegister = function _Doc_applyCreateRegister(op) {
128
- const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
129
- if (parent == null) {
130
- return;
131
- }
132
- if (!(parent instanceof LiveMap) && !(parent instanceof LiveList)) {
133
- throw new Error("LiveRegister can only be attached to a LiveMap or LiveList");
134
- }
135
- const newRegister = new LiveRegister(op.data);
136
- parent._attachChild(op.id, op.parentKey, newRegister);
137
- }, _Doc_applyDeleteRecordKey = function _Doc_applyDeleteRecordKey(op) {
138
- const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
139
- if (item && item instanceof LiveObject) {
140
- item._apply(op);
141
- }
142
- }, _Doc_applyUpdateRecord = function _Doc_applyUpdateRecord(op) {
143
- const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
144
- if (item && item instanceof LiveObject) {
145
- item._apply(op);
146
- }
147
- }, _Doc_applyCreateMap = function _Doc_applyCreateMap(op) {
148
- const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
149
- if (parent == null) {
150
- return;
151
- }
152
- const newMap = new LiveMap();
153
- parent._attachChild(op.id, op.parentKey, newMap);
154
- }, _Doc_applyCreateList = function _Doc_applyCreateList(op) {
155
- const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
156
- if (parent == null) {
157
- return;
158
- }
159
- const list = new LiveList();
160
- parent._attachChild(op.id, op.parentKey, list);
161
- }, _Doc_applyCreateObject = function _Doc_applyCreateObject(op) {
162
- if (op.parentId && op.parentKey) {
163
- const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
164
- if (parent == null) {
165
- return;
129
+ _Doc_clock = new WeakMap(), _Doc_opClock = new WeakMap(), _Doc_items = new WeakMap(), _Doc_root = new WeakMap(), _Doc_actor = new WeakMap(), _Doc_dispatch = new WeakMap(), _Doc_undoStack = new WeakMap(), _Doc_redoStack = new WeakMap(), _Doc_instances = new WeakSet(), _Doc_applyOp = function _Doc_applyOp(op) {
130
+ switch (op.type) {
131
+ case live_1.OpType.DeleteObjectKey:
132
+ case live_1.OpType.UpdateObject:
133
+ case live_1.OpType.DeleteCrdt:
134
+ case live_1.OpType.SetParentKey: {
135
+ const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
136
+ if (item == null) {
137
+ return [];
138
+ }
139
+ return item._apply(op);
140
+ break;
141
+ }
142
+ case live_1.OpType.CreateList:
143
+ case live_1.OpType.CreateObject:
144
+ case live_1.OpType.CreateMap:
145
+ case live_1.OpType.CreateRegister: {
146
+ const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
147
+ if (parent == null) {
148
+ return [];
149
+ }
150
+ return parent._apply(op);
151
+ break;
166
152
  }
167
- const newObj = new LiveObject(op.data);
168
- parent._attachChild(op.id, op.parentKey, newObj);
169
- }
170
- }, _Doc_applyDeleteRecord = function _Doc_applyDeleteRecord(op) {
171
- const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
172
- if (item == null) {
173
- return;
174
- }
175
- const parent = item._parent;
176
- if (parent == null) {
177
- return;
178
- }
179
- if (parent) {
180
- parent._detachChild(item);
181
- }
182
- }, _Doc_applySetParentKey = function _Doc_applySetParentKey(op) {
183
- const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
184
- if (item == null) {
185
- return;
186
- }
187
- if (item._parent == null) {
188
- return;
189
- }
190
- if (item._parent instanceof LiveList) {
191
- item._parent._setChildKey(op.parentKey, item);
192
153
  }
154
+ return [];
193
155
  };
194
156
  class AbstractCrdt {
195
157
  constructor() {
158
+ _AbstractCrdt_instances.add(this);
196
159
  _AbstractCrdt_listeners.set(this, []);
197
160
  _AbstractCrdt_deepListeners.set(this, []);
198
161
  _AbstractCrdt_parent.set(this, void 0);
199
162
  _AbstractCrdt_doc.set(this, void 0);
200
163
  _AbstractCrdt_id.set(this, void 0);
164
+ _AbstractCrdt_parentKey.set(this, void 0);
201
165
  }
202
166
  /**
203
167
  * INTERNAL
@@ -220,10 +184,45 @@ class AbstractCrdt {
220
184
  /**
221
185
  * INTERNAL
222
186
  */
223
- _setParent(parent) {
224
- if (__classPrivateFieldGet(this, _AbstractCrdt_parent, "f")) {
187
+ get _parentKey() {
188
+ return __classPrivateFieldGet(this, _AbstractCrdt_parentKey, "f");
189
+ }
190
+ _apply(op) {
191
+ switch (op.type) {
192
+ case live_1.OpType.DeleteCrdt: {
193
+ if (this._parent != null && this._parentKey != null) {
194
+ const reverse = this._serialize(this._parent._id, this._parentKey);
195
+ this._parent._detachChild(this);
196
+ return reverse;
197
+ }
198
+ return [];
199
+ }
200
+ case live_1.OpType.CreateObject: {
201
+ return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateObject).call(this, op);
202
+ }
203
+ case live_1.OpType.CreateMap: {
204
+ return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateMap).call(this, op);
205
+ }
206
+ case live_1.OpType.CreateRegister: {
207
+ return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyRegister).call(this, op);
208
+ }
209
+ case live_1.OpType.CreateList: {
210
+ return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateList).call(this, op);
211
+ }
212
+ case live_1.OpType.SetParentKey: {
213
+ return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applySetParentKey).call(this, op);
214
+ }
215
+ }
216
+ return [];
217
+ }
218
+ /**
219
+ * INTERNAL
220
+ */
221
+ _setParentLink(parent, key) {
222
+ if (__classPrivateFieldGet(this, _AbstractCrdt_parent, "f") != null && __classPrivateFieldGet(this, _AbstractCrdt_parent, "f") !== parent) {
225
223
  throw new Error("Cannot attach parent if it already exist");
226
224
  }
225
+ __classPrivateFieldSet(this, _AbstractCrdt_parentKey, key, "f");
227
226
  __classPrivateFieldSet(this, _AbstractCrdt_parent, parent, "f");
228
227
  }
229
228
  /**
@@ -247,19 +246,34 @@ class AbstractCrdt {
247
246
  __classPrivateFieldSet(this, _AbstractCrdt_parent, undefined, "f");
248
247
  __classPrivateFieldSet(this, _AbstractCrdt_doc, undefined, "f");
249
248
  }
249
+ /**
250
+ * Subscribes to updates.
251
+ */
250
252
  subscribe(listener) {
251
253
  __classPrivateFieldGet(this, _AbstractCrdt_listeners, "f").push(listener);
252
254
  }
255
+ /**
256
+ * Subscribes to updates and children updates.
257
+ */
253
258
  subscribeDeep(listener) {
254
259
  __classPrivateFieldGet(this, _AbstractCrdt_deepListeners, "f").push(listener);
255
260
  }
261
+ /**
262
+ * Unsubscribes to updates.
263
+ */
256
264
  unsubscribe(listener) {
257
265
  (0, utils_1.remove)(__classPrivateFieldGet(this, _AbstractCrdt_listeners, "f"), listener);
258
266
  }
267
+ /**
268
+ * Unsubscribes to updates and children updates.
269
+ */
259
270
  unsubscribeDeep(listener) {
260
271
  (0, utils_1.remove)(__classPrivateFieldGet(this, _AbstractCrdt_deepListeners, "f"), listener);
261
272
  }
262
- notify(onlyDeep = false) {
273
+ /**
274
+ * INTERNAL
275
+ */
276
+ _notify(onlyDeep = false) {
263
277
  if (onlyDeep === false) {
264
278
  for (const listener of __classPrivateFieldGet(this, _AbstractCrdt_listeners, "f")) {
265
279
  listener();
@@ -269,19 +283,70 @@ class AbstractCrdt {
269
283
  listener();
270
284
  }
271
285
  if (this._parent) {
272
- this._parent.notify(true);
286
+ this._parent._notify(true);
273
287
  }
274
288
  }
275
289
  }
276
- _AbstractCrdt_listeners = new WeakMap(), _AbstractCrdt_deepListeners = new WeakMap(), _AbstractCrdt_parent = new WeakMap(), _AbstractCrdt_doc = new WeakMap(), _AbstractCrdt_id = new WeakMap();
290
+ _AbstractCrdt_listeners = new WeakMap(), _AbstractCrdt_deepListeners = new WeakMap(), _AbstractCrdt_parent = new WeakMap(), _AbstractCrdt_doc = new WeakMap(), _AbstractCrdt_id = new WeakMap(), _AbstractCrdt_parentKey = new WeakMap(), _AbstractCrdt_instances = new WeakSet(), _AbstractCrdt_applySetParentKey = function _AbstractCrdt_applySetParentKey(op) {
291
+ if (this._parent == null) {
292
+ return [];
293
+ }
294
+ if (this._parent instanceof LiveList) {
295
+ const previousKey = this._parentKey;
296
+ this._parent._setChildKey(op.parentKey, this);
297
+ return [
298
+ { type: live_1.OpType.SetParentKey, id: this._id, parentKey: previousKey },
299
+ ];
300
+ }
301
+ return [];
302
+ }, _AbstractCrdt_applyRegister = function _AbstractCrdt_applyRegister(op) {
303
+ if (this._doc == null) {
304
+ throw new Error("Internal: doc should exist");
305
+ }
306
+ if (this._doc.getItem(op.id) != null) {
307
+ return [];
308
+ }
309
+ return this._attachChild(op.id, op.parentKey, new LiveRegister(op.data));
310
+ }, _AbstractCrdt_applyCreateObject = function _AbstractCrdt_applyCreateObject(op) {
311
+ if (this._doc == null) {
312
+ throw new Error("Internal: doc should exist");
313
+ }
314
+ if (this._doc.getItem(op.id) != null) {
315
+ return [];
316
+ }
317
+ return this._attachChild(op.id, op.parentKey, new LiveObject(op.data));
318
+ }, _AbstractCrdt_applyCreateMap = function _AbstractCrdt_applyCreateMap(op) {
319
+ if (this._doc == null) {
320
+ throw new Error("Internal: doc should exist");
321
+ }
322
+ if (this._doc.getItem(op.id) != null) {
323
+ return [];
324
+ }
325
+ return this._attachChild(op.id, op.parentKey, new LiveMap());
326
+ }, _AbstractCrdt_applyCreateList = function _AbstractCrdt_applyCreateList(op) {
327
+ if (this._doc == null) {
328
+ throw new Error("Internal: doc should exist");
329
+ }
330
+ if (this._doc.getItem(op.id) != null) {
331
+ return [];
332
+ }
333
+ return this._attachChild(op.id, op.parentKey, new LiveList());
334
+ };
335
+ /**
336
+ * The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
337
+ * Keys should be a string, and values should be serializable to JSON.
338
+ * If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
339
+ */
277
340
  class LiveObject extends AbstractCrdt {
278
341
  constructor(object = {}) {
279
342
  super();
343
+ _LiveObject_instances.add(this);
280
344
  _LiveObject_map.set(this, void 0);
345
+ _LiveObject_propToLastUpdate.set(this, new Map());
281
346
  for (const key in object) {
282
347
  const value = object[key];
283
348
  if (value instanceof AbstractCrdt) {
284
- value._setParent(this);
349
+ value._setParentLink(this, key);
285
350
  }
286
351
  }
287
352
  __classPrivateFieldSet(this, _LiveObject_map, new Map(Object.entries(object)), "f");
@@ -299,7 +364,7 @@ class LiveObject extends AbstractCrdt {
299
364
  type: live_1.OpType.CreateObject,
300
365
  parentId,
301
366
  parentKey,
302
- data: {}
367
+ data: {},
303
368
  };
304
369
  ops.push(op);
305
370
  for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
@@ -331,7 +396,7 @@ class LiveObject extends AbstractCrdt {
331
396
  throw new Error("Tried to deserialize a crdt but it does not have a parentKey and is not the root");
332
397
  }
333
398
  const child = deserialize(entry, parentToChildren, doc);
334
- child._setParent(object);
399
+ child._setParentLink(object, crdt.parentKey);
335
400
  __classPrivateFieldGet(object, _LiveObject_map, "f").set(crdt.parentKey, child);
336
401
  }
337
402
  return object;
@@ -355,13 +420,30 @@ class LiveObject extends AbstractCrdt {
355
420
  throw new Error("Can't attach child if doc is not present");
356
421
  }
357
422
  const previousValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
423
+ let result;
358
424
  if (isCrdt(previousValue)) {
425
+ result = previousValue._serialize(this._id, key);
359
426
  previousValue._detach();
360
427
  }
428
+ else if (previousValue === undefined) {
429
+ result = [
430
+ { type: live_1.OpType.DeleteObjectKey, id: this._id, key: key },
431
+ ];
432
+ }
433
+ else {
434
+ result = [
435
+ {
436
+ type: live_1.OpType.UpdateObject,
437
+ id: this._id,
438
+ data: { [key]: previousValue },
439
+ },
440
+ ];
441
+ }
361
442
  __classPrivateFieldGet(this, _LiveObject_map, "f").set(key, child);
362
- child._setParent(this);
443
+ child._setParentLink(this, key);
363
444
  child._attach(id, this._doc);
364
- this.notify();
445
+ this._notify();
446
+ return result;
365
447
  }
366
448
  /**
367
449
  * INTERNAL
@@ -375,7 +457,7 @@ class LiveObject extends AbstractCrdt {
375
457
  if (child) {
376
458
  child._detach();
377
459
  }
378
- this.notify();
460
+ this._notify();
379
461
  }
380
462
  /**
381
463
  * INTERNAL
@@ -392,8 +474,36 @@ class LiveObject extends AbstractCrdt {
392
474
  * INTERNAL
393
475
  */
394
476
  _apply(op) {
477
+ var _a;
395
478
  if (op.type === live_1.OpType.UpdateObject) {
479
+ const reverse = [];
480
+ const reverseUpdate = {
481
+ type: live_1.OpType.UpdateObject,
482
+ id: this._id,
483
+ data: {},
484
+ };
485
+ reverse.push(reverseUpdate);
486
+ for (const key in op.data) {
487
+ const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
488
+ if (oldValue !== undefined) {
489
+ reverseUpdate.data[key] = oldValue;
490
+ }
491
+ else if (oldValue === undefined) {
492
+ reverse.push({ type: live_1.OpType.DeleteObjectKey, id: this._id, key });
493
+ }
494
+ }
396
495
  for (const key in op.data) {
496
+ if (op.opId == null) {
497
+ op.opId = (_a = this._doc) === null || _a === void 0 ? void 0 : _a.generateOpId();
498
+ }
499
+ const lastOpId = __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").get(key);
500
+ if (lastOpId === op.opId) {
501
+ __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").delete(key);
502
+ continue;
503
+ }
504
+ else if (lastOpId != null) {
505
+ continue;
506
+ }
397
507
  const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
398
508
  if (isCrdt(oldValue)) {
399
509
  oldValue._detach();
@@ -401,86 +511,128 @@ class LiveObject extends AbstractCrdt {
401
511
  const value = op.data[key];
402
512
  __classPrivateFieldGet(this, _LiveObject_map, "f").set(key, value);
403
513
  }
404
- this.notify();
514
+ this._notify();
515
+ return reverse;
405
516
  }
406
517
  else if (op.type === live_1.OpType.DeleteObjectKey) {
407
- const key = op.key;
408
- const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
409
- if (isCrdt(oldValue)) {
410
- oldValue._detach();
411
- }
412
- __classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
413
- this.notify();
518
+ return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyDeleteObjectKey).call(this, op);
414
519
  }
520
+ return super._apply(op);
415
521
  }
522
+ /**
523
+ * Transform the LiveObject into a javascript object
524
+ */
416
525
  toObject() {
417
526
  return Object.fromEntries(__classPrivateFieldGet(this, _LiveObject_map, "f"));
418
527
  }
528
+ /**
529
+ * Adds or updates a property with a specified key and a value.
530
+ * @param key The key of the property to add
531
+ * @param value The value of the property to add
532
+ */
419
533
  set(key, value) {
420
534
  // TODO: Find out why typescript complains
421
535
  this.update({ [key]: value });
422
536
  }
537
+ /**
538
+ * Returns a specified property from the LiveObject.
539
+ * @param key The key of the property to get
540
+ */
423
541
  get(key) {
424
542
  return __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
425
543
  }
426
- // delete<TKey extends keyof T>(key: TKey) {
427
- // if (this.doc && this.id) {
428
- // const item = this._map.get(key as string);
429
- // if (isCrdt(item)) {
430
- // item.detach();
431
- // }
432
- // this.doc.dispatch([
433
- // { type: OpType.DeleteObjectKey, id: this.id, key: key as string },
434
- // ]);
435
- // }
436
- // this._map.delete(key as string);
437
- // this.notify();
438
- // }
544
+ /**
545
+ * Adds or updates multiple properties at once with an object.
546
+ * @param overrides The object used to overrides properties
547
+ */
439
548
  update(overrides) {
440
- if (this._doc && this._id) {
441
- const ops = [];
442
- const updateOp = {
443
- id: this._id,
444
- type: live_1.OpType.UpdateObject,
445
- data: {}
446
- };
447
- ops.push(updateOp);
549
+ if (this._doc == null || this._id == null) {
448
550
  for (const key in overrides) {
449
551
  const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
450
- if (oldValue instanceof LiveObject) {
552
+ if (oldValue instanceof AbstractCrdt) {
451
553
  oldValue._detach();
452
554
  }
453
555
  const newValue = overrides[key];
454
556
  if (newValue instanceof AbstractCrdt) {
455
- newValue._setParent(this);
456
- newValue._attach(this._doc.generateId(), this._doc);
457
- ops.push(...newValue._serialize(this._id, key));
458
- }
459
- else {
460
- updateOp.data[key] = newValue;
557
+ newValue._setParentLink(this, key);
461
558
  }
462
559
  __classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
463
560
  }
464
- this._doc.dispatch(ops);
465
- this.notify();
561
+ this._notify();
466
562
  return;
467
563
  }
564
+ const ops = [];
565
+ const reverseOps = [];
566
+ const opId = this._doc.generateOpId();
567
+ const updateOp = {
568
+ opId,
569
+ id: this._id,
570
+ type: live_1.OpType.UpdateObject,
571
+ data: {},
572
+ };
573
+ ops.push(updateOp);
574
+ const reverseUpdateOp = {
575
+ id: this._id,
576
+ type: live_1.OpType.UpdateObject,
577
+ data: {},
578
+ };
579
+ reverseOps.push(reverseUpdateOp);
468
580
  for (const key in overrides) {
581
+ __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, opId);
469
582
  const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
470
583
  if (oldValue instanceof AbstractCrdt) {
584
+ reverseOps.push(...oldValue._serialize(this._id, key));
471
585
  oldValue._detach();
472
586
  }
587
+ else if (oldValue === undefined) {
588
+ reverseOps.push({ type: live_1.OpType.DeleteObjectKey, id: this._id, key });
589
+ }
590
+ else {
591
+ reverseUpdateOp.data[key] = oldValue;
592
+ }
473
593
  const newValue = overrides[key];
474
594
  if (newValue instanceof AbstractCrdt) {
475
- newValue._setParent(this);
595
+ newValue._setParentLink(this, key);
596
+ newValue._attach(this._doc.generateId(), this._doc);
597
+ ops.push(...newValue._serialize(this._id, key));
598
+ }
599
+ else {
600
+ updateOp.data[key] = newValue;
476
601
  }
477
602
  __classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
478
603
  }
479
- this.notify();
604
+ this._doc.addToUndoStack(reverseOps);
605
+ this._doc.dispatch(ops);
606
+ this._notify();
480
607
  }
481
608
  }
482
609
  exports.LiveObject = LiveObject;
483
- _LiveObject_map = new WeakMap();
610
+ _LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _LiveObject_instances = new WeakSet(), _LiveObject_applyDeleteObjectKey = function _LiveObject_applyDeleteObjectKey(op) {
611
+ const key = op.key;
612
+ const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
613
+ let result = [];
614
+ if (isCrdt(oldValue)) {
615
+ result = oldValue._serialize(this._id, op.key);
616
+ oldValue._detach();
617
+ }
618
+ else if (oldValue !== undefined) {
619
+ result = [
620
+ {
621
+ type: live_1.OpType.UpdateObject,
622
+ id: this._id,
623
+ data: { [key]: oldValue },
624
+ },
625
+ ];
626
+ }
627
+ __classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
628
+ this._notify();
629
+ return result;
630
+ };
631
+ /**
632
+ * The LiveMap class is similar to a JavaScript Map that is synchronized on all clients.
633
+ * Keys should be a string, and values should be serializable to JSON.
634
+ * If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
635
+ */
484
636
  class LiveMap extends AbstractCrdt {
485
637
  constructor(entries) {
486
638
  super();
@@ -489,7 +641,7 @@ class LiveMap extends AbstractCrdt {
489
641
  const mappedEntries = [];
490
642
  for (const entry of entries) {
491
643
  const value = selfOrRegister(entry[1]);
492
- value._setParent(this);
644
+ value._setParentLink(this, entry[0]);
493
645
  mappedEntries.push([entry[0], value]);
494
646
  }
495
647
  __classPrivateFieldSet(this, _LiveMap_map, new Map(mappedEntries), "f");
@@ -540,7 +692,7 @@ class LiveMap extends AbstractCrdt {
540
692
  throw new Error("Tried to deserialize a crdt but it does not have a parentKey and is not the root");
541
693
  }
542
694
  const child = deserialize(entry, parentToChildren, doc);
543
- child._setParent(map);
695
+ child._setParentLink(map, crdt.parentKey);
544
696
  __classPrivateFieldGet(map, _LiveMap_map, "f").set(crdt.parentKey, child);
545
697
  }
546
698
  return map;
@@ -564,13 +716,19 @@ class LiveMap extends AbstractCrdt {
564
716
  throw new Error("Can't attach child if doc is not present");
565
717
  }
566
718
  const previousValue = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);
719
+ let result;
567
720
  if (previousValue) {
721
+ result = previousValue._serialize(this._id, key);
568
722
  previousValue._detach();
569
723
  }
570
- child._setParent(this);
724
+ else {
725
+ result = [{ type: live_1.OpType.DeleteCrdt, id }];
726
+ }
727
+ child._setParentLink(this, key);
571
728
  child._attach(id, this._doc);
572
729
  __classPrivateFieldGet(this, _LiveMap_map, "f").set(key, child);
573
- this.notify();
730
+ this._notify();
731
+ return result;
574
732
  }
575
733
  /**
576
734
  * INTERNAL
@@ -591,8 +749,13 @@ class LiveMap extends AbstractCrdt {
591
749
  }
592
750
  }
593
751
  child._detach();
594
- this.notify();
752
+ this._notify();
595
753
  }
754
+ /**
755
+ * Returns a specified element from the LiveMap.
756
+ * @param key The key of the element to return.
757
+ * @returns The element associated with the specified key, or undefined if the key can't be found in the LiveMap.
758
+ */
596
759
  get(key) {
597
760
  const value = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);
598
761
  if (value == undefined) {
@@ -600,27 +763,47 @@ class LiveMap extends AbstractCrdt {
600
763
  }
601
764
  return selfOrRegisterValue(value);
602
765
  }
766
+ /**
767
+ * Adds or updates an element with a specified key and a value.
768
+ * @param key The key of the element to add. Should be a string.
769
+ * @param value The value of the element to add. Should be serializable to JSON.
770
+ */
603
771
  set(key, value) {
604
772
  const oldValue = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);
605
773
  if (oldValue) {
606
774
  oldValue._detach();
607
775
  }
608
776
  const item = selfOrRegister(value);
609
- item._setParent(this);
777
+ item._setParentLink(this, key);
610
778
  __classPrivateFieldGet(this, _LiveMap_map, "f").set(key, item);
611
779
  if (this._doc && this._id) {
612
- item._attach(this._doc.generateId(), this._doc);
613
- const ops = item._serialize(this._id, key);
614
- this._doc.dispatch(ops);
780
+ const id = this._doc.generateId();
781
+ item._attach(id, this._doc);
782
+ this._doc.addToUndoStack(oldValue
783
+ ? oldValue._serialize(this._id, key)
784
+ : [{ type: live_1.OpType.DeleteCrdt, id }]);
785
+ this._doc.dispatch(item._serialize(this._id, key));
615
786
  }
616
- this.notify();
787
+ this._notify();
617
788
  }
789
+ /**
790
+ * Returns the number of elements in the LiveMap.
791
+ */
618
792
  get size() {
619
793
  return __classPrivateFieldGet(this, _LiveMap_map, "f").size;
620
794
  }
795
+ /**
796
+ * Returns a boolean indicating whether an element with the specified key exists or not.
797
+ * @param key The key of the element to test for presence.
798
+ */
621
799
  has(key) {
622
800
  return __classPrivateFieldGet(this, _LiveMap_map, "f").has(key);
623
801
  }
802
+ /**
803
+ * Removes the specified element by key.
804
+ * @param key The key of the element to remove.
805
+ * @returns true if an element existed and has been removed, or false if the element does not exist.
806
+ */
624
807
  delete(key) {
625
808
  const item = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);
626
809
  if (item == null) {
@@ -628,12 +811,16 @@ class LiveMap extends AbstractCrdt {
628
811
  }
629
812
  item._detach();
630
813
  if (this._doc && item._id) {
814
+ this._doc.addToUndoStack(item._serialize(this._id, key));
631
815
  this._doc.dispatch([{ type: live_1.OpType.DeleteCrdt, id: item._id }]);
632
816
  }
633
817
  __classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
634
- this.notify();
818
+ this._notify();
635
819
  return true;
636
820
  }
821
+ /**
822
+ * Returns a new Iterator object that contains the [key, value] pairs for each element.
823
+ */
637
824
  entries() {
638
825
  const innerIterator = __classPrivateFieldGet(this, _LiveMap_map, "f").entries();
639
826
  return {
@@ -655,12 +842,21 @@ class LiveMap extends AbstractCrdt {
655
842
  },
656
843
  };
657
844
  }
845
+ /**
846
+ * Same function object as the initial value of the entries method.
847
+ */
658
848
  [(_LiveMap_map = new WeakMap(), Symbol.iterator)]() {
659
849
  return this.entries();
660
850
  }
851
+ /**
852
+ * Returns a new Iterator object that contains the keys for each element.
853
+ */
661
854
  keys() {
662
855
  return __classPrivateFieldGet(this, _LiveMap_map, "f").keys();
663
856
  }
857
+ /**
858
+ * Returns a new Iterator object that contains the values for each element.
859
+ */
664
860
  values() {
665
861
  const innerIterator = __classPrivateFieldGet(this, _LiveMap_map, "f").values();
666
862
  return {
@@ -681,6 +877,10 @@ class LiveMap extends AbstractCrdt {
681
877
  },
682
878
  };
683
879
  }
880
+ /**
881
+ * Executes a provided function once per each key/value pair in the Map object, in insertion order.
882
+ * @param callback Function to execute for each entry in the map.
883
+ */
684
884
  forEach(callback) {
685
885
  for (const entry of this) {
686
886
  callback(entry[1], entry[0], this);
@@ -688,6 +888,9 @@ class LiveMap extends AbstractCrdt {
688
888
  }
689
889
  }
690
890
  exports.LiveMap = LiveMap;
891
+ /**
892
+ * INTERNAL
893
+ */
691
894
  class LiveRegister extends AbstractCrdt {
692
895
  constructor(data) {
693
896
  super();
@@ -715,13 +918,15 @@ class LiveRegister extends AbstractCrdt {
715
918
  if (this._id == null || parentId == null || parentKey == null) {
716
919
  throw new Error("Cannot serialize register if parentId or parentKey is undefined");
717
920
  }
718
- return [{
921
+ return [
922
+ {
719
923
  type: live_1.OpType.CreateRegister,
720
924
  id: this._id,
721
925
  parentId,
722
926
  parentKey,
723
- data: this.data
724
- }];
927
+ data: this.data,
928
+ },
929
+ ];
725
930
  }
726
931
  _attachChild(id, key, crdt) {
727
932
  throw new Error("Method not implemented.");
@@ -729,12 +934,18 @@ class LiveRegister extends AbstractCrdt {
729
934
  _detachChild(crdt) {
730
935
  throw new Error("Method not implemented.");
731
936
  }
937
+ _apply(op) {
938
+ return super._apply(op);
939
+ }
732
940
  }
733
941
  _LiveRegister_data = new WeakMap();
942
+ /**
943
+ * The LiveList class represents an ordered collection of items that is synchorinized across clients.
944
+ */
734
945
  class LiveList extends AbstractCrdt {
735
946
  constructor(items = []) {
736
947
  super();
737
- // TODO: Naive array at first, find a better data structure
948
+ // TODO: Naive array at first, find a better data structure. Maybe an Order statistics tree?
738
949
  _LiveList_items.set(this, []);
739
950
  let position = undefined;
740
951
  for (let i = 0; i < items.length; i++) {
@@ -756,9 +967,9 @@ class LiveList extends AbstractCrdt {
756
967
  }
757
968
  for (const entry of children) {
758
969
  const child = deserialize(entry, parentToChildren, doc);
759
- child._setParent(list);
970
+ child._setParentLink(list, entry[1].parentKey);
760
971
  __classPrivateFieldGet(list, _LiveList_items, "f").push([child, entry[1].parentKey]);
761
- __classPrivateFieldGet(list, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)({ position: itemA[1] }, { position: itemB[1] }));
972
+ __classPrivateFieldGet(list, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
762
973
  }
763
974
  return list;
764
975
  }
@@ -807,15 +1018,21 @@ class LiveList extends AbstractCrdt {
807
1018
  * INTERNAL
808
1019
  */
809
1020
  _attachChild(id, key, child) {
1021
+ var _a;
810
1022
  if (this._doc == null) {
811
1023
  throw new Error("Can't attach child if doc is not present");
812
1024
  }
813
1025
  child._attach(id, this._doc);
814
- child._setParent(this);
815
- // TODO: Handle list conflict
1026
+ child._setParentLink(this, key);
1027
+ const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
1028
+ // Assign a temporary position until we get the fix from the backend
1029
+ if (index !== -1) {
1030
+ __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]);
1031
+ }
816
1032
  __classPrivateFieldGet(this, _LiveList_items, "f").push([child, key]);
817
- __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)({ position: itemA[1] }, { position: itemB[1] }));
818
- this.notify();
1033
+ __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
1034
+ this._notify();
1035
+ return [{ type: live_1.OpType.DeleteCrdt, id }];
819
1036
  }
820
1037
  /**
821
1038
  * INTERNAL
@@ -826,49 +1043,74 @@ class LiveList extends AbstractCrdt {
826
1043
  if (child) {
827
1044
  child._detach();
828
1045
  }
829
- this.notify();
1046
+ this._notify();
830
1047
  }
831
1048
  /**
832
1049
  * INTERNAL
833
1050
  */
834
1051
  _setChildKey(key, child) {
1052
+ var _a;
1053
+ child._setParentLink(this, key);
1054
+ const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
1055
+ // Assign a temporary position until we get the fix from the backend
1056
+ if (index !== -1) {
1057
+ __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]);
1058
+ }
835
1059
  const item = __classPrivateFieldGet(this, _LiveList_items, "f").find((item) => item[0] === child);
836
1060
  if (item) {
837
1061
  item[1] = key;
838
1062
  }
839
- __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)({ position: itemA[1] }, { position: itemB[1] }));
840
- this.notify();
1063
+ __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
1064
+ this._notify();
841
1065
  }
842
- push(item) {
843
- const position = __classPrivateFieldGet(this, _LiveList_items, "f").length === 0
844
- ? (0, position_1.makePosition)()
845
- : (0, position_1.makePosition)(__classPrivateFieldGet(this, _LiveList_items, "f")[__classPrivateFieldGet(this, _LiveList_items, "f").length - 1][1]);
846
- const value = selfOrRegister(item);
847
- value._setParent(this);
848
- __classPrivateFieldGet(this, _LiveList_items, "f").push([value, position]);
849
- this.notify();
850
- if (this._doc && this._id) {
851
- value._attach(this._doc.generateId(), this._doc);
852
- this._doc.dispatch(value._serialize(this._id, position));
853
- }
1066
+ /**
1067
+ * INTERNAL
1068
+ */
1069
+ _apply(op) {
1070
+ return super._apply(op);
1071
+ }
1072
+ /**
1073
+ * Returns the number of elements.
1074
+ */
1075
+ get length() {
1076
+ return __classPrivateFieldGet(this, _LiveList_items, "f").length;
1077
+ }
1078
+ /**
1079
+ * Adds one element to the end of the LiveList.
1080
+ * @param element The element to add to the end of the LiveList.
1081
+ */
1082
+ push(element) {
1083
+ return this.insert(element, this.length);
854
1084
  }
855
- insert(item, index) {
1085
+ /**
1086
+ * Inserts one element at a specified index.
1087
+ * @param element The element to insert.
1088
+ * @param index The index at which you want to insert the element.
1089
+ */
1090
+ insert(element, index) {
856
1091
  if (index < 0 || index > __classPrivateFieldGet(this, _LiveList_items, "f").length) {
857
1092
  throw new Error(`Cannot delete list item at index "${index}". index should be between 0 and ${__classPrivateFieldGet(this, _LiveList_items, "f").length}`);
858
1093
  }
859
1094
  let before = __classPrivateFieldGet(this, _LiveList_items, "f")[index - 1] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index - 1][1] : undefined;
860
1095
  let after = __classPrivateFieldGet(this, _LiveList_items, "f")[index] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] : undefined;
861
1096
  const position = (0, position_1.makePosition)(before, after);
862
- const value = selfOrRegister(item);
863
- value._setParent(this);
1097
+ const value = selfOrRegister(element);
1098
+ value._setParentLink(this, position);
864
1099
  __classPrivateFieldGet(this, _LiveList_items, "f").push([value, position]);
865
- __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)({ position: itemA[1] }, { position: itemB[1] }));
866
- this.notify();
1100
+ __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
1101
+ this._notify();
867
1102
  if (this._doc && this._id) {
868
- value._attach(this._doc.generateId(), this._doc);
1103
+ const id = this._doc.generateId();
1104
+ value._attach(id, this._doc);
1105
+ this._doc.addToUndoStack([{ type: live_1.OpType.DeleteCrdt, id }]);
869
1106
  this._doc.dispatch(value._serialize(this._id, position));
870
1107
  }
871
1108
  }
1109
+ /**
1110
+ * Move one element from one index to another.
1111
+ * @param index The index of the element to move
1112
+ * @param targetIndex The index where the element should be after moving.
1113
+ */
872
1114
  move(index, targetIndex) {
873
1115
  if (targetIndex < 0) {
874
1116
  throw new Error("targetIndex cannot be less than 0");
@@ -898,17 +1140,32 @@ class LiveList extends AbstractCrdt {
898
1140
  }
899
1141
  const position = (0, position_1.makePosition)(beforePosition, afterPosition);
900
1142
  const item = __classPrivateFieldGet(this, _LiveList_items, "f")[index];
1143
+ const previousPosition = item[1];
901
1144
  item[1] = position;
902
- __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)({ position: itemA[1] }, { position: itemB[1] }));
903
- this.notify();
1145
+ item[0]._setParentLink(this, position);
1146
+ __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
1147
+ this._notify();
904
1148
  if (this._doc && this._id) {
905
- this._doc.dispatch([{
1149
+ this._doc.addToUndoStack([
1150
+ {
1151
+ type: live_1.OpType.SetParentKey,
1152
+ id: item[0]._id,
1153
+ parentKey: previousPosition,
1154
+ },
1155
+ ]);
1156
+ this._doc.dispatch([
1157
+ {
906
1158
  type: live_1.OpType.SetParentKey,
907
1159
  id: item[0]._id,
908
1160
  parentKey: position,
909
- },]);
1161
+ },
1162
+ ]);
910
1163
  }
911
1164
  }
1165
+ /**
1166
+ * Deletes an element at the specified index
1167
+ * @param index The index of the element to delete
1168
+ */
912
1169
  delete(index) {
913
1170
  if (index < 0 || index >= __classPrivateFieldGet(this, _LiveList_items, "f").length) {
914
1171
  throw new Error(`Cannot delete list item at index "${index}". index should be between 0 and ${__classPrivateFieldGet(this, _LiveList_items, "f").length - 1}`);
@@ -919,6 +1176,7 @@ class LiveList extends AbstractCrdt {
919
1176
  if (this._doc) {
920
1177
  const childRecordId = item[0]._id;
921
1178
  if (childRecordId) {
1179
+ this._doc.addToUndoStack(item[0]._serialize(this._id, item[1]));
922
1180
  this._doc.dispatch([
923
1181
  {
924
1182
  id: childRecordId,
@@ -927,38 +1185,95 @@ class LiveList extends AbstractCrdt {
927
1185
  ]);
928
1186
  }
929
1187
  }
930
- this.notify();
1188
+ this._notify();
931
1189
  }
1190
+ /**
1191
+ * Returns an Array of all the elements in the LiveList.
1192
+ */
932
1193
  toArray() {
933
1194
  return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry) => selfOrRegisterValue(entry[0]));
934
1195
  }
1196
+ /**
1197
+ * Tests whether all elements pass the test implemented by the provided function.
1198
+ * @param predicate Function to test for each element, taking two arguments (the element and its index).
1199
+ * @returns true if the predicate function returns a truthy value for every element. Otherwise, false.
1200
+ */
935
1201
  every(predicate) {
936
1202
  return this.toArray().every(predicate);
937
1203
  }
1204
+ /**
1205
+ * Creates an array with all elements that pass the test implemented by the provided function.
1206
+ * @param predicate Function to test each element of the LiveList. Return a value that coerces to true to keep the element, or to false otherwise.
1207
+ * @returns An array with the elements that pass the test.
1208
+ */
938
1209
  filter(predicate) {
939
1210
  return this.toArray().filter(predicate);
940
1211
  }
1212
+ /**
1213
+ * Returns the first element that satisfies the provided testing function.
1214
+ * @param predicate Function to execute on each value.
1215
+ * @returns The value of the first element in the LiveList that satisfies the provided testing function. Otherwise, undefined is returned.
1216
+ */
941
1217
  find(predicate) {
942
1218
  return this.toArray().find(predicate);
943
1219
  }
1220
+ /**
1221
+ * Returns the index of the first element in the LiveList that satisfies the provided testing function.
1222
+ * @param predicate Function to execute on each value until the function returns true, indicating that the satisfying element was found.
1223
+ * @returns The index of the first element in the LiveList that passes the test. Otherwise, -1.
1224
+ */
944
1225
  findIndex(predicate) {
945
1226
  return this.toArray().findIndex(predicate);
946
1227
  }
1228
+ /**
1229
+ * Executes a provided function once for each element.
1230
+ * @param callbackfn Function to execute on each element.
1231
+ */
947
1232
  forEach(callbackfn) {
948
1233
  return this.toArray().forEach(callbackfn);
949
1234
  }
1235
+ /**
1236
+ * Get the element at the specified index.
1237
+ * @param index The index on the element to get.
1238
+ * @returns The element at the specified index or undefined.
1239
+ */
950
1240
  get(index) {
1241
+ if (index < 0 || index >= __classPrivateFieldGet(this, _LiveList_items, "f").length) {
1242
+ return undefined;
1243
+ }
951
1244
  return selfOrRegisterValue(__classPrivateFieldGet(this, _LiveList_items, "f")[index][0]);
952
1245
  }
1246
+ /**
1247
+ * Returns the first index at which a given element can be found in the LiveList, or -1 if it is not present.
1248
+ * @param searchElement Element to locate.
1249
+ * @param fromIndex The index to start the search at.
1250
+ * @returns The first index of the element in the LiveList; -1 if not found.
1251
+ */
953
1252
  indexOf(searchElement, fromIndex) {
954
1253
  return this.toArray().indexOf(searchElement, fromIndex);
955
1254
  }
1255
+ /**
1256
+ * Returns the last index at which a given element can be found in the LiveList, or -1 if it is not present. The LiveLsit is searched backwards, starting at fromIndex.
1257
+ * @param searchElement Element to locate.
1258
+ * @param fromIndex The index at which to start searching backwards.
1259
+ * @returns
1260
+ */
956
1261
  lastIndexOf(searchElement, fromIndex) {
957
1262
  return this.toArray().lastIndexOf(searchElement, fromIndex);
958
1263
  }
1264
+ /**
1265
+ * Creates an array populated with the results of calling a provided function on every element.
1266
+ * @param callback Function that is called for every element.
1267
+ * @returns An array with each element being the result of the callback function.
1268
+ */
959
1269
  map(callback) {
960
1270
  return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry, i) => callback(selfOrRegisterValue(entry[0]), i));
961
1271
  }
1272
+ /**
1273
+ * Tests whether at least one element in the LiveList passes the test implemented by the provided function.
1274
+ * @param predicate Function to test for each element.
1275
+ * @returns true if the callback function returns a truthy value for at least one element. Otherwise, false.
1276
+ */
962
1277
  some(predicate) {
963
1278
  return this.toArray().some(predicate);
964
1279
  }