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