@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/README.md +2 -12
- package/lib/cjs/authentication.d.ts +1 -1
- package/lib/cjs/authentication.js +4 -3
- package/lib/cjs/doc.d.ts +182 -11
- package/lib/cjs/doc.js +513 -198
- package/lib/cjs/live.d.ts +1 -0
- package/lib/cjs/position.d.ts +1 -5
- package/lib/cjs/position.js +4 -4
- package/lib/cjs/room.d.ts +3 -0
- package/lib/cjs/room.js +22 -3
- package/lib/cjs/storage.d.ts +2 -0
- package/lib/cjs/storage.js +14 -8
- package/lib/cjs/types.d.ts +13 -6
- package/lib/esm/authentication.d.ts +1 -1
- package/lib/esm/authentication.js +4 -3
- package/lib/esm/doc.d.ts +182 -11
- package/lib/esm/doc.js +513 -198
- package/lib/esm/live.d.ts +1 -0
- package/lib/esm/position.d.ts +1 -5
- package/lib/esm/position.js +4 -4
- package/lib/esm/room.d.ts +3 -0
- package/lib/esm/room.js +22 -3
- package/lib/esm/storage.d.ts +2 -0
- package/lib/esm/storage.js +14 -8
- package/lib/esm/types.d.ts +13 -6
- package/package.json +1 -1
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,
|
|
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(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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(),
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
224
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
443
|
+
child._setParentLink(this, key);
|
|
363
444
|
child._attach(id, this._doc);
|
|
364
|
-
this.
|
|
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.
|
|
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.
|
|
514
|
+
this._notify();
|
|
515
|
+
return reverse;
|
|
405
516
|
}
|
|
406
517
|
else if (op.type === live_1.OpType.DeleteObjectKey) {
|
|
407
|
-
|
|
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
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
777
|
+
item._setParentLink(this, key);
|
|
610
778
|
__classPrivateFieldGet(this, _LiveMap_map, "f").set(key, item);
|
|
611
779
|
if (this._doc && this._id) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
this._doc.
|
|
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.
|
|
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.
|
|
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.
|
|
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)(
|
|
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.
|
|
815
|
-
|
|
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)(
|
|
818
|
-
this.
|
|
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.
|
|
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)(
|
|
840
|
-
this.
|
|
1063
|
+
__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
|
|
1064
|
+
this._notify();
|
|
841
1065
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
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
|
-
|
|
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(
|
|
863
|
-
value.
|
|
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)(
|
|
866
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
903
|
-
this.
|
|
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.
|
|
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.
|
|
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
|
}
|