@liveblocks/client 0.17.7 → 0.17.10-debug
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/.built-by-link-script +1 -0
- package/chunk-QLMVHHAZ.js +3592 -0
- package/index-0007883d.d.ts +793 -0
- package/index.d.ts +7 -27
- package/index.js +2007 -1269
- package/index.mjs +1 -1114
- package/internal.d.ts +198 -307
- package/internal.js +526 -309
- package/internal.mjs +29 -281
- package/package.json +1 -1
- package/shared.d.ts +0 -855
- package/shared.js +0 -2655
- package/shared.mjs +0 -2069
package/shared.mjs
DELETED
|
@@ -1,2069 +0,0 @@
|
|
|
1
|
-
const _emittedDeprecationWarnings = new Set();
|
|
2
|
-
function deprecate(message, key = message) {
|
|
3
|
-
"production" !== process.env.NODE_ENV &&
|
|
4
|
-
(_emittedDeprecationWarnings.has(key) ||
|
|
5
|
-
(_emittedDeprecationWarnings.add(key),
|
|
6
|
-
console.error(`DEPRECATION WARNING: ${message}`)));
|
|
7
|
-
}
|
|
8
|
-
function deprecateIf(condition, message, key = message) {
|
|
9
|
-
"production" !== process.env.NODE_ENV && condition && deprecate(message, key);
|
|
10
|
-
}
|
|
11
|
-
function throwUsageError(message) {
|
|
12
|
-
if ("production" !== process.env.NODE_ENV) {
|
|
13
|
-
const usageError = new Error(message);
|
|
14
|
-
throw ((usageError.name = "Usage error"), usageError);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
function errorIf(condition, message) {
|
|
18
|
-
"production" !== process.env.NODE_ENV &&
|
|
19
|
-
condition &&
|
|
20
|
-
throwUsageError(message);
|
|
21
|
-
}
|
|
22
|
-
function __rest(s, e) {
|
|
23
|
-
var t = {};
|
|
24
|
-
for (var p in s)
|
|
25
|
-
Object.prototype.hasOwnProperty.call(s, p) &&
|
|
26
|
-
e.indexOf(p) < 0 &&
|
|
27
|
-
(t[p] = s[p]);
|
|
28
|
-
if (null != s && "function" == typeof Object.getOwnPropertySymbols) {
|
|
29
|
-
var i = 0;
|
|
30
|
-
for (p = Object.getOwnPropertySymbols(s); i < p.length; i++)
|
|
31
|
-
e.indexOf(p[i]) < 0 &&
|
|
32
|
-
Object.prototype.propertyIsEnumerable.call(s, p[i]) &&
|
|
33
|
-
(t[p[i]] = s[p[i]]);
|
|
34
|
-
}
|
|
35
|
-
return t;
|
|
36
|
-
}
|
|
37
|
-
function assertNever(_value, errmsg) {
|
|
38
|
-
throw new Error(errmsg);
|
|
39
|
-
}
|
|
40
|
-
function nn(value, errmsg = "Expected value to be non-nullable") {
|
|
41
|
-
return (
|
|
42
|
-
(function (condition, errmsg) {
|
|
43
|
-
if ("production" !== process.env.NODE_ENV && !condition) {
|
|
44
|
-
const err = new Error(errmsg);
|
|
45
|
-
throw ((err.name = "Assertion failure"), err);
|
|
46
|
-
}
|
|
47
|
-
})(null != value, errmsg),
|
|
48
|
-
value
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
var ClientMsgCode,
|
|
52
|
-
OpCode,
|
|
53
|
-
CrdtType,
|
|
54
|
-
ServerMsgCode,
|
|
55
|
-
WebsocketCloseCodes,
|
|
56
|
-
OpSource;
|
|
57
|
-
function isRootCrdt(crdt) {
|
|
58
|
-
return crdt.type === CrdtType.OBJECT && !isChildCrdt(crdt);
|
|
59
|
-
}
|
|
60
|
-
function isChildCrdt(crdt) {
|
|
61
|
-
return void 0 !== crdt.parentId && void 0 !== crdt.parentKey;
|
|
62
|
-
}
|
|
63
|
-
function isRoomEventName(value) {
|
|
64
|
-
return (
|
|
65
|
-
"my-presence" === value ||
|
|
66
|
-
"others" === value ||
|
|
67
|
-
"event" === value ||
|
|
68
|
-
"error" === value ||
|
|
69
|
-
"connection" === value
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
function HasParent(node, key) {
|
|
73
|
-
return Object.freeze({ type: "HasParent", node: node, key: key });
|
|
74
|
-
}
|
|
75
|
-
!(function (ClientMsgCode) {
|
|
76
|
-
(ClientMsgCode[(ClientMsgCode.UPDATE_PRESENCE = 100)] = "UPDATE_PRESENCE"),
|
|
77
|
-
(ClientMsgCode[(ClientMsgCode.BROADCAST_EVENT = 103)] = "BROADCAST_EVENT"),
|
|
78
|
-
(ClientMsgCode[(ClientMsgCode.FETCH_STORAGE = 200)] = "FETCH_STORAGE"),
|
|
79
|
-
(ClientMsgCode[(ClientMsgCode.UPDATE_STORAGE = 201)] = "UPDATE_STORAGE");
|
|
80
|
-
})(ClientMsgCode || (ClientMsgCode = {})),
|
|
81
|
-
(function (OpCode) {
|
|
82
|
-
(OpCode[(OpCode.INIT = 0)] = "INIT"),
|
|
83
|
-
(OpCode[(OpCode.SET_PARENT_KEY = 1)] = "SET_PARENT_KEY"),
|
|
84
|
-
(OpCode[(OpCode.CREATE_LIST = 2)] = "CREATE_LIST"),
|
|
85
|
-
(OpCode[(OpCode.UPDATE_OBJECT = 3)] = "UPDATE_OBJECT"),
|
|
86
|
-
(OpCode[(OpCode.CREATE_OBJECT = 4)] = "CREATE_OBJECT"),
|
|
87
|
-
(OpCode[(OpCode.DELETE_CRDT = 5)] = "DELETE_CRDT"),
|
|
88
|
-
(OpCode[(OpCode.DELETE_OBJECT_KEY = 6)] = "DELETE_OBJECT_KEY"),
|
|
89
|
-
(OpCode[(OpCode.CREATE_MAP = 7)] = "CREATE_MAP"),
|
|
90
|
-
(OpCode[(OpCode.CREATE_REGISTER = 8)] = "CREATE_REGISTER");
|
|
91
|
-
})(OpCode || (OpCode = {})),
|
|
92
|
-
(function (CrdtType) {
|
|
93
|
-
(CrdtType[(CrdtType.OBJECT = 0)] = "OBJECT"),
|
|
94
|
-
(CrdtType[(CrdtType.LIST = 1)] = "LIST"),
|
|
95
|
-
(CrdtType[(CrdtType.MAP = 2)] = "MAP"),
|
|
96
|
-
(CrdtType[(CrdtType.REGISTER = 3)] = "REGISTER");
|
|
97
|
-
})(CrdtType || (CrdtType = {})),
|
|
98
|
-
(function (ServerMsgCode) {
|
|
99
|
-
(ServerMsgCode[(ServerMsgCode.UPDATE_PRESENCE = 100)] = "UPDATE_PRESENCE"),
|
|
100
|
-
(ServerMsgCode[(ServerMsgCode.USER_JOINED = 101)] = "USER_JOINED"),
|
|
101
|
-
(ServerMsgCode[(ServerMsgCode.USER_LEFT = 102)] = "USER_LEFT"),
|
|
102
|
-
(ServerMsgCode[(ServerMsgCode.BROADCASTED_EVENT = 103)] =
|
|
103
|
-
"BROADCASTED_EVENT"),
|
|
104
|
-
(ServerMsgCode[(ServerMsgCode.ROOM_STATE = 104)] = "ROOM_STATE"),
|
|
105
|
-
(ServerMsgCode[(ServerMsgCode.INITIAL_STORAGE_STATE = 200)] =
|
|
106
|
-
"INITIAL_STORAGE_STATE"),
|
|
107
|
-
(ServerMsgCode[(ServerMsgCode.UPDATE_STORAGE = 201)] = "UPDATE_STORAGE");
|
|
108
|
-
})(ServerMsgCode || (ServerMsgCode = {})),
|
|
109
|
-
(function (WebsocketCloseCodes) {
|
|
110
|
-
(WebsocketCloseCodes[(WebsocketCloseCodes.CLOSE_ABNORMAL = 1006)] =
|
|
111
|
-
"CLOSE_ABNORMAL"),
|
|
112
|
-
(WebsocketCloseCodes[(WebsocketCloseCodes.INVALID_MESSAGE_FORMAT = 4e3)] =
|
|
113
|
-
"INVALID_MESSAGE_FORMAT"),
|
|
114
|
-
(WebsocketCloseCodes[(WebsocketCloseCodes.NOT_ALLOWED = 4001)] =
|
|
115
|
-
"NOT_ALLOWED"),
|
|
116
|
-
(WebsocketCloseCodes[
|
|
117
|
-
(WebsocketCloseCodes.MAX_NUMBER_OF_MESSAGES_PER_SECONDS = 4002)
|
|
118
|
-
] = "MAX_NUMBER_OF_MESSAGES_PER_SECONDS"),
|
|
119
|
-
(WebsocketCloseCodes[
|
|
120
|
-
(WebsocketCloseCodes.MAX_NUMBER_OF_CONCURRENT_CONNECTIONS = 4003)
|
|
121
|
-
] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS"),
|
|
122
|
-
(WebsocketCloseCodes[
|
|
123
|
-
(WebsocketCloseCodes.MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP = 4004)
|
|
124
|
-
] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"),
|
|
125
|
-
(WebsocketCloseCodes[
|
|
126
|
-
(WebsocketCloseCodes.MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM = 4005)
|
|
127
|
-
] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"),
|
|
128
|
-
(WebsocketCloseCodes[(WebsocketCloseCodes.CLOSE_WITHOUT_RETRY = 4999)] =
|
|
129
|
-
"CLOSE_WITHOUT_RETRY");
|
|
130
|
-
})(WebsocketCloseCodes || (WebsocketCloseCodes = {})),
|
|
131
|
-
(function (OpSource) {
|
|
132
|
-
(OpSource[(OpSource.UNDOREDO_RECONNECT = 0)] = "UNDOREDO_RECONNECT"),
|
|
133
|
-
(OpSource[(OpSource.REMOTE = 1)] = "REMOTE"),
|
|
134
|
-
(OpSource[(OpSource.ACK = 2)] = "ACK");
|
|
135
|
-
})(OpSource || (OpSource = {}));
|
|
136
|
-
const NoParent = Object.freeze({ type: "NoParent" });
|
|
137
|
-
function Orphaned(oldKey) {
|
|
138
|
-
return Object.freeze({ type: "Orphaned", oldKey: oldKey });
|
|
139
|
-
}
|
|
140
|
-
class AbstractCrdt {
|
|
141
|
-
constructor() {
|
|
142
|
-
this._parent = NoParent;
|
|
143
|
-
}
|
|
144
|
-
_getParentKeyOrThrow() {
|
|
145
|
-
switch (this.parent.type) {
|
|
146
|
-
case "HasParent":
|
|
147
|
-
return this.parent.key;
|
|
148
|
-
case "NoParent":
|
|
149
|
-
throw new Error("Parent key is missing");
|
|
150
|
-
case "Orphaned":
|
|
151
|
-
return this.parent.oldKey;
|
|
152
|
-
default:
|
|
153
|
-
return assertNever(this.parent, "Unknown state");
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
get _doc() {
|
|
157
|
-
return this.__doc;
|
|
158
|
-
}
|
|
159
|
-
get roomId() {
|
|
160
|
-
return this.__doc ? this.__doc.roomId : null;
|
|
161
|
-
}
|
|
162
|
-
get _id() {
|
|
163
|
-
return this.__id;
|
|
164
|
-
}
|
|
165
|
-
get parent() {
|
|
166
|
-
return this._parent;
|
|
167
|
-
}
|
|
168
|
-
get _parentNode() {
|
|
169
|
-
switch (this.parent.type) {
|
|
170
|
-
case "HasParent":
|
|
171
|
-
return this.parent.node;
|
|
172
|
-
case "NoParent":
|
|
173
|
-
case "Orphaned":
|
|
174
|
-
return null;
|
|
175
|
-
default:
|
|
176
|
-
return assertNever(this.parent, "Unknown state");
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
get _parentKey() {
|
|
180
|
-
switch (this.parent.type) {
|
|
181
|
-
case "HasParent":
|
|
182
|
-
return this.parent.key;
|
|
183
|
-
case "NoParent":
|
|
184
|
-
return null;
|
|
185
|
-
case "Orphaned":
|
|
186
|
-
return this.parent.oldKey;
|
|
187
|
-
default:
|
|
188
|
-
return assertNever(this.parent, "Unknown state");
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
_apply(op, _isLocal) {
|
|
192
|
-
return op.type === OpCode.DELETE_CRDT && "HasParent" === this.parent.type
|
|
193
|
-
? this.parent.node._detachChild(this)
|
|
194
|
-
: { modified: !1 };
|
|
195
|
-
}
|
|
196
|
-
_setParentLink(newParentNode, newParentKey) {
|
|
197
|
-
switch (this.parent.type) {
|
|
198
|
-
case "HasParent":
|
|
199
|
-
if (this.parent.node !== newParentNode)
|
|
200
|
-
throw new Error("Cannot attach parent if it already exist");
|
|
201
|
-
return void (this._parent = HasParent(newParentNode, newParentKey));
|
|
202
|
-
case "Orphaned":
|
|
203
|
-
case "NoParent":
|
|
204
|
-
return void (this._parent = HasParent(newParentNode, newParentKey));
|
|
205
|
-
default:
|
|
206
|
-
return assertNever(this.parent, "Unknown state");
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
_attach(id, doc) {
|
|
210
|
-
if (this.__id || this.__doc)
|
|
211
|
-
throw new Error("Cannot attach if CRDT is already attached");
|
|
212
|
-
doc.addItem(id, this), (this.__id = id), (this.__doc = doc);
|
|
213
|
-
}
|
|
214
|
-
_detach() {
|
|
215
|
-
switch (
|
|
216
|
-
(this.__doc && this.__id && this.__doc.deleteItem(this.__id),
|
|
217
|
-
this.parent.type)
|
|
218
|
-
) {
|
|
219
|
-
case "HasParent":
|
|
220
|
-
this._parent = Orphaned(this.parent.key);
|
|
221
|
-
break;
|
|
222
|
-
case "NoParent":
|
|
223
|
-
this._parent = NoParent;
|
|
224
|
-
break;
|
|
225
|
-
case "Orphaned":
|
|
226
|
-
this._parent = Orphaned(this.parent.oldKey);
|
|
227
|
-
break;
|
|
228
|
-
default:
|
|
229
|
-
assertNever(this.parent, "Unknown state");
|
|
230
|
-
}
|
|
231
|
-
this.__doc = void 0;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
class LiveRegister extends AbstractCrdt {
|
|
235
|
-
constructor(data) {
|
|
236
|
-
super(), (this._data = data);
|
|
237
|
-
}
|
|
238
|
-
get data() {
|
|
239
|
-
return this._data;
|
|
240
|
-
}
|
|
241
|
-
static _deserialize([id, item], _parentToChildren, doc) {
|
|
242
|
-
const register = new LiveRegister(item.data);
|
|
243
|
-
return register._attach(id, doc), register;
|
|
244
|
-
}
|
|
245
|
-
_serialize(parentId, parentKey, doc) {
|
|
246
|
-
if (null == this._id || null == parentId || null == parentKey)
|
|
247
|
-
throw new Error(
|
|
248
|
-
"Cannot serialize register if parentId or parentKey is undefined"
|
|
249
|
-
);
|
|
250
|
-
return [
|
|
251
|
-
{
|
|
252
|
-
type: OpCode.CREATE_REGISTER,
|
|
253
|
-
opId: null == doc ? void 0 : doc.generateOpId(),
|
|
254
|
-
id: this._id,
|
|
255
|
-
parentId: parentId,
|
|
256
|
-
parentKey: parentKey,
|
|
257
|
-
data: this.data,
|
|
258
|
-
},
|
|
259
|
-
];
|
|
260
|
-
}
|
|
261
|
-
_toSerializedCrdt() {
|
|
262
|
-
if ("HasParent" !== this.parent.type)
|
|
263
|
-
throw new Error("Cannot serialize LiveRegister if parent is missing");
|
|
264
|
-
return {
|
|
265
|
-
type: CrdtType.REGISTER,
|
|
266
|
-
parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
|
|
267
|
-
parentKey: this.parent.key,
|
|
268
|
-
data: this.data,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
_attachChild(_op) {
|
|
272
|
-
throw new Error("Method not implemented.");
|
|
273
|
-
}
|
|
274
|
-
_detachChild(_crdt) {
|
|
275
|
-
throw new Error("Method not implemented.");
|
|
276
|
-
}
|
|
277
|
-
_apply(op, isLocal) {
|
|
278
|
-
return super._apply(op, isLocal);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
function makePosition(before, after) {
|
|
282
|
-
return null != before && null != after
|
|
283
|
-
? pos(makePositionFromCodes(posCodes(before), posCodes(after)))
|
|
284
|
-
: null != before
|
|
285
|
-
? (function (before) {
|
|
286
|
-
const result = [],
|
|
287
|
-
beforeCodes = posCodes(before);
|
|
288
|
-
for (let i = 0; i < beforeCodes.length; i++) {
|
|
289
|
-
const code = beforeCodes[i];
|
|
290
|
-
if (126 !== code) {
|
|
291
|
-
result.push(code + 1);
|
|
292
|
-
break;
|
|
293
|
-
}
|
|
294
|
-
if ((result.push(code), beforeCodes.length - 1 === i)) {
|
|
295
|
-
result.push(33);
|
|
296
|
-
break;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return pos(result);
|
|
300
|
-
})(before)
|
|
301
|
-
: null != after
|
|
302
|
-
? (function (after) {
|
|
303
|
-
const result = [],
|
|
304
|
-
afterCodes = posCodes(after);
|
|
305
|
-
for (let i = 0; i < afterCodes.length; i++) {
|
|
306
|
-
const code = afterCodes[i];
|
|
307
|
-
if (!(code <= 33)) {
|
|
308
|
-
result.push(code - 1);
|
|
309
|
-
break;
|
|
310
|
-
}
|
|
311
|
-
if ((result.push(32), afterCodes.length - 1 === i)) {
|
|
312
|
-
result.push(126);
|
|
313
|
-
break;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
return pos(result);
|
|
317
|
-
})(after)
|
|
318
|
-
: pos([33]);
|
|
319
|
-
}
|
|
320
|
-
function makePositionFromCodes(before, after) {
|
|
321
|
-
let index = 0;
|
|
322
|
-
const result = [];
|
|
323
|
-
for (;;) {
|
|
324
|
-
const beforeDigit = before[index] || 32,
|
|
325
|
-
afterDigit = after[index] || 126;
|
|
326
|
-
if (beforeDigit > afterDigit)
|
|
327
|
-
throw new Error(
|
|
328
|
-
`Impossible to generate position between ${before} and ${after}`
|
|
329
|
-
);
|
|
330
|
-
if (beforeDigit === afterDigit) {
|
|
331
|
-
result.push(beforeDigit), index++;
|
|
332
|
-
continue;
|
|
333
|
-
}
|
|
334
|
-
if (afterDigit - beforeDigit == 1) {
|
|
335
|
-
result.push(beforeDigit),
|
|
336
|
-
result.push(...makePositionFromCodes(before.slice(index + 1), []));
|
|
337
|
-
break;
|
|
338
|
-
}
|
|
339
|
-
const mid = (afterDigit + beforeDigit) >> 1;
|
|
340
|
-
result.push(mid);
|
|
341
|
-
break;
|
|
342
|
-
}
|
|
343
|
-
return result;
|
|
344
|
-
}
|
|
345
|
-
function posCodes(str) {
|
|
346
|
-
const codes = [];
|
|
347
|
-
for (let i = 0; i < str.length; i++) codes.push(str.charCodeAt(i));
|
|
348
|
-
return codes;
|
|
349
|
-
}
|
|
350
|
-
function pos(codes) {
|
|
351
|
-
return String.fromCharCode(...codes);
|
|
352
|
-
}
|
|
353
|
-
function comparePosition(posA, posB) {
|
|
354
|
-
const aCodes = posCodes(posA),
|
|
355
|
-
bCodes = posCodes(posB),
|
|
356
|
-
maxLength = Math.max(aCodes.length, bCodes.length);
|
|
357
|
-
for (let i = 0; i < maxLength; i++) {
|
|
358
|
-
const a = null == aCodes[i] ? 32 : aCodes[i],
|
|
359
|
-
b = null == bCodes[i] ? 32 : bCodes[i];
|
|
360
|
-
if (a !== b) return a - b;
|
|
361
|
-
}
|
|
362
|
-
throw new Error(
|
|
363
|
-
`Impossible to compare similar position "${posA}" and "${posB}"`
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
function compareNodePosition(itemA, itemB) {
|
|
367
|
-
return comparePosition(
|
|
368
|
-
itemA._getParentKeyOrThrow(),
|
|
369
|
-
itemB._getParentKeyOrThrow()
|
|
370
|
-
);
|
|
371
|
-
}
|
|
372
|
-
class LiveList extends AbstractCrdt {
|
|
373
|
-
constructor(items = []) {
|
|
374
|
-
let position;
|
|
375
|
-
super(),
|
|
376
|
-
(this._items = []),
|
|
377
|
-
(this._implicitlyDeletedItems = new Set()),
|
|
378
|
-
(this._unacknowledgedSets = new Map());
|
|
379
|
-
for (let i = 0; i < items.length; i++) {
|
|
380
|
-
const newPosition = makePosition(position),
|
|
381
|
-
item = lsonToLiveNode(items[i]);
|
|
382
|
-
item._setParentLink(this, newPosition),
|
|
383
|
-
this._items.push(item),
|
|
384
|
-
(position = newPosition);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
static _deserialize([id], parentToChildren, doc) {
|
|
388
|
-
const list = new LiveList();
|
|
389
|
-
list._attach(id, doc);
|
|
390
|
-
const children = parentToChildren.get(id);
|
|
391
|
-
if (null == children) return list;
|
|
392
|
-
for (const [id, crdt] of children) {
|
|
393
|
-
const child = deserialize([id, crdt], parentToChildren, doc);
|
|
394
|
-
child._setParentLink(list, crdt.parentKey), list._insertAndSort(child);
|
|
395
|
-
}
|
|
396
|
-
return list;
|
|
397
|
-
}
|
|
398
|
-
_serialize(parentId, parentKey, doc) {
|
|
399
|
-
if (null == this._id)
|
|
400
|
-
throw new Error("Cannot serialize item is not attached");
|
|
401
|
-
const ops = [],
|
|
402
|
-
op = {
|
|
403
|
-
id: this._id,
|
|
404
|
-
opId: null == doc ? void 0 : doc.generateOpId(),
|
|
405
|
-
type: OpCode.CREATE_LIST,
|
|
406
|
-
parentId: parentId,
|
|
407
|
-
parentKey: parentKey,
|
|
408
|
-
};
|
|
409
|
-
ops.push(op);
|
|
410
|
-
for (const item of this._items)
|
|
411
|
-
ops.push(...item._serialize(this._id, item._getParentKeyOrThrow(), doc));
|
|
412
|
-
return ops;
|
|
413
|
-
}
|
|
414
|
-
_insertAndSort(item) {
|
|
415
|
-
this._items.push(item), this._sortItems();
|
|
416
|
-
}
|
|
417
|
-
_sortItems() {
|
|
418
|
-
this._items.sort(compareNodePosition);
|
|
419
|
-
}
|
|
420
|
-
_indexOfPosition(position) {
|
|
421
|
-
return this._items.findIndex(
|
|
422
|
-
(item) => item._getParentKeyOrThrow() === position
|
|
423
|
-
);
|
|
424
|
-
}
|
|
425
|
-
_attach(id, doc) {
|
|
426
|
-
super._attach(id, doc);
|
|
427
|
-
for (const item of this._items) item._attach(doc.generateId(), doc);
|
|
428
|
-
}
|
|
429
|
-
_detach() {
|
|
430
|
-
super._detach();
|
|
431
|
-
for (const item of this._items) item._detach();
|
|
432
|
-
}
|
|
433
|
-
_applySetRemote(op) {
|
|
434
|
-
if (null == this._doc)
|
|
435
|
-
throw new Error("Can't attach child if doc is not present");
|
|
436
|
-
const { id: id, parentKey: key } = op,
|
|
437
|
-
child = creationOpToLiveNode(op);
|
|
438
|
-
child._attach(id, this._doc), child._setParentLink(this, key);
|
|
439
|
-
const deletedId = op.deletedId,
|
|
440
|
-
indexOfItemWithSamePosition = this._indexOfPosition(key);
|
|
441
|
-
if (-1 !== indexOfItemWithSamePosition) {
|
|
442
|
-
const itemWithSamePosition = this._items[indexOfItemWithSamePosition];
|
|
443
|
-
if (itemWithSamePosition._id === deletedId)
|
|
444
|
-
return (
|
|
445
|
-
itemWithSamePosition._detach(),
|
|
446
|
-
(this._items[indexOfItemWithSamePosition] = child),
|
|
447
|
-
{
|
|
448
|
-
modified: makeUpdate(this, [
|
|
449
|
-
setDelta(indexOfItemWithSamePosition, child),
|
|
450
|
-
]),
|
|
451
|
-
reverse: [],
|
|
452
|
-
}
|
|
453
|
-
);
|
|
454
|
-
{
|
|
455
|
-
this._implicitlyDeletedItems.add(itemWithSamePosition),
|
|
456
|
-
(this._items[indexOfItemWithSamePosition] = child);
|
|
457
|
-
const delta = [setDelta(indexOfItemWithSamePosition, child)],
|
|
458
|
-
deleteDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
459
|
-
return (
|
|
460
|
-
deleteDelta && delta.push(deleteDelta),
|
|
461
|
-
{ modified: makeUpdate(this, delta), reverse: [] }
|
|
462
|
-
);
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
{
|
|
466
|
-
const updates = [],
|
|
467
|
-
deleteDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
468
|
-
return (
|
|
469
|
-
deleteDelta && updates.push(deleteDelta),
|
|
470
|
-
this._insertAndSort(child),
|
|
471
|
-
updates.push(insertDelta(this._indexOfPosition(key), child)),
|
|
472
|
-
{ reverse: [], modified: makeUpdate(this, updates) }
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
_applySetAck(op) {
|
|
477
|
-
if (null == this._doc)
|
|
478
|
-
throw new Error("Can't attach child if doc is not present");
|
|
479
|
-
const delta = [],
|
|
480
|
-
deletedDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
481
|
-
deletedDelta && delta.push(deletedDelta);
|
|
482
|
-
const unacknowledgedOpId = this._unacknowledgedSets.get(op.parentKey);
|
|
483
|
-
if (null != unacknowledgedOpId) {
|
|
484
|
-
if (unacknowledgedOpId !== op.opId)
|
|
485
|
-
return 0 === delta.length
|
|
486
|
-
? { modified: !1 }
|
|
487
|
-
: { modified: makeUpdate(this, delta), reverse: [] };
|
|
488
|
-
this._unacknowledgedSets.delete(op.parentKey);
|
|
489
|
-
}
|
|
490
|
-
const indexOfItemWithSamePosition = this._indexOfPosition(op.parentKey),
|
|
491
|
-
existingItem = this._items.find((item) => item._id === op.id);
|
|
492
|
-
if (null != existingItem) {
|
|
493
|
-
if (existingItem._parentKey === op.parentKey)
|
|
494
|
-
return {
|
|
495
|
-
modified: delta.length > 0 && makeUpdate(this, delta),
|
|
496
|
-
reverse: [],
|
|
497
|
-
};
|
|
498
|
-
-1 !== indexOfItemWithSamePosition &&
|
|
499
|
-
(this._implicitlyDeletedItems.add(
|
|
500
|
-
this._items[indexOfItemWithSamePosition]
|
|
501
|
-
),
|
|
502
|
-
this._items.splice(indexOfItemWithSamePosition, 1),
|
|
503
|
-
delta.push(deleteDelta(indexOfItemWithSamePosition)));
|
|
504
|
-
const previousIndex = this._items.indexOf(existingItem);
|
|
505
|
-
existingItem._setParentLink(this, op.parentKey), this._sortItems();
|
|
506
|
-
const newIndex = this._items.indexOf(existingItem);
|
|
507
|
-
return (
|
|
508
|
-
newIndex !== previousIndex &&
|
|
509
|
-
delta.push(moveDelta(previousIndex, newIndex, existingItem)),
|
|
510
|
-
{ modified: delta.length > 0 && makeUpdate(this, delta), reverse: [] }
|
|
511
|
-
);
|
|
512
|
-
}
|
|
513
|
-
{
|
|
514
|
-
const orphan = this._doc.getItem(op.id);
|
|
515
|
-
if (orphan && this._implicitlyDeletedItems.has(orphan)) {
|
|
516
|
-
orphan._setParentLink(this, op.parentKey),
|
|
517
|
-
this._implicitlyDeletedItems.delete(orphan),
|
|
518
|
-
this._insertAndSort(orphan);
|
|
519
|
-
const recreatedItemIndex = this._items.indexOf(orphan);
|
|
520
|
-
return {
|
|
521
|
-
modified: makeUpdate(this, [
|
|
522
|
-
-1 === indexOfItemWithSamePosition
|
|
523
|
-
? insertDelta(recreatedItemIndex, orphan)
|
|
524
|
-
: setDelta(recreatedItemIndex, orphan),
|
|
525
|
-
...delta,
|
|
526
|
-
]),
|
|
527
|
-
reverse: [],
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
{
|
|
531
|
-
-1 !== indexOfItemWithSamePosition &&
|
|
532
|
-
this._items.splice(indexOfItemWithSamePosition, 1);
|
|
533
|
-
const { newItem: newItem, newIndex: newIndex } =
|
|
534
|
-
this._createAttachItemAndSort(op, op.parentKey);
|
|
535
|
-
return {
|
|
536
|
-
modified: makeUpdate(this, [
|
|
537
|
-
-1 === indexOfItemWithSamePosition
|
|
538
|
-
? insertDelta(newIndex, newItem)
|
|
539
|
-
: setDelta(newIndex, newItem),
|
|
540
|
-
...delta,
|
|
541
|
-
]),
|
|
542
|
-
reverse: [],
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
_detachItemAssociatedToSetOperation(deletedId) {
|
|
548
|
-
if (null == deletedId || null == this._doc) return null;
|
|
549
|
-
const deletedItem = this._doc.getItem(deletedId);
|
|
550
|
-
if (null == deletedItem) return null;
|
|
551
|
-
const result = this._detachChild(deletedItem);
|
|
552
|
-
return !1 === result.modified ? null : result.modified.updates[0];
|
|
553
|
-
}
|
|
554
|
-
_applyRemoteInsert(op) {
|
|
555
|
-
if (null == this._doc)
|
|
556
|
-
throw new Error("Can't attach child if doc is not present");
|
|
557
|
-
const key = op.parentKey,
|
|
558
|
-
existingItemIndex = this._indexOfPosition(key);
|
|
559
|
-
-1 !== existingItemIndex && this._shiftItemPosition(existingItemIndex, key);
|
|
560
|
-
const { newItem: newItem, newIndex: newIndex } =
|
|
561
|
-
this._createAttachItemAndSort(op, key);
|
|
562
|
-
return {
|
|
563
|
-
modified: makeUpdate(this, [insertDelta(newIndex, newItem)]),
|
|
564
|
-
reverse: [],
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
_applyInsertAck(op) {
|
|
568
|
-
const existingItem = this._items.find((item) => item._id === op.id),
|
|
569
|
-
key = op.parentKey,
|
|
570
|
-
itemIndexAtPosition = this._indexOfPosition(key);
|
|
571
|
-
if (existingItem) {
|
|
572
|
-
if (existingItem._parentKey === key) return { modified: !1 };
|
|
573
|
-
{
|
|
574
|
-
const oldPositionIndex = this._items.indexOf(existingItem);
|
|
575
|
-
-1 !== itemIndexAtPosition &&
|
|
576
|
-
this._shiftItemPosition(itemIndexAtPosition, key),
|
|
577
|
-
existingItem._setParentLink(this, key),
|
|
578
|
-
this._sortItems();
|
|
579
|
-
const newIndex = this._indexOfPosition(key);
|
|
580
|
-
return newIndex === oldPositionIndex
|
|
581
|
-
? { modified: !1 }
|
|
582
|
-
: {
|
|
583
|
-
modified: makeUpdate(this, [
|
|
584
|
-
moveDelta(oldPositionIndex, newIndex, existingItem),
|
|
585
|
-
]),
|
|
586
|
-
reverse: [],
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
{
|
|
591
|
-
const orphan = nn(this._doc).getItem(op.id);
|
|
592
|
-
if (orphan && this._implicitlyDeletedItems.has(orphan)) {
|
|
593
|
-
orphan._setParentLink(this, key),
|
|
594
|
-
this._implicitlyDeletedItems.delete(orphan),
|
|
595
|
-
this._insertAndSort(orphan);
|
|
596
|
-
return {
|
|
597
|
-
modified: makeUpdate(this, [
|
|
598
|
-
insertDelta(this._indexOfPosition(key), orphan),
|
|
599
|
-
]),
|
|
600
|
-
reverse: [],
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
{
|
|
604
|
-
-1 !== itemIndexAtPosition &&
|
|
605
|
-
this._shiftItemPosition(itemIndexAtPosition, key);
|
|
606
|
-
const { newItem: newItem, newIndex: newIndex } =
|
|
607
|
-
this._createAttachItemAndSort(op, key);
|
|
608
|
-
return {
|
|
609
|
-
modified: makeUpdate(this, [insertDelta(newIndex, newItem)]),
|
|
610
|
-
reverse: [],
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
_applyInsertUndoRedo(op) {
|
|
616
|
-
var _a;
|
|
617
|
-
const { id: id, parentKey: key } = op,
|
|
618
|
-
child = creationOpToLiveNode(op);
|
|
619
|
-
if (
|
|
620
|
-
void 0 !==
|
|
621
|
-
(null === (_a = this._doc) || void 0 === _a ? void 0 : _a.getItem(id))
|
|
622
|
-
)
|
|
623
|
-
return { modified: !1 };
|
|
624
|
-
child._attach(id, nn(this._doc)), child._setParentLink(this, key);
|
|
625
|
-
const existingItemIndex = this._indexOfPosition(key);
|
|
626
|
-
let newKey = key;
|
|
627
|
-
if (-1 !== existingItemIndex) {
|
|
628
|
-
(newKey = makePosition(
|
|
629
|
-
this._items[existingItemIndex]
|
|
630
|
-
? this._items[existingItemIndex]._getParentKeyOrThrow()
|
|
631
|
-
: void 0,
|
|
632
|
-
this._items[existingItemIndex + 1]
|
|
633
|
-
? this._items[existingItemIndex + 1]._getParentKeyOrThrow()
|
|
634
|
-
: void 0
|
|
635
|
-
)),
|
|
636
|
-
child._setParentLink(this, newKey);
|
|
637
|
-
}
|
|
638
|
-
this._insertAndSort(child);
|
|
639
|
-
return {
|
|
640
|
-
modified: makeUpdate(this, [
|
|
641
|
-
insertDelta(this._indexOfPosition(newKey), child),
|
|
642
|
-
]),
|
|
643
|
-
reverse: [{ type: OpCode.DELETE_CRDT, id: id }],
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
_applySetUndoRedo(op) {
|
|
647
|
-
var _a;
|
|
648
|
-
const { id: id, parentKey: key } = op,
|
|
649
|
-
child = creationOpToLiveNode(op);
|
|
650
|
-
if (
|
|
651
|
-
void 0 !==
|
|
652
|
-
(null === (_a = this._doc) || void 0 === _a ? void 0 : _a.getItem(id))
|
|
653
|
-
)
|
|
654
|
-
return { modified: !1 };
|
|
655
|
-
this._unacknowledgedSets.set(key, nn(op.opId));
|
|
656
|
-
const indexOfItemWithSameKey = this._indexOfPosition(key);
|
|
657
|
-
child._attach(id, nn(this._doc)), child._setParentLink(this, key);
|
|
658
|
-
const newKey = key;
|
|
659
|
-
if (-1 !== indexOfItemWithSameKey) {
|
|
660
|
-
const existingItem = this._items[indexOfItemWithSameKey];
|
|
661
|
-
existingItem._detach(), (this._items[indexOfItemWithSameKey] = child);
|
|
662
|
-
const reverse = existingItem._serialize(nn(this._id), key, this._doc);
|
|
663
|
-
addIntentAndDeletedIdToOperation(reverse, op.id);
|
|
664
|
-
const delta = [setDelta(indexOfItemWithSameKey, child)],
|
|
665
|
-
deletedDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
666
|
-
return (
|
|
667
|
-
deletedDelta && delta.push(deletedDelta),
|
|
668
|
-
{ modified: makeUpdate(this, delta), reverse: reverse }
|
|
669
|
-
);
|
|
670
|
-
}
|
|
671
|
-
{
|
|
672
|
-
this._insertAndSort(child),
|
|
673
|
-
this._detachItemAssociatedToSetOperation(op.deletedId);
|
|
674
|
-
const newIndex = this._indexOfPosition(newKey);
|
|
675
|
-
return {
|
|
676
|
-
reverse: [{ type: OpCode.DELETE_CRDT, id: id }],
|
|
677
|
-
modified: makeUpdate(this, [insertDelta(newIndex, child)]),
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
_attachChild(op, source) {
|
|
682
|
-
if (null == this._doc)
|
|
683
|
-
throw new Error("Can't attach child if doc is not present");
|
|
684
|
-
if ("set" === op.intent) {
|
|
685
|
-
if (source === OpSource.REMOTE) return this._applySetRemote(op);
|
|
686
|
-
if (source === OpSource.UNDOREDO_RECONNECT)
|
|
687
|
-
return this._applySetUndoRedo(op);
|
|
688
|
-
if (source === OpSource.ACK) return this._applySetAck(op);
|
|
689
|
-
}
|
|
690
|
-
return source === OpSource.REMOTE
|
|
691
|
-
? this._applyRemoteInsert(op)
|
|
692
|
-
: source === OpSource.ACK
|
|
693
|
-
? this._applyInsertAck(op)
|
|
694
|
-
: this._applyInsertUndoRedo(op);
|
|
695
|
-
}
|
|
696
|
-
_detachChild(child) {
|
|
697
|
-
if (child) {
|
|
698
|
-
const parentKey = nn(child._parentKey),
|
|
699
|
-
reverse = child._serialize(nn(this._id), parentKey, this._doc),
|
|
700
|
-
indexToDelete = this._items.indexOf(child);
|
|
701
|
-
return -1 === indexToDelete
|
|
702
|
-
? { modified: !1 }
|
|
703
|
-
: (this._items.splice(indexToDelete, 1),
|
|
704
|
-
child._detach(),
|
|
705
|
-
{
|
|
706
|
-
modified: makeUpdate(this, [deleteDelta(indexToDelete)]),
|
|
707
|
-
reverse: reverse,
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
return { modified: !1 };
|
|
711
|
-
}
|
|
712
|
-
_applySetChildKeyRemote(newKey, child) {
|
|
713
|
-
var _a;
|
|
714
|
-
if (this._implicitlyDeletedItems.has(child)) {
|
|
715
|
-
this._implicitlyDeletedItems.delete(child),
|
|
716
|
-
child._setParentLink(this, newKey),
|
|
717
|
-
this._insertAndSort(child);
|
|
718
|
-
return {
|
|
719
|
-
modified: makeUpdate(this, [
|
|
720
|
-
insertDelta(this._items.indexOf(child), child),
|
|
721
|
-
]),
|
|
722
|
-
reverse: [],
|
|
723
|
-
};
|
|
724
|
-
}
|
|
725
|
-
if (newKey === child._parentKey) return { modified: !1 };
|
|
726
|
-
const existingItemIndex = this._indexOfPosition(newKey);
|
|
727
|
-
if (-1 === existingItemIndex) {
|
|
728
|
-
const previousIndex = this._items.indexOf(child);
|
|
729
|
-
child._setParentLink(this, newKey), this._sortItems();
|
|
730
|
-
const newIndex = this._items.indexOf(child);
|
|
731
|
-
return newIndex === previousIndex
|
|
732
|
-
? { modified: !1 }
|
|
733
|
-
: {
|
|
734
|
-
modified: makeUpdate(this, [
|
|
735
|
-
moveDelta(previousIndex, newIndex, child),
|
|
736
|
-
]),
|
|
737
|
-
reverse: [],
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
{
|
|
741
|
-
this._items[existingItemIndex]._setParentLink(
|
|
742
|
-
this,
|
|
743
|
-
makePosition(
|
|
744
|
-
newKey,
|
|
745
|
-
null === (_a = this._items[existingItemIndex + 1]) || void 0 === _a
|
|
746
|
-
? void 0
|
|
747
|
-
: _a._getParentKeyOrThrow()
|
|
748
|
-
)
|
|
749
|
-
);
|
|
750
|
-
const previousIndex = this._items.indexOf(child);
|
|
751
|
-
child._setParentLink(this, newKey), this._sortItems();
|
|
752
|
-
const newIndex = this._items.indexOf(child);
|
|
753
|
-
return newIndex === previousIndex
|
|
754
|
-
? { modified: !1 }
|
|
755
|
-
: {
|
|
756
|
-
modified: makeUpdate(this, [
|
|
757
|
-
moveDelta(previousIndex, newIndex, child),
|
|
758
|
-
]),
|
|
759
|
-
reverse: [],
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
_applySetChildKeyAck(newKey, child) {
|
|
764
|
-
var _a, _b;
|
|
765
|
-
const previousKey = nn(child._parentKey);
|
|
766
|
-
if (this._implicitlyDeletedItems.has(child)) {
|
|
767
|
-
const existingItemIndex = this._indexOfPosition(newKey);
|
|
768
|
-
return (
|
|
769
|
-
this._implicitlyDeletedItems.delete(child),
|
|
770
|
-
-1 !== existingItemIndex &&
|
|
771
|
-
this._items[existingItemIndex]._setParentLink(
|
|
772
|
-
this,
|
|
773
|
-
makePosition(
|
|
774
|
-
newKey,
|
|
775
|
-
null === (_a = this._items[existingItemIndex + 1]) ||
|
|
776
|
-
void 0 === _a
|
|
777
|
-
? void 0
|
|
778
|
-
: _a._getParentKeyOrThrow()
|
|
779
|
-
)
|
|
780
|
-
),
|
|
781
|
-
child._setParentLink(this, newKey),
|
|
782
|
-
this._insertAndSort(child),
|
|
783
|
-
{ modified: !1 }
|
|
784
|
-
);
|
|
785
|
-
}
|
|
786
|
-
{
|
|
787
|
-
if (newKey === previousKey) return { modified: !1 };
|
|
788
|
-
const previousIndex = this._items.indexOf(child),
|
|
789
|
-
existingItemIndex = this._indexOfPosition(newKey);
|
|
790
|
-
-1 !== existingItemIndex &&
|
|
791
|
-
this._items[existingItemIndex]._setParentLink(
|
|
792
|
-
this,
|
|
793
|
-
makePosition(
|
|
794
|
-
newKey,
|
|
795
|
-
null === (_b = this._items[existingItemIndex + 1]) || void 0 === _b
|
|
796
|
-
? void 0
|
|
797
|
-
: _b._getParentKeyOrThrow()
|
|
798
|
-
)
|
|
799
|
-
),
|
|
800
|
-
child._setParentLink(this, newKey),
|
|
801
|
-
this._sortItems();
|
|
802
|
-
const newIndex = this._items.indexOf(child);
|
|
803
|
-
return previousIndex === newIndex
|
|
804
|
-
? { modified: !1 }
|
|
805
|
-
: {
|
|
806
|
-
modified: makeUpdate(this, [
|
|
807
|
-
moveDelta(previousIndex, newIndex, child),
|
|
808
|
-
]),
|
|
809
|
-
reverse: [],
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
_applySetChildKeyUndoRedo(newKey, child) {
|
|
814
|
-
var _a;
|
|
815
|
-
const previousKey = nn(child._parentKey),
|
|
816
|
-
previousIndex = this._items.indexOf(child),
|
|
817
|
-
existingItemIndex = this._indexOfPosition(newKey);
|
|
818
|
-
-1 !== existingItemIndex &&
|
|
819
|
-
this._items[existingItemIndex]._setParentLink(
|
|
820
|
-
this,
|
|
821
|
-
makePosition(
|
|
822
|
-
newKey,
|
|
823
|
-
null === (_a = this._items[existingItemIndex + 1]) || void 0 === _a
|
|
824
|
-
? void 0
|
|
825
|
-
: _a._getParentKeyOrThrow()
|
|
826
|
-
)
|
|
827
|
-
),
|
|
828
|
-
child._setParentLink(this, newKey),
|
|
829
|
-
this._sortItems();
|
|
830
|
-
const newIndex = this._items.indexOf(child);
|
|
831
|
-
return previousIndex === newIndex
|
|
832
|
-
? { modified: !1 }
|
|
833
|
-
: {
|
|
834
|
-
modified: makeUpdate(this, [
|
|
835
|
-
moveDelta(previousIndex, newIndex, child),
|
|
836
|
-
]),
|
|
837
|
-
reverse: [
|
|
838
|
-
{
|
|
839
|
-
type: OpCode.SET_PARENT_KEY,
|
|
840
|
-
id: nn(child._id),
|
|
841
|
-
parentKey: previousKey,
|
|
842
|
-
},
|
|
843
|
-
],
|
|
844
|
-
};
|
|
845
|
-
}
|
|
846
|
-
_setChildKey(newKey, child, source) {
|
|
847
|
-
return source === OpSource.REMOTE
|
|
848
|
-
? this._applySetChildKeyRemote(newKey, child)
|
|
849
|
-
: source === OpSource.ACK
|
|
850
|
-
? this._applySetChildKeyAck(newKey, child)
|
|
851
|
-
: this._applySetChildKeyUndoRedo(newKey, child);
|
|
852
|
-
}
|
|
853
|
-
_apply(op, isLocal) {
|
|
854
|
-
return super._apply(op, isLocal);
|
|
855
|
-
}
|
|
856
|
-
_toSerializedCrdt() {
|
|
857
|
-
if ("HasParent" !== this.parent.type)
|
|
858
|
-
throw new Error("Cannot serialize LiveList if parent is missing");
|
|
859
|
-
return {
|
|
860
|
-
type: CrdtType.LIST,
|
|
861
|
-
parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
|
|
862
|
-
parentKey: this.parent.key,
|
|
863
|
-
};
|
|
864
|
-
}
|
|
865
|
-
get length() {
|
|
866
|
-
return this._items.length;
|
|
867
|
-
}
|
|
868
|
-
push(element) {
|
|
869
|
-
return this.insert(element, this.length);
|
|
870
|
-
}
|
|
871
|
-
insert(element, index) {
|
|
872
|
-
if (index < 0 || index > this._items.length)
|
|
873
|
-
throw new Error(
|
|
874
|
-
`Cannot insert list item at index "${index}". index should be between 0 and ${this._items.length}`
|
|
875
|
-
);
|
|
876
|
-
const position = makePosition(
|
|
877
|
-
this._items[index - 1]
|
|
878
|
-
? this._items[index - 1]._getParentKeyOrThrow()
|
|
879
|
-
: void 0,
|
|
880
|
-
this._items[index] ? this._items[index]._getParentKeyOrThrow() : void 0
|
|
881
|
-
),
|
|
882
|
-
value = lsonToLiveNode(element);
|
|
883
|
-
if (
|
|
884
|
-
(value._setParentLink(this, position),
|
|
885
|
-
this._insertAndSort(value),
|
|
886
|
-
this._doc && this._id)
|
|
887
|
-
) {
|
|
888
|
-
const id = this._doc.generateId();
|
|
889
|
-
value._attach(id, this._doc),
|
|
890
|
-
this._doc.dispatch(
|
|
891
|
-
value._serialize(this._id, position, this._doc),
|
|
892
|
-
[{ type: OpCode.DELETE_CRDT, id: id }],
|
|
893
|
-
new Map([[this._id, makeUpdate(this, [insertDelta(index, value)])]])
|
|
894
|
-
);
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
move(index, targetIndex) {
|
|
898
|
-
if (targetIndex < 0) throw new Error("targetIndex cannot be less than 0");
|
|
899
|
-
if (targetIndex >= this._items.length)
|
|
900
|
-
throw new Error(
|
|
901
|
-
"targetIndex cannot be greater or equal than the list length"
|
|
902
|
-
);
|
|
903
|
-
if (index < 0) throw new Error("index cannot be less than 0");
|
|
904
|
-
if (index >= this._items.length)
|
|
905
|
-
throw new Error("index cannot be greater or equal than the list length");
|
|
906
|
-
let beforePosition = null,
|
|
907
|
-
afterPosition = null;
|
|
908
|
-
index < targetIndex
|
|
909
|
-
? ((afterPosition =
|
|
910
|
-
targetIndex === this._items.length - 1
|
|
911
|
-
? void 0
|
|
912
|
-
: this._items[targetIndex + 1]._getParentKeyOrThrow()),
|
|
913
|
-
(beforePosition = this._items[targetIndex]._getParentKeyOrThrow()))
|
|
914
|
-
: ((afterPosition = this._items[targetIndex]._getParentKeyOrThrow()),
|
|
915
|
-
(beforePosition =
|
|
916
|
-
0 === targetIndex
|
|
917
|
-
? void 0
|
|
918
|
-
: this._items[targetIndex - 1]._getParentKeyOrThrow()));
|
|
919
|
-
const position = makePosition(beforePosition, afterPosition),
|
|
920
|
-
item = this._items[index],
|
|
921
|
-
previousPosition = item._getParentKeyOrThrow();
|
|
922
|
-
if (
|
|
923
|
-
(item._setParentLink(this, position),
|
|
924
|
-
this._sortItems(),
|
|
925
|
-
this._doc && this._id)
|
|
926
|
-
) {
|
|
927
|
-
const storageUpdates = new Map([
|
|
928
|
-
[this._id, makeUpdate(this, [moveDelta(index, targetIndex, item)])],
|
|
929
|
-
]);
|
|
930
|
-
this._doc.dispatch(
|
|
931
|
-
[
|
|
932
|
-
{
|
|
933
|
-
type: OpCode.SET_PARENT_KEY,
|
|
934
|
-
id: nn(item._id),
|
|
935
|
-
opId: this._doc.generateOpId(),
|
|
936
|
-
parentKey: position,
|
|
937
|
-
},
|
|
938
|
-
],
|
|
939
|
-
[
|
|
940
|
-
{
|
|
941
|
-
type: OpCode.SET_PARENT_KEY,
|
|
942
|
-
id: nn(item._id),
|
|
943
|
-
parentKey: previousPosition,
|
|
944
|
-
},
|
|
945
|
-
],
|
|
946
|
-
storageUpdates
|
|
947
|
-
);
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
delete(index) {
|
|
951
|
-
if (index < 0 || index >= this._items.length)
|
|
952
|
-
throw new Error(
|
|
953
|
-
`Cannot delete list item at index "${index}". index should be between 0 and ${
|
|
954
|
-
this._items.length - 1
|
|
955
|
-
}`
|
|
956
|
-
);
|
|
957
|
-
const item = this._items[index];
|
|
958
|
-
if ((item._detach(), this._items.splice(index, 1), this._doc)) {
|
|
959
|
-
const childRecordId = item._id;
|
|
960
|
-
if (childRecordId) {
|
|
961
|
-
const storageUpdates = new Map();
|
|
962
|
-
storageUpdates.set(
|
|
963
|
-
nn(this._id),
|
|
964
|
-
makeUpdate(this, [deleteDelta(index)])
|
|
965
|
-
),
|
|
966
|
-
this._doc.dispatch(
|
|
967
|
-
[
|
|
968
|
-
{
|
|
969
|
-
id: childRecordId,
|
|
970
|
-
opId: this._doc.generateOpId(),
|
|
971
|
-
type: OpCode.DELETE_CRDT,
|
|
972
|
-
},
|
|
973
|
-
],
|
|
974
|
-
item._serialize(nn(this._id), item._getParentKeyOrThrow()),
|
|
975
|
-
storageUpdates
|
|
976
|
-
);
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
clear() {
|
|
981
|
-
if (this._doc) {
|
|
982
|
-
const ops = [],
|
|
983
|
-
reverseOps = [],
|
|
984
|
-
updateDelta = [];
|
|
985
|
-
for (const item of this._items) {
|
|
986
|
-
item._detach();
|
|
987
|
-
const childId = item._id;
|
|
988
|
-
childId &&
|
|
989
|
-
(ops.push({
|
|
990
|
-
type: OpCode.DELETE_CRDT,
|
|
991
|
-
id: childId,
|
|
992
|
-
opId: this._doc.generateOpId(),
|
|
993
|
-
}),
|
|
994
|
-
reverseOps.push(
|
|
995
|
-
...item._serialize(nn(this._id), item._getParentKeyOrThrow())
|
|
996
|
-
),
|
|
997
|
-
updateDelta.push(deleteDelta(0)));
|
|
998
|
-
}
|
|
999
|
-
this._items = [];
|
|
1000
|
-
const storageUpdates = new Map();
|
|
1001
|
-
storageUpdates.set(nn(this._id), makeUpdate(this, updateDelta)),
|
|
1002
|
-
this._doc.dispatch(ops, reverseOps, storageUpdates);
|
|
1003
|
-
} else {
|
|
1004
|
-
for (const item of this._items) item._detach();
|
|
1005
|
-
this._items = [];
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
set(index, item) {
|
|
1009
|
-
if (index < 0 || index >= this._items.length)
|
|
1010
|
-
throw new Error(
|
|
1011
|
-
`Cannot set list item at index "${index}". index should be between 0 and ${
|
|
1012
|
-
this._items.length - 1
|
|
1013
|
-
}`
|
|
1014
|
-
);
|
|
1015
|
-
const existingItem = this._items[index],
|
|
1016
|
-
position = existingItem._getParentKeyOrThrow(),
|
|
1017
|
-
existingId = existingItem._id;
|
|
1018
|
-
existingItem._detach();
|
|
1019
|
-
const value = lsonToLiveNode(item);
|
|
1020
|
-
if (
|
|
1021
|
-
(value._setParentLink(this, position),
|
|
1022
|
-
(this._items[index] = value),
|
|
1023
|
-
this._doc && this._id)
|
|
1024
|
-
) {
|
|
1025
|
-
const id = this._doc.generateId();
|
|
1026
|
-
value._attach(id, this._doc);
|
|
1027
|
-
const storageUpdates = new Map();
|
|
1028
|
-
storageUpdates.set(this._id, makeUpdate(this, [setDelta(index, value)]));
|
|
1029
|
-
const ops = value._serialize(this._id, position, this._doc);
|
|
1030
|
-
addIntentAndDeletedIdToOperation(ops, existingId),
|
|
1031
|
-
this._unacknowledgedSets.set(position, nn(ops[0].opId));
|
|
1032
|
-
const reverseOps = existingItem._serialize(this._id, position, void 0);
|
|
1033
|
-
addIntentAndDeletedIdToOperation(reverseOps, id),
|
|
1034
|
-
this._doc.dispatch(ops, reverseOps, storageUpdates);
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
toArray() {
|
|
1038
|
-
return this._items.map((entry) => liveNodeToLson(entry));
|
|
1039
|
-
}
|
|
1040
|
-
every(predicate) {
|
|
1041
|
-
return this.toArray().every(predicate);
|
|
1042
|
-
}
|
|
1043
|
-
filter(predicate) {
|
|
1044
|
-
return this.toArray().filter(predicate);
|
|
1045
|
-
}
|
|
1046
|
-
find(predicate) {
|
|
1047
|
-
return this.toArray().find(predicate);
|
|
1048
|
-
}
|
|
1049
|
-
findIndex(predicate) {
|
|
1050
|
-
return this.toArray().findIndex(predicate);
|
|
1051
|
-
}
|
|
1052
|
-
forEach(callbackfn) {
|
|
1053
|
-
return this.toArray().forEach(callbackfn);
|
|
1054
|
-
}
|
|
1055
|
-
get(index) {
|
|
1056
|
-
if (!(index < 0 || index >= this._items.length))
|
|
1057
|
-
return liveNodeToLson(this._items[index]);
|
|
1058
|
-
}
|
|
1059
|
-
indexOf(searchElement, fromIndex) {
|
|
1060
|
-
return this.toArray().indexOf(searchElement, fromIndex);
|
|
1061
|
-
}
|
|
1062
|
-
lastIndexOf(searchElement, fromIndex) {
|
|
1063
|
-
return this.toArray().lastIndexOf(searchElement, fromIndex);
|
|
1064
|
-
}
|
|
1065
|
-
map(callback) {
|
|
1066
|
-
return this._items.map((entry, i) => callback(liveNodeToLson(entry), i));
|
|
1067
|
-
}
|
|
1068
|
-
some(predicate) {
|
|
1069
|
-
return this.toArray().some(predicate);
|
|
1070
|
-
}
|
|
1071
|
-
[Symbol.iterator]() {
|
|
1072
|
-
return new LiveListIterator(this._items);
|
|
1073
|
-
}
|
|
1074
|
-
_createAttachItemAndSort(op, key) {
|
|
1075
|
-
const newItem = creationOpToLiveNode(op);
|
|
1076
|
-
newItem._attach(op.id, nn(this._doc)),
|
|
1077
|
-
newItem._setParentLink(this, key),
|
|
1078
|
-
this._insertAndSort(newItem);
|
|
1079
|
-
return { newItem: newItem, newIndex: this._indexOfPosition(key) };
|
|
1080
|
-
}
|
|
1081
|
-
_shiftItemPosition(index, key) {
|
|
1082
|
-
var _a;
|
|
1083
|
-
const shiftedPosition = makePosition(
|
|
1084
|
-
key,
|
|
1085
|
-
this._items.length > index + 1
|
|
1086
|
-
? null === (_a = this._items[index + 1]) || void 0 === _a
|
|
1087
|
-
? void 0
|
|
1088
|
-
: _a._getParentKeyOrThrow()
|
|
1089
|
-
: void 0
|
|
1090
|
-
);
|
|
1091
|
-
this._items[index]._setParentLink(this, shiftedPosition);
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
class LiveListIterator {
|
|
1095
|
-
constructor(items) {
|
|
1096
|
-
this._innerIterator = items[Symbol.iterator]();
|
|
1097
|
-
}
|
|
1098
|
-
[Symbol.iterator]() {
|
|
1099
|
-
return this;
|
|
1100
|
-
}
|
|
1101
|
-
next() {
|
|
1102
|
-
const result = this._innerIterator.next();
|
|
1103
|
-
if (result.done) return { done: !0, value: void 0 };
|
|
1104
|
-
return { value: liveNodeToLson(result.value) };
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
function makeUpdate(liveList, deltaUpdates) {
|
|
1108
|
-
return { node: liveList, type: "LiveList", updates: deltaUpdates };
|
|
1109
|
-
}
|
|
1110
|
-
function setDelta(index, item) {
|
|
1111
|
-
return {
|
|
1112
|
-
index: index,
|
|
1113
|
-
type: "set",
|
|
1114
|
-
item: item instanceof LiveRegister ? item.data : item,
|
|
1115
|
-
};
|
|
1116
|
-
}
|
|
1117
|
-
function deleteDelta(index) {
|
|
1118
|
-
return { index: index, type: "delete" };
|
|
1119
|
-
}
|
|
1120
|
-
function insertDelta(index, item) {
|
|
1121
|
-
return {
|
|
1122
|
-
index: index,
|
|
1123
|
-
type: "insert",
|
|
1124
|
-
item: item instanceof LiveRegister ? item.data : item,
|
|
1125
|
-
};
|
|
1126
|
-
}
|
|
1127
|
-
function moveDelta(previousIndex, index, item) {
|
|
1128
|
-
return {
|
|
1129
|
-
index: index,
|
|
1130
|
-
type: "move",
|
|
1131
|
-
previousIndex: previousIndex,
|
|
1132
|
-
item: item instanceof LiveRegister ? item.data : item,
|
|
1133
|
-
};
|
|
1134
|
-
}
|
|
1135
|
-
function addIntentAndDeletedIdToOperation(ops, deletedId) {
|
|
1136
|
-
if (0 === ops.length)
|
|
1137
|
-
throw new Error(
|
|
1138
|
-
"Internal error. Serialized LiveStructure should have at least 1 operation"
|
|
1139
|
-
);
|
|
1140
|
-
const firstOp = ops[0];
|
|
1141
|
-
(firstOp.intent = "set"), (firstOp.deletedId = deletedId);
|
|
1142
|
-
}
|
|
1143
|
-
class LiveMap extends AbstractCrdt {
|
|
1144
|
-
constructor(entries) {
|
|
1145
|
-
if (
|
|
1146
|
-
(super(),
|
|
1147
|
-
errorIf(
|
|
1148
|
-
null === entries,
|
|
1149
|
-
"Support for calling `new LiveMap(null)` will be removed in @liveblocks/client 0.18. Please call as `new LiveMap()`, or `new LiveMap([])`."
|
|
1150
|
-
),
|
|
1151
|
-
(this.unacknowledgedSet = new Map()),
|
|
1152
|
-
entries)
|
|
1153
|
-
) {
|
|
1154
|
-
const mappedEntries = [];
|
|
1155
|
-
for (const entry of entries) {
|
|
1156
|
-
const value = lsonToLiveNode(entry[1]);
|
|
1157
|
-
value._setParentLink(this, entry[0]),
|
|
1158
|
-
mappedEntries.push([entry[0], value]);
|
|
1159
|
-
}
|
|
1160
|
-
this._map = new Map(mappedEntries);
|
|
1161
|
-
} else this._map = new Map();
|
|
1162
|
-
}
|
|
1163
|
-
_serialize(parentId, parentKey, doc) {
|
|
1164
|
-
if (null == this._id)
|
|
1165
|
-
throw new Error("Cannot serialize item is not attached");
|
|
1166
|
-
const ops = [],
|
|
1167
|
-
op = {
|
|
1168
|
-
id: this._id,
|
|
1169
|
-
opId: null == doc ? void 0 : doc.generateOpId(),
|
|
1170
|
-
type: OpCode.CREATE_MAP,
|
|
1171
|
-
parentId: parentId,
|
|
1172
|
-
parentKey: parentKey,
|
|
1173
|
-
};
|
|
1174
|
-
ops.push(op);
|
|
1175
|
-
for (const [key, value] of this._map)
|
|
1176
|
-
ops.push(...value._serialize(this._id, key, doc));
|
|
1177
|
-
return ops;
|
|
1178
|
-
}
|
|
1179
|
-
static _deserialize([id, _item], parentToChildren, doc) {
|
|
1180
|
-
const map = new LiveMap();
|
|
1181
|
-
map._attach(id, doc);
|
|
1182
|
-
const children = parentToChildren.get(id);
|
|
1183
|
-
if (null == children) return map;
|
|
1184
|
-
for (const [id, crdt] of children) {
|
|
1185
|
-
const child = deserialize([id, crdt], parentToChildren, doc);
|
|
1186
|
-
child._setParentLink(map, crdt.parentKey),
|
|
1187
|
-
map._map.set(crdt.parentKey, child);
|
|
1188
|
-
}
|
|
1189
|
-
return map;
|
|
1190
|
-
}
|
|
1191
|
-
_attach(id, doc) {
|
|
1192
|
-
super._attach(id, doc);
|
|
1193
|
-
for (const [_key, value] of this._map)
|
|
1194
|
-
isLiveNode(value) && value._attach(doc.generateId(), doc);
|
|
1195
|
-
}
|
|
1196
|
-
_attachChild(op, source) {
|
|
1197
|
-
if (null == this._doc)
|
|
1198
|
-
throw new Error("Can't attach child if doc is not present");
|
|
1199
|
-
const { id: id, parentKey: parentKey, opId: opId } = op,
|
|
1200
|
-
key = parentKey,
|
|
1201
|
-
child = creationOpToLiveNode(op);
|
|
1202
|
-
if (void 0 !== this._doc.getItem(id)) return { modified: !1 };
|
|
1203
|
-
if (source === OpSource.ACK) {
|
|
1204
|
-
const lastUpdateOpId = this.unacknowledgedSet.get(key);
|
|
1205
|
-
if (lastUpdateOpId === opId)
|
|
1206
|
-
return this.unacknowledgedSet.delete(key), { modified: !1 };
|
|
1207
|
-
if (null != lastUpdateOpId) return { modified: !1 };
|
|
1208
|
-
} else source === OpSource.REMOTE && this.unacknowledgedSet.delete(key);
|
|
1209
|
-
const previousValue = this._map.get(key);
|
|
1210
|
-
let reverse;
|
|
1211
|
-
if (previousValue) {
|
|
1212
|
-
const thisId = nn(this._id);
|
|
1213
|
-
(reverse = previousValue._serialize(thisId, key)),
|
|
1214
|
-
previousValue._detach();
|
|
1215
|
-
} else reverse = [{ type: OpCode.DELETE_CRDT, id: id }];
|
|
1216
|
-
return (
|
|
1217
|
-
child._setParentLink(this, key),
|
|
1218
|
-
child._attach(id, this._doc),
|
|
1219
|
-
this._map.set(key, child),
|
|
1220
|
-
{
|
|
1221
|
-
modified: {
|
|
1222
|
-
node: this,
|
|
1223
|
-
type: "LiveMap",
|
|
1224
|
-
updates: { [key]: { type: "update" } },
|
|
1225
|
-
},
|
|
1226
|
-
reverse: reverse,
|
|
1227
|
-
}
|
|
1228
|
-
);
|
|
1229
|
-
}
|
|
1230
|
-
_detach() {
|
|
1231
|
-
super._detach();
|
|
1232
|
-
for (const item of this._map.values()) item._detach();
|
|
1233
|
-
}
|
|
1234
|
-
_detachChild(child) {
|
|
1235
|
-
const id = nn(this._id),
|
|
1236
|
-
parentKey = nn(child._parentKey),
|
|
1237
|
-
reverse = child._serialize(id, parentKey, this._doc);
|
|
1238
|
-
for (const [key, value] of this._map)
|
|
1239
|
-
value === child && this._map.delete(key);
|
|
1240
|
-
child._detach();
|
|
1241
|
-
return {
|
|
1242
|
-
modified: {
|
|
1243
|
-
node: this,
|
|
1244
|
-
type: "LiveMap",
|
|
1245
|
-
updates: { [parentKey]: { type: "delete" } },
|
|
1246
|
-
},
|
|
1247
|
-
reverse: reverse,
|
|
1248
|
-
};
|
|
1249
|
-
}
|
|
1250
|
-
_toSerializedCrdt() {
|
|
1251
|
-
if ("HasParent" !== this.parent.type)
|
|
1252
|
-
throw new Error("Cannot serialize LiveMap if parent is missing");
|
|
1253
|
-
return {
|
|
1254
|
-
type: CrdtType.MAP,
|
|
1255
|
-
parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
|
|
1256
|
-
parentKey: this.parent.key,
|
|
1257
|
-
};
|
|
1258
|
-
}
|
|
1259
|
-
get(key) {
|
|
1260
|
-
const value = this._map.get(key);
|
|
1261
|
-
if (null != value) return liveNodeToLson(value);
|
|
1262
|
-
}
|
|
1263
|
-
set(key, value) {
|
|
1264
|
-
const oldValue = this._map.get(key);
|
|
1265
|
-
oldValue && oldValue._detach();
|
|
1266
|
-
const item = lsonToLiveNode(value);
|
|
1267
|
-
if (
|
|
1268
|
-
(item._setParentLink(this, key),
|
|
1269
|
-
this._map.set(key, item),
|
|
1270
|
-
this._doc && this._id)
|
|
1271
|
-
) {
|
|
1272
|
-
const id = this._doc.generateId();
|
|
1273
|
-
item._attach(id, this._doc);
|
|
1274
|
-
const storageUpdates = new Map();
|
|
1275
|
-
storageUpdates.set(this._id, {
|
|
1276
|
-
node: this,
|
|
1277
|
-
type: "LiveMap",
|
|
1278
|
-
updates: { [key]: { type: "update" } },
|
|
1279
|
-
});
|
|
1280
|
-
const ops = item._serialize(this._id, key, this._doc);
|
|
1281
|
-
this.unacknowledgedSet.set(key, nn(ops[0].opId)),
|
|
1282
|
-
this._doc.dispatch(
|
|
1283
|
-
item._serialize(this._id, key, this._doc),
|
|
1284
|
-
oldValue
|
|
1285
|
-
? oldValue._serialize(this._id, key)
|
|
1286
|
-
: [{ type: OpCode.DELETE_CRDT, id: id }],
|
|
1287
|
-
storageUpdates
|
|
1288
|
-
);
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
get size() {
|
|
1292
|
-
return this._map.size;
|
|
1293
|
-
}
|
|
1294
|
-
has(key) {
|
|
1295
|
-
return this._map.has(key);
|
|
1296
|
-
}
|
|
1297
|
-
delete(key) {
|
|
1298
|
-
const item = this._map.get(key);
|
|
1299
|
-
if (null == item) return !1;
|
|
1300
|
-
if ((item._detach(), this._map.delete(key), this._doc && item._id)) {
|
|
1301
|
-
const thisId = nn(this._id),
|
|
1302
|
-
storageUpdates = new Map();
|
|
1303
|
-
storageUpdates.set(thisId, {
|
|
1304
|
-
node: this,
|
|
1305
|
-
type: "LiveMap",
|
|
1306
|
-
updates: { [key]: { type: "delete" } },
|
|
1307
|
-
}),
|
|
1308
|
-
this._doc.dispatch(
|
|
1309
|
-
[
|
|
1310
|
-
{
|
|
1311
|
-
type: OpCode.DELETE_CRDT,
|
|
1312
|
-
id: item._id,
|
|
1313
|
-
opId: this._doc.generateOpId(),
|
|
1314
|
-
},
|
|
1315
|
-
],
|
|
1316
|
-
item._serialize(thisId, key),
|
|
1317
|
-
storageUpdates
|
|
1318
|
-
);
|
|
1319
|
-
}
|
|
1320
|
-
return !0;
|
|
1321
|
-
}
|
|
1322
|
-
entries() {
|
|
1323
|
-
const innerIterator = this._map.entries();
|
|
1324
|
-
return {
|
|
1325
|
-
[Symbol.iterator]() {
|
|
1326
|
-
return this;
|
|
1327
|
-
},
|
|
1328
|
-
next() {
|
|
1329
|
-
const iteratorValue = innerIterator.next();
|
|
1330
|
-
if (iteratorValue.done) return { done: !0, value: void 0 };
|
|
1331
|
-
return {
|
|
1332
|
-
value: [
|
|
1333
|
-
iteratorValue.value[0],
|
|
1334
|
-
liveNodeToLson(iteratorValue.value[1]),
|
|
1335
|
-
],
|
|
1336
|
-
};
|
|
1337
|
-
},
|
|
1338
|
-
};
|
|
1339
|
-
}
|
|
1340
|
-
[Symbol.iterator]() {
|
|
1341
|
-
return this.entries();
|
|
1342
|
-
}
|
|
1343
|
-
keys() {
|
|
1344
|
-
return this._map.keys();
|
|
1345
|
-
}
|
|
1346
|
-
values() {
|
|
1347
|
-
const innerIterator = this._map.values();
|
|
1348
|
-
return {
|
|
1349
|
-
[Symbol.iterator]() {
|
|
1350
|
-
return this;
|
|
1351
|
-
},
|
|
1352
|
-
next() {
|
|
1353
|
-
const iteratorValue = innerIterator.next();
|
|
1354
|
-
if (iteratorValue.done) return { done: !0, value: void 0 };
|
|
1355
|
-
return { value: liveNodeToLson(iteratorValue.value) };
|
|
1356
|
-
},
|
|
1357
|
-
};
|
|
1358
|
-
}
|
|
1359
|
-
forEach(callback) {
|
|
1360
|
-
for (const entry of this) callback(entry[1], entry[0], this);
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
class LiveObject extends AbstractCrdt {
|
|
1364
|
-
constructor(obj = {}) {
|
|
1365
|
-
super(), (this._propToLastUpdate = new Map());
|
|
1366
|
-
for (const key in obj) {
|
|
1367
|
-
const value = obj[key];
|
|
1368
|
-
void 0 !== value && isLiveNode(value) && value._setParentLink(this, key);
|
|
1369
|
-
}
|
|
1370
|
-
this._map = new Map(Object.entries(obj));
|
|
1371
|
-
}
|
|
1372
|
-
_serialize(parentId, parentKey, doc) {
|
|
1373
|
-
if (null == this._id)
|
|
1374
|
-
throw new Error("Cannot serialize item is not attached");
|
|
1375
|
-
const opId = null == doc ? void 0 : doc.generateOpId(),
|
|
1376
|
-
ops = [],
|
|
1377
|
-
op =
|
|
1378
|
-
void 0 !== parentId && void 0 !== parentKey
|
|
1379
|
-
? {
|
|
1380
|
-
type: OpCode.CREATE_OBJECT,
|
|
1381
|
-
id: this._id,
|
|
1382
|
-
opId: opId,
|
|
1383
|
-
parentId: parentId,
|
|
1384
|
-
parentKey: parentKey,
|
|
1385
|
-
data: {},
|
|
1386
|
-
}
|
|
1387
|
-
: { type: OpCode.CREATE_OBJECT, id: this._id, opId: opId, data: {} };
|
|
1388
|
-
ops.push(op);
|
|
1389
|
-
for (const [key, value] of this._map)
|
|
1390
|
-
isLiveNode(value)
|
|
1391
|
-
? ops.push(...value._serialize(this._id, key, doc))
|
|
1392
|
-
: (op.data[key] = value);
|
|
1393
|
-
return ops;
|
|
1394
|
-
}
|
|
1395
|
-
static _deserialize([id, item], parentToChildren, doc) {
|
|
1396
|
-
const liveObj = new LiveObject(item.data);
|
|
1397
|
-
return (
|
|
1398
|
-
liveObj._attach(id, doc),
|
|
1399
|
-
this._deserializeChildren(liveObj, parentToChildren, doc)
|
|
1400
|
-
);
|
|
1401
|
-
}
|
|
1402
|
-
static _deserializeChildren(liveObj, parentToChildren, doc) {
|
|
1403
|
-
const children = parentToChildren.get(nn(liveObj._id));
|
|
1404
|
-
if (null == children) return liveObj;
|
|
1405
|
-
for (const [id, crdt] of children) {
|
|
1406
|
-
const child = deserializeToLson([id, crdt], parentToChildren, doc);
|
|
1407
|
-
isLiveStructure(child) && child._setParentLink(liveObj, crdt.parentKey),
|
|
1408
|
-
liveObj._map.set(crdt.parentKey, child);
|
|
1409
|
-
}
|
|
1410
|
-
return liveObj;
|
|
1411
|
-
}
|
|
1412
|
-
_attach(id, doc) {
|
|
1413
|
-
super._attach(id, doc);
|
|
1414
|
-
for (const [_key, value] of this._map)
|
|
1415
|
-
isLiveNode(value) && value._attach(doc.generateId(), doc);
|
|
1416
|
-
}
|
|
1417
|
-
_attachChild(op, source) {
|
|
1418
|
-
if (null == this._doc)
|
|
1419
|
-
throw new Error("Can't attach child if doc is not present");
|
|
1420
|
-
const { id: id, opId: opId, parentKey: key } = op,
|
|
1421
|
-
child = creationOpToLson(op);
|
|
1422
|
-
if (void 0 !== this._doc.getItem(id))
|
|
1423
|
-
return (
|
|
1424
|
-
this._propToLastUpdate.get(key) === opId &&
|
|
1425
|
-
this._propToLastUpdate.delete(key),
|
|
1426
|
-
{ modified: !1 }
|
|
1427
|
-
);
|
|
1428
|
-
if (source === OpSource.UNDOREDO_RECONNECT)
|
|
1429
|
-
this._propToLastUpdate.set(key, nn(opId));
|
|
1430
|
-
else if (void 0 !== this._propToLastUpdate.get(key))
|
|
1431
|
-
return this._propToLastUpdate.get(key) === opId
|
|
1432
|
-
? (this._propToLastUpdate.delete(key), { modified: !1 })
|
|
1433
|
-
: { modified: !1 };
|
|
1434
|
-
const thisId = nn(this._id),
|
|
1435
|
-
previousValue = this._map.get(key);
|
|
1436
|
-
let reverse;
|
|
1437
|
-
return (
|
|
1438
|
-
isLiveNode(previousValue)
|
|
1439
|
-
? ((reverse = previousValue._serialize(thisId, key)),
|
|
1440
|
-
previousValue._detach())
|
|
1441
|
-
: (reverse =
|
|
1442
|
-
void 0 === previousValue
|
|
1443
|
-
? [{ type: OpCode.DELETE_OBJECT_KEY, id: thisId, key: key }]
|
|
1444
|
-
: [
|
|
1445
|
-
{
|
|
1446
|
-
type: OpCode.UPDATE_OBJECT,
|
|
1447
|
-
id: thisId,
|
|
1448
|
-
data: { [key]: previousValue },
|
|
1449
|
-
},
|
|
1450
|
-
]),
|
|
1451
|
-
this._map.set(key, child),
|
|
1452
|
-
isLiveStructure(child) &&
|
|
1453
|
-
(child._setParentLink(this, key), child._attach(id, this._doc)),
|
|
1454
|
-
{
|
|
1455
|
-
reverse: reverse,
|
|
1456
|
-
modified: {
|
|
1457
|
-
node: this,
|
|
1458
|
-
type: "LiveObject",
|
|
1459
|
-
updates: { [key]: { type: "update" } },
|
|
1460
|
-
},
|
|
1461
|
-
}
|
|
1462
|
-
);
|
|
1463
|
-
}
|
|
1464
|
-
_detachChild(child) {
|
|
1465
|
-
if (child) {
|
|
1466
|
-
const id = nn(this._id),
|
|
1467
|
-
parentKey = nn(child._parentKey),
|
|
1468
|
-
reverse = child._serialize(id, parentKey, this._doc);
|
|
1469
|
-
for (const [key, value] of this._map)
|
|
1470
|
-
value === child && this._map.delete(key);
|
|
1471
|
-
child._detach();
|
|
1472
|
-
return {
|
|
1473
|
-
modified: {
|
|
1474
|
-
node: this,
|
|
1475
|
-
type: "LiveObject",
|
|
1476
|
-
updates: { [parentKey]: { type: "delete" } },
|
|
1477
|
-
},
|
|
1478
|
-
reverse: reverse,
|
|
1479
|
-
};
|
|
1480
|
-
}
|
|
1481
|
-
return { modified: !1 };
|
|
1482
|
-
}
|
|
1483
|
-
_detach() {
|
|
1484
|
-
super._detach();
|
|
1485
|
-
for (const value of this._map.values())
|
|
1486
|
-
isLiveNode(value) && value._detach();
|
|
1487
|
-
}
|
|
1488
|
-
_apply(op, isLocal) {
|
|
1489
|
-
return op.type === OpCode.UPDATE_OBJECT
|
|
1490
|
-
? this._applyUpdate(op, isLocal)
|
|
1491
|
-
: op.type === OpCode.DELETE_OBJECT_KEY
|
|
1492
|
-
? this._applyDeleteObjectKey(op)
|
|
1493
|
-
: super._apply(op, isLocal);
|
|
1494
|
-
}
|
|
1495
|
-
_toSerializedCrdt() {
|
|
1496
|
-
const data = {};
|
|
1497
|
-
for (const [key, value] of this._map)
|
|
1498
|
-
isLiveNode(value) || (data[key] = value);
|
|
1499
|
-
return "HasParent" === this.parent.type && this.parent.node._id
|
|
1500
|
-
? {
|
|
1501
|
-
type: CrdtType.OBJECT,
|
|
1502
|
-
parentId: this.parent.node._id,
|
|
1503
|
-
parentKey: this.parent.key,
|
|
1504
|
-
data: data,
|
|
1505
|
-
}
|
|
1506
|
-
: { type: CrdtType.OBJECT, data: data };
|
|
1507
|
-
}
|
|
1508
|
-
_applyUpdate(op, isLocal) {
|
|
1509
|
-
let isModified = !1;
|
|
1510
|
-
const id = nn(this._id),
|
|
1511
|
-
reverse = [],
|
|
1512
|
-
reverseUpdate = { type: OpCode.UPDATE_OBJECT, id: id, data: {} };
|
|
1513
|
-
reverse.push(reverseUpdate);
|
|
1514
|
-
for (const key in op.data) {
|
|
1515
|
-
const oldValue = this._map.get(key);
|
|
1516
|
-
isLiveNode(oldValue)
|
|
1517
|
-
? (reverse.push(...oldValue._serialize(id, key)), oldValue._detach())
|
|
1518
|
-
: void 0 !== oldValue
|
|
1519
|
-
? (reverseUpdate.data[key] = oldValue)
|
|
1520
|
-
: void 0 === oldValue &&
|
|
1521
|
-
reverse.push({ type: OpCode.DELETE_OBJECT_KEY, id: id, key: key });
|
|
1522
|
-
}
|
|
1523
|
-
const updateDelta = {};
|
|
1524
|
-
for (const key in op.data) {
|
|
1525
|
-
const value = op.data[key];
|
|
1526
|
-
if (void 0 === value) continue;
|
|
1527
|
-
if (isLocal) this._propToLastUpdate.set(key, nn(op.opId));
|
|
1528
|
-
else {
|
|
1529
|
-
if (null != this._propToLastUpdate.get(key)) {
|
|
1530
|
-
if (this._propToLastUpdate.get(key) === op.opId) {
|
|
1531
|
-
this._propToLastUpdate.delete(key);
|
|
1532
|
-
continue;
|
|
1533
|
-
}
|
|
1534
|
-
continue;
|
|
1535
|
-
}
|
|
1536
|
-
isModified = !0;
|
|
1537
|
-
}
|
|
1538
|
-
const oldValue = this._map.get(key);
|
|
1539
|
-
isLiveNode(oldValue) && oldValue._detach(),
|
|
1540
|
-
(isModified = !0),
|
|
1541
|
-
(updateDelta[key] = { type: "update" }),
|
|
1542
|
-
this._map.set(key, value);
|
|
1543
|
-
}
|
|
1544
|
-
return (
|
|
1545
|
-
0 !== Object.keys(reverseUpdate.data).length &&
|
|
1546
|
-
reverse.unshift(reverseUpdate),
|
|
1547
|
-
isModified
|
|
1548
|
-
? {
|
|
1549
|
-
modified: { node: this, type: "LiveObject", updates: updateDelta },
|
|
1550
|
-
reverse: reverse,
|
|
1551
|
-
}
|
|
1552
|
-
: { modified: !1 }
|
|
1553
|
-
);
|
|
1554
|
-
}
|
|
1555
|
-
_applyDeleteObjectKey(op) {
|
|
1556
|
-
const key = op.key;
|
|
1557
|
-
if (!1 === this._map.has(key)) return { modified: !1 };
|
|
1558
|
-
if (void 0 !== this._propToLastUpdate.get(key)) return { modified: !1 };
|
|
1559
|
-
const oldValue = this._map.get(key),
|
|
1560
|
-
id = nn(this._id);
|
|
1561
|
-
let reverse = [];
|
|
1562
|
-
return (
|
|
1563
|
-
isLiveNode(oldValue)
|
|
1564
|
-
? ((reverse = oldValue._serialize(id, op.key)), oldValue._detach())
|
|
1565
|
-
: void 0 !== oldValue &&
|
|
1566
|
-
(reverse = [
|
|
1567
|
-
{ type: OpCode.UPDATE_OBJECT, id: id, data: { [key]: oldValue } },
|
|
1568
|
-
]),
|
|
1569
|
-
this._map.delete(key),
|
|
1570
|
-
{
|
|
1571
|
-
modified: {
|
|
1572
|
-
node: this,
|
|
1573
|
-
type: "LiveObject",
|
|
1574
|
-
updates: { [op.key]: { type: "delete" } },
|
|
1575
|
-
},
|
|
1576
|
-
reverse: reverse,
|
|
1577
|
-
}
|
|
1578
|
-
);
|
|
1579
|
-
}
|
|
1580
|
-
toObject() {
|
|
1581
|
-
return (function (iterable) {
|
|
1582
|
-
const obj = {};
|
|
1583
|
-
for (const [key, val] of iterable) obj[key] = val;
|
|
1584
|
-
return obj;
|
|
1585
|
-
})(this._map);
|
|
1586
|
-
}
|
|
1587
|
-
set(key, value) {
|
|
1588
|
-
this.update({ [key]: value });
|
|
1589
|
-
}
|
|
1590
|
-
get(key) {
|
|
1591
|
-
return this._map.get(key);
|
|
1592
|
-
}
|
|
1593
|
-
delete(key) {
|
|
1594
|
-
const keyAsString = key,
|
|
1595
|
-
oldValue = this._map.get(keyAsString);
|
|
1596
|
-
if (void 0 === oldValue) return;
|
|
1597
|
-
if (null == this._doc || null == this._id)
|
|
1598
|
-
return (
|
|
1599
|
-
isLiveNode(oldValue) && oldValue._detach(),
|
|
1600
|
-
void this._map.delete(keyAsString)
|
|
1601
|
-
);
|
|
1602
|
-
let reverse;
|
|
1603
|
-
isLiveNode(oldValue)
|
|
1604
|
-
? (oldValue._detach(),
|
|
1605
|
-
(reverse = oldValue._serialize(this._id, keyAsString)))
|
|
1606
|
-
: (reverse = [
|
|
1607
|
-
{
|
|
1608
|
-
type: OpCode.UPDATE_OBJECT,
|
|
1609
|
-
data: { [keyAsString]: oldValue },
|
|
1610
|
-
id: this._id,
|
|
1611
|
-
},
|
|
1612
|
-
]),
|
|
1613
|
-
this._map.delete(keyAsString);
|
|
1614
|
-
const storageUpdates = new Map();
|
|
1615
|
-
storageUpdates.set(this._id, {
|
|
1616
|
-
node: this,
|
|
1617
|
-
type: "LiveObject",
|
|
1618
|
-
updates: { [key]: { type: "delete" } },
|
|
1619
|
-
}),
|
|
1620
|
-
this._doc.dispatch(
|
|
1621
|
-
[
|
|
1622
|
-
{
|
|
1623
|
-
type: OpCode.DELETE_OBJECT_KEY,
|
|
1624
|
-
key: keyAsString,
|
|
1625
|
-
id: this._id,
|
|
1626
|
-
opId: this._doc.generateOpId(),
|
|
1627
|
-
},
|
|
1628
|
-
],
|
|
1629
|
-
reverse,
|
|
1630
|
-
storageUpdates
|
|
1631
|
-
);
|
|
1632
|
-
}
|
|
1633
|
-
update(overrides) {
|
|
1634
|
-
if (null == this._doc || null == this._id) {
|
|
1635
|
-
for (const key in overrides) {
|
|
1636
|
-
const newValue = overrides[key];
|
|
1637
|
-
if (void 0 === newValue) continue;
|
|
1638
|
-
const oldValue = this._map.get(key);
|
|
1639
|
-
isLiveNode(oldValue) && oldValue._detach(),
|
|
1640
|
-
isLiveNode(newValue) && newValue._setParentLink(this, key),
|
|
1641
|
-
this._map.set(key, newValue);
|
|
1642
|
-
}
|
|
1643
|
-
return;
|
|
1644
|
-
}
|
|
1645
|
-
const ops = [],
|
|
1646
|
-
reverseOps = [],
|
|
1647
|
-
opId = this._doc.generateOpId(),
|
|
1648
|
-
updatedProps = {},
|
|
1649
|
-
reverseUpdateOp = { id: this._id, type: OpCode.UPDATE_OBJECT, data: {} },
|
|
1650
|
-
updateDelta = {};
|
|
1651
|
-
for (const key in overrides) {
|
|
1652
|
-
const newValue = overrides[key];
|
|
1653
|
-
if (void 0 === newValue) continue;
|
|
1654
|
-
const oldValue = this._map.get(key);
|
|
1655
|
-
if (
|
|
1656
|
-
(isLiveNode(oldValue)
|
|
1657
|
-
? (reverseOps.push(...oldValue._serialize(this._id, key)),
|
|
1658
|
-
oldValue._detach())
|
|
1659
|
-
: void 0 === oldValue
|
|
1660
|
-
? reverseOps.push({
|
|
1661
|
-
type: OpCode.DELETE_OBJECT_KEY,
|
|
1662
|
-
id: this._id,
|
|
1663
|
-
key: key,
|
|
1664
|
-
})
|
|
1665
|
-
: (reverseUpdateOp.data[key] = oldValue),
|
|
1666
|
-
isLiveNode(newValue))
|
|
1667
|
-
) {
|
|
1668
|
-
newValue._setParentLink(this, key),
|
|
1669
|
-
newValue._attach(this._doc.generateId(), this._doc);
|
|
1670
|
-
const newAttachChildOps = newValue._serialize(this._id, key, this._doc),
|
|
1671
|
-
createCrdtOp = newAttachChildOps.find(
|
|
1672
|
-
(op) => op.parentId === this._id
|
|
1673
|
-
);
|
|
1674
|
-
createCrdtOp && this._propToLastUpdate.set(key, nn(createCrdtOp.opId)),
|
|
1675
|
-
ops.push(...newAttachChildOps);
|
|
1676
|
-
} else
|
|
1677
|
-
(updatedProps[key] = newValue), this._propToLastUpdate.set(key, opId);
|
|
1678
|
-
this._map.set(key, newValue), (updateDelta[key] = { type: "update" });
|
|
1679
|
-
}
|
|
1680
|
-
0 !== Object.keys(reverseUpdateOp.data).length &&
|
|
1681
|
-
reverseOps.unshift(reverseUpdateOp),
|
|
1682
|
-
0 !== Object.keys(updatedProps).length &&
|
|
1683
|
-
ops.unshift({
|
|
1684
|
-
opId: opId,
|
|
1685
|
-
id: this._id,
|
|
1686
|
-
type: OpCode.UPDATE_OBJECT,
|
|
1687
|
-
data: updatedProps,
|
|
1688
|
-
});
|
|
1689
|
-
const storageUpdates = new Map();
|
|
1690
|
-
storageUpdates.set(this._id, {
|
|
1691
|
-
node: this,
|
|
1692
|
-
type: "LiveObject",
|
|
1693
|
-
updates: updateDelta,
|
|
1694
|
-
}),
|
|
1695
|
-
this._doc.dispatch(ops, reverseOps, storageUpdates);
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
function remove(array, item) {
|
|
1699
|
-
for (let i = 0; i < array.length; i++)
|
|
1700
|
-
if (array[i] === item) {
|
|
1701
|
-
array.splice(i, 1);
|
|
1702
|
-
break;
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
function compact(items) {
|
|
1706
|
-
return items.filter((item) => null != item);
|
|
1707
|
-
}
|
|
1708
|
-
function creationOpToLiveNode(op) {
|
|
1709
|
-
return lsonToLiveNode(creationOpToLson(op));
|
|
1710
|
-
}
|
|
1711
|
-
function creationOpToLson(op) {
|
|
1712
|
-
switch (op.type) {
|
|
1713
|
-
case OpCode.CREATE_REGISTER:
|
|
1714
|
-
return op.data;
|
|
1715
|
-
case OpCode.CREATE_OBJECT:
|
|
1716
|
-
return new LiveObject(op.data);
|
|
1717
|
-
case OpCode.CREATE_MAP:
|
|
1718
|
-
return new LiveMap();
|
|
1719
|
-
case OpCode.CREATE_LIST:
|
|
1720
|
-
return new LiveList();
|
|
1721
|
-
default:
|
|
1722
|
-
return assertNever(0, "Unknown creation Op");
|
|
1723
|
-
}
|
|
1724
|
-
}
|
|
1725
|
-
function isSameNodeOrChildOf(node, parent) {
|
|
1726
|
-
return (
|
|
1727
|
-
node === parent ||
|
|
1728
|
-
("HasParent" === node.parent.type &&
|
|
1729
|
-
isSameNodeOrChildOf(node.parent.node, parent))
|
|
1730
|
-
);
|
|
1731
|
-
}
|
|
1732
|
-
function deserialize([id, crdt], parentToChildren, doc) {
|
|
1733
|
-
switch (crdt.type) {
|
|
1734
|
-
case CrdtType.OBJECT:
|
|
1735
|
-
return LiveObject._deserialize([id, crdt], parentToChildren, doc);
|
|
1736
|
-
case CrdtType.LIST:
|
|
1737
|
-
return LiveList._deserialize([id, crdt], parentToChildren, doc);
|
|
1738
|
-
case CrdtType.MAP:
|
|
1739
|
-
return LiveMap._deserialize([id, crdt], parentToChildren, doc);
|
|
1740
|
-
case CrdtType.REGISTER:
|
|
1741
|
-
return LiveRegister._deserialize([id, crdt], parentToChildren, doc);
|
|
1742
|
-
default:
|
|
1743
|
-
throw new Error("Unexpected CRDT type");
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
function deserializeToLson([id, crdt], parentToChildren, doc) {
|
|
1747
|
-
switch (crdt.type) {
|
|
1748
|
-
case CrdtType.OBJECT:
|
|
1749
|
-
return LiveObject._deserialize([id, crdt], parentToChildren, doc);
|
|
1750
|
-
case CrdtType.LIST:
|
|
1751
|
-
return LiveList._deserialize([id, crdt], parentToChildren, doc);
|
|
1752
|
-
case CrdtType.MAP:
|
|
1753
|
-
return LiveMap._deserialize([id, crdt], parentToChildren, doc);
|
|
1754
|
-
case CrdtType.REGISTER:
|
|
1755
|
-
return crdt.data;
|
|
1756
|
-
default:
|
|
1757
|
-
throw new Error("Unexpected CRDT type");
|
|
1758
|
-
}
|
|
1759
|
-
}
|
|
1760
|
-
function isLiveStructure(value) {
|
|
1761
|
-
return (
|
|
1762
|
-
isLiveList(value) ||
|
|
1763
|
-
(function (value) {
|
|
1764
|
-
return value instanceof LiveMap;
|
|
1765
|
-
})(value) ||
|
|
1766
|
-
isLiveObject(value)
|
|
1767
|
-
);
|
|
1768
|
-
}
|
|
1769
|
-
function isLiveNode(value) {
|
|
1770
|
-
return (
|
|
1771
|
-
isLiveStructure(value) ||
|
|
1772
|
-
(function (value) {
|
|
1773
|
-
return value instanceof LiveRegister;
|
|
1774
|
-
})(value)
|
|
1775
|
-
);
|
|
1776
|
-
}
|
|
1777
|
-
function isLiveList(value) {
|
|
1778
|
-
return value instanceof LiveList;
|
|
1779
|
-
}
|
|
1780
|
-
function isLiveObject(value) {
|
|
1781
|
-
return value instanceof LiveObject;
|
|
1782
|
-
}
|
|
1783
|
-
function liveNodeToLson(obj) {
|
|
1784
|
-
return obj instanceof LiveRegister
|
|
1785
|
-
? obj.data
|
|
1786
|
-
: obj instanceof LiveList ||
|
|
1787
|
-
obj instanceof LiveMap ||
|
|
1788
|
-
obj instanceof LiveObject
|
|
1789
|
-
? obj
|
|
1790
|
-
: assertNever(0, "Unknown AbstractCrdt");
|
|
1791
|
-
}
|
|
1792
|
-
function lsonToLiveNode(value) {
|
|
1793
|
-
return value instanceof LiveObject ||
|
|
1794
|
-
value instanceof LiveMap ||
|
|
1795
|
-
value instanceof LiveList
|
|
1796
|
-
? value
|
|
1797
|
-
: new LiveRegister(value);
|
|
1798
|
-
}
|
|
1799
|
-
function getTreesDiffOperations(currentItems, newItems) {
|
|
1800
|
-
const ops = [];
|
|
1801
|
-
return (
|
|
1802
|
-
currentItems.forEach((_, id) => {
|
|
1803
|
-
newItems.get(id) || ops.push({ type: OpCode.DELETE_CRDT, id: id });
|
|
1804
|
-
}),
|
|
1805
|
-
newItems.forEach((crdt, id) => {
|
|
1806
|
-
const currentCrdt = currentItems.get(id);
|
|
1807
|
-
if (currentCrdt)
|
|
1808
|
-
crdt.type === CrdtType.OBJECT &&
|
|
1809
|
-
((currentCrdt.type === CrdtType.OBJECT &&
|
|
1810
|
-
JSON.stringify(crdt.data) === JSON.stringify(currentCrdt.data)) ||
|
|
1811
|
-
ops.push({ type: OpCode.UPDATE_OBJECT, id: id, data: crdt.data })),
|
|
1812
|
-
crdt.parentKey !== currentCrdt.parentKey &&
|
|
1813
|
-
ops.push({
|
|
1814
|
-
type: OpCode.SET_PARENT_KEY,
|
|
1815
|
-
id: id,
|
|
1816
|
-
parentKey: nn(crdt.parentKey, "Parent key must not be missing"),
|
|
1817
|
-
});
|
|
1818
|
-
else
|
|
1819
|
-
switch (crdt.type) {
|
|
1820
|
-
case CrdtType.REGISTER:
|
|
1821
|
-
ops.push({
|
|
1822
|
-
type: OpCode.CREATE_REGISTER,
|
|
1823
|
-
id: id,
|
|
1824
|
-
parentId: crdt.parentId,
|
|
1825
|
-
parentKey: crdt.parentKey,
|
|
1826
|
-
data: crdt.data,
|
|
1827
|
-
});
|
|
1828
|
-
break;
|
|
1829
|
-
case CrdtType.LIST:
|
|
1830
|
-
ops.push({
|
|
1831
|
-
type: OpCode.CREATE_LIST,
|
|
1832
|
-
id: id,
|
|
1833
|
-
parentId: crdt.parentId,
|
|
1834
|
-
parentKey: crdt.parentKey,
|
|
1835
|
-
});
|
|
1836
|
-
break;
|
|
1837
|
-
case CrdtType.OBJECT:
|
|
1838
|
-
ops.push(
|
|
1839
|
-
crdt.parentId
|
|
1840
|
-
? {
|
|
1841
|
-
type: OpCode.CREATE_OBJECT,
|
|
1842
|
-
id: id,
|
|
1843
|
-
parentId: crdt.parentId,
|
|
1844
|
-
parentKey: crdt.parentKey,
|
|
1845
|
-
data: crdt.data,
|
|
1846
|
-
}
|
|
1847
|
-
: { type: OpCode.CREATE_OBJECT, id: id, data: crdt.data }
|
|
1848
|
-
);
|
|
1849
|
-
break;
|
|
1850
|
-
case CrdtType.MAP:
|
|
1851
|
-
ops.push({
|
|
1852
|
-
type: OpCode.CREATE_MAP,
|
|
1853
|
-
id: id,
|
|
1854
|
-
parentId: crdt.parentId,
|
|
1855
|
-
parentKey: crdt.parentKey,
|
|
1856
|
-
});
|
|
1857
|
-
}
|
|
1858
|
-
}),
|
|
1859
|
-
ops
|
|
1860
|
-
);
|
|
1861
|
-
}
|
|
1862
|
-
function mergeStorageUpdates(first, second) {
|
|
1863
|
-
return first
|
|
1864
|
-
? "LiveObject" === first.type && "LiveObject" === second.type
|
|
1865
|
-
? (function (first, second) {
|
|
1866
|
-
const updates = first.updates;
|
|
1867
|
-
for (const [key, value] of entries(second.updates))
|
|
1868
|
-
updates[key] = value;
|
|
1869
|
-
return Object.assign(Object.assign({}, second), { updates: updates });
|
|
1870
|
-
})(first, second)
|
|
1871
|
-
: "LiveMap" === first.type && "LiveMap" === second.type
|
|
1872
|
-
? (function (first, second) {
|
|
1873
|
-
const updates = first.updates;
|
|
1874
|
-
for (const [key, value] of entries(second.updates))
|
|
1875
|
-
updates[key] = value;
|
|
1876
|
-
return Object.assign(Object.assign({}, second), { updates: updates });
|
|
1877
|
-
})(first, second)
|
|
1878
|
-
: "LiveList" === first.type && "LiveList" === second.type
|
|
1879
|
-
? (function (first, second) {
|
|
1880
|
-
const updates = first.updates;
|
|
1881
|
-
return Object.assign(Object.assign({}, second), {
|
|
1882
|
-
updates: updates.concat(second.updates),
|
|
1883
|
-
});
|
|
1884
|
-
})(first, second)
|
|
1885
|
-
: second
|
|
1886
|
-
: second;
|
|
1887
|
-
}
|
|
1888
|
-
function isPlain(value) {
|
|
1889
|
-
const type = typeof value;
|
|
1890
|
-
return (
|
|
1891
|
-
null == value ||
|
|
1892
|
-
"string" === type ||
|
|
1893
|
-
"boolean" === type ||
|
|
1894
|
-
"number" === type ||
|
|
1895
|
-
Array.isArray(value) ||
|
|
1896
|
-
isPlainObject(value)
|
|
1897
|
-
);
|
|
1898
|
-
}
|
|
1899
|
-
function isPlainObject(blob) {
|
|
1900
|
-
return (
|
|
1901
|
-
null !== blob &&
|
|
1902
|
-
"object" == typeof blob &&
|
|
1903
|
-
"[object Object]" === Object.prototype.toString.call(blob)
|
|
1904
|
-
);
|
|
1905
|
-
}
|
|
1906
|
-
function findNonSerializableValue(value, path = "") {
|
|
1907
|
-
if (!isPlain) return { path: path || "root", value: value };
|
|
1908
|
-
if ("object" != typeof value || null === value) return !1;
|
|
1909
|
-
for (const [key, nestedValue] of Object.entries(value)) {
|
|
1910
|
-
const nestedPath = path ? path + "." + key : key;
|
|
1911
|
-
if (!isPlain(nestedValue)) return { path: nestedPath, value: nestedValue };
|
|
1912
|
-
if ("object" == typeof nestedValue) {
|
|
1913
|
-
const nonSerializableNestedValue = findNonSerializableValue(
|
|
1914
|
-
nestedValue,
|
|
1915
|
-
nestedPath
|
|
1916
|
-
);
|
|
1917
|
-
if (nonSerializableNestedValue) return nonSerializableNestedValue;
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1920
|
-
return !1;
|
|
1921
|
-
}
|
|
1922
|
-
function entries(obj) {
|
|
1923
|
-
return Object.entries(obj);
|
|
1924
|
-
}
|
|
1925
|
-
function tryParseJson(rawMessage) {
|
|
1926
|
-
try {
|
|
1927
|
-
return JSON.parse(rawMessage);
|
|
1928
|
-
} catch (e) {
|
|
1929
|
-
return;
|
|
1930
|
-
}
|
|
1931
|
-
}
|
|
1932
|
-
function b64decode(b64value) {
|
|
1933
|
-
try {
|
|
1934
|
-
const formattedValue = b64value.replace(/-/g, "+").replace(/_/g, "/");
|
|
1935
|
-
return decodeURIComponent(
|
|
1936
|
-
atob(formattedValue)
|
|
1937
|
-
.split("")
|
|
1938
|
-
.map(function (c) {
|
|
1939
|
-
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
1940
|
-
})
|
|
1941
|
-
.join("")
|
|
1942
|
-
);
|
|
1943
|
-
} catch (err) {
|
|
1944
|
-
return atob(b64value);
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
const SCOPES = [
|
|
1948
|
-
"websocket:presence",
|
|
1949
|
-
"websocket:storage",
|
|
1950
|
-
"room:read",
|
|
1951
|
-
"room:write",
|
|
1952
|
-
"rooms:read",
|
|
1953
|
-
"rooms:write",
|
|
1954
|
-
];
|
|
1955
|
-
function isTokenExpired(token) {
|
|
1956
|
-
const now = Date.now() / 1e3;
|
|
1957
|
-
return now > token.exp - 300 || now < token.iat + 300;
|
|
1958
|
-
}
|
|
1959
|
-
function isScope(value) {
|
|
1960
|
-
return SCOPES.includes(value);
|
|
1961
|
-
}
|
|
1962
|
-
function isStringList(value) {
|
|
1963
|
-
return Array.isArray(value) && value.every((i) => "string" == typeof i);
|
|
1964
|
-
}
|
|
1965
|
-
function isAppOnlyAuthToken(data) {
|
|
1966
|
-
return (
|
|
1967
|
-
"string" == typeof data.appId &&
|
|
1968
|
-
void 0 === data.roomId &&
|
|
1969
|
-
isStringList(data.scopes)
|
|
1970
|
-
);
|
|
1971
|
-
}
|
|
1972
|
-
function isRoomAuthToken(data) {
|
|
1973
|
-
return (
|
|
1974
|
-
"string" == typeof data.appId &&
|
|
1975
|
-
"string" == typeof data.roomId &&
|
|
1976
|
-
"number" == typeof data.actor &&
|
|
1977
|
-
(void 0 === data.id || "string" == typeof data.id) &&
|
|
1978
|
-
isStringList(data.scopes) &&
|
|
1979
|
-
(void 0 === data.maxConnectionsPerRoom ||
|
|
1980
|
-
"number" == typeof data.maxConnectionsPerRoom)
|
|
1981
|
-
);
|
|
1982
|
-
}
|
|
1983
|
-
function isAuthToken(data) {
|
|
1984
|
-
return isAppOnlyAuthToken(data) || isRoomAuthToken(data);
|
|
1985
|
-
}
|
|
1986
|
-
function parseJwtToken(token) {
|
|
1987
|
-
const tokenParts = token.split(".");
|
|
1988
|
-
if (3 !== tokenParts.length)
|
|
1989
|
-
throw new Error("Authentication error: invalid JWT token");
|
|
1990
|
-
const data = tryParseJson(b64decode(tokenParts[1]));
|
|
1991
|
-
if (
|
|
1992
|
-
data &&
|
|
1993
|
-
(function (data) {
|
|
1994
|
-
if (!isPlainObject(data)) return !1;
|
|
1995
|
-
const { iat: iat, exp: exp } = data;
|
|
1996
|
-
return "number" == typeof iat && "number" == typeof exp;
|
|
1997
|
-
})(data)
|
|
1998
|
-
)
|
|
1999
|
-
return data;
|
|
2000
|
-
throw new Error("Authentication error: missing JWT metadata");
|
|
2001
|
-
}
|
|
2002
|
-
function parseRoomAuthToken(tokenString) {
|
|
2003
|
-
const data = parseJwtToken(tokenString);
|
|
2004
|
-
if (data && isRoomAuthToken(data)) {
|
|
2005
|
-
return __rest(data, ["maxConnections"]);
|
|
2006
|
-
}
|
|
2007
|
-
throw new Error(
|
|
2008
|
-
"Authentication error: we expected a room token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback"
|
|
2009
|
-
);
|
|
2010
|
-
}
|
|
2011
|
-
function isJsonScalar(data) {
|
|
2012
|
-
return (
|
|
2013
|
-
null === data ||
|
|
2014
|
-
"string" == typeof data ||
|
|
2015
|
-
"number" == typeof data ||
|
|
2016
|
-
"boolean" == typeof data
|
|
2017
|
-
);
|
|
2018
|
-
}
|
|
2019
|
-
function isJsonArray(data) {
|
|
2020
|
-
return Array.isArray(data);
|
|
2021
|
-
}
|
|
2022
|
-
function isJsonObject(data) {
|
|
2023
|
-
return !isJsonScalar(data) && !isJsonArray(data);
|
|
2024
|
-
}
|
|
2025
|
-
export {
|
|
2026
|
-
isRoomAuthToken as A,
|
|
2027
|
-
isScope as B,
|
|
2028
|
-
ClientMsgCode as C,
|
|
2029
|
-
deprecate as D,
|
|
2030
|
-
deprecateIf as E,
|
|
2031
|
-
throwUsageError as F,
|
|
2032
|
-
comparePosition as G,
|
|
2033
|
-
makePosition as H,
|
|
2034
|
-
CrdtType as I,
|
|
2035
|
-
isJsonScalar as J,
|
|
2036
|
-
isChildCrdt as K,
|
|
2037
|
-
LiveObject as L,
|
|
2038
|
-
b64decode as M,
|
|
2039
|
-
OpSource as O,
|
|
2040
|
-
ServerMsgCode as S,
|
|
2041
|
-
WebsocketCloseCodes as W,
|
|
2042
|
-
__rest as _,
|
|
2043
|
-
isRoomEventName as a,
|
|
2044
|
-
isPlainObject as b,
|
|
2045
|
-
isTokenExpired as c,
|
|
2046
|
-
isSameNodeOrChildOf as d,
|
|
2047
|
-
OpCode as e,
|
|
2048
|
-
isLiveList as f,
|
|
2049
|
-
getTreesDiffOperations as g,
|
|
2050
|
-
isJsonArray as h,
|
|
2051
|
-
isLiveNode as i,
|
|
2052
|
-
compact as j,
|
|
2053
|
-
isRootCrdt as k,
|
|
2054
|
-
isJsonObject as l,
|
|
2055
|
-
mergeStorageUpdates as m,
|
|
2056
|
-
nn as n,
|
|
2057
|
-
errorIf as o,
|
|
2058
|
-
parseRoomAuthToken as p,
|
|
2059
|
-
LiveList as q,
|
|
2060
|
-
remove as r,
|
|
2061
|
-
LiveMap as s,
|
|
2062
|
-
tryParseJson as t,
|
|
2063
|
-
LiveRegister as u,
|
|
2064
|
-
findNonSerializableValue as v,
|
|
2065
|
-
isLiveObject as w,
|
|
2066
|
-
assertNever as x,
|
|
2067
|
-
isAppOnlyAuthToken as y,
|
|
2068
|
-
isAuthToken as z,
|
|
2069
|
-
};
|