@liveblocks/client 0.16.3 → 0.16.4-beta1

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/esm/index.js DELETED
@@ -1,3068 +0,0 @@
1
- var ServerMessageType = /* @__PURE__ */ ((ServerMessageType2) => {
2
- ServerMessageType2[ServerMessageType2["UpdatePresence"] = 100] = "UpdatePresence";
3
- ServerMessageType2[ServerMessageType2["UserJoined"] = 101] = "UserJoined";
4
- ServerMessageType2[ServerMessageType2["UserLeft"] = 102] = "UserLeft";
5
- ServerMessageType2[ServerMessageType2["Event"] = 103] = "Event";
6
- ServerMessageType2[ServerMessageType2["RoomState"] = 104] = "RoomState";
7
- ServerMessageType2[ServerMessageType2["InitialStorageState"] = 200] = "InitialStorageState";
8
- ServerMessageType2[ServerMessageType2["UpdateStorage"] = 201] = "UpdateStorage";
9
- return ServerMessageType2;
10
- })(ServerMessageType || {});
11
- var ClientMessageType = /* @__PURE__ */ ((ClientMessageType2) => {
12
- ClientMessageType2[ClientMessageType2["UpdatePresence"] = 100] = "UpdatePresence";
13
- ClientMessageType2[ClientMessageType2["ClientEvent"] = 103] = "ClientEvent";
14
- ClientMessageType2[ClientMessageType2["FetchStorage"] = 200] = "FetchStorage";
15
- ClientMessageType2[ClientMessageType2["UpdateStorage"] = 201] = "UpdateStorage";
16
- return ClientMessageType2;
17
- })(ClientMessageType || {});
18
- var CrdtType = /* @__PURE__ */ ((CrdtType2) => {
19
- CrdtType2[CrdtType2["Object"] = 0] = "Object";
20
- CrdtType2[CrdtType2["List"] = 1] = "List";
21
- CrdtType2[CrdtType2["Map"] = 2] = "Map";
22
- CrdtType2[CrdtType2["Register"] = 3] = "Register";
23
- return CrdtType2;
24
- })(CrdtType || {});
25
- var OpType = /* @__PURE__ */ ((OpType2) => {
26
- OpType2[OpType2["Init"] = 0] = "Init";
27
- OpType2[OpType2["SetParentKey"] = 1] = "SetParentKey";
28
- OpType2[OpType2["CreateList"] = 2] = "CreateList";
29
- OpType2[OpType2["UpdateObject"] = 3] = "UpdateObject";
30
- OpType2[OpType2["CreateObject"] = 4] = "CreateObject";
31
- OpType2[OpType2["DeleteCrdt"] = 5] = "DeleteCrdt";
32
- OpType2[OpType2["DeleteObjectKey"] = 6] = "DeleteObjectKey";
33
- OpType2[OpType2["CreateMap"] = 7] = "CreateMap";
34
- OpType2[OpType2["CreateRegister"] = 8] = "CreateRegister";
35
- return OpType2;
36
- })(OpType || {});
37
- var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
38
- WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_ABNORMAL"] = 1006] = "CLOSE_ABNORMAL";
39
- WebsocketCloseCodes2[WebsocketCloseCodes2["INVALID_MESSAGE_FORMAT"] = 4e3] = "INVALID_MESSAGE_FORMAT";
40
- WebsocketCloseCodes2[WebsocketCloseCodes2["NOT_ALLOWED"] = 4001] = "NOT_ALLOWED";
41
- WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_SECONDS"] = 4002] = "MAX_NUMBER_OF_MESSAGES_PER_SECONDS";
42
- WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS"] = 4003] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS";
43
- WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"] = 4004] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP";
44
- WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"] = 4005] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM";
45
- WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_WITHOUT_RETRY"] = 4999] = "CLOSE_WITHOUT_RETRY";
46
- return WebsocketCloseCodes2;
47
- })(WebsocketCloseCodes || {});
48
-
49
- class AbstractCrdt {
50
- get _doc() {
51
- return this.__doc;
52
- }
53
- get roomId() {
54
- return this.__doc ? this.__doc.roomId : null;
55
- }
56
- get _id() {
57
- return this.__id;
58
- }
59
- get _parent() {
60
- return this.__parent;
61
- }
62
- get _parentKey() {
63
- return this.__parentKey;
64
- }
65
- _apply(op, _isLocal) {
66
- switch (op.type) {
67
- case OpType.DeleteCrdt: {
68
- if (this._parent != null && this._parentKey != null) {
69
- return this._parent._detachChild(this);
70
- }
71
- return { modified: false };
72
- }
73
- }
74
- return { modified: false };
75
- }
76
- _setParentLink(parent, key) {
77
- if (this.__parent != null && this.__parent !== parent) {
78
- throw new Error("Cannot attach parent if it already exist");
79
- }
80
- this.__parentKey = key;
81
- this.__parent = parent;
82
- }
83
- _attach(id, doc) {
84
- if (this.__id || this.__doc) {
85
- throw new Error("Cannot attach if CRDT is already attached");
86
- }
87
- doc.addItem(id, this);
88
- this.__id = id;
89
- this.__doc = doc;
90
- }
91
- _detach() {
92
- if (this.__doc && this.__id) {
93
- this.__doc.deleteItem(this.__id);
94
- }
95
- this.__parent = void 0;
96
- this.__doc = void 0;
97
- }
98
- }
99
-
100
- const min = 32;
101
- const max = 126;
102
- function makePosition(before, after) {
103
- if (before == null && after == null) {
104
- return pos([min + 1]);
105
- }
106
- if (before != null && after == null) {
107
- return getNextPosition(before);
108
- }
109
- if (before == null && after != null) {
110
- return getPreviousPosition(after);
111
- }
112
- return pos(makePositionFromCodes(posCodes(before), posCodes(after)));
113
- }
114
- function getPreviousPosition(after) {
115
- const result = [];
116
- const afterCodes = posCodes(after);
117
- for (let i = 0; i < afterCodes.length; i++) {
118
- const code = afterCodes[i];
119
- if (code <= min + 1) {
120
- result.push(min);
121
- if (afterCodes.length - 1 === i) {
122
- result.push(max);
123
- break;
124
- }
125
- } else {
126
- result.push(code - 1);
127
- break;
128
- }
129
- }
130
- return pos(result);
131
- }
132
- function getNextPosition(before) {
133
- const result = [];
134
- const beforeCodes = posCodes(before);
135
- for (let i = 0; i < beforeCodes.length; i++) {
136
- const code = beforeCodes[i];
137
- if (code === max) {
138
- result.push(code);
139
- if (beforeCodes.length - 1 === i) {
140
- result.push(min + 1);
141
- break;
142
- }
143
- } else {
144
- result.push(code + 1);
145
- break;
146
- }
147
- }
148
- return pos(result);
149
- }
150
- function makePositionFromCodes(before, after) {
151
- let index = 0;
152
- const result = [];
153
- while (true) {
154
- const beforeDigit = before[index] || min;
155
- const afterDigit = after[index] || max;
156
- if (beforeDigit > afterDigit) {
157
- throw new Error(`Impossible to generate position between ${before} and ${after}`);
158
- }
159
- if (beforeDigit === afterDigit) {
160
- result.push(beforeDigit);
161
- index++;
162
- continue;
163
- }
164
- if (afterDigit - beforeDigit === 1) {
165
- result.push(beforeDigit);
166
- result.push(...makePositionFromCodes(before.slice(index + 1), []));
167
- break;
168
- }
169
- const mid = afterDigit + beforeDigit >> 1;
170
- result.push(mid);
171
- break;
172
- }
173
- return result;
174
- }
175
- function posCodes(str) {
176
- const codes = [];
177
- for (let i = 0; i < str.length; i++) {
178
- codes.push(str.charCodeAt(i));
179
- }
180
- return codes;
181
- }
182
- function pos(codes) {
183
- return String.fromCharCode(...codes);
184
- }
185
- function compare(posA, posB) {
186
- const aCodes = posCodes(posA);
187
- const bCodes = posCodes(posB);
188
- const maxLength = Math.max(aCodes.length, bCodes.length);
189
- for (let i = 0; i < maxLength; i++) {
190
- const a = aCodes[i] == null ? min : aCodes[i];
191
- const b = bCodes[i] == null ? min : bCodes[i];
192
- if (a === b) {
193
- continue;
194
- } else {
195
- return a - b;
196
- }
197
- }
198
- throw new Error(`Impossible to compare similar position "${posA}" and "${posB}"`);
199
- }
200
-
201
- class LiveRegister extends AbstractCrdt {
202
- constructor(data) {
203
- super();
204
- this._data = data;
205
- }
206
- get data() {
207
- return this._data;
208
- }
209
- static _deserialize([id, item], _parentToChildren, doc) {
210
- if (item.type !== CrdtType.Register) {
211
- throw new Error(`Tried to deserialize a map but item type is "${item.type}"`);
212
- }
213
- const register = new LiveRegister(item.data);
214
- register._attach(id, doc);
215
- return register;
216
- }
217
- _serialize(parentId, parentKey, doc, intent) {
218
- if (this._id == null || parentId == null || parentKey == null) {
219
- throw new Error("Cannot serialize register if parentId or parentKey is undefined");
220
- }
221
- return [
222
- {
223
- type: OpType.CreateRegister,
224
- opId: doc == null ? void 0 : doc.generateOpId(),
225
- id: this._id,
226
- intent,
227
- parentId,
228
- parentKey,
229
- data: this.data
230
- }
231
- ];
232
- }
233
- _toSerializedCrdt() {
234
- var _a;
235
- return {
236
- type: CrdtType.Register,
237
- parentId: (_a = this._parent) == null ? void 0 : _a._id,
238
- parentKey: this._parentKey,
239
- data: this.data
240
- };
241
- }
242
- _attachChild(_op, _isLocal) {
243
- throw new Error("Method not implemented.");
244
- }
245
- _detachChild(_crdt) {
246
- throw new Error("Method not implemented.");
247
- }
248
- _apply(op, isLocal) {
249
- return super._apply(op, isLocal);
250
- }
251
- }
252
-
253
- class LiveList extends AbstractCrdt {
254
- constructor(items = []) {
255
- super();
256
- this._items = [];
257
- let position = void 0;
258
- for (let i = 0; i < items.length; i++) {
259
- const newPosition = makePosition(position);
260
- const item = selfOrRegister(items[i]);
261
- this._items.push([item, newPosition]);
262
- position = newPosition;
263
- }
264
- }
265
- static _deserialize([id], parentToChildren, doc) {
266
- const list = new LiveList([]);
267
- list._attach(id, doc);
268
- const children = parentToChildren.get(id);
269
- if (children == null) {
270
- return list;
271
- }
272
- for (const entry of children) {
273
- const child = deserialize(entry, parentToChildren, doc);
274
- child._setParentLink(list, entry[1].parentKey);
275
- list._items.push([child, entry[1].parentKey]);
276
- list._items.sort((itemA, itemB) => compare(itemA[1], itemB[1]));
277
- }
278
- return list;
279
- }
280
- _serialize(parentId, parentKey, doc, intent) {
281
- if (this._id == null) {
282
- throw new Error("Cannot serialize item is not attached");
283
- }
284
- if (parentId == null || parentKey == null) {
285
- throw new Error("Cannot serialize list if parentId or parentKey is undefined");
286
- }
287
- const ops = [];
288
- const op = {
289
- id: this._id,
290
- opId: doc == null ? void 0 : doc.generateOpId(),
291
- intent,
292
- type: OpType.CreateList,
293
- parentId,
294
- parentKey
295
- };
296
- ops.push(op);
297
- for (const [value, key] of this._items) {
298
- ops.push(...value._serialize(this._id, key, doc));
299
- }
300
- return ops;
301
- }
302
- _indexOfPosition(position) {
303
- return this._items.findIndex((item) => item[1] === position);
304
- }
305
- _attach(id, doc) {
306
- super._attach(id, doc);
307
- for (const [item] of this._items) {
308
- item._attach(doc.generateId(), doc);
309
- }
310
- }
311
- _detach() {
312
- super._detach();
313
- for (const [value] of this._items) {
314
- value._detach();
315
- }
316
- }
317
- _attachChild(op, isLocal) {
318
- var _a;
319
- if (this._doc == null) {
320
- throw new Error("Can't attach child if doc is not present");
321
- }
322
- const { id, parentKey, intent } = op;
323
- const key = parentKey;
324
- const child = creationOpToLiveStructure(op);
325
- if (this._doc.getItem(id) !== void 0) {
326
- return { modified: false };
327
- }
328
- child._attach(id, this._doc);
329
- child._setParentLink(this, key);
330
- const index = this._items.findIndex((entry) => entry[1] === key);
331
- let newKey = key;
332
- if (index !== -1) {
333
- if (intent === "set") {
334
- const existingItem = this._items[index][0];
335
- existingItem._detach();
336
- const storageUpdate = {
337
- node: this,
338
- type: "LiveList",
339
- updates: [
340
- {
341
- index,
342
- type: "set",
343
- item: child instanceof LiveRegister ? child.data : child
344
- }
345
- ]
346
- };
347
- this._items[index][0] = child;
348
- return {
349
- modified: storageUpdate,
350
- reverse: existingItem._serialize(this._id, key, this._doc, "set")
351
- };
352
- } else if (isLocal) {
353
- const before = this._items[index] ? this._items[index][1] : void 0;
354
- const after = this._items[index + 1] ? this._items[index + 1][1] : void 0;
355
- newKey = makePosition(before, after);
356
- child._setParentLink(this, newKey);
357
- } else {
358
- this._items[index][1] = makePosition(key, (_a = this._items[index + 1]) == null ? void 0 : _a[1]);
359
- }
360
- }
361
- this._items.push([child, newKey]);
362
- this._items.sort((itemA, itemB) => compare(itemA[1], itemB[1]));
363
- const newIndex = this._items.findIndex((entry) => entry[1] === newKey);
364
- return {
365
- reverse: [{ type: OpType.DeleteCrdt, id }],
366
- modified: {
367
- node: this,
368
- type: "LiveList",
369
- updates: [
370
- {
371
- index: newIndex,
372
- type: "insert",
373
- item: child instanceof LiveRegister ? child.data : child
374
- }
375
- ]
376
- }
377
- };
378
- }
379
- _detachChild(child) {
380
- if (child) {
381
- const reverse = child._serialize(this._id, child._parentKey, this._doc);
382
- const indexToDelete = this._items.findIndex((item) => item[0] === child);
383
- this._items.splice(indexToDelete, 1);
384
- child._detach();
385
- const storageUpdate = {
386
- node: this,
387
- type: "LiveList",
388
- updates: [{ index: indexToDelete, type: "delete" }]
389
- };
390
- return { modified: storageUpdate, reverse };
391
- }
392
- return { modified: false };
393
- }
394
- _setChildKey(key, child, previousKey) {
395
- var _a;
396
- child._setParentLink(this, key);
397
- const previousIndex = this._items.findIndex((entry) => entry[0]._id === child._id);
398
- const index = this._items.findIndex((entry) => entry[1] === key);
399
- if (index !== -1) {
400
- this._items[index][1] = makePosition(key, (_a = this._items[index + 1]) == null ? void 0 : _a[1]);
401
- }
402
- const item = this._items.find((item2) => item2[0] === child);
403
- if (item) {
404
- item[1] = key;
405
- }
406
- this._items.sort((itemA, itemB) => compare(itemA[1], itemB[1]));
407
- const newIndex = this._items.findIndex((entry) => entry[0]._id === child._id);
408
- const updatesDelta = newIndex === previousIndex ? [] : [
409
- {
410
- index: newIndex,
411
- item: child instanceof LiveRegister ? child.data : child,
412
- previousIndex,
413
- type: "move"
414
- }
415
- ];
416
- return {
417
- modified: {
418
- node: this,
419
- type: "LiveList",
420
- updates: updatesDelta
421
- },
422
- reverse: [
423
- {
424
- type: OpType.SetParentKey,
425
- id: item == null ? void 0 : item[0]._id,
426
- parentKey: previousKey
427
- }
428
- ]
429
- };
430
- }
431
- _apply(op, isLocal) {
432
- return super._apply(op, isLocal);
433
- }
434
- _toSerializedCrdt() {
435
- var _a;
436
- return {
437
- type: CrdtType.List,
438
- parentId: (_a = this._parent) == null ? void 0 : _a._id,
439
- parentKey: this._parentKey
440
- };
441
- }
442
- get length() {
443
- return this._items.length;
444
- }
445
- push(element) {
446
- return this.insert(element, this.length);
447
- }
448
- insert(element, index) {
449
- if (index < 0 || index > this._items.length) {
450
- throw new Error(`Cannot insert list item at index "${index}". index should be between 0 and ${this._items.length}`);
451
- }
452
- const before = this._items[index - 1] ? this._items[index - 1][1] : void 0;
453
- const after = this._items[index] ? this._items[index][1] : void 0;
454
- const position = makePosition(before, after);
455
- const value = selfOrRegister(element);
456
- value._setParentLink(this, position);
457
- this._items.push([value, position]);
458
- this._items.sort((itemA, itemB) => compare(itemA[1], itemB[1]));
459
- const newIndex = this._items.findIndex((entry) => entry[1] === position);
460
- if (this._doc && this._id) {
461
- const id = this._doc.generateId();
462
- value._attach(id, this._doc);
463
- const storageUpdates = /* @__PURE__ */ new Map();
464
- storageUpdates.set(this._id, {
465
- node: this,
466
- type: "LiveList",
467
- updates: [
468
- {
469
- index: newIndex,
470
- item: value instanceof LiveRegister ? value.data : value,
471
- type: "insert"
472
- }
473
- ]
474
- });
475
- this._doc.dispatch(value._serialize(this._id, position, this._doc), [{ type: OpType.DeleteCrdt, id }], storageUpdates);
476
- }
477
- }
478
- move(index, targetIndex) {
479
- if (targetIndex < 0) {
480
- throw new Error("targetIndex cannot be less than 0");
481
- }
482
- if (targetIndex >= this._items.length) {
483
- throw new Error("targetIndex cannot be greater or equal than the list length");
484
- }
485
- if (index < 0) {
486
- throw new Error("index cannot be less than 0");
487
- }
488
- if (index >= this._items.length) {
489
- throw new Error("index cannot be greater or equal than the list length");
490
- }
491
- let beforePosition = null;
492
- let afterPosition = null;
493
- if (index < targetIndex) {
494
- afterPosition = targetIndex === this._items.length - 1 ? void 0 : this._items[targetIndex + 1][1];
495
- beforePosition = this._items[targetIndex][1];
496
- } else {
497
- afterPosition = this._items[targetIndex][1];
498
- beforePosition = targetIndex === 0 ? void 0 : this._items[targetIndex - 1][1];
499
- }
500
- const position = makePosition(beforePosition, afterPosition);
501
- const item = this._items[index];
502
- const previousPosition = item[1];
503
- item[1] = position;
504
- item[0]._setParentLink(this, position);
505
- this._items.sort((itemA, itemB) => compare(itemA[1], itemB[1]));
506
- const newIndex = this._items.findIndex((entry) => entry[1] === position);
507
- if (this._doc && this._id) {
508
- const storageUpdates = /* @__PURE__ */ new Map();
509
- storageUpdates.set(this._id, {
510
- node: this,
511
- type: "LiveList",
512
- updates: [
513
- {
514
- index: newIndex,
515
- previousIndex: index,
516
- item: item[0],
517
- type: "move"
518
- }
519
- ]
520
- });
521
- this._doc.dispatch([
522
- {
523
- type: OpType.SetParentKey,
524
- id: item[0]._id,
525
- opId: this._doc.generateOpId(),
526
- parentKey: position
527
- }
528
- ], [
529
- {
530
- type: OpType.SetParentKey,
531
- id: item[0]._id,
532
- parentKey: previousPosition
533
- }
534
- ], storageUpdates);
535
- }
536
- }
537
- delete(index) {
538
- if (index < 0 || index >= this._items.length) {
539
- throw new Error(`Cannot delete list item at index "${index}". index should be between 0 and ${this._items.length - 1}`);
540
- }
541
- const item = this._items[index];
542
- item[0]._detach();
543
- this._items.splice(index, 1);
544
- if (this._doc) {
545
- const childRecordId = item[0]._id;
546
- if (childRecordId) {
547
- const storageUpdates = /* @__PURE__ */ new Map();
548
- storageUpdates.set(this._id, {
549
- node: this,
550
- type: "LiveList",
551
- updates: [{ index, type: "delete" }]
552
- });
553
- this._doc.dispatch([
554
- {
555
- id: childRecordId,
556
- opId: this._doc.generateOpId(),
557
- type: OpType.DeleteCrdt
558
- }
559
- ], item[0]._serialize(this._id, item[1]), storageUpdates);
560
- }
561
- }
562
- }
563
- clear() {
564
- if (this._doc) {
565
- const ops = [];
566
- const reverseOps = [];
567
- const updateDelta = [];
568
- let i = 0;
569
- for (const item of this._items) {
570
- item[0]._detach();
571
- const childId = item[0]._id;
572
- if (childId) {
573
- ops.push({ id: childId, type: OpType.DeleteCrdt });
574
- reverseOps.push(...item[0]._serialize(this._id, item[1]));
575
- updateDelta.push({ index: i, type: "delete" });
576
- }
577
- i++;
578
- }
579
- this._items = [];
580
- const storageUpdates = /* @__PURE__ */ new Map();
581
- storageUpdates.set(this._id, {
582
- node: this,
583
- type: "LiveList",
584
- updates: updateDelta
585
- });
586
- this._doc.dispatch(ops, reverseOps, storageUpdates);
587
- } else {
588
- for (const item of this._items) {
589
- item[0]._detach();
590
- }
591
- this._items = [];
592
- }
593
- }
594
- set(index, item) {
595
- if (index < 0 || index >= this._items.length) {
596
- throw new Error(`Cannot set list item at index "${index}". index should be between 0 and ${this._items.length - 1}`);
597
- }
598
- const [existingItem, position] = this._items[index];
599
- existingItem._detach();
600
- const value = selfOrRegister(item);
601
- value._setParentLink(this, position);
602
- this._items[index][0] = value;
603
- if (this._doc && this._id) {
604
- const id = this._doc.generateId();
605
- value._attach(id, this._doc);
606
- const storageUpdates = /* @__PURE__ */ new Map();
607
- storageUpdates.set(this._id, {
608
- node: this,
609
- type: "LiveList",
610
- updates: [
611
- {
612
- index,
613
- item: value instanceof LiveRegister ? value.data : value,
614
- type: "set"
615
- }
616
- ]
617
- });
618
- this._doc.dispatch(value._serialize(this._id, position, this._doc, "set"), existingItem._serialize(this._id, position, void 0, "set"), storageUpdates);
619
- }
620
- }
621
- toArray() {
622
- return this._items.map((entry) => selfOrRegisterValue(entry[0]));
623
- }
624
- every(predicate) {
625
- return this.toArray().every(predicate);
626
- }
627
- filter(predicate) {
628
- return this.toArray().filter(predicate);
629
- }
630
- find(predicate) {
631
- return this.toArray().find(predicate);
632
- }
633
- findIndex(predicate) {
634
- return this.toArray().findIndex(predicate);
635
- }
636
- forEach(callbackfn) {
637
- return this.toArray().forEach(callbackfn);
638
- }
639
- get(index) {
640
- if (index < 0 || index >= this._items.length) {
641
- return void 0;
642
- }
643
- return selfOrRegisterValue(this._items[index][0]);
644
- }
645
- indexOf(searchElement, fromIndex) {
646
- return this.toArray().indexOf(searchElement, fromIndex);
647
- }
648
- lastIndexOf(searchElement, fromIndex) {
649
- return this.toArray().lastIndexOf(searchElement, fromIndex);
650
- }
651
- map(callback) {
652
- return this._items.map((entry, i) => callback(selfOrRegisterValue(entry[0]), i));
653
- }
654
- some(predicate) {
655
- return this.toArray().some(predicate);
656
- }
657
- [Symbol.iterator]() {
658
- return new LiveListIterator(this._items);
659
- }
660
- }
661
- class LiveListIterator {
662
- constructor(items) {
663
- this._innerIterator = items[Symbol.iterator]();
664
- }
665
- [Symbol.iterator]() {
666
- return this;
667
- }
668
- next() {
669
- const result = this._innerIterator.next();
670
- if (result.done) {
671
- return {
672
- done: true,
673
- value: void 0
674
- };
675
- }
676
- return {
677
- value: selfOrRegisterValue(result.value[0])
678
- };
679
- }
680
- }
681
-
682
- class LiveMap extends AbstractCrdt {
683
- constructor(entries) {
684
- super();
685
- if (entries) {
686
- const mappedEntries = [];
687
- for (const entry of entries) {
688
- const value = selfOrRegister(entry[1]);
689
- value._setParentLink(this, entry[0]);
690
- mappedEntries.push([entry[0], value]);
691
- }
692
- this._map = new Map(mappedEntries);
693
- } else {
694
- this._map = /* @__PURE__ */ new Map();
695
- }
696
- }
697
- _serialize(parentId, parentKey, doc, intent) {
698
- if (this._id == null) {
699
- throw new Error("Cannot serialize item is not attached");
700
- }
701
- if (parentId == null || parentKey == null) {
702
- throw new Error("Cannot serialize map if parentId or parentKey is undefined");
703
- }
704
- const ops = [];
705
- const op = {
706
- id: this._id,
707
- opId: doc == null ? void 0 : doc.generateOpId(),
708
- type: OpType.CreateMap,
709
- intent,
710
- parentId,
711
- parentKey
712
- };
713
- ops.push(op);
714
- for (const [key, value] of this._map) {
715
- ops.push(...value._serialize(this._id, key, doc));
716
- }
717
- return ops;
718
- }
719
- static _deserialize([id, item], parentToChildren, doc) {
720
- if (item.type !== CrdtType.Map) {
721
- throw new Error(`Tried to deserialize a map but item type is "${item.type}"`);
722
- }
723
- const map = new LiveMap();
724
- map._attach(id, doc);
725
- const children = parentToChildren.get(id);
726
- if (children == null) {
727
- return map;
728
- }
729
- for (const entry of children) {
730
- const crdt = entry[1];
731
- if (crdt.parentKey == null) {
732
- throw new Error("Tried to deserialize a crdt but it does not have a parentKey and is not the root");
733
- }
734
- const child = deserialize(entry, parentToChildren, doc);
735
- child._setParentLink(map, crdt.parentKey);
736
- map._map.set(crdt.parentKey, child);
737
- }
738
- return map;
739
- }
740
- _attach(id, doc) {
741
- super._attach(id, doc);
742
- for (const [_key, value] of this._map) {
743
- if (isCrdt(value)) {
744
- value._attach(doc.generateId(), doc);
745
- }
746
- }
747
- }
748
- _attachChild(op, _isLocal) {
749
- if (this._doc == null) {
750
- throw new Error("Can't attach child if doc is not present");
751
- }
752
- const { id, parentKey } = op;
753
- const key = parentKey;
754
- const child = creationOpToLiveStructure(op);
755
- if (this._doc.getItem(id) !== void 0) {
756
- return { modified: false };
757
- }
758
- const previousValue = this._map.get(key);
759
- let reverse;
760
- if (previousValue) {
761
- reverse = previousValue._serialize(this._id, key);
762
- previousValue._detach();
763
- } else {
764
- reverse = [{ type: OpType.DeleteCrdt, id }];
765
- }
766
- child._setParentLink(this, key);
767
- child._attach(id, this._doc);
768
- this._map.set(key, child);
769
- return {
770
- modified: {
771
- node: this,
772
- type: "LiveMap",
773
- updates: { [key]: { type: "update" } }
774
- },
775
- reverse
776
- };
777
- }
778
- _detach() {
779
- super._detach();
780
- for (const item of this._map.values()) {
781
- item._detach();
782
- }
783
- }
784
- _detachChild(child) {
785
- const reverse = child._serialize(this._id, child._parentKey, this._doc);
786
- for (const [key, value] of this._map) {
787
- if (value === child) {
788
- this._map.delete(key);
789
- }
790
- }
791
- child._detach();
792
- const storageUpdate = {
793
- node: this,
794
- type: "LiveMap",
795
- updates: { [child._parentKey]: { type: "delete" } }
796
- };
797
- return { modified: storageUpdate, reverse };
798
- }
799
- _toSerializedCrdt() {
800
- var _a;
801
- return {
802
- type: CrdtType.Map,
803
- parentId: (_a = this._parent) == null ? void 0 : _a._id,
804
- parentKey: this._parentKey
805
- };
806
- }
807
- get(key) {
808
- const value = this._map.get(key);
809
- if (value == void 0) {
810
- return void 0;
811
- }
812
- return selfOrRegisterValue(value);
813
- }
814
- set(key, value) {
815
- const oldValue = this._map.get(key);
816
- if (oldValue) {
817
- oldValue._detach();
818
- }
819
- const item = selfOrRegister(value);
820
- item._setParentLink(this, key);
821
- this._map.set(key, item);
822
- if (this._doc && this._id) {
823
- const id = this._doc.generateId();
824
- item._attach(id, this._doc);
825
- const storageUpdates = /* @__PURE__ */ new Map();
826
- storageUpdates.set(this._id, {
827
- node: this,
828
- type: "LiveMap",
829
- updates: { [key]: { type: "update" } }
830
- });
831
- this._doc.dispatch(item._serialize(this._id, key, this._doc), oldValue ? oldValue._serialize(this._id, key) : [{ type: OpType.DeleteCrdt, id }], storageUpdates);
832
- }
833
- }
834
- get size() {
835
- return this._map.size;
836
- }
837
- has(key) {
838
- return this._map.has(key);
839
- }
840
- delete(key) {
841
- const item = this._map.get(key);
842
- if (item == null) {
843
- return false;
844
- }
845
- item._detach();
846
- this._map.delete(key);
847
- if (this._doc && item._id) {
848
- const storageUpdates = /* @__PURE__ */ new Map();
849
- storageUpdates.set(this._id, {
850
- node: this,
851
- type: "LiveMap",
852
- updates: { [key]: { type: "delete" } }
853
- });
854
- this._doc.dispatch([
855
- {
856
- type: OpType.DeleteCrdt,
857
- id: item._id,
858
- opId: this._doc.generateOpId()
859
- }
860
- ], item._serialize(this._id, key), storageUpdates);
861
- }
862
- return true;
863
- }
864
- entries() {
865
- const innerIterator = this._map.entries();
866
- return {
867
- [Symbol.iterator]: function() {
868
- return this;
869
- },
870
- next() {
871
- const iteratorValue = innerIterator.next();
872
- if (iteratorValue.done) {
873
- return {
874
- done: true,
875
- value: void 0
876
- };
877
- }
878
- const entry = iteratorValue.value;
879
- return {
880
- value: [entry[0], selfOrRegisterValue(iteratorValue.value[1])]
881
- };
882
- }
883
- };
884
- }
885
- [Symbol.iterator]() {
886
- return this.entries();
887
- }
888
- keys() {
889
- return this._map.keys();
890
- }
891
- values() {
892
- const innerIterator = this._map.values();
893
- return {
894
- [Symbol.iterator]: function() {
895
- return this;
896
- },
897
- next() {
898
- const iteratorValue = innerIterator.next();
899
- if (iteratorValue.done) {
900
- return {
901
- done: true,
902
- value: void 0
903
- };
904
- }
905
- return {
906
- value: selfOrRegisterValue(iteratorValue.value)
907
- };
908
- }
909
- };
910
- }
911
- forEach(callback) {
912
- for (const entry of this) {
913
- callback(entry[1], entry[0], this);
914
- }
915
- }
916
- }
917
-
918
- function parseJson(rawMessage) {
919
- try {
920
- return JSON.parse(rawMessage);
921
- } catch (e) {
922
- return void 0;
923
- }
924
- }
925
- function isJsonArray(data) {
926
- return Array.isArray(data);
927
- }
928
- function isJsonObject(data) {
929
- return data !== null && typeof data === "object" && !isJsonArray(data);
930
- }
931
-
932
- var __defProp$2 = Object.defineProperty;
933
- var __defProps$2 = Object.defineProperties;
934
- var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors;
935
- var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
936
- var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
937
- var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
938
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
939
- var __spreadValues$2 = (a, b) => {
940
- for (var prop in b || (b = {}))
941
- if (__hasOwnProp$2.call(b, prop))
942
- __defNormalProp$2(a, prop, b[prop]);
943
- if (__getOwnPropSymbols$2)
944
- for (var prop of __getOwnPropSymbols$2(b)) {
945
- if (__propIsEnum$2.call(b, prop))
946
- __defNormalProp$2(a, prop, b[prop]);
947
- }
948
- return a;
949
- };
950
- var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
951
- function remove(array, item) {
952
- for (let i = 0; i < array.length; i++) {
953
- if (array[i] === item) {
954
- array.splice(i, 1);
955
- break;
956
- }
957
- }
958
- }
959
- function compact(items) {
960
- return items.filter((item) => item != null);
961
- }
962
- function creationOpToLiveStructure(op) {
963
- switch (op.type) {
964
- case OpType.CreateRegister:
965
- return new LiveRegister(op.data);
966
- case OpType.CreateObject:
967
- return new LiveObject(op.data);
968
- case OpType.CreateMap:
969
- return new LiveMap();
970
- case OpType.CreateList:
971
- return new LiveList();
972
- }
973
- }
974
- function isSameNodeOrChildOf(node, parent) {
975
- if (node === parent) {
976
- return true;
977
- }
978
- if (node._parent) {
979
- return isSameNodeOrChildOf(node._parent, parent);
980
- }
981
- return false;
982
- }
983
- function deserialize(entry, parentToChildren, doc) {
984
- switch (entry[1].type) {
985
- case CrdtType.Object: {
986
- return LiveObject._deserialize(entry, parentToChildren, doc);
987
- }
988
- case CrdtType.List: {
989
- return LiveList._deserialize(entry, parentToChildren, doc);
990
- }
991
- case CrdtType.Map: {
992
- return LiveMap._deserialize(entry, parentToChildren, doc);
993
- }
994
- case CrdtType.Register: {
995
- return LiveRegister._deserialize(entry, parentToChildren, doc);
996
- }
997
- default: {
998
- throw new Error("Unexpected CRDT type");
999
- }
1000
- }
1001
- }
1002
- function isCrdt(obj) {
1003
- return obj instanceof LiveObject || obj instanceof LiveMap || obj instanceof LiveList || obj instanceof LiveRegister;
1004
- }
1005
- function selfOrRegisterValue(obj) {
1006
- if (obj instanceof LiveRegister) {
1007
- return obj.data;
1008
- }
1009
- return obj;
1010
- }
1011
- function selfOrRegister(obj) {
1012
- if (obj instanceof LiveObject || obj instanceof LiveMap || obj instanceof LiveList) {
1013
- return obj;
1014
- } else if (obj instanceof LiveRegister) {
1015
- throw new Error("Internal error. LiveRegister should not be created from selfOrRegister");
1016
- } else {
1017
- return new LiveRegister(obj);
1018
- }
1019
- }
1020
- function getTreesDiffOperations(currentItems, newItems) {
1021
- const ops = [];
1022
- currentItems.forEach((_, id) => {
1023
- if (!newItems.get(id)) {
1024
- ops.push({
1025
- type: OpType.DeleteCrdt,
1026
- id
1027
- });
1028
- }
1029
- });
1030
- newItems.forEach((crdt, id) => {
1031
- const currentCrdt = currentItems.get(id);
1032
- if (currentCrdt) {
1033
- if (crdt.type === CrdtType.Object) {
1034
- if (JSON.stringify(crdt.data) !== JSON.stringify(currentCrdt.data)) {
1035
- ops.push({
1036
- type: OpType.UpdateObject,
1037
- id,
1038
- data: crdt.data
1039
- });
1040
- }
1041
- }
1042
- if (crdt.parentKey !== currentCrdt.parentKey) {
1043
- ops.push({
1044
- type: OpType.SetParentKey,
1045
- id,
1046
- parentKey: crdt.parentKey
1047
- });
1048
- }
1049
- } else {
1050
- switch (crdt.type) {
1051
- case CrdtType.Register:
1052
- ops.push({
1053
- type: OpType.CreateRegister,
1054
- id,
1055
- parentId: crdt.parentId,
1056
- parentKey: crdt.parentKey,
1057
- data: crdt.data
1058
- });
1059
- break;
1060
- case CrdtType.List:
1061
- ops.push({
1062
- type: OpType.CreateList,
1063
- id,
1064
- parentId: crdt.parentId,
1065
- parentKey: crdt.parentKey
1066
- });
1067
- break;
1068
- case CrdtType.Object:
1069
- ops.push({
1070
- type: OpType.CreateObject,
1071
- id,
1072
- parentId: crdt.parentId,
1073
- parentKey: crdt.parentKey,
1074
- data: crdt.data
1075
- });
1076
- break;
1077
- case CrdtType.Map:
1078
- ops.push({
1079
- type: OpType.CreateMap,
1080
- id,
1081
- parentId: crdt.parentId,
1082
- parentKey: crdt.parentKey
1083
- });
1084
- break;
1085
- }
1086
- }
1087
- });
1088
- return ops;
1089
- }
1090
- function mergeObjectStorageUpdates(first, second) {
1091
- const updates = first.updates;
1092
- for (const [key, value] of entries(second.updates)) {
1093
- updates[key] = value;
1094
- }
1095
- return __spreadProps$2(__spreadValues$2({}, second), {
1096
- updates
1097
- });
1098
- }
1099
- function mergeMapStorageUpdates(first, second) {
1100
- const updates = first.updates;
1101
- for (const [key, value] of entries(second.updates)) {
1102
- updates[key] = value;
1103
- }
1104
- return __spreadProps$2(__spreadValues$2({}, second), {
1105
- updates
1106
- });
1107
- }
1108
- function mergeListStorageUpdates(first, second) {
1109
- const updates = first.updates;
1110
- return __spreadProps$2(__spreadValues$2({}, second), {
1111
- updates: updates.concat(second.updates)
1112
- });
1113
- }
1114
- function mergeStorageUpdates(first, second) {
1115
- if (!first) {
1116
- return second;
1117
- }
1118
- if (first.type === "LiveObject" && second.type === "LiveObject") {
1119
- return mergeObjectStorageUpdates(first, second);
1120
- } else if (first.type === "LiveMap" && second.type === "LiveMap") {
1121
- return mergeMapStorageUpdates(first, second);
1122
- } else if (first.type === "LiveList" && second.type === "LiveList") {
1123
- return mergeListStorageUpdates(first, second);
1124
- } else ;
1125
- return second;
1126
- }
1127
- function isPlain(value) {
1128
- const type = typeof value;
1129
- return type === "undefined" || value === null || type === "string" || type === "boolean" || type === "number" || Array.isArray(value) || isPlainObject$1(value);
1130
- }
1131
- function isPlainObject$1(value) {
1132
- if (typeof value !== "object" || value === null)
1133
- return false;
1134
- const proto = Object.getPrototypeOf(value);
1135
- if (proto === null)
1136
- return true;
1137
- let baseProto = proto;
1138
- while (Object.getPrototypeOf(baseProto) !== null) {
1139
- baseProto = Object.getPrototypeOf(baseProto);
1140
- }
1141
- return proto === baseProto;
1142
- }
1143
- function findNonSerializableValue(value, path = "") {
1144
- if (!isPlain) {
1145
- return {
1146
- path: path || "root",
1147
- value
1148
- };
1149
- }
1150
- if (typeof value !== "object" || value === null) {
1151
- return false;
1152
- }
1153
- for (const [key, nestedValue] of Object.entries(value)) {
1154
- const nestedPath = path ? path + "." + key : key;
1155
- if (!isPlain(nestedValue)) {
1156
- return {
1157
- path: nestedPath,
1158
- value: nestedValue
1159
- };
1160
- }
1161
- if (typeof nestedValue === "object") {
1162
- const nonSerializableNestedValue = findNonSerializableValue(nestedValue, nestedPath);
1163
- if (nonSerializableNestedValue) {
1164
- return nonSerializableNestedValue;
1165
- }
1166
- }
1167
- }
1168
- return false;
1169
- }
1170
- function isTokenValid(token) {
1171
- const tokenParts = token.split(".");
1172
- if (tokenParts.length !== 3) {
1173
- return false;
1174
- }
1175
- const data = parseJson(atob(tokenParts[1]));
1176
- if (data === void 0 || !isJsonObject(data) || typeof data.exp !== "number") {
1177
- return false;
1178
- }
1179
- const now = Date.now();
1180
- if (now / 1e3 > data.exp - 300) {
1181
- return false;
1182
- }
1183
- return true;
1184
- }
1185
- function entries(obj) {
1186
- return Object.entries(obj);
1187
- }
1188
-
1189
- class LiveObject extends AbstractCrdt {
1190
- constructor(object = {}) {
1191
- super();
1192
- this._propToLastUpdate = /* @__PURE__ */ new Map();
1193
- for (const key in object) {
1194
- const value = object[key];
1195
- if (value instanceof AbstractCrdt) {
1196
- value._setParentLink(this, key);
1197
- }
1198
- }
1199
- this._map = new Map(Object.entries(object));
1200
- }
1201
- _serialize(parentId, parentKey, doc, intent) {
1202
- if (this._id == null) {
1203
- throw new Error("Cannot serialize item is not attached");
1204
- }
1205
- const ops = [];
1206
- const op = {
1207
- id: this._id,
1208
- opId: doc == null ? void 0 : doc.generateOpId(),
1209
- intent,
1210
- type: OpType.CreateObject,
1211
- parentId,
1212
- parentKey,
1213
- data: {}
1214
- };
1215
- ops.push(op);
1216
- for (const [key, value] of this._map) {
1217
- if (value instanceof AbstractCrdt) {
1218
- ops.push(...value._serialize(this._id, key, doc));
1219
- } else {
1220
- op.data[key] = value;
1221
- }
1222
- }
1223
- return ops;
1224
- }
1225
- static _deserialize([id, item], parentToChildren, doc) {
1226
- if (item.type !== CrdtType.Object) {
1227
- throw new Error(`Tried to deserialize a record but item type is "${item.type}"`);
1228
- }
1229
- const object = new LiveObject(item.data);
1230
- object._attach(id, doc);
1231
- return this._deserializeChildren(object, parentToChildren, doc);
1232
- }
1233
- static _deserializeChildren(object, parentToChildren, doc) {
1234
- const children = parentToChildren.get(object._id);
1235
- if (children == null) {
1236
- return object;
1237
- }
1238
- for (const entry of children) {
1239
- const crdt = entry[1];
1240
- if (crdt.parentKey == null) {
1241
- throw new Error("Tried to deserialize a crdt but it does not have a parentKey and is not the root");
1242
- }
1243
- const child = deserialize(entry, parentToChildren, doc);
1244
- child._setParentLink(object, crdt.parentKey);
1245
- object._map.set(crdt.parentKey, child);
1246
- }
1247
- return object;
1248
- }
1249
- _attach(id, doc) {
1250
- super._attach(id, doc);
1251
- for (const [_key, value] of this._map) {
1252
- if (value instanceof AbstractCrdt) {
1253
- value._attach(doc.generateId(), doc);
1254
- }
1255
- }
1256
- }
1257
- _attachChild(op, isLocal) {
1258
- if (this._doc == null) {
1259
- throw new Error("Can't attach child if doc is not present");
1260
- }
1261
- const { id, parentKey, opId } = op;
1262
- const key = parentKey;
1263
- const child = creationOpToLiveStructure(op);
1264
- if (this._doc.getItem(id) !== void 0) {
1265
- if (this._propToLastUpdate.get(key) === opId) {
1266
- this._propToLastUpdate.delete(key);
1267
- }
1268
- return { modified: false };
1269
- }
1270
- if (isLocal) {
1271
- this._propToLastUpdate.set(key, opId);
1272
- } else if (this._propToLastUpdate.get(key) === void 0) ; else if (this._propToLastUpdate.get(key) === opId) {
1273
- this._propToLastUpdate.delete(key);
1274
- return { modified: false };
1275
- } else {
1276
- return { modified: false };
1277
- }
1278
- const previousValue = this._map.get(key);
1279
- let reverse;
1280
- if (isCrdt(previousValue)) {
1281
- reverse = previousValue._serialize(this._id, key);
1282
- previousValue._detach();
1283
- } else if (previousValue === void 0) {
1284
- reverse = [
1285
- { type: OpType.DeleteObjectKey, id: this._id, key }
1286
- ];
1287
- } else {
1288
- reverse = [
1289
- {
1290
- type: OpType.UpdateObject,
1291
- id: this._id,
1292
- data: { [key]: previousValue }
1293
- }
1294
- ];
1295
- }
1296
- this._map.set(key, child);
1297
- child._setParentLink(this, key);
1298
- child._attach(id, this._doc);
1299
- return {
1300
- reverse,
1301
- modified: {
1302
- node: this,
1303
- type: "LiveObject",
1304
- updates: { [key]: { type: "update" } }
1305
- }
1306
- };
1307
- }
1308
- _detachChild(child) {
1309
- if (child) {
1310
- const reverse = child._serialize(this._id, child._parentKey, this._doc);
1311
- for (const [key, value] of this._map) {
1312
- if (value === child) {
1313
- this._map.delete(key);
1314
- }
1315
- }
1316
- child._detach();
1317
- const storageUpdate = {
1318
- node: this,
1319
- type: "LiveObject",
1320
- updates: {
1321
- [child._parentKey]: { type: "delete" }
1322
- }
1323
- };
1324
- return { modified: storageUpdate, reverse };
1325
- }
1326
- return { modified: false };
1327
- }
1328
- _detachChildren() {
1329
- for (const [key, value] of this._map) {
1330
- this._map.delete(key);
1331
- value._detach();
1332
- }
1333
- }
1334
- _detach() {
1335
- super._detach();
1336
- for (const value of this._map.values()) {
1337
- if (isCrdt(value)) {
1338
- value._detach();
1339
- }
1340
- }
1341
- }
1342
- _apply(op, isLocal) {
1343
- if (op.type === OpType.UpdateObject) {
1344
- return this._applyUpdate(op, isLocal);
1345
- } else if (op.type === OpType.DeleteObjectKey) {
1346
- return this._applyDeleteObjectKey(op);
1347
- }
1348
- return super._apply(op, isLocal);
1349
- }
1350
- _toSerializedCrdt() {
1351
- var _a;
1352
- const data = {};
1353
- for (const [key, value] of this._map) {
1354
- if (value instanceof AbstractCrdt === false) {
1355
- data[key] = value;
1356
- }
1357
- }
1358
- return {
1359
- type: CrdtType.Object,
1360
- parentId: (_a = this._parent) == null ? void 0 : _a._id,
1361
- parentKey: this._parentKey,
1362
- data
1363
- };
1364
- }
1365
- _applyUpdate(op, isLocal) {
1366
- let isModified = false;
1367
- const reverse = [];
1368
- const reverseUpdate = {
1369
- type: OpType.UpdateObject,
1370
- id: this._id,
1371
- data: {}
1372
- };
1373
- reverse.push(reverseUpdate);
1374
- for (const key in op.data) {
1375
- const oldValue = this._map.get(key);
1376
- if (oldValue instanceof AbstractCrdt) {
1377
- reverse.push(...oldValue._serialize(this._id, key));
1378
- oldValue._detach();
1379
- } else if (oldValue !== void 0) {
1380
- reverseUpdate.data[key] = oldValue;
1381
- } else if (oldValue === void 0) {
1382
- reverse.push({ type: OpType.DeleteObjectKey, id: this._id, key });
1383
- }
1384
- }
1385
- const updateDelta = {};
1386
- for (const key in op.data) {
1387
- if (isLocal) {
1388
- this._propToLastUpdate.set(key, op.opId);
1389
- } else if (this._propToLastUpdate.get(key) == null) {
1390
- isModified = true;
1391
- } else if (this._propToLastUpdate.get(key) === op.opId) {
1392
- this._propToLastUpdate.delete(key);
1393
- continue;
1394
- } else {
1395
- continue;
1396
- }
1397
- const oldValue = this._map.get(key);
1398
- if (isCrdt(oldValue)) {
1399
- oldValue._detach();
1400
- }
1401
- isModified = true;
1402
- updateDelta[key] = { type: "update" };
1403
- this._map.set(key, op.data[key]);
1404
- }
1405
- if (Object.keys(reverseUpdate.data).length !== 0) {
1406
- reverse.unshift(reverseUpdate);
1407
- }
1408
- return isModified ? {
1409
- modified: {
1410
- node: this,
1411
- type: "LiveObject",
1412
- updates: updateDelta
1413
- },
1414
- reverse
1415
- } : { modified: false };
1416
- }
1417
- _applyDeleteObjectKey(op) {
1418
- const key = op.key;
1419
- if (this._map.has(key) === false) {
1420
- return { modified: false };
1421
- }
1422
- if (this._propToLastUpdate.get(key) !== void 0) {
1423
- return { modified: false };
1424
- }
1425
- const oldValue = this._map.get(key);
1426
- let reverse = [];
1427
- if (isCrdt(oldValue)) {
1428
- reverse = oldValue._serialize(this._id, op.key);
1429
- oldValue._detach();
1430
- } else if (oldValue !== void 0) {
1431
- reverse = [
1432
- {
1433
- type: OpType.UpdateObject,
1434
- id: this._id,
1435
- data: { [key]: oldValue }
1436
- }
1437
- ];
1438
- }
1439
- this._map.delete(key);
1440
- return {
1441
- modified: {
1442
- node: this,
1443
- type: "LiveObject",
1444
- updates: { [op.key]: { type: "delete" } }
1445
- },
1446
- reverse
1447
- };
1448
- }
1449
- toObject() {
1450
- return Object.fromEntries(this._map);
1451
- }
1452
- set(key, value) {
1453
- this.update({ [key]: value });
1454
- }
1455
- get(key) {
1456
- return this._map.get(key);
1457
- }
1458
- delete(key) {
1459
- const keyAsString = key;
1460
- const oldValue = this._map.get(keyAsString);
1461
- if (oldValue === void 0) {
1462
- return;
1463
- }
1464
- if (this._doc == null || this._id == null) {
1465
- if (oldValue instanceof AbstractCrdt) {
1466
- oldValue._detach();
1467
- }
1468
- this._map.delete(keyAsString);
1469
- return;
1470
- }
1471
- let reverse;
1472
- if (oldValue instanceof AbstractCrdt) {
1473
- oldValue._detach();
1474
- reverse = oldValue._serialize(this._id, keyAsString);
1475
- } else {
1476
- reverse = [
1477
- {
1478
- type: OpType.UpdateObject,
1479
- data: { [keyAsString]: oldValue },
1480
- id: this._id
1481
- }
1482
- ];
1483
- }
1484
- this._map.delete(keyAsString);
1485
- const storageUpdates = /* @__PURE__ */ new Map();
1486
- storageUpdates.set(this._id, {
1487
- node: this,
1488
- type: "LiveObject",
1489
- updates: { [key]: { type: "delete" } }
1490
- });
1491
- this._doc.dispatch([
1492
- {
1493
- type: OpType.DeleteObjectKey,
1494
- key: keyAsString,
1495
- id: this._id,
1496
- opId: this._doc.generateOpId()
1497
- }
1498
- ], reverse, storageUpdates);
1499
- }
1500
- update(overrides) {
1501
- if (this._doc == null || this._id == null) {
1502
- for (const key in overrides) {
1503
- const oldValue = this._map.get(key);
1504
- if (oldValue instanceof AbstractCrdt) {
1505
- oldValue._detach();
1506
- }
1507
- const newValue = overrides[key];
1508
- if (newValue instanceof AbstractCrdt) {
1509
- newValue._setParentLink(this, key);
1510
- }
1511
- this._map.set(key, newValue);
1512
- }
1513
- return;
1514
- }
1515
- const ops = [];
1516
- const reverseOps = [];
1517
- const opId = this._doc.generateOpId();
1518
- const updatedProps = {};
1519
- const reverseUpdateOp = {
1520
- id: this._id,
1521
- type: OpType.UpdateObject,
1522
- data: {}
1523
- };
1524
- const updateDelta = {};
1525
- for (const key in overrides) {
1526
- const oldValue = this._map.get(key);
1527
- if (oldValue instanceof AbstractCrdt) {
1528
- reverseOps.push(...oldValue._serialize(this._id, key));
1529
- oldValue._detach();
1530
- } else if (oldValue === void 0) {
1531
- reverseOps.push({ type: OpType.DeleteObjectKey, id: this._id, key });
1532
- } else {
1533
- reverseUpdateOp.data[key] = oldValue;
1534
- }
1535
- const newValue = overrides[key];
1536
- if (newValue instanceof AbstractCrdt) {
1537
- newValue._setParentLink(this, key);
1538
- newValue._attach(this._doc.generateId(), this._doc);
1539
- const newAttachChildOps = newValue._serialize(this._id, key, this._doc);
1540
- const createCrdtOp = newAttachChildOps.find((op) => op.parentId === this._id);
1541
- if (createCrdtOp) {
1542
- this._propToLastUpdate.set(key, createCrdtOp.opId);
1543
- }
1544
- ops.push(...newAttachChildOps);
1545
- } else {
1546
- updatedProps[key] = newValue;
1547
- this._propToLastUpdate.set(key, opId);
1548
- }
1549
- this._map.set(key, newValue);
1550
- updateDelta[key] = { type: "update" };
1551
- }
1552
- if (Object.keys(reverseUpdateOp.data).length !== 0) {
1553
- reverseOps.unshift(reverseUpdateOp);
1554
- }
1555
- if (Object.keys(updatedProps).length !== 0) {
1556
- ops.unshift({
1557
- opId,
1558
- id: this._id,
1559
- type: OpType.UpdateObject,
1560
- data: updatedProps
1561
- });
1562
- }
1563
- const storageUpdates = /* @__PURE__ */ new Map();
1564
- storageUpdates.set(this._id, {
1565
- node: this,
1566
- type: "LiveObject",
1567
- updates: updateDelta
1568
- });
1569
- this._doc.dispatch(ops, reverseOps, storageUpdates);
1570
- }
1571
- }
1572
-
1573
- var __defProp$1 = Object.defineProperty;
1574
- var __defProps$1 = Object.defineProperties;
1575
- var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
1576
- var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
1577
- var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
1578
- var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
1579
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1580
- var __spreadValues$1 = (a, b) => {
1581
- for (var prop in b || (b = {}))
1582
- if (__hasOwnProp$1.call(b, prop))
1583
- __defNormalProp$1(a, prop, b[prop]);
1584
- if (__getOwnPropSymbols$1)
1585
- for (var prop of __getOwnPropSymbols$1(b)) {
1586
- if (__propIsEnum$1.call(b, prop))
1587
- __defNormalProp$1(a, prop, b[prop]);
1588
- }
1589
- return a;
1590
- };
1591
- var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
1592
- var __objRest = (source, exclude) => {
1593
- var target = {};
1594
- for (var prop in source)
1595
- if (__hasOwnProp$1.call(source, prop) && exclude.indexOf(prop) < 0)
1596
- target[prop] = source[prop];
1597
- if (source != null && __getOwnPropSymbols$1)
1598
- for (var prop of __getOwnPropSymbols$1(source)) {
1599
- if (exclude.indexOf(prop) < 0 && __propIsEnum$1.call(source, prop))
1600
- target[prop] = source[prop];
1601
- }
1602
- return target;
1603
- };
1604
- const BACKOFF_RETRY_DELAYS = [250, 500, 1e3, 2e3, 4e3, 8e3, 1e4];
1605
- const BACKOFF_RETRY_DELAYS_SLOW = [2e3, 3e4, 6e4, 3e5];
1606
- const HEARTBEAT_INTERVAL = 3e4;
1607
- const PONG_TIMEOUT = 2e3;
1608
- function isValidRoomEventType(value) {
1609
- return value === "my-presence" || value === "others" || value === "event" || value === "error" || value === "connection";
1610
- }
1611
- function makeIdFactory(connectionId) {
1612
- let count = 0;
1613
- return () => `${connectionId}:${count++}`;
1614
- }
1615
- function makeOthers(userMap) {
1616
- const users = Object.values(userMap).map((user) => {
1617
- const _a = user, publicKeys = __objRest(_a, ["_hasReceivedInitialPresence"]);
1618
- return publicKeys;
1619
- });
1620
- return {
1621
- get count() {
1622
- return users.length;
1623
- },
1624
- [Symbol.iterator]() {
1625
- return users[Symbol.iterator]();
1626
- },
1627
- map(callback) {
1628
- return users.map(callback);
1629
- },
1630
- toArray() {
1631
- return users;
1632
- }
1633
- };
1634
- }
1635
- function makeStateMachine(state, context, mockedEffects) {
1636
- const effects = mockedEffects || {
1637
- authenticate(auth, createWebSocket) {
1638
- const token = state.token;
1639
- if (token && isTokenValid(token)) {
1640
- const parsedToken = parseToken(token);
1641
- const socket = createWebSocket(token);
1642
- authenticationSuccess(parsedToken, socket);
1643
- } else {
1644
- return auth(context.roomId).then(({ token: token2 }) => {
1645
- if (state.connection.state !== "authenticating") {
1646
- return;
1647
- }
1648
- const parsedToken = parseToken(token2);
1649
- const socket = createWebSocket(token2);
1650
- authenticationSuccess(parsedToken, socket);
1651
- state.token = token2;
1652
- }).catch((er) => authenticationFailure(er));
1653
- }
1654
- },
1655
- send(messageOrMessages) {
1656
- if (state.socket == null) {
1657
- throw new Error("Can't send message if socket is null");
1658
- }
1659
- state.socket.send(JSON.stringify(messageOrMessages));
1660
- },
1661
- delayFlush(delay) {
1662
- return setTimeout(tryFlushing, delay);
1663
- },
1664
- startHeartbeatInterval() {
1665
- return setInterval(heartbeat, HEARTBEAT_INTERVAL);
1666
- },
1667
- schedulePongTimeout() {
1668
- return setTimeout(pongTimeout, PONG_TIMEOUT);
1669
- },
1670
- scheduleReconnect(delay) {
1671
- return setTimeout(connect, delay);
1672
- }
1673
- };
1674
- function genericSubscribe(callback) {
1675
- state.listeners.storage.push(callback);
1676
- return () => remove(state.listeners.storage, callback);
1677
- }
1678
- function crdtSubscribe(crdt, innerCallback, options) {
1679
- const cb = (updates) => {
1680
- const relatedUpdates = [];
1681
- for (const update of updates) {
1682
- if ((options == null ? void 0 : options.isDeep) && isSameNodeOrChildOf(update.node, crdt)) {
1683
- relatedUpdates.push(update);
1684
- } else if (update.node._id === crdt._id) {
1685
- innerCallback(update.node);
1686
- }
1687
- }
1688
- if ((options == null ? void 0 : options.isDeep) && relatedUpdates.length > 0) {
1689
- innerCallback(relatedUpdates);
1690
- }
1691
- };
1692
- return genericSubscribe(cb);
1693
- }
1694
- function createOrUpdateRootFromMessage(message) {
1695
- if (message.items.length === 0) {
1696
- throw new Error("Internal error: cannot load storage without items");
1697
- }
1698
- if (state.root) {
1699
- updateRoot(message.items);
1700
- } else {
1701
- state.root = load(message.items);
1702
- }
1703
- for (const key in state.defaultStorageRoot) {
1704
- if (state.root.get(key) == null) {
1705
- state.root.set(key, state.defaultStorageRoot[key]);
1706
- }
1707
- }
1708
- }
1709
- function buildRootAndParentToChildren(items) {
1710
- const parentToChildren = /* @__PURE__ */ new Map();
1711
- let root = null;
1712
- for (const tuple of items) {
1713
- const parentId = tuple[1].parentId;
1714
- if (parentId == null) {
1715
- root = tuple;
1716
- } else {
1717
- const children = parentToChildren.get(parentId);
1718
- if (children != null) {
1719
- children.push(tuple);
1720
- } else {
1721
- parentToChildren.set(parentId, [tuple]);
1722
- }
1723
- }
1724
- }
1725
- if (root == null) {
1726
- throw new Error("Root can't be null");
1727
- }
1728
- return [root, parentToChildren];
1729
- }
1730
- function updateRoot(items) {
1731
- if (!state.root) {
1732
- return;
1733
- }
1734
- const currentItems = /* @__PURE__ */ new Map();
1735
- state.items.forEach((liveCrdt, id) => {
1736
- currentItems.set(id, liveCrdt._toSerializedCrdt());
1737
- });
1738
- const ops = getTreesDiffOperations(currentItems, new Map(items));
1739
- const result = apply(ops, false);
1740
- notify(result.updates);
1741
- }
1742
- function load(items) {
1743
- const [root, parentToChildren] = buildRootAndParentToChildren(items);
1744
- return LiveObject._deserialize(root, parentToChildren, {
1745
- getItem,
1746
- addItem,
1747
- deleteItem,
1748
- generateId,
1749
- generateOpId,
1750
- dispatch: storageDispatch,
1751
- roomId: context.roomId
1752
- });
1753
- }
1754
- function addItem(id, item) {
1755
- state.items.set(id, item);
1756
- }
1757
- function deleteItem(id) {
1758
- state.items.delete(id);
1759
- }
1760
- function getItem(id) {
1761
- return state.items.get(id);
1762
- }
1763
- function addToUndoStack(historyItem) {
1764
- if (state.undoStack.length >= 50) {
1765
- state.undoStack.shift();
1766
- }
1767
- if (state.isHistoryPaused) {
1768
- state.pausedHistory.unshift(...historyItem);
1769
- } else {
1770
- state.undoStack.push(historyItem);
1771
- }
1772
- }
1773
- function storageDispatch(ops, reverse, storageUpdates) {
1774
- if (state.isBatching) {
1775
- state.batch.ops.push(...ops);
1776
- storageUpdates.forEach((value, key) => {
1777
- state.batch.updates.storageUpdates.set(key, mergeStorageUpdates(state.batch.updates.storageUpdates.get(key), value));
1778
- });
1779
- state.batch.reverseOps.push(...reverse);
1780
- } else {
1781
- addToUndoStack(reverse);
1782
- state.redoStack = [];
1783
- dispatch(ops);
1784
- notify({ storageUpdates });
1785
- }
1786
- }
1787
- function notify({
1788
- storageUpdates = /* @__PURE__ */ new Map(),
1789
- presence = false,
1790
- others: otherEvents = []
1791
- }) {
1792
- if (otherEvents.length > 0) {
1793
- state.others = makeOthers(state.users);
1794
- for (const event of otherEvents) {
1795
- for (const listener of state.listeners.others) {
1796
- listener(state.others, event);
1797
- }
1798
- }
1799
- }
1800
- if (presence) {
1801
- for (const listener of state.listeners["my-presence"]) {
1802
- listener(state.me);
1803
- }
1804
- }
1805
- if (storageUpdates.size > 0) {
1806
- for (const subscriber of state.listeners.storage) {
1807
- subscriber(Array.from(storageUpdates.values()));
1808
- }
1809
- }
1810
- }
1811
- function getConnectionId() {
1812
- if (state.connection.state === "open" || state.connection.state === "connecting") {
1813
- return state.connection.id;
1814
- } else if (state.lastConnectionId !== null) {
1815
- return state.lastConnectionId;
1816
- }
1817
- throw new Error("Internal. Tried to get connection id but connection was never open");
1818
- }
1819
- function generateId() {
1820
- return `${getConnectionId()}:${state.clock++}`;
1821
- }
1822
- function generateOpId() {
1823
- return `${getConnectionId()}:${state.opClock++}`;
1824
- }
1825
- function apply(item, isLocal) {
1826
- var _a;
1827
- const result = {
1828
- reverse: [],
1829
- updates: {
1830
- storageUpdates: /* @__PURE__ */ new Map(),
1831
- presence: false
1832
- }
1833
- };
1834
- const createdNodeIds = /* @__PURE__ */ new Set();
1835
- for (const op of item) {
1836
- if (op.type === "presence") {
1837
- const reverse = {
1838
- type: "presence",
1839
- data: {}
1840
- };
1841
- for (const key in op.data) {
1842
- reverse.data[key] = state.me[key];
1843
- }
1844
- state.me = __spreadValues$1(__spreadValues$1({}, state.me), op.data);
1845
- if (state.buffer.presence == null) {
1846
- state.buffer.presence = op.data;
1847
- } else {
1848
- for (const key in op.data) {
1849
- state.buffer.presence[key] = op.data[key];
1850
- }
1851
- }
1852
- result.reverse.unshift(reverse);
1853
- result.updates.presence = true;
1854
- } else {
1855
- if (isLocal && !op.opId) {
1856
- op.opId = generateOpId();
1857
- }
1858
- const applyOpResult = applyOp(op, isLocal);
1859
- if (applyOpResult.modified) {
1860
- const parentId = (_a = applyOpResult.modified.node._parent) == null ? void 0 : _a._id;
1861
- if (!createdNodeIds.has(parentId)) {
1862
- result.updates.storageUpdates.set(applyOpResult.modified.node._id, mergeStorageUpdates(result.updates.storageUpdates.get(applyOpResult.modified.node._id), applyOpResult.modified));
1863
- result.reverse.unshift(...applyOpResult.reverse);
1864
- }
1865
- if (op.type === OpType.CreateList || op.type === OpType.CreateMap || op.type === OpType.CreateObject) {
1866
- createdNodeIds.add(applyOpResult.modified.node._id);
1867
- }
1868
- }
1869
- }
1870
- }
1871
- return result;
1872
- }
1873
- function applyOp(op, isLocal) {
1874
- if (op.opId) {
1875
- state.offlineOperations.delete(op.opId);
1876
- }
1877
- switch (op.type) {
1878
- case OpType.DeleteObjectKey:
1879
- case OpType.UpdateObject:
1880
- case OpType.DeleteCrdt: {
1881
- const item = state.items.get(op.id);
1882
- if (item == null) {
1883
- return { modified: false };
1884
- }
1885
- return item._apply(op, isLocal);
1886
- }
1887
- case OpType.SetParentKey: {
1888
- const item = state.items.get(op.id);
1889
- if (item == null) {
1890
- return { modified: false };
1891
- }
1892
- if (item._parent instanceof LiveList) {
1893
- const previousKey = item._parentKey;
1894
- if (previousKey === op.parentKey) {
1895
- return { modified: false };
1896
- } else {
1897
- return item._parent._setChildKey(op.parentKey, item, previousKey);
1898
- }
1899
- }
1900
- return { modified: false };
1901
- }
1902
- case OpType.CreateObject:
1903
- case OpType.CreateList:
1904
- case OpType.CreateMap:
1905
- case OpType.CreateRegister: {
1906
- const parent = state.items.get(op.parentId);
1907
- if (parent == null) {
1908
- return { modified: false };
1909
- }
1910
- return parent._attachChild(op, isLocal);
1911
- }
1912
- }
1913
- return { modified: false };
1914
- }
1915
- function subscribe(firstParam, listener, options) {
1916
- if (firstParam instanceof AbstractCrdt) {
1917
- return crdtSubscribe(firstParam, listener, options);
1918
- } else if (typeof firstParam === "function") {
1919
- return genericSubscribe(firstParam);
1920
- } else if (!isValidRoomEventType(firstParam)) {
1921
- throw new Error(`"${firstParam}" is not a valid event name`);
1922
- }
1923
- state.listeners[firstParam].push(listener);
1924
- return () => {
1925
- const callbacks = state.listeners[firstParam];
1926
- remove(callbacks, listener);
1927
- };
1928
- }
1929
- function unsubscribe(event, callback) {
1930
- console.warn(`unsubscribe is depreacted and will be removed in a future version.
1931
- use the callback returned by subscribe instead.
1932
- See v0.13 release notes for more information.
1933
- `);
1934
- if (!isValidRoomEventType(event)) {
1935
- throw new Error(`"${event}" is not a valid event name`);
1936
- }
1937
- const callbacks = state.listeners[event];
1938
- remove(callbacks, callback);
1939
- }
1940
- function getConnectionState() {
1941
- return state.connection.state;
1942
- }
1943
- function getSelf() {
1944
- return state.connection.state === "open" || state.connection.state === "connecting" ? {
1945
- connectionId: state.connection.id,
1946
- id: state.connection.userId,
1947
- info: state.connection.userInfo,
1948
- presence: getPresence()
1949
- } : null;
1950
- }
1951
- function connect() {
1952
- if (state.connection.state !== "closed" && state.connection.state !== "unavailable") {
1953
- return null;
1954
- }
1955
- const auth = prepareAuthEndpoint(context.authentication, context.fetchPolyfill);
1956
- const createWebSocket = prepareCreateWebSocket(context.liveblocksServer, context.WebSocketPolyfill);
1957
- updateConnection({ state: "authenticating" });
1958
- effects.authenticate(auth, createWebSocket);
1959
- }
1960
- function updatePresence(overrides, options) {
1961
- const oldValues = {};
1962
- if (state.buffer.presence == null) {
1963
- state.buffer.presence = {};
1964
- }
1965
- for (const key in overrides) {
1966
- state.buffer.presence[key] = overrides[key];
1967
- oldValues[key] = state.me[key];
1968
- }
1969
- state.me = __spreadValues$1(__spreadValues$1({}, state.me), overrides);
1970
- if (state.isBatching) {
1971
- if (options == null ? void 0 : options.addToHistory) {
1972
- state.batch.reverseOps.push({ type: "presence", data: oldValues });
1973
- }
1974
- state.batch.updates.presence = true;
1975
- } else {
1976
- tryFlushing();
1977
- if (options == null ? void 0 : options.addToHistory) {
1978
- addToUndoStack([{ type: "presence", data: oldValues }]);
1979
- }
1980
- notify({ presence: true });
1981
- }
1982
- }
1983
- function authenticationSuccess(token, socket) {
1984
- socket.addEventListener("message", onMessage);
1985
- socket.addEventListener("open", onOpen);
1986
- socket.addEventListener("close", onClose);
1987
- socket.addEventListener("error", onError);
1988
- updateConnection({
1989
- state: "connecting",
1990
- id: token.actor,
1991
- userInfo: token.info,
1992
- userId: token.id
1993
- });
1994
- state.idFactory = makeIdFactory(token.actor);
1995
- state.socket = socket;
1996
- }
1997
- function authenticationFailure(error) {
1998
- if (process.env.NODE_ENV !== "production") {
1999
- console.error("Call to authentication endpoint failed", error);
2000
- }
2001
- state.token = null;
2002
- updateConnection({ state: "unavailable" });
2003
- state.numberOfRetry++;
2004
- state.timeoutHandles.reconnect = effects.scheduleReconnect(getRetryDelay());
2005
- }
2006
- function onVisibilityChange(visibilityState) {
2007
- if (visibilityState === "visible" && state.connection.state === "open") {
2008
- heartbeat();
2009
- }
2010
- }
2011
- function onUpdatePresenceMessage(message) {
2012
- const user = state.users[message.actor];
2013
- if (message.targetActor === void 0 && user != null && !user._hasReceivedInitialPresence) {
2014
- return void 0;
2015
- }
2016
- if (user == null) {
2017
- state.users[message.actor] = {
2018
- connectionId: message.actor,
2019
- presence: message.data,
2020
- _hasReceivedInitialPresence: true
2021
- };
2022
- } else {
2023
- state.users[message.actor] = {
2024
- id: user.id,
2025
- info: user.info,
2026
- connectionId: message.actor,
2027
- presence: __spreadValues$1(__spreadValues$1({}, user.presence), message.data),
2028
- _hasReceivedInitialPresence: true
2029
- };
2030
- }
2031
- return {
2032
- type: "update",
2033
- updates: message.data,
2034
- user: state.users[message.actor]
2035
- };
2036
- }
2037
- function onUserLeftMessage(message) {
2038
- const userLeftMessage = message;
2039
- const user = state.users[userLeftMessage.actor];
2040
- if (user) {
2041
- delete state.users[userLeftMessage.actor];
2042
- return { type: "leave", user };
2043
- }
2044
- return null;
2045
- }
2046
- function onRoomStateMessage(message) {
2047
- const newUsers = {};
2048
- for (const key in message.users) {
2049
- const connectionId = Number.parseInt(key);
2050
- const user = message.users[key];
2051
- newUsers[connectionId] = {
2052
- connectionId,
2053
- info: user.info,
2054
- id: user.id
2055
- };
2056
- }
2057
- state.users = newUsers;
2058
- return { type: "reset" };
2059
- }
2060
- function onNavigatorOnline() {
2061
- if (state.connection.state === "unavailable") {
2062
- reconnect();
2063
- }
2064
- }
2065
- function onEvent(message) {
2066
- for (const listener of state.listeners.event) {
2067
- listener({ connectionId: message.actor, event: message.event });
2068
- }
2069
- }
2070
- function onUserJoinedMessage(message) {
2071
- state.users[message.actor] = {
2072
- connectionId: message.actor,
2073
- info: message.info,
2074
- id: message.id,
2075
- _hasReceivedInitialPresence: true
2076
- };
2077
- if (state.me) {
2078
- state.buffer.messages.push({
2079
- type: ClientMessageType.UpdatePresence,
2080
- data: state.me,
2081
- targetActor: message.actor
2082
- });
2083
- tryFlushing();
2084
- }
2085
- return { type: "enter", user: state.users[message.actor] };
2086
- }
2087
- function parseServerMessage(data) {
2088
- if (!isJsonObject(data)) {
2089
- return null;
2090
- }
2091
- return data;
2092
- }
2093
- function parseServerMessages(text) {
2094
- const data = parseJson(text);
2095
- if (data === void 0) {
2096
- return null;
2097
- } else if (isJsonArray(data)) {
2098
- return compact(data.map((item) => parseServerMessage(item)));
2099
- } else {
2100
- return compact([parseServerMessage(data)]);
2101
- }
2102
- }
2103
- function onMessage(event) {
2104
- if (event.data === "pong") {
2105
- clearTimeout(state.timeoutHandles.pongTimeout);
2106
- return;
2107
- }
2108
- const messages = parseServerMessages(event.data);
2109
- if (messages === null || messages.length === 0) {
2110
- return;
2111
- }
2112
- const updates = {
2113
- storageUpdates: /* @__PURE__ */ new Map(),
2114
- others: []
2115
- };
2116
- for (const message of messages) {
2117
- switch (message.type) {
2118
- case ServerMessageType.UserJoined: {
2119
- updates.others.push(onUserJoinedMessage(message));
2120
- break;
2121
- }
2122
- case ServerMessageType.UpdatePresence: {
2123
- const othersPresenceUpdate = onUpdatePresenceMessage(message);
2124
- if (othersPresenceUpdate) {
2125
- updates.others.push(othersPresenceUpdate);
2126
- }
2127
- break;
2128
- }
2129
- case ServerMessageType.Event: {
2130
- onEvent(message);
2131
- break;
2132
- }
2133
- case ServerMessageType.UserLeft: {
2134
- const event2 = onUserLeftMessage(message);
2135
- if (event2) {
2136
- updates.others.push(event2);
2137
- }
2138
- break;
2139
- }
2140
- case ServerMessageType.RoomState: {
2141
- updates.others.push(onRoomStateMessage(message));
2142
- break;
2143
- }
2144
- case ServerMessageType.InitialStorageState: {
2145
- const offlineOps = new Map(state.offlineOperations);
2146
- createOrUpdateRootFromMessage(message);
2147
- applyAndSendOfflineOps(offlineOps);
2148
- _getInitialStateResolver == null ? void 0 : _getInitialStateResolver();
2149
- break;
2150
- }
2151
- case ServerMessageType.UpdateStorage: {
2152
- const applyResult = apply(message.ops, false);
2153
- applyResult.updates.storageUpdates.forEach((value, key) => {
2154
- updates.storageUpdates.set(key, mergeStorageUpdates(updates.storageUpdates.get(key), value));
2155
- });
2156
- break;
2157
- }
2158
- }
2159
- }
2160
- notify(updates);
2161
- }
2162
- function onClose(event) {
2163
- state.socket = null;
2164
- clearTimeout(state.timeoutHandles.pongTimeout);
2165
- clearInterval(state.intervalHandles.heartbeat);
2166
- if (state.timeoutHandles.flush) {
2167
- clearTimeout(state.timeoutHandles.flush);
2168
- }
2169
- clearTimeout(state.timeoutHandles.reconnect);
2170
- state.users = {};
2171
- notify({ others: [{ type: "reset" }] });
2172
- if (event.code >= 4e3 && event.code <= 4100) {
2173
- updateConnection({ state: "failed" });
2174
- const error = new LiveblocksError(event.reason, event.code);
2175
- for (const listener of state.listeners.error) {
2176
- listener(error);
2177
- }
2178
- const delay = getRetryDelay(true);
2179
- state.numberOfRetry++;
2180
- if (process.env.NODE_ENV !== "production") {
2181
- console.error(`Connection to Liveblocks websocket server closed. Reason: ${error.message} (code: ${error.code}). Retrying in ${delay}ms.`);
2182
- }
2183
- updateConnection({ state: "unavailable" });
2184
- state.timeoutHandles.reconnect = effects.scheduleReconnect(delay);
2185
- } else if (event.code === WebsocketCloseCodes.CLOSE_WITHOUT_RETRY) {
2186
- updateConnection({ state: "closed" });
2187
- } else {
2188
- const delay = getRetryDelay();
2189
- state.numberOfRetry++;
2190
- if (process.env.NODE_ENV !== "production") {
2191
- console.warn(`Connection to Liveblocks websocket server closed (code: ${event.code}). Retrying in ${delay}ms.`);
2192
- }
2193
- updateConnection({ state: "unavailable" });
2194
- state.timeoutHandles.reconnect = effects.scheduleReconnect(delay);
2195
- }
2196
- }
2197
- function updateConnection(connection) {
2198
- state.connection = connection;
2199
- for (const listener of state.listeners.connection) {
2200
- listener(connection.state);
2201
- }
2202
- }
2203
- function getRetryDelay(slow = false) {
2204
- if (slow) {
2205
- return BACKOFF_RETRY_DELAYS_SLOW[state.numberOfRetry < BACKOFF_RETRY_DELAYS_SLOW.length ? state.numberOfRetry : BACKOFF_RETRY_DELAYS_SLOW.length - 1];
2206
- }
2207
- return BACKOFF_RETRY_DELAYS[state.numberOfRetry < BACKOFF_RETRY_DELAYS.length ? state.numberOfRetry : BACKOFF_RETRY_DELAYS.length - 1];
2208
- }
2209
- function onError() {
2210
- }
2211
- function onOpen() {
2212
- clearInterval(state.intervalHandles.heartbeat);
2213
- state.intervalHandles.heartbeat = effects.startHeartbeatInterval();
2214
- if (state.connection.state === "connecting") {
2215
- updateConnection(__spreadProps$1(__spreadValues$1({}, state.connection), { state: "open" }));
2216
- state.numberOfRetry = 0;
2217
- if (state.lastConnectionId !== void 0) {
2218
- state.buffer.presence = state.me;
2219
- tryFlushing();
2220
- }
2221
- state.lastConnectionId = state.connection.id;
2222
- if (state.root) {
2223
- state.buffer.messages.push({ type: ClientMessageType.FetchStorage });
2224
- }
2225
- tryFlushing();
2226
- }
2227
- }
2228
- function heartbeat() {
2229
- if (state.socket == null) {
2230
- return;
2231
- }
2232
- clearTimeout(state.timeoutHandles.pongTimeout);
2233
- state.timeoutHandles.pongTimeout = effects.schedulePongTimeout();
2234
- if (state.socket.readyState === state.socket.OPEN) {
2235
- state.socket.send("ping");
2236
- }
2237
- }
2238
- function pongTimeout() {
2239
- reconnect();
2240
- }
2241
- function reconnect() {
2242
- if (state.socket) {
2243
- state.socket.removeEventListener("open", onOpen);
2244
- state.socket.removeEventListener("message", onMessage);
2245
- state.socket.removeEventListener("close", onClose);
2246
- state.socket.removeEventListener("error", onError);
2247
- state.socket.close();
2248
- state.socket = null;
2249
- }
2250
- updateConnection({ state: "unavailable" });
2251
- clearTimeout(state.timeoutHandles.pongTimeout);
2252
- if (state.timeoutHandles.flush) {
2253
- clearTimeout(state.timeoutHandles.flush);
2254
- }
2255
- clearTimeout(state.timeoutHandles.reconnect);
2256
- clearInterval(state.intervalHandles.heartbeat);
2257
- connect();
2258
- }
2259
- function applyAndSendOfflineOps(offlineOps) {
2260
- if (offlineOps.size === 0) {
2261
- return;
2262
- }
2263
- const messages = [];
2264
- const ops = Array.from(offlineOps.values());
2265
- const result = apply(ops, true);
2266
- messages.push({
2267
- type: ClientMessageType.UpdateStorage,
2268
- ops
2269
- });
2270
- notify(result.updates);
2271
- effects.send(messages);
2272
- }
2273
- function tryFlushing() {
2274
- const storageOps = state.buffer.storageOperations;
2275
- if (storageOps.length > 0) {
2276
- storageOps.forEach((op) => {
2277
- state.offlineOperations.set(op.opId, op);
2278
- });
2279
- }
2280
- if (state.socket == null || state.socket.readyState !== state.socket.OPEN) {
2281
- state.buffer.storageOperations = [];
2282
- return;
2283
- }
2284
- const now = Date.now();
2285
- const elapsedTime = now - state.lastFlushTime;
2286
- if (elapsedTime > context.throttleDelay) {
2287
- const messages = flushDataToMessages(state);
2288
- if (messages.length === 0) {
2289
- return;
2290
- }
2291
- effects.send(messages);
2292
- state.buffer = {
2293
- messages: [],
2294
- storageOperations: [],
2295
- presence: null
2296
- };
2297
- state.lastFlushTime = now;
2298
- } else {
2299
- if (state.timeoutHandles.flush != null) {
2300
- clearTimeout(state.timeoutHandles.flush);
2301
- }
2302
- state.timeoutHandles.flush = effects.delayFlush(context.throttleDelay - (now - state.lastFlushTime));
2303
- }
2304
- }
2305
- function flushDataToMessages(state2) {
2306
- const messages = [];
2307
- if (state2.buffer.presence) {
2308
- messages.push({
2309
- type: ClientMessageType.UpdatePresence,
2310
- data: state2.buffer.presence
2311
- });
2312
- }
2313
- for (const event of state2.buffer.messages) {
2314
- messages.push(event);
2315
- }
2316
- if (state2.buffer.storageOperations.length > 0) {
2317
- messages.push({
2318
- type: ClientMessageType.UpdateStorage,
2319
- ops: state2.buffer.storageOperations
2320
- });
2321
- }
2322
- return messages;
2323
- }
2324
- function disconnect() {
2325
- if (state.socket) {
2326
- state.socket.removeEventListener("open", onOpen);
2327
- state.socket.removeEventListener("message", onMessage);
2328
- state.socket.removeEventListener("close", onClose);
2329
- state.socket.removeEventListener("error", onError);
2330
- state.socket.close();
2331
- state.socket = null;
2332
- }
2333
- updateConnection({ state: "closed" });
2334
- if (state.timeoutHandles.flush) {
2335
- clearTimeout(state.timeoutHandles.flush);
2336
- }
2337
- clearTimeout(state.timeoutHandles.reconnect);
2338
- clearTimeout(state.timeoutHandles.pongTimeout);
2339
- clearInterval(state.intervalHandles.heartbeat);
2340
- state.users = {};
2341
- notify({ others: [{ type: "reset" }] });
2342
- clearListeners();
2343
- }
2344
- function clearListeners() {
2345
- for (const key in state.listeners) {
2346
- state.listeners[key] = [];
2347
- }
2348
- }
2349
- function getPresence() {
2350
- return state.me;
2351
- }
2352
- function getOthers() {
2353
- return state.others;
2354
- }
2355
- function broadcastEvent(event, options = {
2356
- shouldQueueEventIfNotReady: false
2357
- }) {
2358
- if (state.socket == null && options.shouldQueueEventIfNotReady == false) {
2359
- return;
2360
- }
2361
- state.buffer.messages.push({
2362
- type: ClientMessageType.ClientEvent,
2363
- event
2364
- });
2365
- tryFlushing();
2366
- }
2367
- function dispatch(ops) {
2368
- state.buffer.storageOperations.push(...ops);
2369
- tryFlushing();
2370
- }
2371
- let _getInitialStatePromise = null;
2372
- let _getInitialStateResolver = null;
2373
- function getStorage() {
2374
- if (state.root) {
2375
- return new Promise((resolve) => resolve({
2376
- root: state.root
2377
- }));
2378
- }
2379
- if (_getInitialStatePromise == null) {
2380
- state.buffer.messages.push({ type: ClientMessageType.FetchStorage });
2381
- tryFlushing();
2382
- _getInitialStatePromise = new Promise((resolve) => _getInitialStateResolver = resolve);
2383
- }
2384
- return _getInitialStatePromise.then(() => {
2385
- return {
2386
- root: state.root
2387
- };
2388
- });
2389
- }
2390
- function undo() {
2391
- if (state.isBatching) {
2392
- throw new Error("undo is not allowed during a batch");
2393
- }
2394
- const historyItem = state.undoStack.pop();
2395
- if (historyItem == null) {
2396
- return;
2397
- }
2398
- state.isHistoryPaused = false;
2399
- const result = apply(historyItem, true);
2400
- notify(result.updates);
2401
- state.redoStack.push(result.reverse);
2402
- for (const op of historyItem) {
2403
- if (op.type !== "presence") {
2404
- state.buffer.storageOperations.push(op);
2405
- }
2406
- }
2407
- tryFlushing();
2408
- }
2409
- function redo() {
2410
- if (state.isBatching) {
2411
- throw new Error("redo is not allowed during a batch");
2412
- }
2413
- const historyItem = state.redoStack.pop();
2414
- if (historyItem == null) {
2415
- return;
2416
- }
2417
- state.isHistoryPaused = false;
2418
- const result = apply(historyItem, true);
2419
- notify(result.updates);
2420
- state.undoStack.push(result.reverse);
2421
- for (const op of historyItem) {
2422
- if (op.type !== "presence") {
2423
- state.buffer.storageOperations.push(op);
2424
- }
2425
- }
2426
- tryFlushing();
2427
- }
2428
- function batch(callback) {
2429
- if (state.isBatching) {
2430
- throw new Error("batch should not be called during a batch");
2431
- }
2432
- state.isBatching = true;
2433
- try {
2434
- callback();
2435
- } finally {
2436
- state.isBatching = false;
2437
- if (state.batch.reverseOps.length > 0) {
2438
- addToUndoStack(state.batch.reverseOps);
2439
- }
2440
- if (state.batch.ops.length > 0) {
2441
- state.redoStack = [];
2442
- }
2443
- if (state.batch.ops.length > 0) {
2444
- dispatch(state.batch.ops);
2445
- }
2446
- notify(state.batch.updates);
2447
- state.batch = {
2448
- ops: [],
2449
- reverseOps: [],
2450
- updates: {
2451
- others: [],
2452
- storageUpdates: /* @__PURE__ */ new Map(),
2453
- presence: false
2454
- }
2455
- };
2456
- tryFlushing();
2457
- }
2458
- }
2459
- function pauseHistory() {
2460
- state.pausedHistory = [];
2461
- state.isHistoryPaused = true;
2462
- }
2463
- function resumeHistory() {
2464
- state.isHistoryPaused = false;
2465
- if (state.pausedHistory.length > 0) {
2466
- addToUndoStack(state.pausedHistory);
2467
- }
2468
- state.pausedHistory = [];
2469
- }
2470
- function simulateSocketClose() {
2471
- if (state.socket) {
2472
- state.socket.close();
2473
- }
2474
- }
2475
- function simulateSendCloseEvent(event) {
2476
- if (state.socket) {
2477
- onClose(event);
2478
- }
2479
- }
2480
- return {
2481
- onClose,
2482
- onMessage,
2483
- authenticationSuccess,
2484
- heartbeat,
2485
- onNavigatorOnline,
2486
- simulateSocketClose,
2487
- simulateSendCloseEvent,
2488
- onVisibilityChange,
2489
- getUndoStack: () => state.undoStack,
2490
- getItemsCount: () => state.items.size,
2491
- connect,
2492
- disconnect,
2493
- subscribe,
2494
- unsubscribe,
2495
- updatePresence,
2496
- broadcastEvent,
2497
- batch,
2498
- undo,
2499
- redo,
2500
- pauseHistory,
2501
- resumeHistory,
2502
- getStorage,
2503
- selectors: {
2504
- getConnectionState,
2505
- getSelf,
2506
- getPresence,
2507
- getOthers
2508
- }
2509
- };
2510
- }
2511
- function defaultState(me, defaultStorageRoot) {
2512
- return {
2513
- connection: { state: "closed" },
2514
- token: null,
2515
- lastConnectionId: null,
2516
- socket: null,
2517
- listeners: {
2518
- event: [],
2519
- others: [],
2520
- "my-presence": [],
2521
- error: [],
2522
- connection: [],
2523
- storage: []
2524
- },
2525
- numberOfRetry: 0,
2526
- lastFlushTime: 0,
2527
- timeoutHandles: {
2528
- flush: null,
2529
- reconnect: 0,
2530
- pongTimeout: 0
2531
- },
2532
- buffer: {
2533
- presence: me == null ? {} : me,
2534
- messages: [],
2535
- storageOperations: []
2536
- },
2537
- intervalHandles: {
2538
- heartbeat: 0
2539
- },
2540
- me: me == null ? {} : me,
2541
- users: {},
2542
- others: makeOthers({}),
2543
- defaultStorageRoot,
2544
- idFactory: null,
2545
- clock: 0,
2546
- opClock: 0,
2547
- items: /* @__PURE__ */ new Map(),
2548
- root: void 0,
2549
- undoStack: [],
2550
- redoStack: [],
2551
- isHistoryPaused: false,
2552
- pausedHistory: [],
2553
- isBatching: false,
2554
- batch: {
2555
- ops: [],
2556
- updates: {
2557
- storageUpdates: /* @__PURE__ */ new Map(),
2558
- presence: false,
2559
- others: []
2560
- },
2561
- reverseOps: []
2562
- },
2563
- offlineOperations: /* @__PURE__ */ new Map()
2564
- };
2565
- }
2566
- function createRoom(options, context) {
2567
- const state = defaultState(options.defaultPresence, options.defaultStorageRoot);
2568
- const machine = makeStateMachine(state, context);
2569
- const room = {
2570
- id: context.roomId,
2571
- getConnectionState: machine.selectors.getConnectionState,
2572
- getSelf: machine.selectors.getSelf,
2573
- subscribe: machine.subscribe,
2574
- unsubscribe: machine.unsubscribe,
2575
- getPresence: machine.selectors.getPresence,
2576
- updatePresence: machine.updatePresence,
2577
- getOthers: machine.selectors.getOthers,
2578
- broadcastEvent: machine.broadcastEvent,
2579
- getStorage: machine.getStorage,
2580
- batch: machine.batch,
2581
- history: {
2582
- undo: machine.undo,
2583
- redo: machine.redo,
2584
- pause: machine.pauseHistory,
2585
- resume: machine.resumeHistory
2586
- },
2587
- internalDevTools: {
2588
- closeWebsocket: machine.simulateSocketClose,
2589
- sendCloseEvent: machine.simulateSendCloseEvent
2590
- }
2591
- };
2592
- return {
2593
- connect: machine.connect,
2594
- disconnect: machine.disconnect,
2595
- onNavigatorOnline: machine.onNavigatorOnline,
2596
- onVisibilityChange: machine.onVisibilityChange,
2597
- room
2598
- };
2599
- }
2600
- class LiveblocksError extends Error {
2601
- constructor(message, code) {
2602
- super(message);
2603
- this.code = code;
2604
- }
2605
- }
2606
- function parseToken(token) {
2607
- const tokenParts = token.split(".");
2608
- if (tokenParts.length !== 3) {
2609
- throw new Error(`Authentication error. Liveblocks could not parse the response of your authentication endpoint`);
2610
- }
2611
- const data = parseJson(atob(tokenParts[1]));
2612
- if (data !== void 0 && isJsonObject(data) && typeof data.actor === "number" && (data.id === void 0 || typeof data.id === "string")) {
2613
- return {
2614
- actor: data.actor,
2615
- id: data.id,
2616
- info: data.info
2617
- };
2618
- }
2619
- throw new Error(`Authentication error. Liveblocks could not parse the response of your authentication endpoint`);
2620
- }
2621
- function prepareCreateWebSocket(liveblocksServer, WebSocketPolyfill) {
2622
- if (typeof window === "undefined" && WebSocketPolyfill == null) {
2623
- throw new Error("To use Liveblocks client in a non-dom environment, you need to provide a WebSocket polyfill.");
2624
- }
2625
- const ws = WebSocketPolyfill || WebSocket;
2626
- return (token) => {
2627
- return new ws(`${liveblocksServer}/?token=${token}`);
2628
- };
2629
- }
2630
- function prepareAuthEndpoint(authentication, fetchPolyfill) {
2631
- if (authentication.type === "public") {
2632
- if (typeof window === "undefined" && fetchPolyfill == null) {
2633
- throw new Error("To use Liveblocks client in a non-dom environment with a publicApiKey, you need to provide a fetch polyfill.");
2634
- }
2635
- return (room) => fetchAuthEndpoint(fetchPolyfill || fetch, authentication.url, {
2636
- room,
2637
- publicApiKey: authentication.publicApiKey
2638
- });
2639
- }
2640
- if (authentication.type === "private") {
2641
- if (typeof window === "undefined" && fetchPolyfill == null) {
2642
- throw new Error("To use Liveblocks client in a non-dom environment with a url as auth endpoint, you need to provide a fetch polyfill.");
2643
- }
2644
- return (room) => fetchAuthEndpoint(fetchPolyfill || fetch, authentication.url, {
2645
- room
2646
- });
2647
- }
2648
- if (authentication.type === "custom") {
2649
- return authentication.callback;
2650
- }
2651
- throw new Error("Internal error. Unexpected authentication type");
2652
- }
2653
- function fetchAuthEndpoint(fetch2, endpoint, body) {
2654
- return fetch2(endpoint, {
2655
- method: "POST",
2656
- headers: {
2657
- "Content-Type": "application/json"
2658
- },
2659
- body: JSON.stringify(body)
2660
- }).then((res) => {
2661
- if (!res.ok) {
2662
- throw new AuthenticationError(`Expected a status 200 but got ${res.status} when doing a POST request on "${endpoint}"`);
2663
- }
2664
- return res.json().catch((er) => {
2665
- throw new AuthenticationError(`Expected a json when doing a POST request on "${endpoint}". ${er}`);
2666
- });
2667
- }).then((authResponse) => {
2668
- if (typeof authResponse.token !== "string") {
2669
- throw new AuthenticationError(`Expected a json with a string token when doing a POST request on "${endpoint}", but got ${JSON.stringify(authResponse)}`);
2670
- }
2671
- return authResponse;
2672
- });
2673
- }
2674
- class AuthenticationError extends Error {
2675
- constructor(message) {
2676
- super(message);
2677
- }
2678
- }
2679
-
2680
- function createClient(options) {
2681
- const clientOptions = options;
2682
- const throttleDelay = getThrottleDelayFromOptions(options);
2683
- const rooms = /* @__PURE__ */ new Map();
2684
- function getRoom(roomId) {
2685
- const internalRoom = rooms.get(roomId);
2686
- return internalRoom ? internalRoom.room : null;
2687
- }
2688
- function enter(roomId, options2 = {}) {
2689
- let internalRoom = rooms.get(roomId);
2690
- if (internalRoom) {
2691
- return internalRoom.room;
2692
- }
2693
- internalRoom = createRoom({
2694
- defaultPresence: options2.defaultPresence,
2695
- defaultStorageRoot: options2.defaultStorageRoot
2696
- }, {
2697
- roomId,
2698
- throttleDelay,
2699
- WebSocketPolyfill: clientOptions.WebSocketPolyfill,
2700
- fetchPolyfill: clientOptions.fetchPolyfill,
2701
- liveblocksServer: clientOptions.liveblocksServer || "wss://liveblocks.net/v5",
2702
- authentication: prepareAuthentication(clientOptions)
2703
- });
2704
- rooms.set(roomId, internalRoom);
2705
- if (!options2.DO_NOT_USE_withoutConnecting) {
2706
- internalRoom.connect();
2707
- }
2708
- return internalRoom.room;
2709
- }
2710
- function leave(roomId) {
2711
- const room = rooms.get(roomId);
2712
- if (room) {
2713
- room.disconnect();
2714
- rooms.delete(roomId);
2715
- }
2716
- }
2717
- if (typeof window !== "undefined") {
2718
- window.addEventListener("online", () => {
2719
- for (const [, room] of rooms) {
2720
- room.onNavigatorOnline();
2721
- }
2722
- });
2723
- }
2724
- if (typeof document !== "undefined") {
2725
- document.addEventListener("visibilitychange", () => {
2726
- for (const [, room] of rooms) {
2727
- room.onVisibilityChange(document.visibilityState);
2728
- }
2729
- });
2730
- }
2731
- return {
2732
- getRoom,
2733
- enter,
2734
- leave
2735
- };
2736
- }
2737
- function getThrottleDelayFromOptions(options) {
2738
- if (options.throttle === void 0) {
2739
- return 100;
2740
- }
2741
- if (typeof options.throttle !== "number" || options.throttle < 80 || options.throttle > 1e3) {
2742
- throw new Error("throttle should be a number between 80 and 1000.");
2743
- }
2744
- return options.throttle;
2745
- }
2746
- function prepareAuthentication(clientOptions) {
2747
- if (typeof clientOptions.publicApiKey === "string") {
2748
- return {
2749
- type: "public",
2750
- publicApiKey: clientOptions.publicApiKey,
2751
- url: clientOptions.publicAuthorizeEndpoint || "https://liveblocks.io/api/public/authorize"
2752
- };
2753
- } else if (typeof clientOptions.authEndpoint === "string") {
2754
- return {
2755
- type: "private",
2756
- url: clientOptions.authEndpoint
2757
- };
2758
- } else if (typeof clientOptions.authEndpoint === "function") {
2759
- return {
2760
- type: "custom",
2761
- callback: clientOptions.authEndpoint
2762
- };
2763
- }
2764
- throw new Error("Invalid Liveblocks client options. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient");
2765
- }
2766
-
2767
- var __defProp = Object.defineProperty;
2768
- var __defProps = Object.defineProperties;
2769
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
2770
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
2771
- var __hasOwnProp = Object.prototype.hasOwnProperty;
2772
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
2773
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2774
- var __spreadValues = (a, b) => {
2775
- for (var prop in b || (b = {}))
2776
- if (__hasOwnProp.call(b, prop))
2777
- __defNormalProp(a, prop, b[prop]);
2778
- if (__getOwnPropSymbols)
2779
- for (var prop of __getOwnPropSymbols(b)) {
2780
- if (__propIsEnum.call(b, prop))
2781
- __defNormalProp(a, prop, b[prop]);
2782
- }
2783
- return a;
2784
- };
2785
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
2786
- function lsonObjectToJson(obj) {
2787
- const result = {};
2788
- for (const key in obj) {
2789
- const val = obj[key];
2790
- if (val !== void 0) {
2791
- result[key] = lsonToJson(val);
2792
- }
2793
- }
2794
- return result;
2795
- }
2796
- function liveObjectToJson(liveObject) {
2797
- return lsonObjectToJson(liveObject.toObject());
2798
- }
2799
- function liveMapToJson(map) {
2800
- const result = {};
2801
- for (const [key, value] of map.entries()) {
2802
- result[key] = lsonToJson(value);
2803
- }
2804
- return result;
2805
- }
2806
- function lsonListToJson(value) {
2807
- return value.map(lsonToJson);
2808
- }
2809
- function liveListToJson(value) {
2810
- return lsonListToJson(value.toArray());
2811
- }
2812
- function lsonToJson(value) {
2813
- if (value instanceof LiveObject) {
2814
- return liveObjectToJson(value);
2815
- } else if (value instanceof LiveList) {
2816
- return liveListToJson(value);
2817
- } else if (value instanceof LiveMap) {
2818
- return liveMapToJson(value);
2819
- } else if (value instanceof LiveRegister) {
2820
- return value.data;
2821
- } else if (value instanceof AbstractCrdt) {
2822
- throw new Error("Unhandled subclass of AbstractCrdt encountered");
2823
- }
2824
- if (Array.isArray(value)) {
2825
- return lsonListToJson(value);
2826
- } else if (isPlainObject(value)) {
2827
- return lsonObjectToJson(value);
2828
- }
2829
- return value;
2830
- }
2831
- function isPlainObject(obj) {
2832
- return obj !== null && Object.prototype.toString.call(obj) === "[object Object]";
2833
- }
2834
- function anyToCrdt(obj) {
2835
- if (obj == null) {
2836
- return obj;
2837
- }
2838
- if (Array.isArray(obj)) {
2839
- return new LiveList(obj.map(anyToCrdt));
2840
- }
2841
- if (isPlainObject(obj)) {
2842
- const init = {};
2843
- for (const key in obj) {
2844
- init[key] = anyToCrdt(obj[key]);
2845
- }
2846
- return new LiveObject(init);
2847
- }
2848
- return obj;
2849
- }
2850
- function patchLiveList(liveList, prev, next) {
2851
- let i = 0;
2852
- let prevEnd = prev.length - 1;
2853
- let nextEnd = next.length - 1;
2854
- let prevNode = prev[0];
2855
- let nextNode = next[0];
2856
- outer: {
2857
- while (prevNode === nextNode) {
2858
- ++i;
2859
- if (i > prevEnd || i > nextEnd) {
2860
- break outer;
2861
- }
2862
- prevNode = prev[i];
2863
- nextNode = next[i];
2864
- }
2865
- prevNode = prev[prevEnd];
2866
- nextNode = next[nextEnd];
2867
- while (prevNode === nextNode) {
2868
- prevEnd--;
2869
- nextEnd--;
2870
- if (i > prevEnd || i > nextEnd) {
2871
- break outer;
2872
- }
2873
- prevNode = prev[prevEnd];
2874
- nextNode = next[nextEnd];
2875
- }
2876
- }
2877
- if (i > prevEnd) {
2878
- if (i <= nextEnd) {
2879
- while (i <= nextEnd) {
2880
- liveList.insert(anyToCrdt(next[i]), i);
2881
- i++;
2882
- }
2883
- }
2884
- } else if (i > nextEnd) {
2885
- let localI = i;
2886
- while (localI <= prevEnd) {
2887
- liveList.delete(i);
2888
- localI++;
2889
- }
2890
- } else {
2891
- while (i <= prevEnd && i <= nextEnd) {
2892
- prevNode = prev[i];
2893
- nextNode = next[i];
2894
- const liveListNode = liveList.get(i);
2895
- if (liveListNode instanceof LiveObject && isPlainObject(prevNode) && isPlainObject(nextNode)) {
2896
- patchLiveObject(liveListNode, prevNode, nextNode);
2897
- } else {
2898
- liveList.set(i, anyToCrdt(nextNode));
2899
- }
2900
- i++;
2901
- }
2902
- while (i <= nextEnd) {
2903
- liveList.insert(anyToCrdt(next[i]), i);
2904
- i++;
2905
- }
2906
- let localI = i;
2907
- while (localI <= prevEnd) {
2908
- liveList.delete(i);
2909
- localI++;
2910
- }
2911
- }
2912
- }
2913
- function patchLiveObjectKey(liveObject, key, prev, next) {
2914
- if (process.env.NODE_ENV !== "production") {
2915
- const nonSerializableValue = findNonSerializableValue(next);
2916
- if (nonSerializableValue) {
2917
- console.error(`New state path: '${nonSerializableValue.path}' value: '${nonSerializableValue.value}' is not serializable.
2918
- Only serializable value can be synced with Liveblocks.`);
2919
- return;
2920
- }
2921
- }
2922
- const value = liveObject.get(key);
2923
- if (next === void 0) {
2924
- liveObject.delete(key);
2925
- } else if (value === void 0) {
2926
- liveObject.set(key, anyToCrdt(next));
2927
- } else if (prev === next) {
2928
- return;
2929
- } else if (value instanceof LiveList && Array.isArray(prev) && Array.isArray(next)) {
2930
- patchLiveList(value, prev, next);
2931
- } else if (value instanceof LiveObject && isPlainObject(prev) && isPlainObject(next)) {
2932
- patchLiveObject(value, prev, next);
2933
- } else {
2934
- liveObject.set(key, anyToCrdt(next));
2935
- }
2936
- }
2937
- function patchLiveObject(root, prev, next) {
2938
- const updates = {};
2939
- for (const key in next) {
2940
- patchLiveObjectKey(root, key, prev[key], next[key]);
2941
- }
2942
- for (const key in prev) {
2943
- if (next[key] === void 0) {
2944
- root.delete(key);
2945
- }
2946
- }
2947
- if (Object.keys(updates).length > 0) {
2948
- root.update(updates);
2949
- }
2950
- }
2951
- function getParentsPath(node) {
2952
- const path = [];
2953
- while (node._parentKey != null && node._parent != null) {
2954
- if (node._parent instanceof LiveList) {
2955
- path.push(node._parent._indexOfPosition(node._parentKey));
2956
- } else {
2957
- path.push(node._parentKey);
2958
- }
2959
- node = node._parent;
2960
- }
2961
- return path;
2962
- }
2963
- function patchImmutableObject(state, updates) {
2964
- return updates.reduce((state2, update) => patchImmutableObjectWithUpdate(state2, update), state);
2965
- }
2966
- function patchImmutableObjectWithUpdate(state, update) {
2967
- const path = getParentsPath(update.node);
2968
- return patchImmutableNode(state, path, update);
2969
- }
2970
- function patchImmutableNode(state, path, update) {
2971
- var _a, _b, _c, _d;
2972
- const pathItem = path.pop();
2973
- if (pathItem === void 0) {
2974
- switch (update.type) {
2975
- case "LiveObject": {
2976
- if (typeof state !== "object") {
2977
- throw new Error("Internal: received update on LiveObject but state was not an object");
2978
- }
2979
- const newState = Object.assign({}, state);
2980
- for (const key in update.updates) {
2981
- if (((_a = update.updates[key]) == null ? void 0 : _a.type) === "update") {
2982
- const val = update.node.get(key);
2983
- if (val !== void 0) {
2984
- newState[key] = lsonToJson(val);
2985
- }
2986
- } else if (((_b = update.updates[key]) == null ? void 0 : _b.type) === "delete") {
2987
- delete newState[key];
2988
- }
2989
- }
2990
- return newState;
2991
- }
2992
- case "LiveList": {
2993
- if (Array.isArray(state) === false) {
2994
- throw new Error("Internal: received update on LiveList but state was not an array");
2995
- }
2996
- let newState = state.map((x) => x);
2997
- for (const listUpdate of update.updates) {
2998
- if (listUpdate.type === "set") {
2999
- newState = newState.map((item, index) => index === listUpdate.index ? listUpdate.item : item);
3000
- } else if (listUpdate.type === "insert") {
3001
- if (listUpdate.index === newState.length) {
3002
- newState.push(lsonToJson(listUpdate.item));
3003
- } else {
3004
- newState = [
3005
- ...newState.slice(0, listUpdate.index),
3006
- lsonToJson(listUpdate.item),
3007
- ...newState.slice(listUpdate.index)
3008
- ];
3009
- }
3010
- } else if (listUpdate.type === "delete") {
3011
- newState.splice(listUpdate.index, 1);
3012
- } else if (listUpdate.type === "move") {
3013
- if (listUpdate.previousIndex > listUpdate.index) {
3014
- newState = [
3015
- ...newState.slice(0, listUpdate.index),
3016
- lsonToJson(listUpdate.item),
3017
- ...newState.slice(listUpdate.index, listUpdate.previousIndex),
3018
- ...newState.slice(listUpdate.previousIndex + 1)
3019
- ];
3020
- } else {
3021
- newState = [
3022
- ...newState.slice(0, listUpdate.previousIndex),
3023
- ...newState.slice(listUpdate.previousIndex + 1, listUpdate.index + 1),
3024
- lsonToJson(listUpdate.item),
3025
- ...newState.slice(listUpdate.index + 1)
3026
- ];
3027
- }
3028
- }
3029
- }
3030
- return newState;
3031
- }
3032
- case "LiveMap": {
3033
- if (typeof state !== "object") {
3034
- throw new Error("Internal: received update on LiveMap but state was not an object");
3035
- }
3036
- const newState = Object.assign({}, state);
3037
- for (const key in update.updates) {
3038
- if (((_c = update.updates[key]) == null ? void 0 : _c.type) === "update") {
3039
- newState[key] = lsonToJson(update.node.get(key));
3040
- } else if (((_d = update.updates[key]) == null ? void 0 : _d.type) === "delete") {
3041
- delete newState[key];
3042
- }
3043
- }
3044
- return newState;
3045
- }
3046
- }
3047
- }
3048
- if (Array.isArray(state)) {
3049
- const newArray = [...state];
3050
- newArray[pathItem] = patchImmutableNode(state[pathItem], path, update);
3051
- return newArray;
3052
- } else {
3053
- return __spreadProps(__spreadValues({}, state), {
3054
- [pathItem]: patchImmutableNode(state[pathItem], path, update)
3055
- });
3056
- }
3057
- }
3058
-
3059
- const internals = {
3060
- liveObjectToJson,
3061
- lsonToJson,
3062
- patchLiveList,
3063
- patchImmutableObject,
3064
- patchLiveObject,
3065
- patchLiveObjectKey
3066
- };
3067
-
3068
- export { LiveList, LiveMap, LiveObject, createClient, internals };