@liveblocks/client 0.16.13 → 0.16.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/index.d.ts +1 -1
- package/index.js +43 -30
- package/index.mjs +46 -34
- package/internal.d.ts +199 -77
- package/internal.js +15 -13
- package/internal.mjs +16 -14
- package/package.json +9 -13
- package/shared.d.ts +181 -342
- package/shared.js +341 -590
- package/shared.mjs +306 -625
package/shared.mjs
CHANGED
|
@@ -1,39 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
function deprecate(message, key = message) {
|
|
4
|
-
"production" !== process.env.NODE_ENV && (_emittedDeprecationWarnings.has(key) || (_emittedDeprecationWarnings.add(key),
|
|
5
|
-
console.error(`DEPRECATION WARNING: ${message}`)));
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function deprecateIf(condition, message, key = message) {
|
|
9
|
-
"production" !== process.env.NODE_ENV && condition && deprecate(message, key);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function throwUsageError(message) {
|
|
13
|
-
if ("production" !== process.env.NODE_ENV) {
|
|
14
|
-
const usageError = new Error(message);
|
|
15
|
-
throw usageError.name = "Usage error", usageError;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function errorIf(condition, message) {
|
|
20
|
-
"production" !== process.env.NODE_ENV && condition && throwUsageError(message);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function assertNever(_value, errmsg) {
|
|
24
|
-
throw new Error(errmsg);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function nn(value, errmsg = "Expected value to be non-nullable") {
|
|
28
|
-
return function(condition, errmsg) {
|
|
29
|
-
if ("production" !== process.env.NODE_ENV && !condition) {
|
|
30
|
-
const err = new Error(errmsg);
|
|
31
|
-
throw err.name = "Assertion failure", err;
|
|
32
|
-
}
|
|
33
|
-
}(null != value, errmsg), value;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
var ClientMsgCode, OpCode, CrdtType, ServerMsgCode, WebsocketCloseCodes, OpSource;
|
|
1
|
+
var ServerMsgCode, ClientMsgCode, CrdtType, OpCode, WebsocketCloseCodes;
|
|
37
2
|
|
|
38
3
|
function isRootCrdt(crdt) {
|
|
39
4
|
return crdt.type === CrdtType.OBJECT && !isChildCrdt(crdt);
|
|
@@ -43,32 +8,24 @@ function isChildCrdt(crdt) {
|
|
|
43
8
|
return void 0 !== crdt.parentId && void 0 !== crdt.parentKey;
|
|
44
9
|
}
|
|
45
10
|
|
|
46
|
-
function
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
!function(ClientMsgCode) {
|
|
11
|
+
!function(ServerMsgCode) {
|
|
12
|
+
ServerMsgCode[ServerMsgCode.UPDATE_PRESENCE = 100] = "UPDATE_PRESENCE", ServerMsgCode[ServerMsgCode.USER_JOINED = 101] = "USER_JOINED",
|
|
13
|
+
ServerMsgCode[ServerMsgCode.USER_LEFT = 102] = "USER_LEFT", ServerMsgCode[ServerMsgCode.BROADCASTED_EVENT = 103] = "BROADCASTED_EVENT",
|
|
14
|
+
ServerMsgCode[ServerMsgCode.ROOM_STATE = 104] = "ROOM_STATE", ServerMsgCode[ServerMsgCode.INITIAL_STORAGE_STATE = 200] = "INITIAL_STORAGE_STATE",
|
|
15
|
+
ServerMsgCode[ServerMsgCode.UPDATE_STORAGE = 201] = "UPDATE_STORAGE";
|
|
16
|
+
}(ServerMsgCode || (ServerMsgCode = {})), function(ClientMsgCode) {
|
|
55
17
|
ClientMsgCode[ClientMsgCode.UPDATE_PRESENCE = 100] = "UPDATE_PRESENCE", ClientMsgCode[ClientMsgCode.BROADCAST_EVENT = 103] = "BROADCAST_EVENT",
|
|
56
18
|
ClientMsgCode[ClientMsgCode.FETCH_STORAGE = 200] = "FETCH_STORAGE", ClientMsgCode[ClientMsgCode.UPDATE_STORAGE = 201] = "UPDATE_STORAGE";
|
|
57
|
-
}(ClientMsgCode || (ClientMsgCode = {})), function(
|
|
19
|
+
}(ClientMsgCode || (ClientMsgCode = {})), function(CrdtType) {
|
|
20
|
+
CrdtType[CrdtType.OBJECT = 0] = "OBJECT", CrdtType[CrdtType.LIST = 1] = "LIST",
|
|
21
|
+
CrdtType[CrdtType.MAP = 2] = "MAP", CrdtType[CrdtType.REGISTER = 3] = "REGISTER";
|
|
22
|
+
}(CrdtType || (CrdtType = {})), function(OpCode) {
|
|
58
23
|
OpCode[OpCode.INIT = 0] = "INIT", OpCode[OpCode.SET_PARENT_KEY = 1] = "SET_PARENT_KEY",
|
|
59
24
|
OpCode[OpCode.CREATE_LIST = 2] = "CREATE_LIST", OpCode[OpCode.UPDATE_OBJECT = 3] = "UPDATE_OBJECT",
|
|
60
25
|
OpCode[OpCode.CREATE_OBJECT = 4] = "CREATE_OBJECT", OpCode[OpCode.DELETE_CRDT = 5] = "DELETE_CRDT",
|
|
61
26
|
OpCode[OpCode.DELETE_OBJECT_KEY = 6] = "DELETE_OBJECT_KEY", OpCode[OpCode.CREATE_MAP = 7] = "CREATE_MAP",
|
|
62
27
|
OpCode[OpCode.CREATE_REGISTER = 8] = "CREATE_REGISTER";
|
|
63
|
-
}(OpCode || (OpCode = {})), function(
|
|
64
|
-
CrdtType[CrdtType.OBJECT = 0] = "OBJECT", CrdtType[CrdtType.LIST = 1] = "LIST",
|
|
65
|
-
CrdtType[CrdtType.MAP = 2] = "MAP", CrdtType[CrdtType.REGISTER = 3] = "REGISTER";
|
|
66
|
-
}(CrdtType || (CrdtType = {})), function(ServerMsgCode) {
|
|
67
|
-
ServerMsgCode[ServerMsgCode.UPDATE_PRESENCE = 100] = "UPDATE_PRESENCE", ServerMsgCode[ServerMsgCode.USER_JOINED = 101] = "USER_JOINED",
|
|
68
|
-
ServerMsgCode[ServerMsgCode.USER_LEFT = 102] = "USER_LEFT", ServerMsgCode[ServerMsgCode.BROADCASTED_EVENT = 103] = "BROADCASTED_EVENT",
|
|
69
|
-
ServerMsgCode[ServerMsgCode.ROOM_STATE = 104] = "ROOM_STATE", ServerMsgCode[ServerMsgCode.INITIAL_STORAGE_STATE = 200] = "INITIAL_STORAGE_STATE",
|
|
70
|
-
ServerMsgCode[ServerMsgCode.UPDATE_STORAGE = 201] = "UPDATE_STORAGE";
|
|
71
|
-
}(ServerMsgCode || (ServerMsgCode = {})), function(WebsocketCloseCodes) {
|
|
28
|
+
}(OpCode || (OpCode = {})), function(WebsocketCloseCodes) {
|
|
72
29
|
WebsocketCloseCodes[WebsocketCloseCodes.CLOSE_ABNORMAL = 1006] = "CLOSE_ABNORMAL",
|
|
73
30
|
WebsocketCloseCodes[WebsocketCloseCodes.INVALID_MESSAGE_FORMAT = 4e3] = "INVALID_MESSAGE_FORMAT",
|
|
74
31
|
WebsocketCloseCodes[WebsocketCloseCodes.NOT_ALLOWED = 4001] = "NOT_ALLOWED", WebsocketCloseCodes[WebsocketCloseCodes.MAX_NUMBER_OF_MESSAGES_PER_SECONDS = 4002] = "MAX_NUMBER_OF_MESSAGES_PER_SECONDS",
|
|
@@ -76,41 +33,9 @@ function HasParent(node, key) {
|
|
|
76
33
|
WebsocketCloseCodes[WebsocketCloseCodes.MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP = 4004] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP",
|
|
77
34
|
WebsocketCloseCodes[WebsocketCloseCodes.MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM = 4005] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM",
|
|
78
35
|
WebsocketCloseCodes[WebsocketCloseCodes.CLOSE_WITHOUT_RETRY = 4999] = "CLOSE_WITHOUT_RETRY";
|
|
79
|
-
}(WebsocketCloseCodes || (WebsocketCloseCodes = {}))
|
|
80
|
-
OpSource[OpSource.UNDOREDO_RECONNECT = 0] = "UNDOREDO_RECONNECT", OpSource[OpSource.REMOTE = 1] = "REMOTE",
|
|
81
|
-
OpSource[OpSource.ACK = 2] = "ACK";
|
|
82
|
-
}(OpSource || (OpSource = {}));
|
|
83
|
-
|
|
84
|
-
const NoParent = Object.freeze({
|
|
85
|
-
type: "NoParent"
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
function Orphaned(oldKey) {
|
|
89
|
-
return Object.freeze({
|
|
90
|
-
type: "Orphaned",
|
|
91
|
-
oldKey: oldKey
|
|
92
|
-
});
|
|
93
|
-
}
|
|
36
|
+
}(WebsocketCloseCodes || (WebsocketCloseCodes = {}));
|
|
94
37
|
|
|
95
38
|
class AbstractCrdt {
|
|
96
|
-
constructor() {
|
|
97
|
-
this._parent = NoParent;
|
|
98
|
-
}
|
|
99
|
-
_getParentKeyOrThrow() {
|
|
100
|
-
switch (this.parent.type) {
|
|
101
|
-
case "HasParent":
|
|
102
|
-
return this.parent.key;
|
|
103
|
-
|
|
104
|
-
case "NoParent":
|
|
105
|
-
throw new Error("Parent key is missing");
|
|
106
|
-
|
|
107
|
-
case "Orphaned":
|
|
108
|
-
return this.parent.oldKey;
|
|
109
|
-
|
|
110
|
-
default:
|
|
111
|
-
return assertNever(this.parent, "Unknown state");
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
39
|
get _doc() {
|
|
115
40
|
return this.__doc;
|
|
116
41
|
}
|
|
@@ -120,81 +45,39 @@ class AbstractCrdt {
|
|
|
120
45
|
get _id() {
|
|
121
46
|
return this.__id;
|
|
122
47
|
}
|
|
123
|
-
get
|
|
124
|
-
return this.
|
|
125
|
-
}
|
|
126
|
-
get _parentNode() {
|
|
127
|
-
switch (this.parent.type) {
|
|
128
|
-
case "HasParent":
|
|
129
|
-
return this.parent.node;
|
|
130
|
-
|
|
131
|
-
case "NoParent":
|
|
132
|
-
case "Orphaned":
|
|
133
|
-
return null;
|
|
134
|
-
|
|
135
|
-
default:
|
|
136
|
-
return assertNever(this.parent, "Unknown state");
|
|
137
|
-
}
|
|
48
|
+
get _parent() {
|
|
49
|
+
return this.__parent;
|
|
138
50
|
}
|
|
139
51
|
get _parentKey() {
|
|
140
|
-
|
|
141
|
-
case "HasParent":
|
|
142
|
-
return this.parent.key;
|
|
143
|
-
|
|
144
|
-
case "NoParent":
|
|
145
|
-
return null;
|
|
146
|
-
|
|
147
|
-
case "Orphaned":
|
|
148
|
-
return this.parent.oldKey;
|
|
149
|
-
|
|
150
|
-
default:
|
|
151
|
-
return assertNever(this.parent, "Unknown state");
|
|
152
|
-
}
|
|
52
|
+
return this.__parentKey;
|
|
153
53
|
}
|
|
154
54
|
_apply(op, _isLocal) {
|
|
155
|
-
return op.type === OpCode.DELETE_CRDT &&
|
|
55
|
+
return op.type === OpCode.DELETE_CRDT && null != this._parent && null != this._parentKey ? this._parent._detachChild(this) : {
|
|
156
56
|
modified: !1
|
|
157
57
|
};
|
|
158
58
|
}
|
|
159
|
-
_setParentLink(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (this.parent.node !== newParentNode) throw new Error("Cannot attach parent if it already exist");
|
|
163
|
-
return void (this._parent = HasParent(newParentNode, newParentKey));
|
|
164
|
-
|
|
165
|
-
case "Orphaned":
|
|
166
|
-
case "NoParent":
|
|
167
|
-
return void (this._parent = HasParent(newParentNode, newParentKey));
|
|
168
|
-
|
|
169
|
-
default:
|
|
170
|
-
return assertNever(this.parent, "Unknown state");
|
|
171
|
-
}
|
|
59
|
+
_setParentLink(parent, key) {
|
|
60
|
+
if (null != this.__parent && this.__parent !== parent) throw new Error("Cannot attach parent if it already exist");
|
|
61
|
+
this.__parentKey = key, this.__parent = parent;
|
|
172
62
|
}
|
|
173
63
|
_attach(id, doc) {
|
|
174
64
|
if (this.__id || this.__doc) throw new Error("Cannot attach if CRDT is already attached");
|
|
175
65
|
doc.addItem(id, this), this.__id = id, this.__doc = doc;
|
|
176
66
|
}
|
|
177
67
|
_detach() {
|
|
178
|
-
|
|
179
|
-
case "HasParent":
|
|
180
|
-
this._parent = Orphaned(this.parent.key);
|
|
181
|
-
break;
|
|
182
|
-
|
|
183
|
-
case "NoParent":
|
|
184
|
-
this._parent = NoParent;
|
|
185
|
-
break;
|
|
186
|
-
|
|
187
|
-
case "Orphaned":
|
|
188
|
-
this._parent = Orphaned(this.parent.oldKey);
|
|
189
|
-
break;
|
|
190
|
-
|
|
191
|
-
default:
|
|
192
|
-
assertNever(this.parent, "Unknown state");
|
|
193
|
-
}
|
|
68
|
+
this.__doc && this.__id && this.__doc.deleteItem(this.__id), this.__parent = void 0,
|
|
194
69
|
this.__doc = void 0;
|
|
195
70
|
}
|
|
196
71
|
}
|
|
197
72
|
|
|
73
|
+
function isJsonArray(data) {
|
|
74
|
+
return Array.isArray(data);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isJsonObject(data) {
|
|
78
|
+
return null !== data && "object" == typeof data && !isJsonArray(data);
|
|
79
|
+
}
|
|
80
|
+
|
|
198
81
|
class LiveRegister extends AbstractCrdt {
|
|
199
82
|
constructor(data) {
|
|
200
83
|
super(), this._data = data;
|
|
@@ -206,27 +89,28 @@ class LiveRegister extends AbstractCrdt {
|
|
|
206
89
|
const register = new LiveRegister(item.data);
|
|
207
90
|
return register._attach(id, doc), register;
|
|
208
91
|
}
|
|
209
|
-
_serialize(parentId, parentKey, doc) {
|
|
92
|
+
_serialize(parentId, parentKey, doc, intent) {
|
|
210
93
|
if (null == this._id || null == parentId || null == parentKey) throw new Error("Cannot serialize register if parentId or parentKey is undefined");
|
|
211
94
|
return [ {
|
|
212
95
|
type: OpCode.CREATE_REGISTER,
|
|
213
96
|
opId: null == doc ? void 0 : doc.generateOpId(),
|
|
214
97
|
id: this._id,
|
|
98
|
+
intent: intent,
|
|
215
99
|
parentId: parentId,
|
|
216
100
|
parentKey: parentKey,
|
|
217
101
|
data: this.data
|
|
218
102
|
} ];
|
|
219
103
|
}
|
|
220
104
|
_toSerializedCrdt() {
|
|
221
|
-
|
|
105
|
+
var _a;
|
|
222
106
|
return {
|
|
223
107
|
type: CrdtType.REGISTER,
|
|
224
|
-
parentId:
|
|
225
|
-
parentKey: this.
|
|
108
|
+
parentId: null === (_a = this._parent) || void 0 === _a ? void 0 : _a._id,
|
|
109
|
+
parentKey: this._parentKey,
|
|
226
110
|
data: this.data
|
|
227
111
|
};
|
|
228
112
|
}
|
|
229
|
-
_attachChild(_op) {
|
|
113
|
+
_attachChild(_op, _isLocal) {
|
|
230
114
|
throw new Error("Method not implemented.");
|
|
231
115
|
}
|
|
232
116
|
_detachChild(_crdt) {
|
|
@@ -238,7 +122,7 @@ class LiveRegister extends AbstractCrdt {
|
|
|
238
122
|
}
|
|
239
123
|
|
|
240
124
|
function makePosition(before, after) {
|
|
241
|
-
return null
|
|
125
|
+
return null == before && null == after ? pos([ 33 ]) : null != before && null == after ? function(before) {
|
|
242
126
|
const result = [], beforeCodes = posCodes(before);
|
|
243
127
|
for (let i = 0; i < beforeCodes.length; i++) {
|
|
244
128
|
const code = beforeCodes[i];
|
|
@@ -252,7 +136,7 @@ function makePosition(before, after) {
|
|
|
252
136
|
}
|
|
253
137
|
}
|
|
254
138
|
return pos(result);
|
|
255
|
-
}(before) : null != after ? function(after) {
|
|
139
|
+
}(before) : null == before && null != after ? function(after) {
|
|
256
140
|
const result = [], afterCodes = posCodes(after);
|
|
257
141
|
for (let i = 0; i < afterCodes.length; i++) {
|
|
258
142
|
const code = afterCodes[i];
|
|
@@ -266,7 +150,7 @@ function makePosition(before, after) {
|
|
|
266
150
|
}
|
|
267
151
|
}
|
|
268
152
|
return pos(result);
|
|
269
|
-
}(after) : pos(
|
|
153
|
+
}(after) : pos(makePositionFromCodes(posCodes(before), posCodes(after)));
|
|
270
154
|
}
|
|
271
155
|
|
|
272
156
|
function makePositionFromCodes(before, after) {
|
|
@@ -312,243 +196,114 @@ function comparePosition(posA, posB) {
|
|
|
312
196
|
class LiveList extends AbstractCrdt {
|
|
313
197
|
constructor(items = []) {
|
|
314
198
|
let position;
|
|
315
|
-
super(), this._items = []
|
|
199
|
+
super(), this._items = [];
|
|
316
200
|
for (let i = 0; i < items.length; i++) {
|
|
317
|
-
const newPosition = makePosition(position), item =
|
|
318
|
-
|
|
201
|
+
const newPosition = makePosition(position), item = selfOrRegister(items[i]);
|
|
202
|
+
this._items.push([ item, newPosition ]), position = newPosition;
|
|
319
203
|
}
|
|
320
204
|
}
|
|
321
205
|
static _deserialize([id], parentToChildren, doc) {
|
|
322
|
-
const list = new LiveList;
|
|
206
|
+
const list = new LiveList([]);
|
|
323
207
|
list._attach(id, doc);
|
|
324
208
|
const children = parentToChildren.get(id);
|
|
325
209
|
if (null == children) return list;
|
|
326
|
-
for (const
|
|
327
|
-
const child = deserialize(
|
|
328
|
-
child._setParentLink(list,
|
|
210
|
+
for (const entry of children) {
|
|
211
|
+
const child = deserialize(entry, parentToChildren, doc);
|
|
212
|
+
child._setParentLink(list, entry[1].parentKey), list._items.push([ child, entry[1].parentKey ]),
|
|
213
|
+
list._items.sort(((itemA, itemB) => comparePosition(itemA[1], itemB[1])));
|
|
329
214
|
}
|
|
330
215
|
return list;
|
|
331
216
|
}
|
|
332
|
-
_serialize(parentId, parentKey, doc) {
|
|
217
|
+
_serialize(parentId, parentKey, doc, intent) {
|
|
333
218
|
if (null == this._id) throw new Error("Cannot serialize item is not attached");
|
|
219
|
+
if (null == parentId || null == parentKey) throw new Error("Cannot serialize list if parentId or parentKey is undefined");
|
|
334
220
|
const ops = [], op = {
|
|
335
221
|
id: this._id,
|
|
336
222
|
opId: null == doc ? void 0 : doc.generateOpId(),
|
|
223
|
+
intent: intent,
|
|
337
224
|
type: OpCode.CREATE_LIST,
|
|
338
225
|
parentId: parentId,
|
|
339
226
|
parentKey: parentKey
|
|
340
227
|
};
|
|
341
228
|
ops.push(op);
|
|
342
|
-
for (const
|
|
229
|
+
for (const [value, key] of this._items) ops.push(...value._serialize(this._id, key, doc));
|
|
343
230
|
return ops;
|
|
344
231
|
}
|
|
345
232
|
_indexOfPosition(position) {
|
|
346
|
-
return this._items.findIndex((item => item
|
|
233
|
+
return this._items.findIndex((item => item[1] === position));
|
|
347
234
|
}
|
|
348
235
|
_attach(id, doc) {
|
|
349
236
|
super._attach(id, doc);
|
|
350
|
-
for (const item of this._items) item._attach(doc.generateId(), doc);
|
|
237
|
+
for (const [item] of this._items) item._attach(doc.generateId(), doc);
|
|
351
238
|
}
|
|
352
239
|
_detach() {
|
|
353
240
|
super._detach();
|
|
354
|
-
for (const
|
|
355
|
-
}
|
|
356
|
-
_applyRemoteSet(op) {
|
|
357
|
-
if (null == this._doc) throw new Error("Can't attach child if doc is not present");
|
|
358
|
-
const {id: id, parentKey: key} = op, child = creationOpToLiveNode(op);
|
|
359
|
-
child._attach(id, this._doc), child._setParentLink(this, key);
|
|
360
|
-
const deletedId = op.deletedId, existingItemIndex = this._indexOfPosition(key);
|
|
361
|
-
if (-1 !== existingItemIndex) {
|
|
362
|
-
const existingItem = this._items[existingItemIndex];
|
|
363
|
-
if (existingItem._id === deletedId) return existingItem._detach(), this._items[existingItemIndex] = child,
|
|
364
|
-
{
|
|
365
|
-
modified: makeUpdate(this, [ setDelta(existingItemIndex, child) ]),
|
|
366
|
-
reverse: []
|
|
367
|
-
};
|
|
368
|
-
{
|
|
369
|
-
this._implicitlyDeletedItems.add(existingItem), this._items[existingItemIndex] = child;
|
|
370
|
-
const delta = [ setDelta(existingItemIndex, child) ], deleteDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
371
|
-
return deleteDelta && delta.push(deleteDelta), {
|
|
372
|
-
modified: makeUpdate(this, delta),
|
|
373
|
-
reverse: []
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
{
|
|
378
|
-
const updates = [], deleteDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
379
|
-
return deleteDelta && updates.push(deleteDelta), this._items.push(child), sortListItem(this._items),
|
|
380
|
-
updates.push(insertDelta(this._indexOfPosition(key), child)), {
|
|
381
|
-
reverse: [],
|
|
382
|
-
modified: makeUpdate(this, updates)
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
_applySetAck(op) {
|
|
387
|
-
const delta = [], deletedDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
388
|
-
deletedDelta && delta.push(deletedDelta);
|
|
389
|
-
const indexOfItemWithSamePosition = this._indexOfPosition(op.parentKey), existingItem = this._items.find((item => item._id === op.id));
|
|
390
|
-
if (null != existingItem) {
|
|
391
|
-
if (existingItem._parentKey === op.parentKey) return delta.length > 0 ? {
|
|
392
|
-
modified: makeUpdate(this, delta),
|
|
393
|
-
reverse: []
|
|
394
|
-
} : {
|
|
395
|
-
modified: !1
|
|
396
|
-
};
|
|
397
|
-
-1 !== indexOfItemWithSamePosition && (this._implicitlyDeletedItems.add(this._items[indexOfItemWithSamePosition]),
|
|
398
|
-
this._items.splice(indexOfItemWithSamePosition, 1), delta.push(deleteDelta(indexOfItemWithSamePosition)));
|
|
399
|
-
const previousIndex = this._items.indexOf(existingItem);
|
|
400
|
-
existingItem._setParentLink(this, op.parentKey), sortListItem(this._items);
|
|
401
|
-
const newIndex = this._items.indexOf(existingItem);
|
|
402
|
-
return newIndex !== previousIndex && delta.push(moveDelta(previousIndex, newIndex, existingItem)),
|
|
403
|
-
{
|
|
404
|
-
modified: delta.length > 0 && makeUpdate(this, delta),
|
|
405
|
-
reverse: []
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
{
|
|
409
|
-
const orphan = nn(this._doc).getItem(op.id);
|
|
410
|
-
if (orphan && this._implicitlyDeletedItems.has(orphan)) {
|
|
411
|
-
orphan._setParentLink(this, op.parentKey), this._implicitlyDeletedItems.delete(orphan),
|
|
412
|
-
this._items.push(orphan), sortListItem(this._items);
|
|
413
|
-
const recreatedItemIndex = this._items.indexOf(orphan);
|
|
414
|
-
return {
|
|
415
|
-
modified: makeUpdate(this, [ -1 === indexOfItemWithSamePosition ? insertDelta(recreatedItemIndex, orphan) : setDelta(recreatedItemIndex, orphan), ...delta ]),
|
|
416
|
-
reverse: []
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
{
|
|
420
|
-
const {newItem: newItem, newIndex: newIndex} = this._createAttachItemAndSort(op, op.parentKey);
|
|
421
|
-
return {
|
|
422
|
-
modified: makeUpdate(this, [ -1 === indexOfItemWithSamePosition ? insertDelta(newIndex, newItem) : setDelta(newIndex, newItem), ...delta ]),
|
|
423
|
-
reverse: []
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
}
|
|
241
|
+
for (const [value] of this._items) value._detach();
|
|
427
242
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const deletedItem = this._doc.getItem(deletedId);
|
|
431
|
-
if (null == deletedItem) return null;
|
|
432
|
-
const result = this._detachChild(deletedItem);
|
|
433
|
-
return !1 === result.modified ? null : result.modified.updates[0];
|
|
434
|
-
}
|
|
435
|
-
_applyRemoteInsert(op) {
|
|
243
|
+
_attachChild(op, isLocal) {
|
|
244
|
+
var _a;
|
|
436
245
|
if (null == this._doc) throw new Error("Can't attach child if doc is not present");
|
|
437
|
-
const key =
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
return {
|
|
441
|
-
modified: makeUpdate(this, [ insertDelta(newIndex, newItem) ]),
|
|
442
|
-
reverse: []
|
|
246
|
+
const {id: id, parentKey: parentKey, intent: intent} = op, key = parentKey, child = creationOpToLiveStructure(op);
|
|
247
|
+
if (void 0 !== this._doc.getItem(id)) return {
|
|
248
|
+
modified: !1
|
|
443
249
|
};
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
if (
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
modified: makeUpdate(this, [ moveDelta(oldPositionIndex, newIndex, existingItem) ]),
|
|
460
|
-
reverse: []
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
{
|
|
465
|
-
const orphan = nn(this._doc).getItem(op.id);
|
|
466
|
-
if (orphan && this._implicitlyDeletedItems.has(orphan)) {
|
|
467
|
-
orphan._setParentLink(this, key), this._implicitlyDeletedItems.delete(orphan), this._items.push(orphan),
|
|
468
|
-
sortListItem(this._items);
|
|
469
|
-
return {
|
|
470
|
-
modified: makeUpdate(this, [ insertDelta(this._indexOfPosition(key), orphan) ]),
|
|
471
|
-
reverse: []
|
|
250
|
+
child._attach(id, this._doc), child._setParentLink(this, key);
|
|
251
|
+
const index = this._items.findIndex((entry => entry[1] === key));
|
|
252
|
+
let newKey = key;
|
|
253
|
+
if (-1 !== index) {
|
|
254
|
+
if ("set" === intent) {
|
|
255
|
+
const existingItem = this._items[index][0];
|
|
256
|
+
existingItem._detach();
|
|
257
|
+
const storageUpdate = {
|
|
258
|
+
node: this,
|
|
259
|
+
type: "LiveList",
|
|
260
|
+
updates: [ {
|
|
261
|
+
index: index,
|
|
262
|
+
type: "set",
|
|
263
|
+
item: child instanceof LiveRegister ? child.data : child
|
|
264
|
+
} ]
|
|
472
265
|
};
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const {newItem: newItem, newIndex: newIndex} = this._createAttachItemAndSort(op, key);
|
|
477
|
-
return {
|
|
478
|
-
modified: makeUpdate(this, [ insertDelta(newIndex, newItem) ]),
|
|
479
|
-
reverse: []
|
|
266
|
+
return this._items[index][0] = child, {
|
|
267
|
+
modified: storageUpdate,
|
|
268
|
+
reverse: existingItem._serialize(this._id, key, this._doc, "set")
|
|
480
269
|
};
|
|
481
270
|
}
|
|
271
|
+
if (isLocal) {
|
|
272
|
+
const before = this._items[index] ? this._items[index][1] : void 0, after = this._items[index + 1] ? this._items[index + 1][1] : void 0;
|
|
273
|
+
newKey = makePosition(before, after), child._setParentLink(this, newKey);
|
|
274
|
+
} else this._items[index][1] = makePosition(key, null === (_a = this._items[index + 1]) || void 0 === _a ? void 0 : _a[1]);
|
|
482
275
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
var _a;
|
|
486
|
-
const {id: id, parentKey: key} = op, child = creationOpToLiveNode(op);
|
|
487
|
-
if (void 0 !== (null === (_a = this._doc) || void 0 === _a ? void 0 : _a.getItem(id))) return {
|
|
488
|
-
modified: !1
|
|
489
|
-
};
|
|
490
|
-
child._attach(id, nn(this._doc)), child._setParentLink(this, key);
|
|
491
|
-
const existingItemIndex = this._indexOfPosition(key);
|
|
492
|
-
let newKey = key;
|
|
493
|
-
if (-1 !== existingItemIndex) {
|
|
494
|
-
newKey = makePosition(this._items[existingItemIndex] ? this._items[existingItemIndex]._getParentKeyOrThrow() : void 0, this._items[existingItemIndex + 1] ? this._items[existingItemIndex + 1]._getParentKeyOrThrow() : void 0),
|
|
495
|
-
child._setParentLink(this, newKey);
|
|
496
|
-
}
|
|
497
|
-
this._items.push(child), sortListItem(this._items);
|
|
276
|
+
this._items.push([ child, newKey ]), this._items.sort(((itemA, itemB) => comparePosition(itemA[1], itemB[1])));
|
|
277
|
+
const newIndex = this._items.findIndex((entry => entry[1] === newKey));
|
|
498
278
|
return {
|
|
499
|
-
modified: makeUpdate(this, [ insertDelta(this._indexOfPosition(newKey), child) ]),
|
|
500
279
|
reverse: [ {
|
|
501
280
|
type: OpCode.DELETE_CRDT,
|
|
502
281
|
id: id
|
|
503
|
-
} ]
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
282
|
+
} ],
|
|
283
|
+
modified: {
|
|
284
|
+
node: this,
|
|
285
|
+
type: "LiveList",
|
|
286
|
+
updates: [ {
|
|
287
|
+
index: newIndex,
|
|
288
|
+
type: "insert",
|
|
289
|
+
item: child instanceof LiveRegister ? child.data : child
|
|
290
|
+
} ]
|
|
291
|
+
}
|
|
511
292
|
};
|
|
512
|
-
const indexOfItemWithSameKey = this._indexOfPosition(key);
|
|
513
|
-
child._attach(id, nn(this._doc)), child._setParentLink(this, key);
|
|
514
|
-
const newKey = key;
|
|
515
|
-
if (-1 !== indexOfItemWithSameKey) {
|
|
516
|
-
const existingItem = this._items[indexOfItemWithSameKey];
|
|
517
|
-
existingItem._detach(), this._items[indexOfItemWithSameKey] = child;
|
|
518
|
-
const reverse = existingItem._serialize(nn(this._id), key, this._doc);
|
|
519
|
-
addIntentAndDeletedIdToOperation(reverse, op.id);
|
|
520
|
-
const delta = [ setDelta(indexOfItemWithSameKey, child) ], deletedDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
521
|
-
return deletedDelta && delta.push(deletedDelta), {
|
|
522
|
-
modified: makeUpdate(this, delta),
|
|
523
|
-
reverse: reverse
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
{
|
|
527
|
-
this._items.push(child), sortListItem(this._items), this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
528
|
-
const newIndex = this._indexOfPosition(newKey);
|
|
529
|
-
return {
|
|
530
|
-
reverse: [ {
|
|
531
|
-
type: OpCode.DELETE_CRDT,
|
|
532
|
-
id: id
|
|
533
|
-
} ],
|
|
534
|
-
modified: makeUpdate(this, [ insertDelta(newIndex, child) ])
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
_attachChild(op, source) {
|
|
539
|
-
if (null == this._doc) throw new Error("Can't attach child if doc is not present");
|
|
540
|
-
if ("set" === op.intent) {
|
|
541
|
-
if (source === OpSource.REMOTE) return this._applyRemoteSet(op);
|
|
542
|
-
if (source === OpSource.UNDOREDO_RECONNECT) return this._applySetUndoRedo(op);
|
|
543
|
-
if (source === OpSource.ACK) return this._applySetAck(op);
|
|
544
|
-
}
|
|
545
|
-
return source === OpSource.REMOTE ? this._applyRemoteInsert(op) : source === OpSource.ACK ? this._applyInsertAck(op) : this._applyInsertUndoRedo(op);
|
|
546
293
|
}
|
|
547
294
|
_detachChild(child) {
|
|
548
295
|
if (child) {
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
|
|
296
|
+
const reverse = child._serialize(this._id, child._parentKey, this._doc), indexToDelete = this._items.findIndex((item => item[0] === child));
|
|
297
|
+
this._items.splice(indexToDelete, 1), child._detach();
|
|
298
|
+
return {
|
|
299
|
+
modified: {
|
|
300
|
+
node: this,
|
|
301
|
+
type: "LiveList",
|
|
302
|
+
updates: [ {
|
|
303
|
+
index: indexToDelete,
|
|
304
|
+
type: "delete"
|
|
305
|
+
} ]
|
|
306
|
+
},
|
|
552
307
|
reverse: reverse
|
|
553
308
|
};
|
|
554
309
|
}
|
|
@@ -556,100 +311,41 @@ class LiveList extends AbstractCrdt {
|
|
|
556
311
|
modified: !1
|
|
557
312
|
};
|
|
558
313
|
}
|
|
559
|
-
|
|
560
|
-
var _a;
|
|
561
|
-
if (this._implicitlyDeletedItems.has(child)) {
|
|
562
|
-
this._implicitlyDeletedItems.delete(child), child._setParentLink(this, newKey),
|
|
563
|
-
this._items.push(child), sortListItem(this._items);
|
|
564
|
-
return {
|
|
565
|
-
modified: makeUpdate(this, [ insertDelta(this._items.indexOf(child), child) ]),
|
|
566
|
-
reverse: []
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
if (newKey === child._parentKey) return {
|
|
570
|
-
modified: !1
|
|
571
|
-
};
|
|
572
|
-
const existingItemIndex = this._indexOfPosition(newKey);
|
|
573
|
-
if (-1 === existingItemIndex) {
|
|
574
|
-
const previousIndex = this._items.indexOf(child);
|
|
575
|
-
child._setParentLink(this, newKey), sortListItem(this._items);
|
|
576
|
-
const newIndex = this._items.indexOf(child);
|
|
577
|
-
return newIndex === previousIndex ? {
|
|
578
|
-
modified: !1
|
|
579
|
-
} : {
|
|
580
|
-
modified: makeUpdate(this, [ moveDelta(previousIndex, newIndex, child) ]),
|
|
581
|
-
reverse: []
|
|
582
|
-
};
|
|
583
|
-
}
|
|
584
|
-
{
|
|
585
|
-
this._items[existingItemIndex]._setParentLink(this, makePosition(newKey, null === (_a = this._items[existingItemIndex + 1]) || void 0 === _a ? void 0 : _a._getParentKeyOrThrow()));
|
|
586
|
-
const previousIndex = this._items.indexOf(child);
|
|
587
|
-
child._setParentLink(this, newKey), sortListItem(this._items);
|
|
588
|
-
const newIndex = this._items.indexOf(child);
|
|
589
|
-
return newIndex === previousIndex ? {
|
|
590
|
-
modified: !1
|
|
591
|
-
} : {
|
|
592
|
-
modified: makeUpdate(this, [ moveDelta(previousIndex, newIndex, child) ]),
|
|
593
|
-
reverse: []
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
_applySetChildKeyAck(newKey, child) {
|
|
598
|
-
var _a, _b;
|
|
599
|
-
const previousKey = nn(child._parentKey);
|
|
600
|
-
if (this._implicitlyDeletedItems.has(child)) {
|
|
601
|
-
const existingItemIndex = this._indexOfPosition(newKey);
|
|
602
|
-
return this._implicitlyDeletedItems.delete(child), -1 !== existingItemIndex && this._items[existingItemIndex]._setParentLink(this, makePosition(newKey, null === (_a = this._items[existingItemIndex + 1]) || void 0 === _a ? void 0 : _a._getParentKeyOrThrow())),
|
|
603
|
-
child._setParentLink(this, newKey), this._items.push(child), sortListItem(this._items),
|
|
604
|
-
{
|
|
605
|
-
modified: !1
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
{
|
|
609
|
-
if (newKey === previousKey) return {
|
|
610
|
-
modified: !1
|
|
611
|
-
};
|
|
612
|
-
const previousIndex = this._items.indexOf(child), existingItemIndex = this._indexOfPosition(newKey);
|
|
613
|
-
-1 !== existingItemIndex && this._items[existingItemIndex]._setParentLink(this, makePosition(newKey, null === (_b = this._items[existingItemIndex + 1]) || void 0 === _b ? void 0 : _b._getParentKeyOrThrow())),
|
|
614
|
-
child._setParentLink(this, newKey), sortListItem(this._items);
|
|
615
|
-
const newIndex = this._items.indexOf(child);
|
|
616
|
-
return previousIndex === newIndex ? {
|
|
617
|
-
modified: !1
|
|
618
|
-
} : {
|
|
619
|
-
modified: makeUpdate(this, [ moveDelta(previousIndex, newIndex, child) ]),
|
|
620
|
-
reverse: []
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
_applySetChildKeyUndoRedo(newKey, child) {
|
|
314
|
+
_setChildKey(key, child, previousKey) {
|
|
625
315
|
var _a;
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
const
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
modified:
|
|
316
|
+
child._setParentLink(this, key);
|
|
317
|
+
const previousIndex = this._items.findIndex((entry => entry[0]._id === child._id)), index = this._items.findIndex((entry => entry[1] === key));
|
|
318
|
+
-1 !== index && (this._items[index][1] = makePosition(key, null === (_a = this._items[index + 1]) || void 0 === _a ? void 0 : _a[1]));
|
|
319
|
+
const item = this._items.find((item => item[0] === child));
|
|
320
|
+
item && (item[1] = key), this._items.sort(((itemA, itemB) => comparePosition(itemA[1], itemB[1])));
|
|
321
|
+
const newIndex = this._items.findIndex((entry => entry[0]._id === child._id));
|
|
322
|
+
return {
|
|
323
|
+
modified: {
|
|
324
|
+
node: this,
|
|
325
|
+
type: "LiveList",
|
|
326
|
+
updates: newIndex === previousIndex ? [] : [ {
|
|
327
|
+
index: newIndex,
|
|
328
|
+
item: child instanceof LiveRegister ? child.data : child,
|
|
329
|
+
previousIndex: previousIndex,
|
|
330
|
+
type: "move"
|
|
331
|
+
} ]
|
|
332
|
+
},
|
|
634
333
|
reverse: [ {
|
|
635
334
|
type: OpCode.SET_PARENT_KEY,
|
|
636
|
-
id:
|
|
335
|
+
id: null == item ? void 0 : item[0]._id,
|
|
637
336
|
parentKey: previousKey
|
|
638
337
|
} ]
|
|
639
338
|
};
|
|
640
339
|
}
|
|
641
|
-
_setChildKey(newKey, child, source) {
|
|
642
|
-
return source === OpSource.REMOTE ? this._applySetChildKeyRemote(newKey, child) : source === OpSource.ACK ? this._applySetChildKeyAck(newKey, child) : this._applySetChildKeyUndoRedo(newKey, child);
|
|
643
|
-
}
|
|
644
340
|
_apply(op, isLocal) {
|
|
645
341
|
return super._apply(op, isLocal);
|
|
646
342
|
}
|
|
647
343
|
_toSerializedCrdt() {
|
|
648
|
-
|
|
344
|
+
var _a;
|
|
649
345
|
return {
|
|
650
346
|
type: CrdtType.LIST,
|
|
651
|
-
parentId:
|
|
652
|
-
parentKey: this.
|
|
347
|
+
parentId: null === (_a = this._parent) || void 0 === _a ? void 0 : _a._id,
|
|
348
|
+
parentKey: this._parentKey
|
|
653
349
|
};
|
|
654
350
|
}
|
|
655
351
|
get length() {
|
|
@@ -660,14 +356,25 @@ class LiveList extends AbstractCrdt {
|
|
|
660
356
|
}
|
|
661
357
|
insert(element, index) {
|
|
662
358
|
if (index < 0 || index > this._items.length) throw new Error(`Cannot insert list item at index "${index}". index should be between 0 and ${this._items.length}`);
|
|
663
|
-
const position = makePosition(this._items[index - 1] ? this._items[index - 1]
|
|
664
|
-
|
|
665
|
-
this.
|
|
359
|
+
const position = makePosition(this._items[index - 1] ? this._items[index - 1][1] : void 0, this._items[index] ? this._items[index][1] : void 0), value = selfOrRegister(element);
|
|
360
|
+
value._setParentLink(this, position), this._items.push([ value, position ]), this._items.sort(((itemA, itemB) => comparePosition(itemA[1], itemB[1])));
|
|
361
|
+
const newIndex = this._items.findIndex((entry => entry[1] === position));
|
|
362
|
+
if (this._doc && this._id) {
|
|
666
363
|
const id = this._doc.generateId();
|
|
667
|
-
value._attach(id, this._doc)
|
|
364
|
+
value._attach(id, this._doc);
|
|
365
|
+
const storageUpdates = new Map;
|
|
366
|
+
storageUpdates.set(this._id, {
|
|
367
|
+
node: this,
|
|
368
|
+
type: "LiveList",
|
|
369
|
+
updates: [ {
|
|
370
|
+
index: newIndex,
|
|
371
|
+
item: value instanceof LiveRegister ? value.data : value,
|
|
372
|
+
type: "insert"
|
|
373
|
+
} ]
|
|
374
|
+
}), this._doc.dispatch(value._serialize(this._id, position, this._doc), [ {
|
|
668
375
|
type: OpCode.DELETE_CRDT,
|
|
669
376
|
id: id
|
|
670
|
-
} ],
|
|
377
|
+
} ], storageUpdates);
|
|
671
378
|
}
|
|
672
379
|
}
|
|
673
380
|
move(index, targetIndex) {
|
|
@@ -676,20 +383,31 @@ class LiveList extends AbstractCrdt {
|
|
|
676
383
|
if (index < 0) throw new Error("index cannot be less than 0");
|
|
677
384
|
if (index >= this._items.length) throw new Error("index cannot be greater or equal than the list length");
|
|
678
385
|
let beforePosition = null, afterPosition = null;
|
|
679
|
-
index < targetIndex ? (afterPosition = targetIndex === this._items.length - 1 ? void 0 : this._items[targetIndex + 1]
|
|
680
|
-
beforePosition = this._items[targetIndex]
|
|
681
|
-
beforePosition = 0 === targetIndex ? void 0 : this._items[targetIndex - 1]
|
|
682
|
-
const position = makePosition(beforePosition, afterPosition), item = this._items[index], previousPosition = item
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
386
|
+
index < targetIndex ? (afterPosition = targetIndex === this._items.length - 1 ? void 0 : this._items[targetIndex + 1][1],
|
|
387
|
+
beforePosition = this._items[targetIndex][1]) : (afterPosition = this._items[targetIndex][1],
|
|
388
|
+
beforePosition = 0 === targetIndex ? void 0 : this._items[targetIndex - 1][1]);
|
|
389
|
+
const position = makePosition(beforePosition, afterPosition), item = this._items[index], previousPosition = item[1];
|
|
390
|
+
item[1] = position, item[0]._setParentLink(this, position), this._items.sort(((itemA, itemB) => comparePosition(itemA[1], itemB[1])));
|
|
391
|
+
const newIndex = this._items.findIndex((entry => entry[1] === position));
|
|
392
|
+
if (this._doc && this._id) {
|
|
393
|
+
const storageUpdates = new Map;
|
|
394
|
+
storageUpdates.set(this._id, {
|
|
395
|
+
node: this,
|
|
396
|
+
type: "LiveList",
|
|
397
|
+
updates: [ {
|
|
398
|
+
index: newIndex,
|
|
399
|
+
previousIndex: index,
|
|
400
|
+
item: item[0],
|
|
401
|
+
type: "move"
|
|
402
|
+
} ]
|
|
403
|
+
}), this._doc.dispatch([ {
|
|
686
404
|
type: OpCode.SET_PARENT_KEY,
|
|
687
|
-
id:
|
|
405
|
+
id: item[0]._id,
|
|
688
406
|
opId: this._doc.generateOpId(),
|
|
689
407
|
parentKey: position
|
|
690
408
|
} ], [ {
|
|
691
409
|
type: OpCode.SET_PARENT_KEY,
|
|
692
|
-
id:
|
|
410
|
+
id: item[0]._id,
|
|
693
411
|
parentKey: previousPosition
|
|
694
412
|
} ], storageUpdates);
|
|
695
413
|
}
|
|
@@ -697,15 +415,22 @@ class LiveList extends AbstractCrdt {
|
|
|
697
415
|
delete(index) {
|
|
698
416
|
if (index < 0 || index >= this._items.length) throw new Error(`Cannot delete list item at index "${index}". index should be between 0 and ${this._items.length - 1}`);
|
|
699
417
|
const item = this._items[index];
|
|
700
|
-
if (item._detach(), this._items.splice(index, 1), this._doc) {
|
|
701
|
-
const childRecordId = item._id;
|
|
418
|
+
if (item[0]._detach(), this._items.splice(index, 1), this._doc) {
|
|
419
|
+
const childRecordId = item[0]._id;
|
|
702
420
|
if (childRecordId) {
|
|
703
421
|
const storageUpdates = new Map;
|
|
704
|
-
storageUpdates.set(
|
|
422
|
+
storageUpdates.set(this._id, {
|
|
423
|
+
node: this,
|
|
424
|
+
type: "LiveList",
|
|
425
|
+
updates: [ {
|
|
426
|
+
index: index,
|
|
427
|
+
type: "delete"
|
|
428
|
+
} ]
|
|
429
|
+
}), this._doc.dispatch([ {
|
|
705
430
|
id: childRecordId,
|
|
706
431
|
opId: this._doc.generateOpId(),
|
|
707
432
|
type: OpCode.DELETE_CRDT
|
|
708
|
-
} ], item._serialize(
|
|
433
|
+
} ], item[0]._serialize(this._id, item[1]), storageUpdates);
|
|
709
434
|
}
|
|
710
435
|
}
|
|
711
436
|
}
|
|
@@ -714,41 +439,50 @@ class LiveList extends AbstractCrdt {
|
|
|
714
439
|
const ops = [], reverseOps = [], updateDelta = [];
|
|
715
440
|
let i = 0;
|
|
716
441
|
for (const item of this._items) {
|
|
717
|
-
item._detach();
|
|
718
|
-
const childId = item._id;
|
|
442
|
+
item[0]._detach();
|
|
443
|
+
const childId = item[0]._id;
|
|
719
444
|
childId && (ops.push({
|
|
720
|
-
type: OpCode.DELETE_CRDT,
|
|
721
445
|
id: childId,
|
|
722
|
-
|
|
723
|
-
}), reverseOps.push(...item._serialize(
|
|
724
|
-
|
|
446
|
+
type: OpCode.DELETE_CRDT
|
|
447
|
+
}), reverseOps.push(...item[0]._serialize(this._id, item[1])), updateDelta.push({
|
|
448
|
+
index: i,
|
|
449
|
+
type: "delete"
|
|
450
|
+
})), i++;
|
|
725
451
|
}
|
|
726
452
|
this._items = [];
|
|
727
453
|
const storageUpdates = new Map;
|
|
728
|
-
storageUpdates.set(
|
|
454
|
+
storageUpdates.set(this._id, {
|
|
455
|
+
node: this,
|
|
456
|
+
type: "LiveList",
|
|
457
|
+
updates: updateDelta
|
|
458
|
+
}), this._doc.dispatch(ops, reverseOps, storageUpdates);
|
|
729
459
|
} else {
|
|
730
|
-
for (const item of this._items) item._detach();
|
|
460
|
+
for (const item of this._items) item[0]._detach();
|
|
731
461
|
this._items = [];
|
|
732
462
|
}
|
|
733
463
|
}
|
|
734
464
|
set(index, item) {
|
|
735
465
|
if (index < 0 || index >= this._items.length) throw new Error(`Cannot set list item at index "${index}". index should be between 0 and ${this._items.length - 1}`);
|
|
736
|
-
const existingItem = this._items[index]
|
|
466
|
+
const [existingItem, position] = this._items[index];
|
|
737
467
|
existingItem._detach();
|
|
738
|
-
const value =
|
|
739
|
-
if (value._setParentLink(this, position), this._items[index] = value, this._doc && this._id) {
|
|
468
|
+
const value = selfOrRegister(item);
|
|
469
|
+
if (value._setParentLink(this, position), this._items[index][0] = value, this._doc && this._id) {
|
|
740
470
|
const id = this._doc.generateId();
|
|
741
471
|
value._attach(id, this._doc);
|
|
742
472
|
const storageUpdates = new Map;
|
|
743
|
-
storageUpdates.set(this._id,
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
473
|
+
storageUpdates.set(this._id, {
|
|
474
|
+
node: this,
|
|
475
|
+
type: "LiveList",
|
|
476
|
+
updates: [ {
|
|
477
|
+
index: index,
|
|
478
|
+
item: value instanceof LiveRegister ? value.data : value,
|
|
479
|
+
type: "set"
|
|
480
|
+
} ]
|
|
481
|
+
}), this._doc.dispatch(value._serialize(this._id, position, this._doc, "set"), existingItem._serialize(this._id, position, void 0, "set"), storageUpdates);
|
|
748
482
|
}
|
|
749
483
|
}
|
|
750
484
|
toArray() {
|
|
751
|
-
return this._items.map((entry =>
|
|
485
|
+
return this._items.map((entry => selfOrRegisterValue(entry[0])));
|
|
752
486
|
}
|
|
753
487
|
every(predicate) {
|
|
754
488
|
return this.toArray().every(predicate);
|
|
@@ -766,7 +500,7 @@ class LiveList extends AbstractCrdt {
|
|
|
766
500
|
return this.toArray().forEach(callbackfn);
|
|
767
501
|
}
|
|
768
502
|
get(index) {
|
|
769
|
-
if (!(index < 0 || index >= this._items.length)) return
|
|
503
|
+
if (!(index < 0 || index >= this._items.length)) return selfOrRegisterValue(this._items[index][0]);
|
|
770
504
|
}
|
|
771
505
|
indexOf(searchElement, fromIndex) {
|
|
772
506
|
return this.toArray().indexOf(searchElement, fromIndex);
|
|
@@ -775,7 +509,7 @@ class LiveList extends AbstractCrdt {
|
|
|
775
509
|
return this.toArray().lastIndexOf(searchElement, fromIndex);
|
|
776
510
|
}
|
|
777
511
|
map(callback) {
|
|
778
|
-
return this._items.map(((entry, i) => callback(
|
|
512
|
+
return this._items.map(((entry, i) => callback(selfOrRegisterValue(entry[0]), i)));
|
|
779
513
|
}
|
|
780
514
|
some(predicate) {
|
|
781
515
|
return this.toArray().some(predicate);
|
|
@@ -783,20 +517,6 @@ class LiveList extends AbstractCrdt {
|
|
|
783
517
|
[Symbol.iterator]() {
|
|
784
518
|
return new LiveListIterator(this._items);
|
|
785
519
|
}
|
|
786
|
-
_createAttachItemAndSort(op, key) {
|
|
787
|
-
const newItem = creationOpToLiveNode(op);
|
|
788
|
-
newItem._attach(op.id, nn(this._doc)), newItem._setParentLink(this, key), this._items.push(newItem),
|
|
789
|
-
sortListItem(this._items);
|
|
790
|
-
return {
|
|
791
|
-
newItem: newItem,
|
|
792
|
-
newIndex: this._indexOfPosition(key)
|
|
793
|
-
};
|
|
794
|
-
}
|
|
795
|
-
_shiftItemPosition(index, key) {
|
|
796
|
-
var _a;
|
|
797
|
-
const shiftedPosition = makePosition(key, this._items.length > index + 1 ? null === (_a = this._items[index + 1]) || void 0 === _a ? void 0 : _a._getParentKeyOrThrow() : void 0);
|
|
798
|
-
this._items[index]._setParentLink(this, shiftedPosition);
|
|
799
|
-
}
|
|
800
520
|
}
|
|
801
521
|
|
|
802
522
|
class LiveListIterator {
|
|
@@ -808,85 +528,57 @@ class LiveListIterator {
|
|
|
808
528
|
}
|
|
809
529
|
next() {
|
|
810
530
|
const result = this._innerIterator.next();
|
|
811
|
-
|
|
531
|
+
return result.done ? {
|
|
812
532
|
done: !0,
|
|
813
533
|
value: void 0
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
value: liveNodeToLson(result.value)
|
|
534
|
+
} : {
|
|
535
|
+
value: selfOrRegisterValue(result.value[0])
|
|
817
536
|
};
|
|
818
537
|
}
|
|
819
538
|
}
|
|
820
539
|
|
|
821
|
-
|
|
822
|
-
return {
|
|
823
|
-
node: liveList,
|
|
824
|
-
type: "LiveList",
|
|
825
|
-
updates: deltaUpdates
|
|
826
|
-
};
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
function setDelta(index, item) {
|
|
830
|
-
return {
|
|
831
|
-
index: index,
|
|
832
|
-
type: "set",
|
|
833
|
-
item: item instanceof LiveRegister ? item.data : item
|
|
834
|
-
};
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
function deleteDelta(index) {
|
|
838
|
-
return {
|
|
839
|
-
index: index,
|
|
840
|
-
type: "delete"
|
|
841
|
-
};
|
|
842
|
-
}
|
|
540
|
+
const _emittedDeprecationWarnings = new Set;
|
|
843
541
|
|
|
844
|
-
function
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
type: "insert",
|
|
848
|
-
item: item instanceof LiveRegister ? item.data : item
|
|
849
|
-
};
|
|
542
|
+
function deprecate(message, key = message) {
|
|
543
|
+
"production" !== process.env.NODE_ENV && (_emittedDeprecationWarnings.has(key) || (_emittedDeprecationWarnings.add(key),
|
|
544
|
+
console.error(`DEPRECATION WARNING: ${message}`)));
|
|
850
545
|
}
|
|
851
546
|
|
|
852
|
-
function
|
|
853
|
-
|
|
854
|
-
index: index,
|
|
855
|
-
type: "move",
|
|
856
|
-
previousIndex: previousIndex,
|
|
857
|
-
item: item instanceof LiveRegister ? item.data : item
|
|
858
|
-
};
|
|
547
|
+
function deprecateIf(condition, message, key = message) {
|
|
548
|
+
"production" !== process.env.NODE_ENV && condition && deprecate(message, key);
|
|
859
549
|
}
|
|
860
550
|
|
|
861
|
-
function
|
|
862
|
-
|
|
551
|
+
function throwUsageError(message) {
|
|
552
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
553
|
+
const usageError = new Error(message);
|
|
554
|
+
throw usageError.name = "Usage error", usageError;
|
|
555
|
+
}
|
|
863
556
|
}
|
|
864
557
|
|
|
865
|
-
function
|
|
866
|
-
|
|
867
|
-
const firstOp = ops[0];
|
|
868
|
-
if (firstOp.type !== OpCode.CREATE_LIST && firstOp.type !== OpCode.CREATE_OBJECT && firstOp.type !== OpCode.CREATE_REGISTER && firstOp.type !== OpCode.CREATE_MAP) throw new Error("Internal error. Serialized LiveStructure first op should be CreateOp");
|
|
869
|
-
firstOp.intent = "set", firstOp.deletedId = deletedId;
|
|
558
|
+
function errorIf(condition, message) {
|
|
559
|
+
"production" !== process.env.NODE_ENV && condition && throwUsageError(message);
|
|
870
560
|
}
|
|
871
561
|
|
|
872
562
|
class LiveMap extends AbstractCrdt {
|
|
873
563
|
constructor(entries) {
|
|
874
|
-
if (super(),
|
|
564
|
+
if (super(), deprecateIf(null === entries, "Support for calling `new LiveMap(null)` will be removed in @liveblocks/client 0.18. Please call as `new LiveMap()`, or `new LiveMap([])`."),
|
|
875
565
|
entries) {
|
|
876
566
|
const mappedEntries = [];
|
|
877
567
|
for (const entry of entries) {
|
|
878
|
-
const value =
|
|
568
|
+
const value = selfOrRegister(entry[1]);
|
|
879
569
|
value._setParentLink(this, entry[0]), mappedEntries.push([ entry[0], value ]);
|
|
880
570
|
}
|
|
881
571
|
this._map = new Map(mappedEntries);
|
|
882
572
|
} else this._map = new Map;
|
|
883
573
|
}
|
|
884
|
-
_serialize(parentId, parentKey, doc) {
|
|
574
|
+
_serialize(parentId, parentKey, doc, intent) {
|
|
885
575
|
if (null == this._id) throw new Error("Cannot serialize item is not attached");
|
|
576
|
+
if (null == parentId || null == parentKey) throw new Error("Cannot serialize map if parentId or parentKey is undefined");
|
|
886
577
|
const ops = [], op = {
|
|
887
578
|
id: this._id,
|
|
888
579
|
opId: null == doc ? void 0 : doc.generateOpId(),
|
|
889
580
|
type: OpCode.CREATE_MAP,
|
|
581
|
+
intent: intent,
|
|
890
582
|
parentId: parentId,
|
|
891
583
|
parentKey: parentKey
|
|
892
584
|
};
|
|
@@ -899,32 +591,30 @@ class LiveMap extends AbstractCrdt {
|
|
|
899
591
|
map._attach(id, doc);
|
|
900
592
|
const children = parentToChildren.get(id);
|
|
901
593
|
if (null == children) return map;
|
|
902
|
-
for (const
|
|
903
|
-
const
|
|
594
|
+
for (const entry of children) {
|
|
595
|
+
const crdt = entry[1];
|
|
596
|
+
if (null == crdt.parentKey) throw new Error("Tried to deserialize a crdt but it does not have a parentKey and is not the root");
|
|
597
|
+
const child = deserialize(entry, parentToChildren, doc);
|
|
904
598
|
child._setParentLink(map, crdt.parentKey), map._map.set(crdt.parentKey, child);
|
|
905
599
|
}
|
|
906
600
|
return map;
|
|
907
601
|
}
|
|
908
602
|
_attach(id, doc) {
|
|
909
603
|
super._attach(id, doc);
|
|
910
|
-
for (const [_key, value] of this._map)
|
|
604
|
+
for (const [_key, value] of this._map) isCrdt(value) && value._attach(doc.generateId(), doc);
|
|
911
605
|
}
|
|
912
|
-
_attachChild(op) {
|
|
606
|
+
_attachChild(op, _isLocal) {
|
|
913
607
|
if (null == this._doc) throw new Error("Can't attach child if doc is not present");
|
|
914
|
-
const {id: id, parentKey:
|
|
608
|
+
const {id: id, parentKey: parentKey} = op, key = parentKey, child = creationOpToLiveStructure(op);
|
|
915
609
|
if (void 0 !== this._doc.getItem(id)) return {
|
|
916
610
|
modified: !1
|
|
917
611
|
};
|
|
918
612
|
const previousValue = this._map.get(key);
|
|
919
613
|
let reverse;
|
|
920
|
-
|
|
921
|
-
const thisId = nn(this._id);
|
|
922
|
-
reverse = previousValue._serialize(thisId, key), previousValue._detach();
|
|
923
|
-
} else reverse = [ {
|
|
614
|
+
return previousValue ? (reverse = previousValue._serialize(this._id, key), previousValue._detach()) : reverse = [ {
|
|
924
615
|
type: OpCode.DELETE_CRDT,
|
|
925
616
|
id: id
|
|
926
|
-
} ]
|
|
927
|
-
return child._setParentLink(this, key), child._attach(id, this._doc), this._map.set(key, child),
|
|
617
|
+
} ], child._setParentLink(this, key), child._attach(id, this._doc), this._map.set(key, child),
|
|
928
618
|
{
|
|
929
619
|
modified: {
|
|
930
620
|
node: this,
|
|
@@ -943,7 +633,7 @@ class LiveMap extends AbstractCrdt {
|
|
|
943
633
|
for (const item of this._map.values()) item._detach();
|
|
944
634
|
}
|
|
945
635
|
_detachChild(child) {
|
|
946
|
-
const
|
|
636
|
+
const reverse = child._serialize(this._id, child._parentKey, this._doc);
|
|
947
637
|
for (const [key, value] of this._map) value === child && this._map.delete(key);
|
|
948
638
|
child._detach();
|
|
949
639
|
return {
|
|
@@ -951,7 +641,7 @@ class LiveMap extends AbstractCrdt {
|
|
|
951
641
|
node: this,
|
|
952
642
|
type: "LiveMap",
|
|
953
643
|
updates: {
|
|
954
|
-
[
|
|
644
|
+
[child._parentKey]: {
|
|
955
645
|
type: "delete"
|
|
956
646
|
}
|
|
957
647
|
}
|
|
@@ -960,21 +650,21 @@ class LiveMap extends AbstractCrdt {
|
|
|
960
650
|
};
|
|
961
651
|
}
|
|
962
652
|
_toSerializedCrdt() {
|
|
963
|
-
|
|
653
|
+
var _a;
|
|
964
654
|
return {
|
|
965
655
|
type: CrdtType.MAP,
|
|
966
|
-
parentId:
|
|
967
|
-
parentKey: this.
|
|
656
|
+
parentId: null === (_a = this._parent) || void 0 === _a ? void 0 : _a._id,
|
|
657
|
+
parentKey: this._parentKey
|
|
968
658
|
};
|
|
969
659
|
}
|
|
970
660
|
get(key) {
|
|
971
661
|
const value = this._map.get(key);
|
|
972
|
-
if (null != value) return
|
|
662
|
+
if (null != value) return selfOrRegisterValue(value);
|
|
973
663
|
}
|
|
974
664
|
set(key, value) {
|
|
975
665
|
const oldValue = this._map.get(key);
|
|
976
666
|
oldValue && oldValue._detach();
|
|
977
|
-
const item =
|
|
667
|
+
const item = selfOrRegister(value);
|
|
978
668
|
if (item._setParentLink(this, key), this._map.set(key, item), this._doc && this._id) {
|
|
979
669
|
const id = this._doc.generateId();
|
|
980
670
|
item._attach(id, this._doc);
|
|
@@ -1003,8 +693,8 @@ class LiveMap extends AbstractCrdt {
|
|
|
1003
693
|
const item = this._map.get(key);
|
|
1004
694
|
if (null == item) return !1;
|
|
1005
695
|
if (item._detach(), this._map.delete(key), this._doc && item._id) {
|
|
1006
|
-
const
|
|
1007
|
-
storageUpdates.set(
|
|
696
|
+
const storageUpdates = new Map;
|
|
697
|
+
storageUpdates.set(this._id, {
|
|
1008
698
|
node: this,
|
|
1009
699
|
type: "LiveMap",
|
|
1010
700
|
updates: {
|
|
@@ -1016,14 +706,14 @@ class LiveMap extends AbstractCrdt {
|
|
|
1016
706
|
type: OpCode.DELETE_CRDT,
|
|
1017
707
|
id: item._id,
|
|
1018
708
|
opId: this._doc.generateOpId()
|
|
1019
|
-
} ], item._serialize(
|
|
709
|
+
} ], item._serialize(this._id, key), storageUpdates);
|
|
1020
710
|
}
|
|
1021
711
|
return !0;
|
|
1022
712
|
}
|
|
1023
713
|
entries() {
|
|
1024
714
|
const innerIterator = this._map.entries();
|
|
1025
715
|
return {
|
|
1026
|
-
[Symbol.iterator]() {
|
|
716
|
+
[Symbol.iterator]: function() {
|
|
1027
717
|
return this;
|
|
1028
718
|
},
|
|
1029
719
|
next() {
|
|
@@ -1033,7 +723,7 @@ class LiveMap extends AbstractCrdt {
|
|
|
1033
723
|
value: void 0
|
|
1034
724
|
};
|
|
1035
725
|
return {
|
|
1036
|
-
value: [ iteratorValue.value[0],
|
|
726
|
+
value: [ iteratorValue.value[0], selfOrRegisterValue(iteratorValue.value[1]) ]
|
|
1037
727
|
};
|
|
1038
728
|
}
|
|
1039
729
|
};
|
|
@@ -1047,17 +737,16 @@ class LiveMap extends AbstractCrdt {
|
|
|
1047
737
|
values() {
|
|
1048
738
|
const innerIterator = this._map.values();
|
|
1049
739
|
return {
|
|
1050
|
-
[Symbol.iterator]() {
|
|
740
|
+
[Symbol.iterator]: function() {
|
|
1051
741
|
return this;
|
|
1052
742
|
},
|
|
1053
743
|
next() {
|
|
1054
744
|
const iteratorValue = innerIterator.next();
|
|
1055
|
-
|
|
745
|
+
return iteratorValue.done ? {
|
|
1056
746
|
done: !0,
|
|
1057
747
|
value: void 0
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
value: liveNodeToLson(iteratorValue.value)
|
|
748
|
+
} : {
|
|
749
|
+
value: selfOrRegisterValue(iteratorValue.value)
|
|
1061
750
|
};
|
|
1062
751
|
}
|
|
1063
752
|
};
|
|
@@ -1067,12 +756,8 @@ class LiveMap extends AbstractCrdt {
|
|
|
1067
756
|
}
|
|
1068
757
|
}
|
|
1069
758
|
|
|
1070
|
-
function
|
|
1071
|
-
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
function isJsonObject(data) {
|
|
1075
|
-
return null !== data && "object" == typeof data && !isJsonArray(data);
|
|
759
|
+
function assertNever(_value, errmsg) {
|
|
760
|
+
throw new Error(errmsg);
|
|
1076
761
|
}
|
|
1077
762
|
|
|
1078
763
|
function remove(array, item) {
|
|
@@ -1086,7 +771,7 @@ function compact(items) {
|
|
|
1086
771
|
return items.filter((item => null != item));
|
|
1087
772
|
}
|
|
1088
773
|
|
|
1089
|
-
function
|
|
774
|
+
function creationOpToLiveStructure(op) {
|
|
1090
775
|
switch (op.type) {
|
|
1091
776
|
case OpCode.CREATE_REGISTER:
|
|
1092
777
|
return new LiveRegister(op.data);
|
|
@@ -1099,14 +784,11 @@ function creationOpToLiveNode(op) {
|
|
|
1099
784
|
|
|
1100
785
|
case OpCode.CREATE_LIST:
|
|
1101
786
|
return new LiveList;
|
|
1102
|
-
|
|
1103
|
-
default:
|
|
1104
|
-
return assertNever(0, "Unknown creation Op");
|
|
1105
787
|
}
|
|
1106
788
|
}
|
|
1107
789
|
|
|
1108
790
|
function isSameNodeOrChildOf(node, parent) {
|
|
1109
|
-
return node === parent ||
|
|
791
|
+
return node === parent || !!node._parent && isSameNodeOrChildOf(node._parent, parent);
|
|
1110
792
|
}
|
|
1111
793
|
|
|
1112
794
|
function deserialize([id, crdt], parentToChildren, doc) {
|
|
@@ -1128,28 +810,18 @@ function deserialize([id, crdt], parentToChildren, doc) {
|
|
|
1128
810
|
}
|
|
1129
811
|
}
|
|
1130
812
|
|
|
1131
|
-
function
|
|
1132
|
-
return
|
|
1133
|
-
return value instanceof LiveMap;
|
|
1134
|
-
}(value) || isLiveObject(value) || function(value) {
|
|
1135
|
-
return value instanceof LiveRegister;
|
|
1136
|
-
}(value);
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
function isLiveList(value) {
|
|
1140
|
-
return value instanceof LiveList;
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
function isLiveObject(value) {
|
|
1144
|
-
return value instanceof LiveObject;
|
|
813
|
+
function isCrdt(obj) {
|
|
814
|
+
return obj instanceof LiveObject || obj instanceof LiveMap || obj instanceof LiveList || obj instanceof LiveRegister;
|
|
1145
815
|
}
|
|
1146
816
|
|
|
1147
|
-
function
|
|
1148
|
-
return obj instanceof LiveRegister ? obj.data : obj
|
|
817
|
+
function selfOrRegisterValue(obj) {
|
|
818
|
+
return obj instanceof LiveRegister ? obj.data : obj;
|
|
1149
819
|
}
|
|
1150
820
|
|
|
1151
|
-
function
|
|
1152
|
-
|
|
821
|
+
function selfOrRegister(obj) {
|
|
822
|
+
if (obj instanceof LiveObject || obj instanceof LiveMap || obj instanceof LiveList) return obj;
|
|
823
|
+
if (obj instanceof LiveRegister) throw new Error("Internal error. LiveRegister should not be created from selfOrRegister");
|
|
824
|
+
return new LiveRegister(obj);
|
|
1153
825
|
}
|
|
1154
826
|
|
|
1155
827
|
function getTreesDiffOperations(currentItems, newItems) {
|
|
@@ -1168,7 +840,7 @@ function getTreesDiffOperations(currentItems, newItems) {
|
|
|
1168
840
|
})), crdt.parentKey !== currentCrdt.parentKey && ops.push({
|
|
1169
841
|
type: OpCode.SET_PARENT_KEY,
|
|
1170
842
|
id: id,
|
|
1171
|
-
parentKey:
|
|
843
|
+
parentKey: crdt.parentKey
|
|
1172
844
|
}); else switch (crdt.type) {
|
|
1173
845
|
case CrdtType.REGISTER:
|
|
1174
846
|
ops.push({
|
|
@@ -1303,16 +975,17 @@ class LiveObject extends AbstractCrdt {
|
|
|
1303
975
|
super(), this._propToLastUpdate = new Map;
|
|
1304
976
|
for (const key in obj) {
|
|
1305
977
|
const value = obj[key];
|
|
1306
|
-
|
|
978
|
+
value instanceof AbstractCrdt && value._setParentLink(this, key);
|
|
1307
979
|
}
|
|
1308
980
|
this._map = new Map(Object.entries(obj));
|
|
1309
981
|
}
|
|
1310
|
-
_serialize(parentId, parentKey, doc) {
|
|
982
|
+
_serialize(parentId, parentKey, doc, intent) {
|
|
1311
983
|
if (null == this._id) throw new Error("Cannot serialize item is not attached");
|
|
1312
984
|
const opId = null == doc ? void 0 : doc.generateOpId(), ops = [], op = void 0 !== parentId && void 0 !== parentKey ? {
|
|
1313
985
|
type: OpCode.CREATE_OBJECT,
|
|
1314
986
|
id: this._id,
|
|
1315
987
|
opId: opId,
|
|
988
|
+
intent: intent,
|
|
1316
989
|
parentId: parentId,
|
|
1317
990
|
parentKey: parentKey,
|
|
1318
991
|
data: {}
|
|
@@ -1320,10 +993,11 @@ class LiveObject extends AbstractCrdt {
|
|
|
1320
993
|
type: OpCode.CREATE_OBJECT,
|
|
1321
994
|
id: this._id,
|
|
1322
995
|
opId: opId,
|
|
996
|
+
intent: intent,
|
|
1323
997
|
data: {}
|
|
1324
998
|
};
|
|
1325
999
|
ops.push(op);
|
|
1326
|
-
for (const [key, value] of this._map)
|
|
1000
|
+
for (const [key, value] of this._map) value instanceof AbstractCrdt ? ops.push(...value._serialize(this._id, key, doc)) : op.data[key] = value;
|
|
1327
1001
|
return ops;
|
|
1328
1002
|
}
|
|
1329
1003
|
static _deserialize([id, item], parentToChildren, doc) {
|
|
@@ -1331,41 +1005,43 @@ class LiveObject extends AbstractCrdt {
|
|
|
1331
1005
|
return liveObj._attach(id, doc), this._deserializeChildren(liveObj, parentToChildren, doc);
|
|
1332
1006
|
}
|
|
1333
1007
|
static _deserializeChildren(liveObj, parentToChildren, doc) {
|
|
1334
|
-
const children = parentToChildren.get(
|
|
1008
|
+
const children = parentToChildren.get(liveObj._id);
|
|
1335
1009
|
if (null == children) return liveObj;
|
|
1336
|
-
for (const
|
|
1337
|
-
const
|
|
1010
|
+
for (const entry of children) {
|
|
1011
|
+
const crdt = entry[1];
|
|
1012
|
+
if (null == crdt.parentKey) throw new Error("Tried to deserialize a crdt but it does not have a parentKey and is not the root");
|
|
1013
|
+
const child = deserialize(entry, parentToChildren, doc);
|
|
1338
1014
|
child._setParentLink(liveObj, crdt.parentKey), liveObj._map.set(crdt.parentKey, child);
|
|
1339
1015
|
}
|
|
1340
1016
|
return liveObj;
|
|
1341
1017
|
}
|
|
1342
1018
|
_attach(id, doc) {
|
|
1343
1019
|
super._attach(id, doc);
|
|
1344
|
-
for (const [_key, value] of this._map)
|
|
1020
|
+
for (const [_key, value] of this._map) value instanceof AbstractCrdt && value._attach(doc.generateId(), doc);
|
|
1345
1021
|
}
|
|
1346
|
-
_attachChild(op,
|
|
1022
|
+
_attachChild(op, isLocal) {
|
|
1347
1023
|
if (null == this._doc) throw new Error("Can't attach child if doc is not present");
|
|
1348
|
-
const {id: id,
|
|
1024
|
+
const {id: id, parentKey: parentKey, opId: opId} = op, key = parentKey, child = creationOpToLiveStructure(op);
|
|
1349
1025
|
if (void 0 !== this._doc.getItem(id)) return this._propToLastUpdate.get(key) === opId && this._propToLastUpdate.delete(key),
|
|
1350
1026
|
{
|
|
1351
1027
|
modified: !1
|
|
1352
1028
|
};
|
|
1353
|
-
if (
|
|
1029
|
+
if (isLocal) this._propToLastUpdate.set(key, opId); else if (void 0 !== this._propToLastUpdate.get(key)) return this._propToLastUpdate.get(key) === opId ? (this._propToLastUpdate.delete(key),
|
|
1354
1030
|
{
|
|
1355
1031
|
modified: !1
|
|
1356
1032
|
}) : {
|
|
1357
1033
|
modified: !1
|
|
1358
1034
|
};
|
|
1359
|
-
const
|
|
1035
|
+
const previousValue = this._map.get(key);
|
|
1360
1036
|
let reverse;
|
|
1361
|
-
return
|
|
1037
|
+
return isCrdt(previousValue) ? (reverse = previousValue._serialize(this._id, key),
|
|
1362
1038
|
previousValue._detach()) : reverse = void 0 === previousValue ? [ {
|
|
1363
1039
|
type: OpCode.DELETE_OBJECT_KEY,
|
|
1364
|
-
id:
|
|
1040
|
+
id: this._id,
|
|
1365
1041
|
key: key
|
|
1366
1042
|
} ] : [ {
|
|
1367
1043
|
type: OpCode.UPDATE_OBJECT,
|
|
1368
|
-
id:
|
|
1044
|
+
id: this._id,
|
|
1369
1045
|
data: {
|
|
1370
1046
|
[key]: previousValue
|
|
1371
1047
|
}
|
|
@@ -1385,7 +1061,7 @@ class LiveObject extends AbstractCrdt {
|
|
|
1385
1061
|
}
|
|
1386
1062
|
_detachChild(child) {
|
|
1387
1063
|
if (child) {
|
|
1388
|
-
const
|
|
1064
|
+
const reverse = child._serialize(this._id, child._parentKey, this._doc);
|
|
1389
1065
|
for (const [key, value] of this._map) value === child && this._map.delete(key);
|
|
1390
1066
|
child._detach();
|
|
1391
1067
|
return {
|
|
@@ -1393,7 +1069,7 @@ class LiveObject extends AbstractCrdt {
|
|
|
1393
1069
|
node: this,
|
|
1394
1070
|
type: "LiveObject",
|
|
1395
1071
|
updates: {
|
|
1396
|
-
[
|
|
1072
|
+
[child._parentKey]: {
|
|
1397
1073
|
type: "delete"
|
|
1398
1074
|
}
|
|
1399
1075
|
}
|
|
@@ -1405,20 +1081,24 @@ class LiveObject extends AbstractCrdt {
|
|
|
1405
1081
|
modified: !1
|
|
1406
1082
|
};
|
|
1407
1083
|
}
|
|
1084
|
+
_detachChildren() {
|
|
1085
|
+
for (const [key, value] of this._map) this._map.delete(key), value._detach();
|
|
1086
|
+
}
|
|
1408
1087
|
_detach() {
|
|
1409
1088
|
super._detach();
|
|
1410
|
-
for (const value of this._map.values())
|
|
1089
|
+
for (const value of this._map.values()) isCrdt(value) && value._detach();
|
|
1411
1090
|
}
|
|
1412
1091
|
_apply(op, isLocal) {
|
|
1413
1092
|
return op.type === OpCode.UPDATE_OBJECT ? this._applyUpdate(op, isLocal) : op.type === OpCode.DELETE_OBJECT_KEY ? this._applyDeleteObjectKey(op) : super._apply(op, isLocal);
|
|
1414
1093
|
}
|
|
1415
1094
|
_toSerializedCrdt() {
|
|
1095
|
+
var _a;
|
|
1416
1096
|
const data = {};
|
|
1417
|
-
for (const [key, value] of this._map)
|
|
1418
|
-
return
|
|
1097
|
+
for (const [key, value] of this._map) value instanceof AbstractCrdt == !1 && (data[key] = value);
|
|
1098
|
+
return void 0 !== (null === (_a = this._parent) || void 0 === _a ? void 0 : _a._id) && void 0 !== this._parentKey ? {
|
|
1419
1099
|
type: CrdtType.OBJECT,
|
|
1420
|
-
parentId: this.
|
|
1421
|
-
parentKey: this.
|
|
1100
|
+
parentId: this._parent._id,
|
|
1101
|
+
parentKey: this._parentKey,
|
|
1422
1102
|
data: data
|
|
1423
1103
|
} : {
|
|
1424
1104
|
type: CrdtType.OBJECT,
|
|
@@ -1427,23 +1107,24 @@ class LiveObject extends AbstractCrdt {
|
|
|
1427
1107
|
}
|
|
1428
1108
|
_applyUpdate(op, isLocal) {
|
|
1429
1109
|
let isModified = !1;
|
|
1430
|
-
const
|
|
1110
|
+
const reverse = [], reverseUpdate = {
|
|
1431
1111
|
type: OpCode.UPDATE_OBJECT,
|
|
1432
|
-
id:
|
|
1112
|
+
id: this._id,
|
|
1433
1113
|
data: {}
|
|
1434
1114
|
};
|
|
1435
1115
|
reverse.push(reverseUpdate);
|
|
1436
1116
|
for (const key in op.data) {
|
|
1437
1117
|
const oldValue = this._map.get(key);
|
|
1438
|
-
|
|
1118
|
+
oldValue instanceof AbstractCrdt ? (reverse.push(...oldValue._serialize(this._id, key)),
|
|
1119
|
+
oldValue._detach()) : void 0 !== oldValue ? reverseUpdate.data[key] = oldValue : void 0 === oldValue && reverse.push({
|
|
1439
1120
|
type: OpCode.DELETE_OBJECT_KEY,
|
|
1440
|
-
id:
|
|
1121
|
+
id: this._id,
|
|
1441
1122
|
key: key
|
|
1442
1123
|
});
|
|
1443
1124
|
}
|
|
1444
1125
|
const updateDelta = {};
|
|
1445
1126
|
for (const key in op.data) {
|
|
1446
|
-
if (isLocal) this._propToLastUpdate.set(key,
|
|
1127
|
+
if (isLocal) this._propToLastUpdate.set(key, op.opId); else {
|
|
1447
1128
|
if (null != this._propToLastUpdate.get(key)) {
|
|
1448
1129
|
if (this._propToLastUpdate.get(key) === op.opId) {
|
|
1449
1130
|
this._propToLastUpdate.delete(key);
|
|
@@ -1454,7 +1135,7 @@ class LiveObject extends AbstractCrdt {
|
|
|
1454
1135
|
isModified = !0;
|
|
1455
1136
|
}
|
|
1456
1137
|
const oldValue = this._map.get(key);
|
|
1457
|
-
|
|
1138
|
+
isCrdt(oldValue) && oldValue._detach(), isModified = !0, updateDelta[key] = {
|
|
1458
1139
|
type: "update"
|
|
1459
1140
|
}, this._map.set(key, op.data[key]);
|
|
1460
1141
|
}
|
|
@@ -1478,11 +1159,11 @@ class LiveObject extends AbstractCrdt {
|
|
|
1478
1159
|
if (void 0 !== this._propToLastUpdate.get(key)) return {
|
|
1479
1160
|
modified: !1
|
|
1480
1161
|
};
|
|
1481
|
-
const oldValue = this._map.get(key)
|
|
1162
|
+
const oldValue = this._map.get(key);
|
|
1482
1163
|
let reverse = [];
|
|
1483
|
-
return
|
|
1164
|
+
return isCrdt(oldValue) ? (reverse = oldValue._serialize(this._id, op.key), oldValue._detach()) : void 0 !== oldValue && (reverse = [ {
|
|
1484
1165
|
type: OpCode.UPDATE_OBJECT,
|
|
1485
|
-
id:
|
|
1166
|
+
id: this._id,
|
|
1486
1167
|
data: {
|
|
1487
1168
|
[key]: oldValue
|
|
1488
1169
|
}
|
|
@@ -1517,10 +1198,10 @@ class LiveObject extends AbstractCrdt {
|
|
|
1517
1198
|
delete(key) {
|
|
1518
1199
|
const keyAsString = key, oldValue = this._map.get(keyAsString);
|
|
1519
1200
|
if (void 0 === oldValue) return;
|
|
1520
|
-
if (null == this._doc || null == this._id) return
|
|
1201
|
+
if (null == this._doc || null == this._id) return oldValue instanceof AbstractCrdt && oldValue._detach(),
|
|
1521
1202
|
void this._map.delete(keyAsString);
|
|
1522
1203
|
let reverse;
|
|
1523
|
-
|
|
1204
|
+
oldValue instanceof AbstractCrdt ? (oldValue._detach(), reverse = oldValue._serialize(this._id, keyAsString)) : reverse = [ {
|
|
1524
1205
|
type: OpCode.UPDATE_OBJECT,
|
|
1525
1206
|
data: {
|
|
1526
1207
|
[keyAsString]: oldValue
|
|
@@ -1547,9 +1228,9 @@ class LiveObject extends AbstractCrdt {
|
|
|
1547
1228
|
if (null == this._doc || null == this._id) {
|
|
1548
1229
|
for (const key in overrides) {
|
|
1549
1230
|
const oldValue = this._map.get(key);
|
|
1550
|
-
|
|
1231
|
+
oldValue instanceof AbstractCrdt && oldValue._detach();
|
|
1551
1232
|
const newValue = overrides[key];
|
|
1552
|
-
|
|
1233
|
+
newValue instanceof AbstractCrdt && newValue._setParentLink(this, key), this._map.set(key, newValue);
|
|
1553
1234
|
}
|
|
1554
1235
|
return;
|
|
1555
1236
|
}
|
|
@@ -1560,17 +1241,17 @@ class LiveObject extends AbstractCrdt {
|
|
|
1560
1241
|
}, updateDelta = {};
|
|
1561
1242
|
for (const key in overrides) {
|
|
1562
1243
|
const oldValue = this._map.get(key);
|
|
1563
|
-
|
|
1244
|
+
oldValue instanceof AbstractCrdt ? (reverseOps.push(...oldValue._serialize(this._id, key)),
|
|
1564
1245
|
oldValue._detach()) : void 0 === oldValue ? reverseOps.push({
|
|
1565
1246
|
type: OpCode.DELETE_OBJECT_KEY,
|
|
1566
1247
|
id: this._id,
|
|
1567
1248
|
key: key
|
|
1568
1249
|
}) : reverseUpdateOp.data[key] = oldValue;
|
|
1569
1250
|
const newValue = overrides[key];
|
|
1570
|
-
if (
|
|
1251
|
+
if (newValue instanceof AbstractCrdt) {
|
|
1571
1252
|
newValue._setParentLink(this, key), newValue._attach(this._doc.generateId(), this._doc);
|
|
1572
1253
|
const newAttachChildOps = newValue._serialize(this._id, key, this._doc), createCrdtOp = newAttachChildOps.find((op => op.parentId === this._id));
|
|
1573
|
-
createCrdtOp && this._propToLastUpdate.set(key,
|
|
1254
|
+
createCrdtOp && this._propToLastUpdate.set(key, createCrdtOp.opId), ops.push(...newAttachChildOps);
|
|
1574
1255
|
} else updatedProps[key] = newValue, this._propToLastUpdate.set(key, opId);
|
|
1575
1256
|
this._map.set(key, newValue), updateDelta[key] = {
|
|
1576
1257
|
type: "update"
|
|
@@ -1592,4 +1273,4 @@ class LiveObject extends AbstractCrdt {
|
|
|
1592
1273
|
}
|
|
1593
1274
|
}
|
|
1594
1275
|
|
|
1595
|
-
export {
|
|
1276
|
+
export { AbstractCrdt as A, ClientMsgCode as C, LiveObject as L, OpCode as O, ServerMsgCode as S, WebsocketCloseCodes as W, isSameNodeOrChildOf as a, LiveList as b, isJsonArray as c, compact as d, b64decode as e, isJsonObject as f, getTreesDiffOperations as g, isRootCrdt as h, isTokenValid as i, deprecateIf as j, LiveMap as k, LiveRegister as l, mergeStorageUpdates as m, findNonSerializableValue as n, deprecate as o, errorIf as p, throwUsageError as q, remove as r, CrdtType as s, tryParseJson as t, comparePosition as u, makePosition as v, isChildCrdt as w, assertNever as x };
|