@liveblocks/core 0.18.3-test1

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/dist/index.js ADDED
@@ -0,0 +1,4342 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
32
+ var __async = (__this, __arguments, generator) => {
33
+ return new Promise((resolve, reject) => {
34
+ var fulfilled = (value) => {
35
+ try {
36
+ step(generator.next(value));
37
+ } catch (e) {
38
+ reject(e);
39
+ }
40
+ };
41
+ var rejected = (value) => {
42
+ try {
43
+ step(generator.throw(value));
44
+ } catch (e) {
45
+ reject(e);
46
+ }
47
+ };
48
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
49
+ step((generator = generator.apply(__this, __arguments)).next());
50
+ });
51
+ };
52
+
53
+ // src/assert.ts
54
+ function assertNever(_value, errmsg) {
55
+ throw new Error(errmsg);
56
+ }
57
+ function assert(condition, errmsg) {
58
+ if (process.env.NODE_ENV !== "production" && !condition) {
59
+ const err = new Error(errmsg);
60
+ err.name = "Assertion failure";
61
+ throw err;
62
+ }
63
+ }
64
+ function nn(value, errmsg = "Expected value to be non-nullable") {
65
+ assert(value !== null && value !== void 0, errmsg);
66
+ return value;
67
+ }
68
+
69
+ // src/types/ClientMsg.ts
70
+ var ClientMsgCode = /* @__PURE__ */ ((ClientMsgCode2) => {
71
+ ClientMsgCode2[ClientMsgCode2["UPDATE_PRESENCE"] = 100] = "UPDATE_PRESENCE";
72
+ ClientMsgCode2[ClientMsgCode2["BROADCAST_EVENT"] = 103] = "BROADCAST_EVENT";
73
+ ClientMsgCode2[ClientMsgCode2["FETCH_STORAGE"] = 200] = "FETCH_STORAGE";
74
+ ClientMsgCode2[ClientMsgCode2["UPDATE_STORAGE"] = 201] = "UPDATE_STORAGE";
75
+ return ClientMsgCode2;
76
+ })(ClientMsgCode || {});
77
+
78
+ // src/types/Op.ts
79
+ var OpCode = /* @__PURE__ */ ((OpCode2) => {
80
+ OpCode2[OpCode2["INIT"] = 0] = "INIT";
81
+ OpCode2[OpCode2["SET_PARENT_KEY"] = 1] = "SET_PARENT_KEY";
82
+ OpCode2[OpCode2["CREATE_LIST"] = 2] = "CREATE_LIST";
83
+ OpCode2[OpCode2["UPDATE_OBJECT"] = 3] = "UPDATE_OBJECT";
84
+ OpCode2[OpCode2["CREATE_OBJECT"] = 4] = "CREATE_OBJECT";
85
+ OpCode2[OpCode2["DELETE_CRDT"] = 5] = "DELETE_CRDT";
86
+ OpCode2[OpCode2["DELETE_OBJECT_KEY"] = 6] = "DELETE_OBJECT_KEY";
87
+ OpCode2[OpCode2["CREATE_MAP"] = 7] = "CREATE_MAP";
88
+ OpCode2[OpCode2["CREATE_REGISTER"] = 8] = "CREATE_REGISTER";
89
+ return OpCode2;
90
+ })(OpCode || {});
91
+
92
+ // src/types/SerializedCrdt.ts
93
+ var CrdtType = /* @__PURE__ */ ((CrdtType2) => {
94
+ CrdtType2[CrdtType2["OBJECT"] = 0] = "OBJECT";
95
+ CrdtType2[CrdtType2["LIST"] = 1] = "LIST";
96
+ CrdtType2[CrdtType2["MAP"] = 2] = "MAP";
97
+ CrdtType2[CrdtType2["REGISTER"] = 3] = "REGISTER";
98
+ return CrdtType2;
99
+ })(CrdtType || {});
100
+ function isRootCrdt(crdt) {
101
+ return crdt.type === 0 /* OBJECT */ && !isChildCrdt(crdt);
102
+ }
103
+ function isChildCrdt(crdt) {
104
+ return crdt.parentId !== void 0 && crdt.parentKey !== void 0;
105
+ }
106
+
107
+ // src/types/ServerMsg.ts
108
+ var ServerMsgCode = /* @__PURE__ */ ((ServerMsgCode2) => {
109
+ ServerMsgCode2[ServerMsgCode2["UPDATE_PRESENCE"] = 100] = "UPDATE_PRESENCE";
110
+ ServerMsgCode2[ServerMsgCode2["USER_JOINED"] = 101] = "USER_JOINED";
111
+ ServerMsgCode2[ServerMsgCode2["USER_LEFT"] = 102] = "USER_LEFT";
112
+ ServerMsgCode2[ServerMsgCode2["BROADCASTED_EVENT"] = 103] = "BROADCASTED_EVENT";
113
+ ServerMsgCode2[ServerMsgCode2["ROOM_STATE"] = 104] = "ROOM_STATE";
114
+ ServerMsgCode2[ServerMsgCode2["INITIAL_STORAGE_STATE"] = 200] = "INITIAL_STORAGE_STATE";
115
+ ServerMsgCode2[ServerMsgCode2["UPDATE_STORAGE"] = 201] = "UPDATE_STORAGE";
116
+ return ServerMsgCode2;
117
+ })(ServerMsgCode || {});
118
+
119
+ // src/types/index.ts
120
+ function isRoomEventName(value) {
121
+ return value === "my-presence" || value === "others" || value === "event" || value === "error" || value === "connection" || value === "history";
122
+ }
123
+ var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
124
+ WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_ABNORMAL"] = 1006] = "CLOSE_ABNORMAL";
125
+ WebsocketCloseCodes2[WebsocketCloseCodes2["INVALID_MESSAGE_FORMAT"] = 4e3] = "INVALID_MESSAGE_FORMAT";
126
+ WebsocketCloseCodes2[WebsocketCloseCodes2["NOT_ALLOWED"] = 4001] = "NOT_ALLOWED";
127
+ WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_SECONDS"] = 4002] = "MAX_NUMBER_OF_MESSAGES_PER_SECONDS";
128
+ WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS"] = 4003] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS";
129
+ WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"] = 4004] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP";
130
+ WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"] = 4005] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM";
131
+ WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_WITHOUT_RETRY"] = 4999] = "CLOSE_WITHOUT_RETRY";
132
+ return WebsocketCloseCodes2;
133
+ })(WebsocketCloseCodes || {});
134
+
135
+ // src/AbstractCrdt.ts
136
+ function crdtAsLiveNode(value) {
137
+ return value;
138
+ }
139
+ function HasParent(node, key) {
140
+ return Object.freeze({ type: "HasParent", node, key });
141
+ }
142
+ var NoParent = Object.freeze({ type: "NoParent" });
143
+ function Orphaned(oldKey) {
144
+ return Object.freeze({ type: "Orphaned", oldKey });
145
+ }
146
+ var AbstractCrdt = class {
147
+ constructor() {
148
+ this._parent = NoParent;
149
+ }
150
+ _getParentKeyOrThrow() {
151
+ switch (this.parent.type) {
152
+ case "HasParent":
153
+ return this.parent.key;
154
+ case "NoParent":
155
+ throw new Error("Parent key is missing");
156
+ case "Orphaned":
157
+ return this.parent.oldKey;
158
+ default:
159
+ return assertNever(this.parent, "Unknown state");
160
+ }
161
+ }
162
+ get _pool() {
163
+ return this.__pool;
164
+ }
165
+ get roomId() {
166
+ return this.__pool ? this.__pool.roomId : null;
167
+ }
168
+ get _id() {
169
+ return this.__id;
170
+ }
171
+ get parent() {
172
+ return this._parent;
173
+ }
174
+ get _parentNode() {
175
+ switch (this.parent.type) {
176
+ case "HasParent":
177
+ return this.parent.node;
178
+ case "NoParent":
179
+ return null;
180
+ case "Orphaned":
181
+ return null;
182
+ default:
183
+ return assertNever(this.parent, "Unknown state");
184
+ }
185
+ }
186
+ get _parentKey() {
187
+ switch (this.parent.type) {
188
+ case "HasParent":
189
+ return this.parent.key;
190
+ case "NoParent":
191
+ return null;
192
+ case "Orphaned":
193
+ return this.parent.oldKey;
194
+ default:
195
+ return assertNever(this.parent, "Unknown state");
196
+ }
197
+ }
198
+ _apply(op, _isLocal) {
199
+ switch (op.type) {
200
+ case 5 /* DELETE_CRDT */: {
201
+ if (this.parent.type === "HasParent") {
202
+ return this.parent.node._detachChild(crdtAsLiveNode(this));
203
+ }
204
+ return { modified: false };
205
+ }
206
+ }
207
+ return { modified: false };
208
+ }
209
+ _setParentLink(newParentNode, newParentKey) {
210
+ switch (this.parent.type) {
211
+ case "HasParent":
212
+ if (this.parent.node !== newParentNode) {
213
+ throw new Error("Cannot set parent: node already has a parent");
214
+ } else {
215
+ this._parent = HasParent(newParentNode, newParentKey);
216
+ return;
217
+ }
218
+ case "Orphaned":
219
+ case "NoParent": {
220
+ this._parent = HasParent(newParentNode, newParentKey);
221
+ return;
222
+ }
223
+ default:
224
+ return assertNever(this.parent, "Unknown state");
225
+ }
226
+ }
227
+ _attach(id, pool) {
228
+ if (this.__id || this.__pool) {
229
+ throw new Error("Cannot attach node: already attached");
230
+ }
231
+ pool.addNode(id, crdtAsLiveNode(this));
232
+ this.__id = id;
233
+ this.__pool = pool;
234
+ }
235
+ _detach() {
236
+ if (this.__pool && this.__id) {
237
+ this.__pool.deleteNode(this.__id);
238
+ }
239
+ switch (this.parent.type) {
240
+ case "HasParent": {
241
+ this._parent = Orphaned(this.parent.key);
242
+ break;
243
+ }
244
+ case "NoParent": {
245
+ this._parent = NoParent;
246
+ break;
247
+ }
248
+ case "Orphaned": {
249
+ this._parent = Orphaned(this.parent.oldKey);
250
+ break;
251
+ }
252
+ default:
253
+ assertNever(this.parent, "Unknown state");
254
+ }
255
+ this.__pool = void 0;
256
+ }
257
+ invalidate() {
258
+ if (this._cachedImmutable !== void 0) {
259
+ this._cachedImmutable = void 0;
260
+ if (this.parent.type === "HasParent") {
261
+ this.parent.node.invalidate();
262
+ }
263
+ }
264
+ }
265
+ toImmutable() {
266
+ if (this._cachedImmutable === void 0) {
267
+ this._cachedImmutable = this._toImmutable();
268
+ }
269
+ return this._cachedImmutable;
270
+ }
271
+ };
272
+
273
+ // src/LiveRegister.ts
274
+ var LiveRegister = class extends AbstractCrdt {
275
+ constructor(data) {
276
+ super();
277
+ this._data = data;
278
+ }
279
+ get data() {
280
+ return this._data;
281
+ }
282
+ static _deserialize([id, item], _parentToChildren, pool) {
283
+ const register = new LiveRegister(item.data);
284
+ register._attach(id, pool);
285
+ return register;
286
+ }
287
+ _toOps(parentId, parentKey, pool) {
288
+ if (this._id === void 0) {
289
+ throw new Error(
290
+ "Cannot serialize register if parentId or parentKey is undefined"
291
+ );
292
+ }
293
+ return [
294
+ {
295
+ type: 8 /* CREATE_REGISTER */,
296
+ opId: pool == null ? void 0 : pool.generateOpId(),
297
+ id: this._id,
298
+ parentId,
299
+ parentKey,
300
+ data: this.data
301
+ }
302
+ ];
303
+ }
304
+ _serialize() {
305
+ if (this.parent.type !== "HasParent") {
306
+ throw new Error("Cannot serialize LiveRegister if parent is missing");
307
+ }
308
+ return {
309
+ type: 3 /* REGISTER */,
310
+ parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
311
+ parentKey: this.parent.key,
312
+ data: this.data
313
+ };
314
+ }
315
+ _attachChild(_op) {
316
+ throw new Error("Method not implemented.");
317
+ }
318
+ _detachChild(_crdt) {
319
+ throw new Error("Method not implemented.");
320
+ }
321
+ _apply(op, isLocal) {
322
+ return super._apply(op, isLocal);
323
+ }
324
+ _toImmutable() {
325
+ return this._data;
326
+ }
327
+ };
328
+
329
+ // src/position.ts
330
+ var min = 32;
331
+ var max = 126;
332
+ function makePosition(before, after) {
333
+ if (before !== void 0 && after !== void 0) {
334
+ return pos(makePositionFromCodes(posCodes(before), posCodes(after)));
335
+ } else if (before !== void 0) {
336
+ return getNextPosition(before);
337
+ } else if (after !== void 0) {
338
+ return getPreviousPosition(after);
339
+ }
340
+ return pos([min + 1]);
341
+ }
342
+ function getPreviousPosition(after) {
343
+ const result = [];
344
+ const afterCodes = posCodes(after);
345
+ for (let i = 0; i < afterCodes.length; i++) {
346
+ const code = afterCodes[i];
347
+ if (code <= min + 1) {
348
+ result.push(min);
349
+ if (afterCodes.length - 1 === i) {
350
+ result.push(max);
351
+ break;
352
+ }
353
+ } else {
354
+ result.push(code - 1);
355
+ break;
356
+ }
357
+ }
358
+ return pos(result);
359
+ }
360
+ function getNextPosition(before) {
361
+ const result = [];
362
+ const beforeCodes = posCodes(before);
363
+ for (let i = 0; i < beforeCodes.length; i++) {
364
+ const code = beforeCodes[i];
365
+ if (code === max) {
366
+ result.push(code);
367
+ if (beforeCodes.length - 1 === i) {
368
+ result.push(min + 1);
369
+ break;
370
+ }
371
+ } else {
372
+ result.push(code + 1);
373
+ break;
374
+ }
375
+ }
376
+ return pos(result);
377
+ }
378
+ function makePositionFromCodes(before, after) {
379
+ let index = 0;
380
+ const result = [];
381
+ while (true) {
382
+ const beforeDigit = before[index] || min;
383
+ const afterDigit = after[index] || max;
384
+ if (beforeDigit > afterDigit) {
385
+ throw new Error(
386
+ `Impossible to generate position between ${before} and ${after}`
387
+ );
388
+ }
389
+ if (beforeDigit === afterDigit) {
390
+ result.push(beforeDigit);
391
+ index++;
392
+ continue;
393
+ }
394
+ if (afterDigit - beforeDigit === 1) {
395
+ result.push(beforeDigit);
396
+ result.push(...makePositionFromCodes(before.slice(index + 1), []));
397
+ break;
398
+ }
399
+ const mid = afterDigit + beforeDigit >> 1;
400
+ result.push(mid);
401
+ break;
402
+ }
403
+ return result;
404
+ }
405
+ function posCodes(str) {
406
+ const codes = [];
407
+ for (let i = 0; i < str.length; i++) {
408
+ codes.push(str.charCodeAt(i));
409
+ }
410
+ return codes;
411
+ }
412
+ function pos(codes) {
413
+ return String.fromCharCode(...codes);
414
+ }
415
+ function comparePosition(posA, posB) {
416
+ const aCodes = posCodes(posA);
417
+ const bCodes = posCodes(posB);
418
+ const maxLength = Math.max(aCodes.length, bCodes.length);
419
+ for (let i = 0; i < maxLength; i++) {
420
+ const a = aCodes[i] === void 0 ? min : aCodes[i];
421
+ const b = bCodes[i] === void 0 ? min : bCodes[i];
422
+ if (a === b) {
423
+ continue;
424
+ } else {
425
+ return a - b;
426
+ }
427
+ }
428
+ throw new Error(
429
+ `Impossible to compare similar position "${posA}" and "${posB}"`
430
+ );
431
+ }
432
+
433
+ // src/LiveList.ts
434
+ function compareNodePosition(itemA, itemB) {
435
+ return comparePosition(
436
+ itemA._getParentKeyOrThrow(),
437
+ itemB._getParentKeyOrThrow()
438
+ );
439
+ }
440
+ var LiveList = class extends AbstractCrdt {
441
+ constructor(items = []) {
442
+ super();
443
+ this._items = [];
444
+ this._implicitlyDeletedItems = /* @__PURE__ */ new WeakSet();
445
+ this._unacknowledgedSets = /* @__PURE__ */ new Map();
446
+ let position = void 0;
447
+ for (const item of items) {
448
+ const newPosition = makePosition(position);
449
+ const node = lsonToLiveNode(item);
450
+ node._setParentLink(this, newPosition);
451
+ this._items.push(node);
452
+ position = newPosition;
453
+ }
454
+ }
455
+ static _deserialize([id], parentToChildren, pool) {
456
+ const list = new LiveList();
457
+ list._attach(id, pool);
458
+ const children = parentToChildren.get(id);
459
+ if (children === void 0) {
460
+ return list;
461
+ }
462
+ for (const [id2, crdt] of children) {
463
+ const child = deserialize([id2, crdt], parentToChildren, pool);
464
+ child._setParentLink(list, crdt.parentKey);
465
+ list._insertAndSort(child);
466
+ }
467
+ return list;
468
+ }
469
+ _toOps(parentId, parentKey, pool) {
470
+ if (this._id === void 0) {
471
+ throw new Error("Cannot serialize item is not attached");
472
+ }
473
+ const ops = [];
474
+ const op = {
475
+ id: this._id,
476
+ opId: pool == null ? void 0 : pool.generateOpId(),
477
+ type: 2 /* CREATE_LIST */,
478
+ parentId,
479
+ parentKey
480
+ };
481
+ ops.push(op);
482
+ for (const item of this._items) {
483
+ ops.push(...item._toOps(this._id, item._getParentKeyOrThrow(), pool));
484
+ }
485
+ return ops;
486
+ }
487
+ _insertAndSort(item) {
488
+ this._items.push(item);
489
+ this._sortItems();
490
+ }
491
+ _sortItems() {
492
+ this._items.sort(compareNodePosition);
493
+ this.invalidate();
494
+ }
495
+ _indexOfPosition(position) {
496
+ return this._items.findIndex(
497
+ (item) => item._getParentKeyOrThrow() === position
498
+ );
499
+ }
500
+ _attach(id, pool) {
501
+ super._attach(id, pool);
502
+ for (const item of this._items) {
503
+ item._attach(pool.generateId(), pool);
504
+ }
505
+ }
506
+ _detach() {
507
+ super._detach();
508
+ for (const item of this._items) {
509
+ item._detach();
510
+ }
511
+ }
512
+ _applySetRemote(op) {
513
+ if (this._pool === void 0) {
514
+ throw new Error("Can't attach child if managed pool is not present");
515
+ }
516
+ const { id, parentKey: key } = op;
517
+ const child = creationOpToLiveNode(op);
518
+ child._attach(id, this._pool);
519
+ child._setParentLink(this, key);
520
+ const deletedId = op.deletedId;
521
+ const indexOfItemWithSamePosition = this._indexOfPosition(key);
522
+ if (indexOfItemWithSamePosition !== -1) {
523
+ const itemWithSamePosition = this._items[indexOfItemWithSamePosition];
524
+ if (itemWithSamePosition._id === deletedId) {
525
+ itemWithSamePosition._detach();
526
+ this._items[indexOfItemWithSamePosition] = child;
527
+ return {
528
+ modified: makeUpdate(this, [
529
+ setDelta(indexOfItemWithSamePosition, child)
530
+ ]),
531
+ reverse: []
532
+ };
533
+ } else {
534
+ this._implicitlyDeletedItems.add(itemWithSamePosition);
535
+ this._items[indexOfItemWithSamePosition] = child;
536
+ const delta = [
537
+ setDelta(indexOfItemWithSamePosition, child)
538
+ ];
539
+ const deleteDelta2 = this._detachItemAssociatedToSetOperation(
540
+ op.deletedId
541
+ );
542
+ if (deleteDelta2) {
543
+ delta.push(deleteDelta2);
544
+ }
545
+ return {
546
+ modified: makeUpdate(this, delta),
547
+ reverse: []
548
+ };
549
+ }
550
+ } else {
551
+ const updates = [];
552
+ const deleteDelta2 = this._detachItemAssociatedToSetOperation(
553
+ op.deletedId
554
+ );
555
+ if (deleteDelta2) {
556
+ updates.push(deleteDelta2);
557
+ }
558
+ this._insertAndSort(child);
559
+ updates.push(insertDelta(this._indexOfPosition(key), child));
560
+ return {
561
+ reverse: [],
562
+ modified: makeUpdate(this, updates)
563
+ };
564
+ }
565
+ }
566
+ _applySetAck(op) {
567
+ if (this._pool === void 0) {
568
+ throw new Error("Can't attach child if managed pool is not present");
569
+ }
570
+ const delta = [];
571
+ const deletedDelta = this._detachItemAssociatedToSetOperation(op.deletedId);
572
+ if (deletedDelta) {
573
+ delta.push(deletedDelta);
574
+ }
575
+ const unacknowledgedOpId = this._unacknowledgedSets.get(op.parentKey);
576
+ if (unacknowledgedOpId !== void 0) {
577
+ if (unacknowledgedOpId !== op.opId) {
578
+ return delta.length === 0 ? { modified: false } : { modified: makeUpdate(this, delta), reverse: [] };
579
+ } else {
580
+ this._unacknowledgedSets.delete(op.parentKey);
581
+ }
582
+ }
583
+ const indexOfItemWithSamePosition = this._indexOfPosition(op.parentKey);
584
+ const existingItem = this._items.find((item) => item._id === op.id);
585
+ if (existingItem !== void 0) {
586
+ if (existingItem._parentKey === op.parentKey) {
587
+ return {
588
+ modified: delta.length > 0 ? makeUpdate(this, delta) : false,
589
+ reverse: []
590
+ };
591
+ }
592
+ if (indexOfItemWithSamePosition !== -1) {
593
+ this._implicitlyDeletedItems.add(
594
+ this._items[indexOfItemWithSamePosition]
595
+ );
596
+ this._items.splice(indexOfItemWithSamePosition, 1);
597
+ delta.push(deleteDelta(indexOfItemWithSamePosition));
598
+ }
599
+ const previousIndex = this._items.indexOf(existingItem);
600
+ existingItem._setParentLink(this, op.parentKey);
601
+ this._sortItems();
602
+ const newIndex = this._items.indexOf(existingItem);
603
+ if (newIndex !== previousIndex) {
604
+ delta.push(moveDelta(previousIndex, newIndex, existingItem));
605
+ }
606
+ return {
607
+ modified: delta.length > 0 ? makeUpdate(this, delta) : false,
608
+ reverse: []
609
+ };
610
+ } else {
611
+ const orphan = this._pool.getNode(op.id);
612
+ if (orphan && this._implicitlyDeletedItems.has(orphan)) {
613
+ orphan._setParentLink(this, op.parentKey);
614
+ this._implicitlyDeletedItems.delete(orphan);
615
+ this._insertAndSort(orphan);
616
+ const recreatedItemIndex = this._items.indexOf(orphan);
617
+ return {
618
+ modified: makeUpdate(this, [
619
+ indexOfItemWithSamePosition === -1 ? insertDelta(recreatedItemIndex, orphan) : setDelta(recreatedItemIndex, orphan),
620
+ ...delta
621
+ ]),
622
+ reverse: []
623
+ };
624
+ } else {
625
+ if (indexOfItemWithSamePosition !== -1) {
626
+ this._items.splice(indexOfItemWithSamePosition, 1);
627
+ }
628
+ const { newItem, newIndex } = this._createAttachItemAndSort(
629
+ op,
630
+ op.parentKey
631
+ );
632
+ return {
633
+ modified: makeUpdate(this, [
634
+ indexOfItemWithSamePosition === -1 ? insertDelta(newIndex, newItem) : setDelta(newIndex, newItem),
635
+ ...delta
636
+ ]),
637
+ reverse: []
638
+ };
639
+ }
640
+ }
641
+ }
642
+ _detachItemAssociatedToSetOperation(deletedId) {
643
+ if (deletedId === void 0 || this._pool === void 0) {
644
+ return null;
645
+ }
646
+ const deletedItem = this._pool.getNode(deletedId);
647
+ if (deletedItem === void 0) {
648
+ return null;
649
+ }
650
+ const result = this._detachChild(deletedItem);
651
+ if (result.modified === false) {
652
+ return null;
653
+ }
654
+ return result.modified.updates[0];
655
+ }
656
+ _applyRemoteInsert(op) {
657
+ if (this._pool === void 0) {
658
+ throw new Error("Can't attach child if managed pool is not present");
659
+ }
660
+ const key = op.parentKey;
661
+ const existingItemIndex = this._indexOfPosition(key);
662
+ if (existingItemIndex !== -1) {
663
+ this._shiftItemPosition(existingItemIndex, key);
664
+ }
665
+ const { newItem, newIndex } = this._createAttachItemAndSort(op, key);
666
+ return {
667
+ modified: makeUpdate(this, [insertDelta(newIndex, newItem)]),
668
+ reverse: []
669
+ };
670
+ }
671
+ _applyInsertAck(op) {
672
+ const existingItem = this._items.find((item) => item._id === op.id);
673
+ const key = op.parentKey;
674
+ const itemIndexAtPosition = this._indexOfPosition(key);
675
+ if (existingItem) {
676
+ if (existingItem._parentKey === key) {
677
+ return {
678
+ modified: false
679
+ };
680
+ } else {
681
+ const oldPositionIndex = this._items.indexOf(existingItem);
682
+ if (itemIndexAtPosition !== -1) {
683
+ this._shiftItemPosition(itemIndexAtPosition, key);
684
+ }
685
+ existingItem._setParentLink(this, key);
686
+ this._sortItems();
687
+ const newIndex = this._indexOfPosition(key);
688
+ if (newIndex === oldPositionIndex) {
689
+ return { modified: false };
690
+ }
691
+ return {
692
+ modified: makeUpdate(this, [
693
+ moveDelta(oldPositionIndex, newIndex, existingItem)
694
+ ]),
695
+ reverse: []
696
+ };
697
+ }
698
+ } else {
699
+ const orphan = nn(this._pool).getNode(op.id);
700
+ if (orphan && this._implicitlyDeletedItems.has(orphan)) {
701
+ orphan._setParentLink(this, key);
702
+ this._implicitlyDeletedItems.delete(orphan);
703
+ this._insertAndSort(orphan);
704
+ const newIndex = this._indexOfPosition(key);
705
+ return {
706
+ modified: makeUpdate(this, [insertDelta(newIndex, orphan)]),
707
+ reverse: []
708
+ };
709
+ } else {
710
+ if (itemIndexAtPosition !== -1) {
711
+ this._shiftItemPosition(itemIndexAtPosition, key);
712
+ }
713
+ const { newItem, newIndex } = this._createAttachItemAndSort(op, key);
714
+ return {
715
+ modified: makeUpdate(this, [insertDelta(newIndex, newItem)]),
716
+ reverse: []
717
+ };
718
+ }
719
+ }
720
+ }
721
+ _applyInsertUndoRedo(op) {
722
+ var _a, _b, _c;
723
+ const { id, parentKey: key } = op;
724
+ const child = creationOpToLiveNode(op);
725
+ if (((_a = this._pool) == null ? void 0 : _a.getNode(id)) !== void 0) {
726
+ return { modified: false };
727
+ }
728
+ child._attach(id, nn(this._pool));
729
+ child._setParentLink(this, key);
730
+ const existingItemIndex = this._indexOfPosition(key);
731
+ let newKey = key;
732
+ if (existingItemIndex !== -1) {
733
+ const before = (_b = this._items[existingItemIndex]) == null ? void 0 : _b._getParentKeyOrThrow();
734
+ const after = (_c = this._items[existingItemIndex + 1]) == null ? void 0 : _c._getParentKeyOrThrow();
735
+ newKey = makePosition(before, after);
736
+ child._setParentLink(this, newKey);
737
+ }
738
+ this._insertAndSort(child);
739
+ const newIndex = this._indexOfPosition(newKey);
740
+ return {
741
+ modified: makeUpdate(this, [insertDelta(newIndex, child)]),
742
+ reverse: [{ type: 5 /* DELETE_CRDT */, id }]
743
+ };
744
+ }
745
+ _applySetUndoRedo(op) {
746
+ var _a;
747
+ const { id, parentKey: key } = op;
748
+ const child = creationOpToLiveNode(op);
749
+ if (((_a = this._pool) == null ? void 0 : _a.getNode(id)) !== void 0) {
750
+ return { modified: false };
751
+ }
752
+ this._unacknowledgedSets.set(key, nn(op.opId));
753
+ const indexOfItemWithSameKey = this._indexOfPosition(key);
754
+ child._attach(id, nn(this._pool));
755
+ child._setParentLink(this, key);
756
+ const newKey = key;
757
+ if (indexOfItemWithSameKey !== -1) {
758
+ const existingItem = this._items[indexOfItemWithSameKey];
759
+ existingItem._detach();
760
+ this._items[indexOfItemWithSameKey] = child;
761
+ const reverse = existingItem._toOps(nn(this._id), key, this._pool);
762
+ addIntentAndDeletedIdToOperation(reverse, op.id);
763
+ const delta = [setDelta(indexOfItemWithSameKey, child)];
764
+ const deletedDelta = this._detachItemAssociatedToSetOperation(
765
+ op.deletedId
766
+ );
767
+ if (deletedDelta) {
768
+ delta.push(deletedDelta);
769
+ }
770
+ return {
771
+ modified: makeUpdate(this, delta),
772
+ reverse
773
+ };
774
+ } else {
775
+ this._insertAndSort(child);
776
+ this._detachItemAssociatedToSetOperation(op.deletedId);
777
+ const newIndex = this._indexOfPosition(newKey);
778
+ return {
779
+ reverse: [{ type: 5 /* DELETE_CRDT */, id }],
780
+ modified: makeUpdate(this, [insertDelta(newIndex, child)])
781
+ };
782
+ }
783
+ }
784
+ _attachChild(op, source) {
785
+ if (this._pool === void 0) {
786
+ throw new Error("Can't attach child if managed pool is not present");
787
+ }
788
+ let result;
789
+ if (op.intent === "set") {
790
+ if (source === 1 /* REMOTE */) {
791
+ result = this._applySetRemote(op);
792
+ } else if (source === 2 /* ACK */) {
793
+ result = this._applySetAck(op);
794
+ } else {
795
+ result = this._applySetUndoRedo(op);
796
+ }
797
+ } else {
798
+ if (source === 1 /* REMOTE */) {
799
+ result = this._applyRemoteInsert(op);
800
+ } else if (source === 2 /* ACK */) {
801
+ result = this._applyInsertAck(op);
802
+ } else {
803
+ result = this._applyInsertUndoRedo(op);
804
+ }
805
+ }
806
+ if (result.modified !== false) {
807
+ this.invalidate();
808
+ }
809
+ return result;
810
+ }
811
+ _detachChild(child) {
812
+ if (child) {
813
+ const parentKey = nn(child._parentKey);
814
+ const reverse = child._toOps(nn(this._id), parentKey, this._pool);
815
+ const indexToDelete = this._items.indexOf(child);
816
+ if (indexToDelete === -1) {
817
+ return {
818
+ modified: false
819
+ };
820
+ }
821
+ this._items.splice(indexToDelete, 1);
822
+ this.invalidate();
823
+ child._detach();
824
+ return {
825
+ modified: makeUpdate(this, [deleteDelta(indexToDelete)]),
826
+ reverse
827
+ };
828
+ }
829
+ return { modified: false };
830
+ }
831
+ _applySetChildKeyRemote(newKey, child) {
832
+ var _a;
833
+ if (this._implicitlyDeletedItems.has(child)) {
834
+ this._implicitlyDeletedItems.delete(child);
835
+ child._setParentLink(this, newKey);
836
+ this._insertAndSort(child);
837
+ const newIndex = this._items.indexOf(child);
838
+ return {
839
+ modified: makeUpdate(this, [insertDelta(newIndex, child)]),
840
+ reverse: []
841
+ };
842
+ }
843
+ const previousKey = child._parentKey;
844
+ if (newKey === previousKey) {
845
+ return {
846
+ modified: false
847
+ };
848
+ }
849
+ const existingItemIndex = this._indexOfPosition(newKey);
850
+ if (existingItemIndex === -1) {
851
+ const previousIndex = this._items.indexOf(child);
852
+ child._setParentLink(this, newKey);
853
+ this._sortItems();
854
+ const newIndex = this._items.indexOf(child);
855
+ if (newIndex === previousIndex) {
856
+ return {
857
+ modified: false
858
+ };
859
+ }
860
+ return {
861
+ modified: makeUpdate(this, [moveDelta(previousIndex, newIndex, child)]),
862
+ reverse: []
863
+ };
864
+ } else {
865
+ this._items[existingItemIndex]._setParentLink(
866
+ this,
867
+ makePosition(
868
+ newKey,
869
+ (_a = this._items[existingItemIndex + 1]) == null ? void 0 : _a._getParentKeyOrThrow()
870
+ )
871
+ );
872
+ const previousIndex = this._items.indexOf(child);
873
+ child._setParentLink(this, newKey);
874
+ this._sortItems();
875
+ const newIndex = this._items.indexOf(child);
876
+ if (newIndex === previousIndex) {
877
+ return {
878
+ modified: false
879
+ };
880
+ }
881
+ return {
882
+ modified: makeUpdate(this, [moveDelta(previousIndex, newIndex, child)]),
883
+ reverse: []
884
+ };
885
+ }
886
+ }
887
+ _applySetChildKeyAck(newKey, child) {
888
+ var _a, _b;
889
+ const previousKey = nn(child._parentKey);
890
+ if (this._implicitlyDeletedItems.has(child)) {
891
+ const existingItemIndex = this._indexOfPosition(newKey);
892
+ this._implicitlyDeletedItems.delete(child);
893
+ if (existingItemIndex !== -1) {
894
+ this._items[existingItemIndex]._setParentLink(
895
+ this,
896
+ makePosition(
897
+ newKey,
898
+ (_a = this._items[existingItemIndex + 1]) == null ? void 0 : _a._getParentKeyOrThrow()
899
+ )
900
+ );
901
+ }
902
+ child._setParentLink(this, newKey);
903
+ this._insertAndSort(child);
904
+ return {
905
+ modified: false
906
+ };
907
+ } else {
908
+ if (newKey === previousKey) {
909
+ return {
910
+ modified: false
911
+ };
912
+ }
913
+ const previousIndex = this._items.indexOf(child);
914
+ const existingItemIndex = this._indexOfPosition(newKey);
915
+ if (existingItemIndex !== -1) {
916
+ this._items[existingItemIndex]._setParentLink(
917
+ this,
918
+ makePosition(
919
+ newKey,
920
+ (_b = this._items[existingItemIndex + 1]) == null ? void 0 : _b._getParentKeyOrThrow()
921
+ )
922
+ );
923
+ }
924
+ child._setParentLink(this, newKey);
925
+ this._sortItems();
926
+ const newIndex = this._items.indexOf(child);
927
+ if (previousIndex === newIndex) {
928
+ return {
929
+ modified: false
930
+ };
931
+ } else {
932
+ return {
933
+ modified: makeUpdate(this, [
934
+ moveDelta(previousIndex, newIndex, child)
935
+ ]),
936
+ reverse: []
937
+ };
938
+ }
939
+ }
940
+ }
941
+ _applySetChildKeyUndoRedo(newKey, child) {
942
+ var _a;
943
+ const previousKey = nn(child._parentKey);
944
+ const previousIndex = this._items.indexOf(child);
945
+ const existingItemIndex = this._indexOfPosition(newKey);
946
+ if (existingItemIndex !== -1) {
947
+ this._items[existingItemIndex]._setParentLink(
948
+ this,
949
+ makePosition(
950
+ newKey,
951
+ (_a = this._items[existingItemIndex + 1]) == null ? void 0 : _a._getParentKeyOrThrow()
952
+ )
953
+ );
954
+ }
955
+ child._setParentLink(this, newKey);
956
+ this._sortItems();
957
+ const newIndex = this._items.indexOf(child);
958
+ if (previousIndex === newIndex) {
959
+ return {
960
+ modified: false
961
+ };
962
+ }
963
+ return {
964
+ modified: makeUpdate(this, [moveDelta(previousIndex, newIndex, child)]),
965
+ reverse: [
966
+ {
967
+ type: 1 /* SET_PARENT_KEY */,
968
+ id: nn(child._id),
969
+ parentKey: previousKey
970
+ }
971
+ ]
972
+ };
973
+ }
974
+ _setChildKey(newKey, child, source) {
975
+ if (source === 1 /* REMOTE */) {
976
+ return this._applySetChildKeyRemote(newKey, child);
977
+ } else if (source === 2 /* ACK */) {
978
+ return this._applySetChildKeyAck(newKey, child);
979
+ } else {
980
+ return this._applySetChildKeyUndoRedo(newKey, child);
981
+ }
982
+ }
983
+ _apply(op, isLocal) {
984
+ return super._apply(op, isLocal);
985
+ }
986
+ _serialize() {
987
+ if (this.parent.type !== "HasParent") {
988
+ throw new Error("Cannot serialize LiveList if parent is missing");
989
+ }
990
+ return {
991
+ type: 1 /* LIST */,
992
+ parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
993
+ parentKey: this.parent.key
994
+ };
995
+ }
996
+ get length() {
997
+ return this._items.length;
998
+ }
999
+ push(element) {
1000
+ return this.insert(element, this.length);
1001
+ }
1002
+ insert(element, index) {
1003
+ if (index < 0 || index > this._items.length) {
1004
+ throw new Error(
1005
+ `Cannot insert list item at index "${index}". index should be between 0 and ${this._items.length}`
1006
+ );
1007
+ }
1008
+ const before = this._items[index - 1] ? this._items[index - 1]._getParentKeyOrThrow() : void 0;
1009
+ const after = this._items[index] ? this._items[index]._getParentKeyOrThrow() : void 0;
1010
+ const position = makePosition(before, after);
1011
+ const value = lsonToLiveNode(element);
1012
+ value._setParentLink(this, position);
1013
+ this._insertAndSort(value);
1014
+ if (this._pool && this._id) {
1015
+ const id = this._pool.generateId();
1016
+ value._attach(id, this._pool);
1017
+ this._pool.dispatch(
1018
+ value._toOps(this._id, position, this._pool),
1019
+ [{ type: 5 /* DELETE_CRDT */, id }],
1020
+ /* @__PURE__ */ new Map([
1021
+ [this._id, makeUpdate(this, [insertDelta(index, value)])]
1022
+ ])
1023
+ );
1024
+ }
1025
+ }
1026
+ move(index, targetIndex) {
1027
+ if (targetIndex < 0) {
1028
+ throw new Error("targetIndex cannot be less than 0");
1029
+ }
1030
+ if (targetIndex >= this._items.length) {
1031
+ throw new Error(
1032
+ "targetIndex cannot be greater or equal than the list length"
1033
+ );
1034
+ }
1035
+ if (index < 0) {
1036
+ throw new Error("index cannot be less than 0");
1037
+ }
1038
+ if (index >= this._items.length) {
1039
+ throw new Error("index cannot be greater or equal than the list length");
1040
+ }
1041
+ let beforePosition = null;
1042
+ let afterPosition = null;
1043
+ if (index < targetIndex) {
1044
+ afterPosition = targetIndex === this._items.length - 1 ? void 0 : this._items[targetIndex + 1]._getParentKeyOrThrow();
1045
+ beforePosition = this._items[targetIndex]._getParentKeyOrThrow();
1046
+ } else {
1047
+ afterPosition = this._items[targetIndex]._getParentKeyOrThrow();
1048
+ beforePosition = targetIndex === 0 ? void 0 : this._items[targetIndex - 1]._getParentKeyOrThrow();
1049
+ }
1050
+ const position = makePosition(beforePosition, afterPosition);
1051
+ const item = this._items[index];
1052
+ const previousPosition = item._getParentKeyOrThrow();
1053
+ item._setParentLink(this, position);
1054
+ this._sortItems();
1055
+ if (this._pool && this._id) {
1056
+ const storageUpdates = /* @__PURE__ */ new Map([
1057
+ [this._id, makeUpdate(this, [moveDelta(index, targetIndex, item)])]
1058
+ ]);
1059
+ this._pool.dispatch(
1060
+ [
1061
+ {
1062
+ type: 1 /* SET_PARENT_KEY */,
1063
+ id: nn(item._id),
1064
+ opId: this._pool.generateOpId(),
1065
+ parentKey: position
1066
+ }
1067
+ ],
1068
+ [
1069
+ {
1070
+ type: 1 /* SET_PARENT_KEY */,
1071
+ id: nn(item._id),
1072
+ parentKey: previousPosition
1073
+ }
1074
+ ],
1075
+ storageUpdates
1076
+ );
1077
+ }
1078
+ }
1079
+ delete(index) {
1080
+ if (index < 0 || index >= this._items.length) {
1081
+ throw new Error(
1082
+ `Cannot delete list item at index "${index}". index should be between 0 and ${this._items.length - 1}`
1083
+ );
1084
+ }
1085
+ const item = this._items[index];
1086
+ item._detach();
1087
+ this._items.splice(index, 1);
1088
+ this.invalidate();
1089
+ if (this._pool) {
1090
+ const childRecordId = item._id;
1091
+ if (childRecordId) {
1092
+ const storageUpdates = /* @__PURE__ */ new Map();
1093
+ storageUpdates.set(
1094
+ nn(this._id),
1095
+ makeUpdate(this, [deleteDelta(index)])
1096
+ );
1097
+ this._pool.dispatch(
1098
+ [
1099
+ {
1100
+ id: childRecordId,
1101
+ opId: this._pool.generateOpId(),
1102
+ type: 5 /* DELETE_CRDT */
1103
+ }
1104
+ ],
1105
+ item._toOps(nn(this._id), item._getParentKeyOrThrow()),
1106
+ storageUpdates
1107
+ );
1108
+ }
1109
+ }
1110
+ }
1111
+ clear() {
1112
+ if (this._pool) {
1113
+ const ops = [];
1114
+ const reverseOps = [];
1115
+ const updateDelta = [];
1116
+ for (const item of this._items) {
1117
+ item._detach();
1118
+ const childId = item._id;
1119
+ if (childId) {
1120
+ ops.push({
1121
+ type: 5 /* DELETE_CRDT */,
1122
+ id: childId,
1123
+ opId: this._pool.generateOpId()
1124
+ });
1125
+ reverseOps.push(
1126
+ ...item._toOps(nn(this._id), item._getParentKeyOrThrow())
1127
+ );
1128
+ updateDelta.push(deleteDelta(0));
1129
+ }
1130
+ }
1131
+ this._items = [];
1132
+ this.invalidate();
1133
+ const storageUpdates = /* @__PURE__ */ new Map();
1134
+ storageUpdates.set(nn(this._id), makeUpdate(this, updateDelta));
1135
+ this._pool.dispatch(ops, reverseOps, storageUpdates);
1136
+ } else {
1137
+ for (const item of this._items) {
1138
+ item._detach();
1139
+ }
1140
+ this._items = [];
1141
+ this.invalidate();
1142
+ }
1143
+ }
1144
+ set(index, item) {
1145
+ if (index < 0 || index >= this._items.length) {
1146
+ throw new Error(
1147
+ `Cannot set list item at index "${index}". index should be between 0 and ${this._items.length - 1}`
1148
+ );
1149
+ }
1150
+ const existingItem = this._items[index];
1151
+ const position = existingItem._getParentKeyOrThrow();
1152
+ const existingId = existingItem._id;
1153
+ existingItem._detach();
1154
+ const value = lsonToLiveNode(item);
1155
+ value._setParentLink(this, position);
1156
+ this._items[index] = value;
1157
+ this.invalidate();
1158
+ if (this._pool && this._id) {
1159
+ const id = this._pool.generateId();
1160
+ value._attach(id, this._pool);
1161
+ const storageUpdates = /* @__PURE__ */ new Map();
1162
+ storageUpdates.set(this._id, makeUpdate(this, [setDelta(index, value)]));
1163
+ const ops = value._toOps(this._id, position, this._pool);
1164
+ addIntentAndDeletedIdToOperation(ops, existingId);
1165
+ this._unacknowledgedSets.set(position, nn(ops[0].opId));
1166
+ const reverseOps = existingItem._toOps(this._id, position, void 0);
1167
+ addIntentAndDeletedIdToOperation(reverseOps, id);
1168
+ this._pool.dispatch(ops, reverseOps, storageUpdates);
1169
+ }
1170
+ }
1171
+ toArray() {
1172
+ return this._items.map(
1173
+ (entry) => liveNodeToLson(entry)
1174
+ );
1175
+ }
1176
+ every(predicate) {
1177
+ return this.toArray().every(predicate);
1178
+ }
1179
+ filter(predicate) {
1180
+ return this.toArray().filter(predicate);
1181
+ }
1182
+ find(predicate) {
1183
+ return this.toArray().find(predicate);
1184
+ }
1185
+ findIndex(predicate) {
1186
+ return this.toArray().findIndex(predicate);
1187
+ }
1188
+ forEach(callbackfn) {
1189
+ return this.toArray().forEach(callbackfn);
1190
+ }
1191
+ get(index) {
1192
+ if (index < 0 || index >= this._items.length) {
1193
+ return void 0;
1194
+ }
1195
+ return liveNodeToLson(this._items[index]);
1196
+ }
1197
+ indexOf(searchElement, fromIndex) {
1198
+ return this.toArray().indexOf(searchElement, fromIndex);
1199
+ }
1200
+ lastIndexOf(searchElement, fromIndex) {
1201
+ return this.toArray().lastIndexOf(searchElement, fromIndex);
1202
+ }
1203
+ map(callback) {
1204
+ return this._items.map(
1205
+ (entry, i) => callback(
1206
+ liveNodeToLson(entry),
1207
+ i
1208
+ )
1209
+ );
1210
+ }
1211
+ some(predicate) {
1212
+ return this.toArray().some(predicate);
1213
+ }
1214
+ [Symbol.iterator]() {
1215
+ return new LiveListIterator(this._items);
1216
+ }
1217
+ _createAttachItemAndSort(op, key) {
1218
+ const newItem = creationOpToLiveNode(op);
1219
+ newItem._attach(op.id, nn(this._pool));
1220
+ newItem._setParentLink(this, key);
1221
+ this._insertAndSort(newItem);
1222
+ const newIndex = this._indexOfPosition(key);
1223
+ return { newItem, newIndex };
1224
+ }
1225
+ _shiftItemPosition(index, key) {
1226
+ var _a;
1227
+ const shiftedPosition = makePosition(
1228
+ key,
1229
+ this._items.length > index + 1 ? (_a = this._items[index + 1]) == null ? void 0 : _a._getParentKeyOrThrow() : void 0
1230
+ );
1231
+ this._items[index]._setParentLink(this, shiftedPosition);
1232
+ }
1233
+ toImmutable() {
1234
+ return super.toImmutable();
1235
+ }
1236
+ _toImmutable() {
1237
+ const result = this._items.map((node) => node.toImmutable());
1238
+ return process.env.NODE_ENV === "production" ? result : Object.freeze(result);
1239
+ }
1240
+ };
1241
+ var LiveListIterator = class {
1242
+ constructor(items) {
1243
+ this._innerIterator = items[Symbol.iterator]();
1244
+ }
1245
+ [Symbol.iterator]() {
1246
+ return this;
1247
+ }
1248
+ next() {
1249
+ const result = this._innerIterator.next();
1250
+ if (result.done) {
1251
+ return {
1252
+ done: true,
1253
+ value: void 0
1254
+ };
1255
+ }
1256
+ const value = liveNodeToLson(result.value);
1257
+ return { value };
1258
+ }
1259
+ };
1260
+ function makeUpdate(liveList, deltaUpdates) {
1261
+ return {
1262
+ node: liveList,
1263
+ type: "LiveList",
1264
+ updates: deltaUpdates
1265
+ };
1266
+ }
1267
+ function setDelta(index, item) {
1268
+ return {
1269
+ index,
1270
+ type: "set",
1271
+ item: item instanceof LiveRegister ? item.data : item
1272
+ };
1273
+ }
1274
+ function deleteDelta(index) {
1275
+ return {
1276
+ index,
1277
+ type: "delete"
1278
+ };
1279
+ }
1280
+ function insertDelta(index, item) {
1281
+ return {
1282
+ index,
1283
+ type: "insert",
1284
+ item: item instanceof LiveRegister ? item.data : item
1285
+ };
1286
+ }
1287
+ function moveDelta(previousIndex, index, item) {
1288
+ return {
1289
+ index,
1290
+ type: "move",
1291
+ previousIndex,
1292
+ item: item instanceof LiveRegister ? item.data : item
1293
+ };
1294
+ }
1295
+ function addIntentAndDeletedIdToOperation(ops, deletedId) {
1296
+ if (ops.length === 0) {
1297
+ throw new Error(
1298
+ "Internal error. Serialized LiveStructure should have at least 1 operation"
1299
+ );
1300
+ }
1301
+ const firstOp = ops[0];
1302
+ firstOp.intent = "set";
1303
+ firstOp.deletedId = deletedId;
1304
+ }
1305
+
1306
+ // src/LiveMap.ts
1307
+ var LiveMap = class extends AbstractCrdt {
1308
+ constructor(entries2) {
1309
+ super();
1310
+ this.unacknowledgedSet = /* @__PURE__ */ new Map();
1311
+ if (entries2) {
1312
+ const mappedEntries = [];
1313
+ for (const entry of entries2) {
1314
+ const value = lsonToLiveNode(entry[1]);
1315
+ value._setParentLink(this, entry[0]);
1316
+ mappedEntries.push([entry[0], value]);
1317
+ }
1318
+ this._map = new Map(mappedEntries);
1319
+ } else {
1320
+ this._map = /* @__PURE__ */ new Map();
1321
+ }
1322
+ }
1323
+ _toOps(parentId, parentKey, pool) {
1324
+ if (this._id === void 0) {
1325
+ throw new Error("Cannot serialize item is not attached");
1326
+ }
1327
+ const ops = [];
1328
+ const op = {
1329
+ id: this._id,
1330
+ opId: pool == null ? void 0 : pool.generateOpId(),
1331
+ type: 7 /* CREATE_MAP */,
1332
+ parentId,
1333
+ parentKey
1334
+ };
1335
+ ops.push(op);
1336
+ for (const [key, value] of this._map) {
1337
+ ops.push(...value._toOps(this._id, key, pool));
1338
+ }
1339
+ return ops;
1340
+ }
1341
+ static _deserialize([id, _item], parentToChildren, pool) {
1342
+ const map = new LiveMap();
1343
+ map._attach(id, pool);
1344
+ const children = parentToChildren.get(id);
1345
+ if (children === void 0) {
1346
+ return map;
1347
+ }
1348
+ for (const [id2, crdt] of children) {
1349
+ const child = deserialize([id2, crdt], parentToChildren, pool);
1350
+ child._setParentLink(map, crdt.parentKey);
1351
+ map._map.set(crdt.parentKey, child);
1352
+ map.invalidate();
1353
+ }
1354
+ return map;
1355
+ }
1356
+ _attach(id, pool) {
1357
+ super._attach(id, pool);
1358
+ for (const [_key, value] of this._map) {
1359
+ if (isLiveNode(value)) {
1360
+ value._attach(pool.generateId(), pool);
1361
+ }
1362
+ }
1363
+ }
1364
+ _attachChild(op, source) {
1365
+ if (this._pool === void 0) {
1366
+ throw new Error("Can't attach child if managed pool is not present");
1367
+ }
1368
+ const { id, parentKey, opId } = op;
1369
+ const key = parentKey;
1370
+ const child = creationOpToLiveNode(op);
1371
+ if (this._pool.getNode(id) !== void 0) {
1372
+ return { modified: false };
1373
+ }
1374
+ if (source === 2 /* ACK */) {
1375
+ const lastUpdateOpId = this.unacknowledgedSet.get(key);
1376
+ if (lastUpdateOpId === opId) {
1377
+ this.unacknowledgedSet.delete(key);
1378
+ return { modified: false };
1379
+ } else if (lastUpdateOpId !== void 0) {
1380
+ return { modified: false };
1381
+ }
1382
+ } else if (source === 1 /* REMOTE */) {
1383
+ this.unacknowledgedSet.delete(key);
1384
+ }
1385
+ const previousValue = this._map.get(key);
1386
+ let reverse;
1387
+ if (previousValue) {
1388
+ const thisId = nn(this._id);
1389
+ reverse = previousValue._toOps(thisId, key);
1390
+ previousValue._detach();
1391
+ } else {
1392
+ reverse = [{ type: 5 /* DELETE_CRDT */, id }];
1393
+ }
1394
+ child._setParentLink(this, key);
1395
+ child._attach(id, this._pool);
1396
+ this._map.set(key, child);
1397
+ this.invalidate();
1398
+ return {
1399
+ modified: {
1400
+ node: this,
1401
+ type: "LiveMap",
1402
+ updates: { [key]: { type: "update" } }
1403
+ },
1404
+ reverse
1405
+ };
1406
+ }
1407
+ _detach() {
1408
+ super._detach();
1409
+ for (const item of this._map.values()) {
1410
+ item._detach();
1411
+ }
1412
+ }
1413
+ _detachChild(child) {
1414
+ const id = nn(this._id);
1415
+ const parentKey = nn(child._parentKey);
1416
+ const reverse = child._toOps(id, parentKey, this._pool);
1417
+ for (const [key, value] of this._map) {
1418
+ if (value === child) {
1419
+ this._map.delete(key);
1420
+ this.invalidate();
1421
+ }
1422
+ }
1423
+ child._detach();
1424
+ const storageUpdate = {
1425
+ node: this,
1426
+ type: "LiveMap",
1427
+ updates: { [parentKey]: { type: "delete" } }
1428
+ };
1429
+ return { modified: storageUpdate, reverse };
1430
+ }
1431
+ _serialize() {
1432
+ if (this.parent.type !== "HasParent") {
1433
+ throw new Error("Cannot serialize LiveMap if parent is missing");
1434
+ }
1435
+ return {
1436
+ type: 2 /* MAP */,
1437
+ parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
1438
+ parentKey: this.parent.key
1439
+ };
1440
+ }
1441
+ get(key) {
1442
+ const value = this._map.get(key);
1443
+ if (value === void 0) {
1444
+ return void 0;
1445
+ }
1446
+ return liveNodeToLson(value);
1447
+ }
1448
+ set(key, value) {
1449
+ const oldValue = this._map.get(key);
1450
+ if (oldValue) {
1451
+ oldValue._detach();
1452
+ }
1453
+ const item = lsonToLiveNode(value);
1454
+ item._setParentLink(this, key);
1455
+ this._map.set(key, item);
1456
+ this.invalidate();
1457
+ if (this._pool && this._id) {
1458
+ const id = this._pool.generateId();
1459
+ item._attach(id, this._pool);
1460
+ const storageUpdates = /* @__PURE__ */ new Map();
1461
+ storageUpdates.set(this._id, {
1462
+ node: this,
1463
+ type: "LiveMap",
1464
+ updates: { [key]: { type: "update" } }
1465
+ });
1466
+ const ops = item._toOps(this._id, key, this._pool);
1467
+ this.unacknowledgedSet.set(key, nn(ops[0].opId));
1468
+ this._pool.dispatch(
1469
+ item._toOps(this._id, key, this._pool),
1470
+ oldValue ? oldValue._toOps(this._id, key) : [{ type: 5 /* DELETE_CRDT */, id }],
1471
+ storageUpdates
1472
+ );
1473
+ }
1474
+ }
1475
+ get size() {
1476
+ return this._map.size;
1477
+ }
1478
+ has(key) {
1479
+ return this._map.has(key);
1480
+ }
1481
+ delete(key) {
1482
+ const item = this._map.get(key);
1483
+ if (item === void 0) {
1484
+ return false;
1485
+ }
1486
+ item._detach();
1487
+ this._map.delete(key);
1488
+ this.invalidate();
1489
+ if (this._pool && item._id) {
1490
+ const thisId = nn(this._id);
1491
+ const storageUpdates = /* @__PURE__ */ new Map();
1492
+ storageUpdates.set(thisId, {
1493
+ node: this,
1494
+ type: "LiveMap",
1495
+ updates: { [key]: { type: "delete" } }
1496
+ });
1497
+ this._pool.dispatch(
1498
+ [
1499
+ {
1500
+ type: 5 /* DELETE_CRDT */,
1501
+ id: item._id,
1502
+ opId: this._pool.generateOpId()
1503
+ }
1504
+ ],
1505
+ item._toOps(thisId, key),
1506
+ storageUpdates
1507
+ );
1508
+ }
1509
+ return true;
1510
+ }
1511
+ entries() {
1512
+ const innerIterator = this._map.entries();
1513
+ return {
1514
+ [Symbol.iterator]() {
1515
+ return this;
1516
+ },
1517
+ next() {
1518
+ const iteratorValue = innerIterator.next();
1519
+ if (iteratorValue.done) {
1520
+ return {
1521
+ done: true,
1522
+ value: void 0
1523
+ };
1524
+ }
1525
+ const entry = iteratorValue.value;
1526
+ const key = entry[0];
1527
+ const value = liveNodeToLson(iteratorValue.value[1]);
1528
+ return {
1529
+ value: [key, value]
1530
+ };
1531
+ }
1532
+ };
1533
+ }
1534
+ [Symbol.iterator]() {
1535
+ return this.entries();
1536
+ }
1537
+ keys() {
1538
+ return this._map.keys();
1539
+ }
1540
+ values() {
1541
+ const innerIterator = this._map.values();
1542
+ return {
1543
+ [Symbol.iterator]() {
1544
+ return this;
1545
+ },
1546
+ next() {
1547
+ const iteratorValue = innerIterator.next();
1548
+ if (iteratorValue.done) {
1549
+ return {
1550
+ done: true,
1551
+ value: void 0
1552
+ };
1553
+ }
1554
+ const value = liveNodeToLson(iteratorValue.value);
1555
+ return { value };
1556
+ }
1557
+ };
1558
+ }
1559
+ forEach(callback) {
1560
+ for (const entry of this) {
1561
+ callback(entry[1], entry[0], this);
1562
+ }
1563
+ }
1564
+ toImmutable() {
1565
+ return super.toImmutable();
1566
+ }
1567
+ _toImmutable() {
1568
+ const result = /* @__PURE__ */ new Map();
1569
+ for (const [key, value] of this._map) {
1570
+ result.set(key, value.toImmutable());
1571
+ }
1572
+ return freeze(result);
1573
+ }
1574
+ };
1575
+
1576
+ // src/LiveObject.ts
1577
+ var LiveObject = class extends AbstractCrdt {
1578
+ constructor(obj = {}) {
1579
+ super();
1580
+ this._propToLastUpdate = /* @__PURE__ */ new Map();
1581
+ for (const key in obj) {
1582
+ const value = obj[key];
1583
+ if (value === void 0) {
1584
+ continue;
1585
+ } else if (isLiveNode(value)) {
1586
+ value._setParentLink(this, key);
1587
+ }
1588
+ }
1589
+ this._map = new Map(Object.entries(obj));
1590
+ }
1591
+ _toOps(parentId, parentKey, pool) {
1592
+ if (this._id === void 0) {
1593
+ throw new Error("Cannot serialize item is not attached");
1594
+ }
1595
+ const opId = pool == null ? void 0 : pool.generateOpId();
1596
+ const ops = [];
1597
+ const op = parentId !== void 0 && parentKey !== void 0 ? {
1598
+ type: 4 /* CREATE_OBJECT */,
1599
+ id: this._id,
1600
+ opId,
1601
+ parentId,
1602
+ parentKey,
1603
+ data: {}
1604
+ } : { type: 4 /* CREATE_OBJECT */, id: this._id, opId, data: {} };
1605
+ ops.push(op);
1606
+ for (const [key, value] of this._map) {
1607
+ if (isLiveNode(value)) {
1608
+ ops.push(...value._toOps(this._id, key, pool));
1609
+ } else {
1610
+ op.data[key] = value;
1611
+ }
1612
+ }
1613
+ return ops;
1614
+ }
1615
+ static _deserialize([id, item], parentToChildren, pool) {
1616
+ const liveObj = new LiveObject(item.data);
1617
+ liveObj._attach(id, pool);
1618
+ return this._deserializeChildren(liveObj, parentToChildren, pool);
1619
+ }
1620
+ static _deserializeChildren(liveObj, parentToChildren, pool) {
1621
+ const children = parentToChildren.get(nn(liveObj._id));
1622
+ if (children === void 0) {
1623
+ return liveObj;
1624
+ }
1625
+ for (const [id, crdt] of children) {
1626
+ const child = deserializeToLson([id, crdt], parentToChildren, pool);
1627
+ if (isLiveStructure(child)) {
1628
+ child._setParentLink(liveObj, crdt.parentKey);
1629
+ }
1630
+ liveObj._map.set(crdt.parentKey, child);
1631
+ liveObj.invalidate();
1632
+ }
1633
+ return liveObj;
1634
+ }
1635
+ _attach(id, pool) {
1636
+ super._attach(id, pool);
1637
+ for (const [_key, value] of this._map) {
1638
+ if (isLiveNode(value)) {
1639
+ value._attach(pool.generateId(), pool);
1640
+ }
1641
+ }
1642
+ }
1643
+ _attachChild(op, source) {
1644
+ if (this._pool === void 0) {
1645
+ throw new Error("Can't attach child if managed pool is not present");
1646
+ }
1647
+ const { id, opId, parentKey: key } = op;
1648
+ const child = creationOpToLson(op);
1649
+ if (this._pool.getNode(id) !== void 0) {
1650
+ if (this._propToLastUpdate.get(key) === opId) {
1651
+ this._propToLastUpdate.delete(key);
1652
+ }
1653
+ return { modified: false };
1654
+ }
1655
+ if (source === 0 /* UNDOREDO_RECONNECT */) {
1656
+ this._propToLastUpdate.set(key, nn(opId));
1657
+ } else if (this._propToLastUpdate.get(key) === void 0) {
1658
+ } else if (this._propToLastUpdate.get(key) === opId) {
1659
+ this._propToLastUpdate.delete(key);
1660
+ return { modified: false };
1661
+ } else {
1662
+ return { modified: false };
1663
+ }
1664
+ const thisId = nn(this._id);
1665
+ const previousValue = this._map.get(key);
1666
+ let reverse;
1667
+ if (isLiveNode(previousValue)) {
1668
+ reverse = previousValue._toOps(thisId, key);
1669
+ previousValue._detach();
1670
+ } else if (previousValue === void 0) {
1671
+ reverse = [{ type: 6 /* DELETE_OBJECT_KEY */, id: thisId, key }];
1672
+ } else {
1673
+ reverse = [
1674
+ {
1675
+ type: 3 /* UPDATE_OBJECT */,
1676
+ id: thisId,
1677
+ data: { [key]: previousValue }
1678
+ }
1679
+ ];
1680
+ }
1681
+ this._map.set(key, child);
1682
+ this.invalidate();
1683
+ if (isLiveStructure(child)) {
1684
+ child._setParentLink(this, key);
1685
+ child._attach(id, this._pool);
1686
+ }
1687
+ return {
1688
+ reverse,
1689
+ modified: {
1690
+ node: this,
1691
+ type: "LiveObject",
1692
+ updates: { [key]: { type: "update" } }
1693
+ }
1694
+ };
1695
+ }
1696
+ _detachChild(child) {
1697
+ if (child) {
1698
+ const id = nn(this._id);
1699
+ const parentKey = nn(child._parentKey);
1700
+ const reverse = child._toOps(id, parentKey, this._pool);
1701
+ for (const [key, value] of this._map) {
1702
+ if (value === child) {
1703
+ this._map.delete(key);
1704
+ this.invalidate();
1705
+ }
1706
+ }
1707
+ child._detach();
1708
+ const storageUpdate = {
1709
+ node: this,
1710
+ type: "LiveObject",
1711
+ updates: {
1712
+ [parentKey]: { type: "delete" }
1713
+ }
1714
+ };
1715
+ return { modified: storageUpdate, reverse };
1716
+ }
1717
+ return { modified: false };
1718
+ }
1719
+ _detach() {
1720
+ super._detach();
1721
+ for (const value of this._map.values()) {
1722
+ if (isLiveNode(value)) {
1723
+ value._detach();
1724
+ }
1725
+ }
1726
+ }
1727
+ _apply(op, isLocal) {
1728
+ if (op.type === 3 /* UPDATE_OBJECT */) {
1729
+ return this._applyUpdate(op, isLocal);
1730
+ } else if (op.type === 6 /* DELETE_OBJECT_KEY */) {
1731
+ return this._applyDeleteObjectKey(op);
1732
+ }
1733
+ return super._apply(op, isLocal);
1734
+ }
1735
+ _serialize() {
1736
+ const data = {};
1737
+ for (const [key, value] of this._map) {
1738
+ if (!isLiveNode(value)) {
1739
+ data[key] = value;
1740
+ }
1741
+ }
1742
+ if (this.parent.type === "HasParent" && this.parent.node._id) {
1743
+ return {
1744
+ type: 0 /* OBJECT */,
1745
+ parentId: this.parent.node._id,
1746
+ parentKey: this.parent.key,
1747
+ data
1748
+ };
1749
+ } else {
1750
+ return {
1751
+ type: 0 /* OBJECT */,
1752
+ data
1753
+ };
1754
+ }
1755
+ }
1756
+ _applyUpdate(op, isLocal) {
1757
+ let isModified = false;
1758
+ const id = nn(this._id);
1759
+ const reverse = [];
1760
+ const reverseUpdate = {
1761
+ type: 3 /* UPDATE_OBJECT */,
1762
+ id,
1763
+ data: {}
1764
+ };
1765
+ reverse.push(reverseUpdate);
1766
+ for (const key in op.data) {
1767
+ const oldValue = this._map.get(key);
1768
+ if (isLiveNode(oldValue)) {
1769
+ reverse.push(...oldValue._toOps(id, key));
1770
+ oldValue._detach();
1771
+ } else if (oldValue !== void 0) {
1772
+ reverseUpdate.data[key] = oldValue;
1773
+ } else if (oldValue === void 0) {
1774
+ reverse.push({ type: 6 /* DELETE_OBJECT_KEY */, id, key });
1775
+ }
1776
+ }
1777
+ const updateDelta = {};
1778
+ for (const key in op.data) {
1779
+ const value = op.data[key];
1780
+ if (value === void 0) {
1781
+ continue;
1782
+ }
1783
+ if (isLocal) {
1784
+ this._propToLastUpdate.set(key, nn(op.opId));
1785
+ } else if (this._propToLastUpdate.get(key) === void 0) {
1786
+ isModified = true;
1787
+ } else if (this._propToLastUpdate.get(key) === op.opId) {
1788
+ this._propToLastUpdate.delete(key);
1789
+ continue;
1790
+ } else {
1791
+ continue;
1792
+ }
1793
+ const oldValue = this._map.get(key);
1794
+ if (isLiveNode(oldValue)) {
1795
+ oldValue._detach();
1796
+ }
1797
+ isModified = true;
1798
+ updateDelta[key] = { type: "update" };
1799
+ this._map.set(key, value);
1800
+ this.invalidate();
1801
+ }
1802
+ if (Object.keys(reverseUpdate.data).length !== 0) {
1803
+ reverse.unshift(reverseUpdate);
1804
+ }
1805
+ return isModified ? {
1806
+ modified: {
1807
+ node: this,
1808
+ type: "LiveObject",
1809
+ updates: updateDelta
1810
+ },
1811
+ reverse
1812
+ } : { modified: false };
1813
+ }
1814
+ _applyDeleteObjectKey(op) {
1815
+ const key = op.key;
1816
+ if (this._map.has(key) === false) {
1817
+ return { modified: false };
1818
+ }
1819
+ if (this._propToLastUpdate.get(key) !== void 0) {
1820
+ return { modified: false };
1821
+ }
1822
+ const oldValue = this._map.get(key);
1823
+ const id = nn(this._id);
1824
+ let reverse = [];
1825
+ if (isLiveNode(oldValue)) {
1826
+ reverse = oldValue._toOps(id, op.key);
1827
+ oldValue._detach();
1828
+ } else if (oldValue !== void 0) {
1829
+ reverse = [
1830
+ {
1831
+ type: 3 /* UPDATE_OBJECT */,
1832
+ id,
1833
+ data: { [key]: oldValue }
1834
+ }
1835
+ ];
1836
+ }
1837
+ this._map.delete(key);
1838
+ this.invalidate();
1839
+ return {
1840
+ modified: {
1841
+ node: this,
1842
+ type: "LiveObject",
1843
+ updates: { [op.key]: { type: "delete" } }
1844
+ },
1845
+ reverse
1846
+ };
1847
+ }
1848
+ toObject() {
1849
+ return fromEntries(this._map);
1850
+ }
1851
+ set(key, value) {
1852
+ this.update({ [key]: value });
1853
+ }
1854
+ get(key) {
1855
+ return this._map.get(key);
1856
+ }
1857
+ delete(key) {
1858
+ const keyAsString = key;
1859
+ const oldValue = this._map.get(keyAsString);
1860
+ if (oldValue === void 0) {
1861
+ return;
1862
+ }
1863
+ if (this._pool === void 0 || this._id === void 0) {
1864
+ if (isLiveNode(oldValue)) {
1865
+ oldValue._detach();
1866
+ }
1867
+ this._map.delete(keyAsString);
1868
+ this.invalidate();
1869
+ return;
1870
+ }
1871
+ let reverse;
1872
+ if (isLiveNode(oldValue)) {
1873
+ oldValue._detach();
1874
+ reverse = oldValue._toOps(this._id, keyAsString);
1875
+ } else {
1876
+ reverse = [
1877
+ {
1878
+ type: 3 /* UPDATE_OBJECT */,
1879
+ data: { [keyAsString]: oldValue },
1880
+ id: this._id
1881
+ }
1882
+ ];
1883
+ }
1884
+ this._map.delete(keyAsString);
1885
+ this.invalidate();
1886
+ const storageUpdates = /* @__PURE__ */ new Map();
1887
+ storageUpdates.set(this._id, {
1888
+ node: this,
1889
+ type: "LiveObject",
1890
+ updates: { [key]: { type: "delete" } }
1891
+ });
1892
+ this._pool.dispatch(
1893
+ [
1894
+ {
1895
+ type: 6 /* DELETE_OBJECT_KEY */,
1896
+ key: keyAsString,
1897
+ id: this._id,
1898
+ opId: this._pool.generateOpId()
1899
+ }
1900
+ ],
1901
+ reverse,
1902
+ storageUpdates
1903
+ );
1904
+ }
1905
+ update(patch) {
1906
+ if (this._pool === void 0 || this._id === void 0) {
1907
+ for (const key in patch) {
1908
+ const newValue = patch[key];
1909
+ if (newValue === void 0) {
1910
+ continue;
1911
+ }
1912
+ const oldValue = this._map.get(key);
1913
+ if (isLiveNode(oldValue)) {
1914
+ oldValue._detach();
1915
+ }
1916
+ if (isLiveNode(newValue)) {
1917
+ newValue._setParentLink(this, key);
1918
+ }
1919
+ this._map.set(key, newValue);
1920
+ this.invalidate();
1921
+ }
1922
+ return;
1923
+ }
1924
+ const ops = [];
1925
+ const reverseOps = [];
1926
+ const opId = this._pool.generateOpId();
1927
+ const updatedProps = {};
1928
+ const reverseUpdateOp = {
1929
+ id: this._id,
1930
+ type: 3 /* UPDATE_OBJECT */,
1931
+ data: {}
1932
+ };
1933
+ const updateDelta = {};
1934
+ for (const key in patch) {
1935
+ const newValue = patch[key];
1936
+ if (newValue === void 0) {
1937
+ continue;
1938
+ }
1939
+ const oldValue = this._map.get(key);
1940
+ if (isLiveNode(oldValue)) {
1941
+ reverseOps.push(...oldValue._toOps(this._id, key));
1942
+ oldValue._detach();
1943
+ } else if (oldValue === void 0) {
1944
+ reverseOps.push({ type: 6 /* DELETE_OBJECT_KEY */, id: this._id, key });
1945
+ } else {
1946
+ reverseUpdateOp.data[key] = oldValue;
1947
+ }
1948
+ if (isLiveNode(newValue)) {
1949
+ newValue._setParentLink(this, key);
1950
+ newValue._attach(this._pool.generateId(), this._pool);
1951
+ const newAttachChildOps = newValue._toOps(this._id, key, this._pool);
1952
+ const createCrdtOp = newAttachChildOps.find(
1953
+ (op) => op.parentId === this._id
1954
+ );
1955
+ if (createCrdtOp) {
1956
+ this._propToLastUpdate.set(key, nn(createCrdtOp.opId));
1957
+ }
1958
+ ops.push(...newAttachChildOps);
1959
+ } else {
1960
+ updatedProps[key] = newValue;
1961
+ this._propToLastUpdate.set(key, opId);
1962
+ }
1963
+ this._map.set(key, newValue);
1964
+ this.invalidate();
1965
+ updateDelta[key] = { type: "update" };
1966
+ }
1967
+ if (Object.keys(reverseUpdateOp.data).length !== 0) {
1968
+ reverseOps.unshift(reverseUpdateOp);
1969
+ }
1970
+ if (Object.keys(updatedProps).length !== 0) {
1971
+ ops.unshift({
1972
+ opId,
1973
+ id: this._id,
1974
+ type: 3 /* UPDATE_OBJECT */,
1975
+ data: updatedProps
1976
+ });
1977
+ }
1978
+ const storageUpdates = /* @__PURE__ */ new Map();
1979
+ storageUpdates.set(this._id, {
1980
+ node: this,
1981
+ type: "LiveObject",
1982
+ updates: updateDelta
1983
+ });
1984
+ this._pool.dispatch(ops, reverseOps, storageUpdates);
1985
+ }
1986
+ toImmutable() {
1987
+ return super.toImmutable();
1988
+ }
1989
+ _toImmutable() {
1990
+ const result = {};
1991
+ for (const [key, val] of this._map) {
1992
+ result[key] = isLiveStructure(val) ? val.toImmutable() : val;
1993
+ }
1994
+ return process.env.NODE_ENV === "production" ? result : Object.freeze(result);
1995
+ }
1996
+ };
1997
+
1998
+ // src/utils.ts
1999
+ var freeze = process.env.NODE_ENV === "production" ? (x) => x : Object.freeze;
2000
+ function compact(items) {
2001
+ return items.filter(
2002
+ (item) => item !== null && item !== void 0
2003
+ );
2004
+ }
2005
+ function compactObject(obj) {
2006
+ const newObj = __spreadValues({}, obj);
2007
+ Object.keys(obj).forEach((k) => {
2008
+ const key = k;
2009
+ if (newObj[key] === void 0) {
2010
+ delete newObj[key];
2011
+ }
2012
+ });
2013
+ return newObj;
2014
+ }
2015
+ function creationOpToLiveNode(op) {
2016
+ return lsonToLiveNode(creationOpToLson(op));
2017
+ }
2018
+ function creationOpToLson(op) {
2019
+ switch (op.type) {
2020
+ case 8 /* CREATE_REGISTER */:
2021
+ return op.data;
2022
+ case 4 /* CREATE_OBJECT */:
2023
+ return new LiveObject(op.data);
2024
+ case 7 /* CREATE_MAP */:
2025
+ return new LiveMap();
2026
+ case 2 /* CREATE_LIST */:
2027
+ return new LiveList();
2028
+ default:
2029
+ return assertNever(op, "Unknown creation Op");
2030
+ }
2031
+ }
2032
+ function isSameNodeOrChildOf(node, parent) {
2033
+ if (node === parent) {
2034
+ return true;
2035
+ }
2036
+ if (node.parent.type === "HasParent") {
2037
+ return isSameNodeOrChildOf(node.parent.node, parent);
2038
+ }
2039
+ return false;
2040
+ }
2041
+ function deserialize([id, crdt], parentToChildren, pool) {
2042
+ switch (crdt.type) {
2043
+ case 0 /* OBJECT */: {
2044
+ return LiveObject._deserialize([id, crdt], parentToChildren, pool);
2045
+ }
2046
+ case 1 /* LIST */: {
2047
+ return LiveList._deserialize([id, crdt], parentToChildren, pool);
2048
+ }
2049
+ case 2 /* MAP */: {
2050
+ return LiveMap._deserialize([id, crdt], parentToChildren, pool);
2051
+ }
2052
+ case 3 /* REGISTER */: {
2053
+ return LiveRegister._deserialize([id, crdt], parentToChildren, pool);
2054
+ }
2055
+ default: {
2056
+ throw new Error("Unexpected CRDT type");
2057
+ }
2058
+ }
2059
+ }
2060
+ function deserializeToLson([id, crdt], parentToChildren, pool) {
2061
+ switch (crdt.type) {
2062
+ case 0 /* OBJECT */: {
2063
+ return LiveObject._deserialize([id, crdt], parentToChildren, pool);
2064
+ }
2065
+ case 1 /* LIST */: {
2066
+ return LiveList._deserialize([id, crdt], parentToChildren, pool);
2067
+ }
2068
+ case 2 /* MAP */: {
2069
+ return LiveMap._deserialize([id, crdt], parentToChildren, pool);
2070
+ }
2071
+ case 3 /* REGISTER */: {
2072
+ return crdt.data;
2073
+ }
2074
+ default: {
2075
+ throw new Error("Unexpected CRDT type");
2076
+ }
2077
+ }
2078
+ }
2079
+ function isLiveStructure(value) {
2080
+ return isLiveList(value) || isLiveMap(value) || isLiveObject(value);
2081
+ }
2082
+ function isLiveNode(value) {
2083
+ return isLiveStructure(value) || isLiveRegister(value);
2084
+ }
2085
+ function isLiveList(value) {
2086
+ return value instanceof LiveList;
2087
+ }
2088
+ function isLiveMap(value) {
2089
+ return value instanceof LiveMap;
2090
+ }
2091
+ function isLiveObject(value) {
2092
+ return value instanceof LiveObject;
2093
+ }
2094
+ function isLiveRegister(value) {
2095
+ return value instanceof LiveRegister;
2096
+ }
2097
+ function liveNodeToLson(obj) {
2098
+ if (obj instanceof LiveRegister) {
2099
+ return obj.data;
2100
+ } else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject) {
2101
+ return obj;
2102
+ } else {
2103
+ return assertNever(obj, "Unknown AbstractCrdt");
2104
+ }
2105
+ }
2106
+ function lsonToLiveNode(value) {
2107
+ if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList) {
2108
+ return value;
2109
+ } else {
2110
+ return new LiveRegister(value);
2111
+ }
2112
+ }
2113
+ function getTreesDiffOperations(currentItems, newItems) {
2114
+ const ops = [];
2115
+ currentItems.forEach((_, id) => {
2116
+ if (!newItems.get(id)) {
2117
+ ops.push({
2118
+ type: 5 /* DELETE_CRDT */,
2119
+ id
2120
+ });
2121
+ }
2122
+ });
2123
+ newItems.forEach((crdt, id) => {
2124
+ const currentCrdt = currentItems.get(id);
2125
+ if (currentCrdt) {
2126
+ if (crdt.type === 0 /* OBJECT */) {
2127
+ if (currentCrdt.type !== 0 /* OBJECT */ || JSON.stringify(crdt.data) !== JSON.stringify(currentCrdt.data)) {
2128
+ ops.push({
2129
+ type: 3 /* UPDATE_OBJECT */,
2130
+ id,
2131
+ data: crdt.data
2132
+ });
2133
+ }
2134
+ }
2135
+ if (crdt.parentKey !== currentCrdt.parentKey) {
2136
+ ops.push({
2137
+ type: 1 /* SET_PARENT_KEY */,
2138
+ id,
2139
+ parentKey: nn(crdt.parentKey, "Parent key must not be missing")
2140
+ });
2141
+ }
2142
+ } else {
2143
+ switch (crdt.type) {
2144
+ case 3 /* REGISTER */:
2145
+ ops.push({
2146
+ type: 8 /* CREATE_REGISTER */,
2147
+ id,
2148
+ parentId: crdt.parentId,
2149
+ parentKey: crdt.parentKey,
2150
+ data: crdt.data
2151
+ });
2152
+ break;
2153
+ case 1 /* LIST */:
2154
+ ops.push({
2155
+ type: 2 /* CREATE_LIST */,
2156
+ id,
2157
+ parentId: crdt.parentId,
2158
+ parentKey: crdt.parentKey
2159
+ });
2160
+ break;
2161
+ case 0 /* OBJECT */:
2162
+ ops.push(
2163
+ crdt.parentId ? {
2164
+ type: 4 /* CREATE_OBJECT */,
2165
+ id,
2166
+ parentId: crdt.parentId,
2167
+ parentKey: crdt.parentKey,
2168
+ data: crdt.data
2169
+ } : { type: 4 /* CREATE_OBJECT */, id, data: crdt.data }
2170
+ );
2171
+ break;
2172
+ case 2 /* MAP */:
2173
+ ops.push({
2174
+ type: 7 /* CREATE_MAP */,
2175
+ id,
2176
+ parentId: crdt.parentId,
2177
+ parentKey: crdt.parentKey
2178
+ });
2179
+ break;
2180
+ }
2181
+ }
2182
+ });
2183
+ return ops;
2184
+ }
2185
+ function mergeObjectStorageUpdates(first, second) {
2186
+ const updates = first.updates;
2187
+ for (const [key, value] of entries(second.updates)) {
2188
+ updates[key] = value;
2189
+ }
2190
+ return __spreadProps(__spreadValues({}, second), {
2191
+ updates
2192
+ });
2193
+ }
2194
+ function mergeMapStorageUpdates(first, second) {
2195
+ const updates = first.updates;
2196
+ for (const [key, value] of entries(second.updates)) {
2197
+ updates[key] = value;
2198
+ }
2199
+ return __spreadProps(__spreadValues({}, second), {
2200
+ updates
2201
+ });
2202
+ }
2203
+ function mergeListStorageUpdates(first, second) {
2204
+ const updates = first.updates;
2205
+ return __spreadProps(__spreadValues({}, second), {
2206
+ updates: updates.concat(second.updates)
2207
+ });
2208
+ }
2209
+ function mergeStorageUpdates(first, second) {
2210
+ if (!first) {
2211
+ return second;
2212
+ }
2213
+ if (first.type === "LiveObject" && second.type === "LiveObject") {
2214
+ return mergeObjectStorageUpdates(first, second);
2215
+ } else if (first.type === "LiveMap" && second.type === "LiveMap") {
2216
+ return mergeMapStorageUpdates(first, second);
2217
+ } else if (first.type === "LiveList" && second.type === "LiveList") {
2218
+ return mergeListStorageUpdates(first, second);
2219
+ } else {
2220
+ }
2221
+ return second;
2222
+ }
2223
+ function isPlain(value) {
2224
+ const type = typeof value;
2225
+ return value === void 0 || value === null || type === "string" || type === "boolean" || type === "number" || Array.isArray(value) || isPlainObject(value);
2226
+ }
2227
+ function isPlainObject(blob) {
2228
+ return blob !== null && typeof blob === "object" && Object.prototype.toString.call(blob) === "[object Object]";
2229
+ }
2230
+ function findNonSerializableValue(value, path = "") {
2231
+ if (!isPlain) {
2232
+ return {
2233
+ path: path || "root",
2234
+ value
2235
+ };
2236
+ }
2237
+ if (typeof value !== "object" || value === null) {
2238
+ return false;
2239
+ }
2240
+ for (const [key, nestedValue] of Object.entries(value)) {
2241
+ const nestedPath = path ? path + "." + key : key;
2242
+ if (!isPlain(nestedValue)) {
2243
+ return {
2244
+ path: nestedPath,
2245
+ value: nestedValue
2246
+ };
2247
+ }
2248
+ if (typeof nestedValue === "object") {
2249
+ const nonSerializableNestedValue = findNonSerializableValue(
2250
+ nestedValue,
2251
+ nestedPath
2252
+ );
2253
+ if (nonSerializableNestedValue) {
2254
+ return nonSerializableNestedValue;
2255
+ }
2256
+ }
2257
+ }
2258
+ return false;
2259
+ }
2260
+ function fromEntries(iterable) {
2261
+ const obj = {};
2262
+ for (const [key, val] of iterable) {
2263
+ obj[key] = val;
2264
+ }
2265
+ return obj;
2266
+ }
2267
+ function entries(obj) {
2268
+ return Object.entries(obj);
2269
+ }
2270
+ function tryParseJson(rawMessage) {
2271
+ try {
2272
+ return JSON.parse(rawMessage);
2273
+ } catch (e) {
2274
+ return void 0;
2275
+ }
2276
+ }
2277
+ function b64decode(b64value) {
2278
+ try {
2279
+ const formattedValue = b64value.replace(/-/g, "+").replace(/_/g, "/");
2280
+ const decodedValue = decodeURIComponent(
2281
+ atob(formattedValue).split("").map(function(c) {
2282
+ return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
2283
+ }).join("")
2284
+ );
2285
+ return decodedValue;
2286
+ } catch (err) {
2287
+ return atob(b64value);
2288
+ }
2289
+ }
2290
+
2291
+ // src/AuthToken.ts
2292
+ function hasJwtMeta(data) {
2293
+ if (!isPlainObject(data)) {
2294
+ return false;
2295
+ }
2296
+ const { iat, exp } = data;
2297
+ return typeof iat === "number" && typeof exp === "number";
2298
+ }
2299
+ function isTokenExpired(token) {
2300
+ const now = Date.now() / 1e3;
2301
+ return now > token.exp - 300 || now < token.iat + 300;
2302
+ }
2303
+ function isStringList(value) {
2304
+ return Array.isArray(value) && value.every((i) => typeof i === "string");
2305
+ }
2306
+ function isAppOnlyAuthToken(data) {
2307
+ return typeof data.appId === "string" && data.roomId === void 0 && isStringList(data.scopes);
2308
+ }
2309
+ function isRoomAuthToken(data) {
2310
+ return typeof data.appId === "string" && typeof data.roomId === "string" && typeof data.actor === "number" && (data.id === void 0 || typeof data.id === "string") && isStringList(data.scopes) && (data.maxConnectionsPerRoom === void 0 || typeof data.maxConnectionsPerRoom === "number");
2311
+ }
2312
+ function isAuthToken(data) {
2313
+ return isAppOnlyAuthToken(data) || isRoomAuthToken(data);
2314
+ }
2315
+ function parseJwtToken(token) {
2316
+ const tokenParts = token.split(".");
2317
+ if (tokenParts.length !== 3) {
2318
+ throw new Error("Authentication error: invalid JWT token");
2319
+ }
2320
+ const data = tryParseJson(b64decode(tokenParts[1]));
2321
+ if (data && hasJwtMeta(data)) {
2322
+ return data;
2323
+ } else {
2324
+ throw new Error("Authentication error: missing JWT metadata");
2325
+ }
2326
+ }
2327
+ function parseRoomAuthToken(tokenString) {
2328
+ const data = parseJwtToken(tokenString);
2329
+ if (data && isRoomAuthToken(data)) {
2330
+ const _a = data, {
2331
+ maxConnections: _legacyField
2332
+ } = _a, token = __objRest(_a, [
2333
+ "maxConnections"
2334
+ ]);
2335
+ return token;
2336
+ } else {
2337
+ throw new Error(
2338
+ "Authentication error: we expected a room token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback"
2339
+ );
2340
+ }
2341
+ }
2342
+
2343
+ // src/fancy-console.ts
2344
+ var badge = "background:radial-gradient(106.94% 108.33% at -10% -5%,#ff1aa3 0,#ff881a 100%);border-radius:3px;color:#fff;padding:2px 5px;font-family:sans-serif;font-weight:600";
2345
+ var bold = "font-weight:600";
2346
+ function wrap(method) {
2347
+ return typeof window === "undefined" || process.env.NODE_ENV === "test" ? console[method] : (message, ...args) => console[method]("%cLiveblocks", badge, message, ...args);
2348
+ }
2349
+ var warn = wrap("warn");
2350
+ var error = wrap("error");
2351
+ function wrapWithTitle(method) {
2352
+ return typeof window === "undefined" || process.env.NODE_ENV === "test" ? console[method] : (title, message, ...args) => console[method](
2353
+ `%cLiveblocks%c ${title}`,
2354
+ badge,
2355
+ bold,
2356
+ message,
2357
+ ...args
2358
+ );
2359
+ }
2360
+ var errorWithTitle = wrapWithTitle("error");
2361
+
2362
+ // src/deprecation.ts
2363
+ var _emittedDeprecationWarnings = /* @__PURE__ */ new Set();
2364
+ function deprecate(message, key = message) {
2365
+ if (process.env.NODE_ENV !== "production") {
2366
+ if (!_emittedDeprecationWarnings.has(key)) {
2367
+ _emittedDeprecationWarnings.add(key);
2368
+ errorWithTitle("Deprecation warning", message);
2369
+ }
2370
+ }
2371
+ }
2372
+ function deprecateIf(condition, message, key = message) {
2373
+ if (process.env.NODE_ENV !== "production") {
2374
+ if (condition) {
2375
+ deprecate(message, key);
2376
+ }
2377
+ }
2378
+ }
2379
+ function throwUsageError(message) {
2380
+ if (process.env.NODE_ENV !== "production") {
2381
+ const usageError = new Error(message);
2382
+ usageError.name = "Usage error";
2383
+ errorWithTitle("Usage error", message);
2384
+ throw usageError;
2385
+ }
2386
+ }
2387
+ function errorIf(condition, message) {
2388
+ if (process.env.NODE_ENV !== "production") {
2389
+ if (condition) {
2390
+ throwUsageError(message);
2391
+ }
2392
+ }
2393
+ }
2394
+
2395
+ // src/EventSource.ts
2396
+ function makeEventSource() {
2397
+ const _onetimeObservers = /* @__PURE__ */ new Set();
2398
+ const _observers = /* @__PURE__ */ new Set();
2399
+ function subscribe(callback) {
2400
+ _observers.add(callback);
2401
+ return () => _observers.delete(callback);
2402
+ }
2403
+ function subscribeOnce(callback) {
2404
+ _onetimeObservers.add(callback);
2405
+ return () => _onetimeObservers.delete(callback);
2406
+ }
2407
+ function notify(event) {
2408
+ _onetimeObservers.forEach((callback) => callback(event));
2409
+ _onetimeObservers.clear();
2410
+ _observers.forEach((callback) => callback(event));
2411
+ }
2412
+ function clear() {
2413
+ _onetimeObservers.clear();
2414
+ _observers.clear();
2415
+ }
2416
+ return {
2417
+ notify,
2418
+ subscribe,
2419
+ subscribeOnce,
2420
+ clear,
2421
+ observable: {
2422
+ subscribe,
2423
+ subscribeOnce
2424
+ }
2425
+ };
2426
+ }
2427
+
2428
+ // src/ImmutableRef.ts
2429
+ function merge(target, patch) {
2430
+ let updated = false;
2431
+ const newValue = __spreadValues({}, target);
2432
+ Object.keys(patch).forEach((k) => {
2433
+ const key = k;
2434
+ const val = patch[key];
2435
+ if (newValue[key] !== val) {
2436
+ if (val === void 0) {
2437
+ delete newValue[key];
2438
+ } else {
2439
+ newValue[key] = val;
2440
+ }
2441
+ updated = true;
2442
+ }
2443
+ });
2444
+ return updated ? newValue : target;
2445
+ }
2446
+ var ImmutableRef = class {
2447
+ constructor() {
2448
+ this._ev = makeEventSource();
2449
+ }
2450
+ get didInvalidate() {
2451
+ return this._ev.observable;
2452
+ }
2453
+ invalidate() {
2454
+ if (this._cache !== void 0) {
2455
+ this._cache = void 0;
2456
+ this._ev.notify();
2457
+ }
2458
+ }
2459
+ get current() {
2460
+ var _a;
2461
+ return (_a = this._cache) != null ? _a : this._cache = this._toImmutable();
2462
+ }
2463
+ };
2464
+
2465
+ // src/MeRef.ts
2466
+ var MeRef = class extends ImmutableRef {
2467
+ constructor(initialPresence) {
2468
+ super();
2469
+ this._me = freeze(compactObject(initialPresence));
2470
+ }
2471
+ _toImmutable() {
2472
+ return this._me;
2473
+ }
2474
+ patch(patch) {
2475
+ const oldMe = this._me;
2476
+ const newMe = merge(oldMe, patch);
2477
+ if (oldMe !== newMe) {
2478
+ this._me = freeze(newMe);
2479
+ this.invalidate();
2480
+ }
2481
+ }
2482
+ };
2483
+
2484
+ // src/LegacyArray.ts
2485
+ function asArrayWithLegacyMethods(arr) {
2486
+ Object.defineProperty(arr, "count", {
2487
+ value: arr.length,
2488
+ enumerable: false
2489
+ });
2490
+ Object.defineProperty(arr, "toArray", {
2491
+ value: () => arr,
2492
+ enumerable: false
2493
+ });
2494
+ return freeze(arr);
2495
+ }
2496
+
2497
+ // src/OthersRef.ts
2498
+ function makeUser(conn, presence) {
2499
+ return freeze(compactObject(__spreadProps(__spreadValues({}, conn), { presence })));
2500
+ }
2501
+ var OthersRef = class extends ImmutableRef {
2502
+ constructor() {
2503
+ super();
2504
+ this._connections = {};
2505
+ this._presences = {};
2506
+ this._users = {};
2507
+ }
2508
+ _toImmutable() {
2509
+ const users = compact(
2510
+ Object.keys(this._presences).map(
2511
+ (connectionId) => this.getUser(Number(connectionId))
2512
+ )
2513
+ );
2514
+ return asArrayWithLegacyMethods(users);
2515
+ }
2516
+ clearOthers() {
2517
+ this._connections = {};
2518
+ this._presences = {};
2519
+ this._users = {};
2520
+ this.invalidate();
2521
+ }
2522
+ _getUser(connectionId) {
2523
+ const conn = this._connections[connectionId];
2524
+ const presence = this._presences[connectionId];
2525
+ if (conn !== void 0 && presence !== void 0) {
2526
+ return makeUser(conn, presence);
2527
+ }
2528
+ return void 0;
2529
+ }
2530
+ getUser(connectionId) {
2531
+ const cachedUser = this._users[connectionId];
2532
+ if (cachedUser) {
2533
+ return cachedUser;
2534
+ }
2535
+ const computedUser = this._getUser(connectionId);
2536
+ if (computedUser) {
2537
+ this._users[connectionId] = computedUser;
2538
+ return computedUser;
2539
+ }
2540
+ return void 0;
2541
+ }
2542
+ _invalidateUser(connectionId) {
2543
+ if (this._users[connectionId] !== void 0) {
2544
+ delete this._users[connectionId];
2545
+ }
2546
+ this.invalidate();
2547
+ }
2548
+ setConnection(connectionId, metaUserId, metaUserInfo) {
2549
+ this._connections[connectionId] = freeze({
2550
+ connectionId,
2551
+ id: metaUserId,
2552
+ info: metaUserInfo
2553
+ });
2554
+ if (this._presences[connectionId] !== void 0) {
2555
+ this._invalidateUser(connectionId);
2556
+ }
2557
+ }
2558
+ removeConnection(connectionId) {
2559
+ delete this._connections[connectionId];
2560
+ delete this._presences[connectionId];
2561
+ this._invalidateUser(connectionId);
2562
+ }
2563
+ setOther(connectionId, presence) {
2564
+ this._presences[connectionId] = freeze(compactObject(presence));
2565
+ if (this._connections[connectionId] !== void 0) {
2566
+ this._invalidateUser(connectionId);
2567
+ }
2568
+ }
2569
+ patchOther(connectionId, patch) {
2570
+ const oldPresence = this._presences[connectionId];
2571
+ if (oldPresence === void 0) {
2572
+ return;
2573
+ }
2574
+ const newPresence = merge(oldPresence, patch);
2575
+ if (oldPresence !== newPresence) {
2576
+ this._presences[connectionId] = freeze(newPresence);
2577
+ this._invalidateUser(connectionId);
2578
+ }
2579
+ }
2580
+ };
2581
+
2582
+ // src/types/Json.ts
2583
+ function isJsonScalar(data) {
2584
+ return data === null || typeof data === "string" || typeof data === "number" || typeof data === "boolean";
2585
+ }
2586
+ function isJsonArray(data) {
2587
+ return Array.isArray(data);
2588
+ }
2589
+ function isJsonObject(data) {
2590
+ return !isJsonScalar(data) && !isJsonArray(data);
2591
+ }
2592
+
2593
+ // src/ValueRef.ts
2594
+ var ValueRef = class extends ImmutableRef {
2595
+ constructor(initialValue) {
2596
+ super();
2597
+ this._value = freeze(compactObject(initialValue));
2598
+ }
2599
+ _toImmutable() {
2600
+ return this._value;
2601
+ }
2602
+ set(newValue) {
2603
+ this._value = freeze(newValue);
2604
+ this.invalidate();
2605
+ }
2606
+ };
2607
+ var DerivedRef = class extends ImmutableRef {
2608
+ constructor(otherRefs, transformFn) {
2609
+ super();
2610
+ this._refs = otherRefs;
2611
+ this._refs.forEach((ref) => {
2612
+ ref.didInvalidate.subscribe(() => this.invalidate());
2613
+ });
2614
+ this._transform = transformFn;
2615
+ }
2616
+ _toImmutable() {
2617
+ return this._transform(this._refs[0].current, this._refs[1].current);
2618
+ }
2619
+ };
2620
+
2621
+ // src/room.ts
2622
+ var BACKOFF_RETRY_DELAYS = [250, 500, 1e3, 2e3, 4e3, 8e3, 1e4];
2623
+ var BACKOFF_RETRY_DELAYS_SLOW = [2e3, 3e4, 6e4, 3e5];
2624
+ var HEARTBEAT_INTERVAL = 3e4;
2625
+ var PONG_TIMEOUT = 2e3;
2626
+ function makeIdFactory(connectionId) {
2627
+ let count = 0;
2628
+ return () => `${connectionId}:${count++}`;
2629
+ }
2630
+ function log(..._params) {
2631
+ return;
2632
+ }
2633
+ function isConnectionSelfAware(connection) {
2634
+ return connection.state === "open" || connection.state === "connecting";
2635
+ }
2636
+ function makeStateMachine(state, config, mockedEffects) {
2637
+ var _a;
2638
+ const doNotBatchUpdates = (cb) => cb();
2639
+ const batchUpdates = (_a = config.unstable_batchedUpdates) != null ? _a : doNotBatchUpdates;
2640
+ const pool = {
2641
+ roomId: config.roomId,
2642
+ getNode: (id) => state.nodes.get(id),
2643
+ addNode: (id, node) => void state.nodes.set(id, node),
2644
+ deleteNode: (id) => void state.nodes.delete(id),
2645
+ generateId: () => `${getConnectionId()}:${state.clock++}`,
2646
+ generateOpId: () => `${getConnectionId()}:${state.opClock++}`,
2647
+ dispatch(ops, reverse, storageUpdates) {
2648
+ const activeBatch = state.activeBatch;
2649
+ if (activeBatch) {
2650
+ activeBatch.ops.push(...ops);
2651
+ storageUpdates.forEach((value, key) => {
2652
+ activeBatch.updates.storageUpdates.set(
2653
+ key,
2654
+ mergeStorageUpdates(
2655
+ activeBatch.updates.storageUpdates.get(key),
2656
+ value
2657
+ )
2658
+ );
2659
+ });
2660
+ activeBatch.reverseOps.push(...reverse);
2661
+ } else {
2662
+ batchUpdates(() => {
2663
+ addToUndoStack(reverse, doNotBatchUpdates);
2664
+ state.redoStack = [];
2665
+ dispatchOps(ops);
2666
+ notify({ storageUpdates }, doNotBatchUpdates);
2667
+ });
2668
+ }
2669
+ }
2670
+ };
2671
+ const eventHub = {
2672
+ customEvent: makeEventSource(),
2673
+ me: makeEventSource(),
2674
+ others: makeEventSource(),
2675
+ error: makeEventSource(),
2676
+ connection: makeEventSource(),
2677
+ storage: makeEventSource(),
2678
+ history: makeEventSource(),
2679
+ storageDidLoad: makeEventSource()
2680
+ };
2681
+ const effects = mockedEffects || {
2682
+ authenticate(auth, createWebSocket) {
2683
+ const rawToken = state.token;
2684
+ const parsedToken = rawToken !== null && parseRoomAuthToken(rawToken);
2685
+ if (parsedToken && !isTokenExpired(parsedToken)) {
2686
+ const socket = createWebSocket(rawToken);
2687
+ authenticationSuccess(parsedToken, socket);
2688
+ return void 0;
2689
+ } else {
2690
+ return auth(config.roomId).then(({ token }) => {
2691
+ if (state.connection.current.state !== "authenticating") {
2692
+ return;
2693
+ }
2694
+ const parsedToken2 = parseRoomAuthToken(token);
2695
+ const socket = createWebSocket(token);
2696
+ authenticationSuccess(parsedToken2, socket);
2697
+ state.token = token;
2698
+ }).catch(
2699
+ (er) => authenticationFailure(
2700
+ er instanceof Error ? er : new Error(String(er))
2701
+ )
2702
+ );
2703
+ }
2704
+ },
2705
+ send(messageOrMessages) {
2706
+ if (state.socket === null) {
2707
+ throw new Error("Can't send message if socket is null");
2708
+ }
2709
+ state.socket.send(JSON.stringify(messageOrMessages));
2710
+ },
2711
+ delayFlush(delay) {
2712
+ return setTimeout(tryFlushing, delay);
2713
+ },
2714
+ startHeartbeatInterval() {
2715
+ return setInterval(heartbeat, HEARTBEAT_INTERVAL);
2716
+ },
2717
+ schedulePongTimeout() {
2718
+ return setTimeout(pongTimeout, PONG_TIMEOUT);
2719
+ },
2720
+ scheduleReconnect(delay) {
2721
+ return setTimeout(connect, delay);
2722
+ }
2723
+ };
2724
+ const self = new DerivedRef(
2725
+ [state.connection, state.me],
2726
+ (conn, me) => isConnectionSelfAware(conn) ? {
2727
+ connectionId: conn.id,
2728
+ id: conn.userId,
2729
+ info: conn.userInfo,
2730
+ presence: me
2731
+ } : null
2732
+ );
2733
+ function createOrUpdateRootFromMessage(message, batchedUpdatesWrapper) {
2734
+ if (message.items.length === 0) {
2735
+ throw new Error("Internal error: cannot load storage without items");
2736
+ }
2737
+ if (state.root) {
2738
+ updateRoot(message.items, batchedUpdatesWrapper);
2739
+ } else {
2740
+ state.root = load(message.items);
2741
+ }
2742
+ for (const key in state.initialStorage) {
2743
+ if (state.root.get(key) === void 0) {
2744
+ state.root.set(key, state.initialStorage[key]);
2745
+ }
2746
+ }
2747
+ }
2748
+ function buildRootAndParentToChildren(items) {
2749
+ const parentToChildren = /* @__PURE__ */ new Map();
2750
+ let root = null;
2751
+ for (const [id, crdt] of items) {
2752
+ if (isRootCrdt(crdt)) {
2753
+ root = [id, crdt];
2754
+ } else {
2755
+ const tuple = [id, crdt];
2756
+ const children = parentToChildren.get(crdt.parentId);
2757
+ if (children !== void 0) {
2758
+ children.push(tuple);
2759
+ } else {
2760
+ parentToChildren.set(crdt.parentId, [tuple]);
2761
+ }
2762
+ }
2763
+ }
2764
+ if (root === null) {
2765
+ throw new Error("Root can't be null");
2766
+ }
2767
+ return [root, parentToChildren];
2768
+ }
2769
+ function updateRoot(items, batchedUpdatesWrapper) {
2770
+ if (!state.root) {
2771
+ return;
2772
+ }
2773
+ const currentItems = /* @__PURE__ */ new Map();
2774
+ state.nodes.forEach((node, id) => {
2775
+ currentItems.set(id, node._serialize());
2776
+ });
2777
+ const ops = getTreesDiffOperations(currentItems, new Map(items));
2778
+ const result = apply(ops, false);
2779
+ notify(result.updates, batchedUpdatesWrapper);
2780
+ }
2781
+ function load(items) {
2782
+ const [root, parentToChildren] = buildRootAndParentToChildren(items);
2783
+ return LiveObject._deserialize(root, parentToChildren, pool);
2784
+ }
2785
+ function _addToRealUndoStack(historyOps, batchedUpdatesWrapper) {
2786
+ if (state.undoStack.length >= 50) {
2787
+ state.undoStack.shift();
2788
+ }
2789
+ state.undoStack.push(historyOps);
2790
+ onHistoryChange(batchedUpdatesWrapper);
2791
+ }
2792
+ function addToUndoStack(historyOps, batchedUpdatesWrapper) {
2793
+ if (state.pausedHistory !== null) {
2794
+ state.pausedHistory.unshift(...historyOps);
2795
+ } else {
2796
+ _addToRealUndoStack(historyOps, batchedUpdatesWrapper);
2797
+ }
2798
+ }
2799
+ function notify({
2800
+ storageUpdates = /* @__PURE__ */ new Map(),
2801
+ presence = false,
2802
+ others: otherEvents = []
2803
+ }, batchedUpdatesWrapper) {
2804
+ batchedUpdatesWrapper(() => {
2805
+ if (otherEvents.length > 0) {
2806
+ const others = state.others.current;
2807
+ for (const event of otherEvents) {
2808
+ eventHub.others.notify({ others, event });
2809
+ }
2810
+ }
2811
+ if (presence) {
2812
+ eventHub.me.notify(state.me.current);
2813
+ }
2814
+ if (storageUpdates.size > 0) {
2815
+ const updates = Array.from(storageUpdates.values());
2816
+ eventHub.storage.notify(updates);
2817
+ }
2818
+ });
2819
+ }
2820
+ function getConnectionId() {
2821
+ const conn = state.connection.current;
2822
+ if (isConnectionSelfAware(conn)) {
2823
+ return conn.id;
2824
+ } else if (state.lastConnectionId !== null) {
2825
+ return state.lastConnectionId;
2826
+ }
2827
+ throw new Error(
2828
+ "Internal. Tried to get connection id but connection was never open"
2829
+ );
2830
+ }
2831
+ function apply(ops, isLocal) {
2832
+ const result = {
2833
+ reverse: [],
2834
+ updates: {
2835
+ storageUpdates: /* @__PURE__ */ new Map(),
2836
+ presence: false
2837
+ }
2838
+ };
2839
+ const createdNodeIds = /* @__PURE__ */ new Set();
2840
+ for (const op of ops) {
2841
+ if (op.type === "presence") {
2842
+ const reverse = {
2843
+ type: "presence",
2844
+ data: {}
2845
+ };
2846
+ for (const key in op.data) {
2847
+ reverse.data[key] = state.me.current[key];
2848
+ }
2849
+ state.me.patch(op.data);
2850
+ if (state.buffer.me === null) {
2851
+ state.buffer.me = { type: "partial", data: op.data };
2852
+ } else {
2853
+ for (const key in op.data) {
2854
+ state.buffer.me.data[key] = op.data[key];
2855
+ }
2856
+ }
2857
+ result.reverse.unshift(reverse);
2858
+ result.updates.presence = true;
2859
+ } else {
2860
+ let source;
2861
+ if (!op.opId) {
2862
+ op.opId = pool.generateOpId();
2863
+ }
2864
+ if (isLocal) {
2865
+ source = 0 /* UNDOREDO_RECONNECT */;
2866
+ } else {
2867
+ const deleted = state.offlineOperations.delete(nn(op.opId));
2868
+ source = deleted ? 2 /* ACK */ : 1 /* REMOTE */;
2869
+ }
2870
+ const applyOpResult = applyOp(op, source);
2871
+ if (applyOpResult.modified) {
2872
+ const parentId = applyOpResult.modified.node.parent.type === "HasParent" ? nn(
2873
+ applyOpResult.modified.node.parent.node._id,
2874
+ "Expected parent node to have an ID"
2875
+ ) : void 0;
2876
+ if (!parentId || !createdNodeIds.has(parentId)) {
2877
+ result.updates.storageUpdates.set(
2878
+ nn(applyOpResult.modified.node._id),
2879
+ mergeStorageUpdates(
2880
+ result.updates.storageUpdates.get(
2881
+ nn(applyOpResult.modified.node._id)
2882
+ ),
2883
+ applyOpResult.modified
2884
+ )
2885
+ );
2886
+ result.reverse.unshift(...applyOpResult.reverse);
2887
+ }
2888
+ if (op.type === 2 /* CREATE_LIST */ || op.type === 7 /* CREATE_MAP */ || op.type === 4 /* CREATE_OBJECT */) {
2889
+ createdNodeIds.add(nn(applyOpResult.modified.node._id));
2890
+ }
2891
+ }
2892
+ }
2893
+ }
2894
+ return result;
2895
+ }
2896
+ function applyOp(op, source) {
2897
+ switch (op.type) {
2898
+ case 6 /* DELETE_OBJECT_KEY */:
2899
+ case 3 /* UPDATE_OBJECT */:
2900
+ case 5 /* DELETE_CRDT */: {
2901
+ const node = state.nodes.get(op.id);
2902
+ if (node === void 0) {
2903
+ return { modified: false };
2904
+ }
2905
+ return node._apply(op, source === 0 /* UNDOREDO_RECONNECT */);
2906
+ }
2907
+ case 1 /* SET_PARENT_KEY */: {
2908
+ const node = state.nodes.get(op.id);
2909
+ if (node === void 0) {
2910
+ return { modified: false };
2911
+ }
2912
+ if (node.parent.type === "HasParent" && isLiveList(node.parent.node)) {
2913
+ return node.parent.node._setChildKey(op.parentKey, node, source);
2914
+ }
2915
+ return { modified: false };
2916
+ }
2917
+ case 4 /* CREATE_OBJECT */:
2918
+ case 2 /* CREATE_LIST */:
2919
+ case 7 /* CREATE_MAP */:
2920
+ case 8 /* CREATE_REGISTER */: {
2921
+ if (op.parentId === void 0) {
2922
+ return { modified: false };
2923
+ }
2924
+ const parentNode = state.nodes.get(op.parentId);
2925
+ if (parentNode === void 0) {
2926
+ return { modified: false };
2927
+ }
2928
+ return parentNode._attachChild(op, source);
2929
+ }
2930
+ }
2931
+ }
2932
+ function subscribeToLiveStructureDeeply(node, callback) {
2933
+ return eventHub.storage.subscribe((updates) => {
2934
+ const relatedUpdates = updates.filter(
2935
+ (update) => isSameNodeOrChildOf(update.node, node)
2936
+ );
2937
+ if (relatedUpdates.length > 0) {
2938
+ callback(relatedUpdates);
2939
+ }
2940
+ });
2941
+ }
2942
+ function subscribeToLiveStructureShallowly(node, callback) {
2943
+ return eventHub.storage.subscribe((updates) => {
2944
+ for (const update of updates) {
2945
+ if (update.node._id === node._id) {
2946
+ callback(update.node);
2947
+ }
2948
+ }
2949
+ });
2950
+ }
2951
+ function subscribe(first, second, options) {
2952
+ if (typeof first === "string" && isRoomEventName(first)) {
2953
+ if (typeof second !== "function") {
2954
+ throw new Error("Second argument must be a callback function");
2955
+ }
2956
+ const callback = second;
2957
+ switch (first) {
2958
+ case "event":
2959
+ return eventHub.customEvent.subscribe(
2960
+ callback
2961
+ );
2962
+ case "my-presence":
2963
+ return eventHub.me.subscribe(callback);
2964
+ case "others": {
2965
+ const cb = callback;
2966
+ return eventHub.others.subscribe(
2967
+ ({ others, event }) => cb(others, event)
2968
+ );
2969
+ }
2970
+ case "error":
2971
+ return eventHub.error.subscribe(callback);
2972
+ case "connection":
2973
+ return eventHub.connection.subscribe(
2974
+ callback
2975
+ );
2976
+ case "storage":
2977
+ return eventHub.storage.subscribe(
2978
+ callback
2979
+ );
2980
+ case "history":
2981
+ return eventHub.history.subscribe(callback);
2982
+ default:
2983
+ return assertNever(first, "Unknown event");
2984
+ }
2985
+ }
2986
+ if (second === void 0 || typeof first === "function") {
2987
+ if (typeof first === "function") {
2988
+ const storageCallback = first;
2989
+ return eventHub.storage.subscribe(storageCallback);
2990
+ } else {
2991
+ throw new Error("Please specify a listener callback");
2992
+ }
2993
+ }
2994
+ if (isLiveNode(first)) {
2995
+ const node = first;
2996
+ if (options == null ? void 0 : options.isDeep) {
2997
+ const storageCallback = second;
2998
+ return subscribeToLiveStructureDeeply(node, storageCallback);
2999
+ } else {
3000
+ const nodeCallback = second;
3001
+ return subscribeToLiveStructureShallowly(node, nodeCallback);
3002
+ }
3003
+ }
3004
+ throw new Error(`"${first}" is not a valid event name`);
3005
+ }
3006
+ function getConnectionState() {
3007
+ return state.connection.current.state;
3008
+ }
3009
+ function connect() {
3010
+ var _a2, _b, _c, _d;
3011
+ if (state.connection.current.state !== "closed" && state.connection.current.state !== "unavailable") {
3012
+ return;
3013
+ }
3014
+ const auth = prepareAuthEndpoint(
3015
+ config.authentication,
3016
+ (_b = (_a2 = config.polyfills) == null ? void 0 : _a2.fetch) != null ? _b : config.fetchPolyfill
3017
+ );
3018
+ const createWebSocket = prepareCreateWebSocket(
3019
+ config.liveblocksServer,
3020
+ (_d = (_c = config.polyfills) == null ? void 0 : _c.WebSocket) != null ? _d : config.WebSocketPolyfill
3021
+ );
3022
+ updateConnection({ state: "authenticating" }, batchUpdates);
3023
+ effects.authenticate(auth, createWebSocket);
3024
+ }
3025
+ function updatePresence(patch, options) {
3026
+ const oldValues = {};
3027
+ if (state.buffer.me === null) {
3028
+ state.buffer.me = {
3029
+ type: "partial",
3030
+ data: {}
3031
+ };
3032
+ }
3033
+ for (const key in patch) {
3034
+ const overrideValue = patch[key];
3035
+ if (overrideValue === void 0) {
3036
+ continue;
3037
+ }
3038
+ state.buffer.me.data[key] = overrideValue;
3039
+ oldValues[key] = state.me.current[key];
3040
+ }
3041
+ state.me.patch(patch);
3042
+ if (state.activeBatch) {
3043
+ if (options == null ? void 0 : options.addToHistory) {
3044
+ state.activeBatch.reverseOps.push({
3045
+ type: "presence",
3046
+ data: oldValues
3047
+ });
3048
+ }
3049
+ state.activeBatch.updates.presence = true;
3050
+ } else {
3051
+ tryFlushing();
3052
+ batchUpdates(() => {
3053
+ if (options == null ? void 0 : options.addToHistory) {
3054
+ addToUndoStack(
3055
+ [{ type: "presence", data: oldValues }],
3056
+ doNotBatchUpdates
3057
+ );
3058
+ }
3059
+ notify({ presence: true }, doNotBatchUpdates);
3060
+ });
3061
+ }
3062
+ }
3063
+ function authenticationSuccess(token, socket) {
3064
+ socket.addEventListener("message", onMessage);
3065
+ socket.addEventListener("open", onOpen);
3066
+ socket.addEventListener("close", onClose);
3067
+ socket.addEventListener("error", onError);
3068
+ updateConnection(
3069
+ {
3070
+ state: "connecting",
3071
+ id: token.actor,
3072
+ userInfo: token.info,
3073
+ userId: token.id
3074
+ },
3075
+ batchUpdates
3076
+ );
3077
+ state.idFactory = makeIdFactory(token.actor);
3078
+ state.socket = socket;
3079
+ }
3080
+ function authenticationFailure(error2) {
3081
+ if (process.env.NODE_ENV !== "production") {
3082
+ error("Call to authentication endpoint failed", error2);
3083
+ }
3084
+ state.token = null;
3085
+ updateConnection({ state: "unavailable" }, batchUpdates);
3086
+ state.numberOfRetry++;
3087
+ state.timeoutHandles.reconnect = effects.scheduleReconnect(getRetryDelay());
3088
+ }
3089
+ function onVisibilityChange(visibilityState) {
3090
+ if (visibilityState === "visible" && state.connection.current.state === "open") {
3091
+ log("Heartbeat after visibility change");
3092
+ heartbeat();
3093
+ }
3094
+ }
3095
+ function onUpdatePresenceMessage(message) {
3096
+ if (message.targetActor !== void 0) {
3097
+ const oldUser = state.others.getUser(message.actor);
3098
+ state.others.setOther(message.actor, message.data);
3099
+ const newUser = state.others.getUser(message.actor);
3100
+ if (oldUser === void 0 && newUser !== void 0) {
3101
+ return { type: "enter", user: newUser };
3102
+ }
3103
+ } else {
3104
+ state.others.patchOther(message.actor, message.data), message;
3105
+ }
3106
+ const user = state.others.getUser(message.actor);
3107
+ if (user) {
3108
+ return {
3109
+ type: "update",
3110
+ updates: message.data,
3111
+ user
3112
+ };
3113
+ } else {
3114
+ return void 0;
3115
+ }
3116
+ }
3117
+ function onUserLeftMessage(message) {
3118
+ const user = state.others.getUser(message.actor);
3119
+ if (user) {
3120
+ state.others.removeConnection(message.actor);
3121
+ return { type: "leave", user };
3122
+ }
3123
+ return null;
3124
+ }
3125
+ function onRoomStateMessage(message) {
3126
+ for (const key in message.users) {
3127
+ const user = message.users[key];
3128
+ const connectionId = Number(key);
3129
+ state.others.setConnection(connectionId, user.id, user.info);
3130
+ }
3131
+ return { type: "reset" };
3132
+ }
3133
+ function onNavigatorOnline() {
3134
+ if (state.connection.current.state === "unavailable") {
3135
+ log("Try to reconnect after connectivity change");
3136
+ reconnect();
3137
+ }
3138
+ }
3139
+ function onHistoryChange(batchedUpdatesWrapper) {
3140
+ batchedUpdatesWrapper(() => {
3141
+ eventHub.history.notify({ canUndo: canUndo(), canRedo: canRedo() });
3142
+ });
3143
+ }
3144
+ function onUserJoinedMessage(message) {
3145
+ state.others.setConnection(message.actor, message.id, message.info);
3146
+ state.buffer.messages.push({
3147
+ type: 100 /* UPDATE_PRESENCE */,
3148
+ data: state.me.current,
3149
+ targetActor: message.actor
3150
+ });
3151
+ tryFlushing();
3152
+ const user = state.others.getUser(message.actor);
3153
+ return user ? { type: "enter", user } : void 0;
3154
+ }
3155
+ function parseServerMessage(data) {
3156
+ if (!isJsonObject(data)) {
3157
+ return null;
3158
+ }
3159
+ return data;
3160
+ }
3161
+ function parseServerMessages(text) {
3162
+ const data = tryParseJson(text);
3163
+ if (data === void 0) {
3164
+ return null;
3165
+ } else if (isJsonArray(data)) {
3166
+ return compact(data.map((item) => parseServerMessage(item)));
3167
+ } else {
3168
+ return compact([parseServerMessage(data)]);
3169
+ }
3170
+ }
3171
+ function onMessage(event) {
3172
+ if (event.data === "pong") {
3173
+ clearTimeout(state.timeoutHandles.pongTimeout);
3174
+ return;
3175
+ }
3176
+ const messages = parseServerMessages(event.data);
3177
+ if (messages === null || messages.length === 0) {
3178
+ return;
3179
+ }
3180
+ const updates = {
3181
+ storageUpdates: /* @__PURE__ */ new Map(),
3182
+ others: []
3183
+ };
3184
+ batchUpdates(() => {
3185
+ for (const message of messages) {
3186
+ switch (message.type) {
3187
+ case 101 /* USER_JOINED */: {
3188
+ const userJoinedUpdate = onUserJoinedMessage(message);
3189
+ if (userJoinedUpdate) {
3190
+ updates.others.push(userJoinedUpdate);
3191
+ }
3192
+ break;
3193
+ }
3194
+ case 100 /* UPDATE_PRESENCE */: {
3195
+ const othersPresenceUpdate = onUpdatePresenceMessage(message);
3196
+ if (othersPresenceUpdate) {
3197
+ updates.others.push(othersPresenceUpdate);
3198
+ }
3199
+ break;
3200
+ }
3201
+ case 103 /* BROADCASTED_EVENT */: {
3202
+ eventHub.customEvent.notify({
3203
+ connectionId: message.actor,
3204
+ event: message.event
3205
+ });
3206
+ break;
3207
+ }
3208
+ case 102 /* USER_LEFT */: {
3209
+ const event2 = onUserLeftMessage(message);
3210
+ if (event2) {
3211
+ updates.others.push(event2);
3212
+ }
3213
+ break;
3214
+ }
3215
+ case 104 /* ROOM_STATE */: {
3216
+ updates.others.push(onRoomStateMessage(message));
3217
+ break;
3218
+ }
3219
+ case 200 /* INITIAL_STORAGE_STATE */: {
3220
+ const offlineOps = new Map(state.offlineOperations);
3221
+ createOrUpdateRootFromMessage(message, doNotBatchUpdates);
3222
+ applyAndSendOfflineOps(offlineOps, doNotBatchUpdates);
3223
+ _getInitialStateResolver == null ? void 0 : _getInitialStateResolver();
3224
+ eventHub.storageDidLoad.notify();
3225
+ break;
3226
+ }
3227
+ case 201 /* UPDATE_STORAGE */: {
3228
+ const applyResult = apply(message.ops, false);
3229
+ applyResult.updates.storageUpdates.forEach((value, key) => {
3230
+ updates.storageUpdates.set(
3231
+ key,
3232
+ mergeStorageUpdates(
3233
+ updates.storageUpdates.get(key),
3234
+ value
3235
+ )
3236
+ );
3237
+ });
3238
+ break;
3239
+ }
3240
+ }
3241
+ }
3242
+ notify(updates, doNotBatchUpdates);
3243
+ });
3244
+ }
3245
+ function onClose(event) {
3246
+ state.socket = null;
3247
+ clearTimeout(state.timeoutHandles.pongTimeout);
3248
+ clearInterval(state.intervalHandles.heartbeat);
3249
+ if (state.timeoutHandles.flush) {
3250
+ clearTimeout(state.timeoutHandles.flush);
3251
+ }
3252
+ clearTimeout(state.timeoutHandles.reconnect);
3253
+ state.others.clearOthers();
3254
+ batchUpdates(() => {
3255
+ notify({ others: [{ type: "reset" }] }, doNotBatchUpdates);
3256
+ if (event.code >= 4e3 && event.code <= 4100) {
3257
+ updateConnection({ state: "failed" }, doNotBatchUpdates);
3258
+ const error2 = new LiveblocksError(event.reason, event.code);
3259
+ eventHub.error.notify(error2);
3260
+ const delay = getRetryDelay(true);
3261
+ state.numberOfRetry++;
3262
+ if (process.env.NODE_ENV !== "production") {
3263
+ error(
3264
+ `Connection to websocket server closed. Reason: ${error2.message} (code: ${error2.code}). Retrying in ${delay}ms.`
3265
+ );
3266
+ }
3267
+ updateConnection({ state: "unavailable" }, doNotBatchUpdates);
3268
+ state.timeoutHandles.reconnect = effects.scheduleReconnect(delay);
3269
+ } else if (event.code === 4999 /* CLOSE_WITHOUT_RETRY */) {
3270
+ updateConnection({ state: "closed" }, doNotBatchUpdates);
3271
+ } else {
3272
+ const delay = getRetryDelay();
3273
+ state.numberOfRetry++;
3274
+ if (process.env.NODE_ENV !== "production") {
3275
+ warn(
3276
+ `Connection to Liveblocks websocket server closed (code: ${event.code}). Retrying in ${delay}ms.`
3277
+ );
3278
+ }
3279
+ updateConnection({ state: "unavailable" }, doNotBatchUpdates);
3280
+ state.timeoutHandles.reconnect = effects.scheduleReconnect(delay);
3281
+ }
3282
+ });
3283
+ }
3284
+ function updateConnection(connection, batchedUpdatesWrapper) {
3285
+ state.connection.set(connection);
3286
+ batchedUpdatesWrapper(() => {
3287
+ eventHub.connection.notify(connection.state);
3288
+ });
3289
+ }
3290
+ function getRetryDelay(slow = false) {
3291
+ if (slow) {
3292
+ return BACKOFF_RETRY_DELAYS_SLOW[state.numberOfRetry < BACKOFF_RETRY_DELAYS_SLOW.length ? state.numberOfRetry : BACKOFF_RETRY_DELAYS_SLOW.length - 1];
3293
+ }
3294
+ return BACKOFF_RETRY_DELAYS[state.numberOfRetry < BACKOFF_RETRY_DELAYS.length ? state.numberOfRetry : BACKOFF_RETRY_DELAYS.length - 1];
3295
+ }
3296
+ function onError() {
3297
+ }
3298
+ function onOpen() {
3299
+ clearInterval(state.intervalHandles.heartbeat);
3300
+ state.intervalHandles.heartbeat = effects.startHeartbeatInterval();
3301
+ if (state.connection.current.state === "connecting") {
3302
+ updateConnection(
3303
+ __spreadProps(__spreadValues({}, state.connection.current), { state: "open" }),
3304
+ batchUpdates
3305
+ );
3306
+ state.numberOfRetry = 0;
3307
+ if (state.lastConnectionId !== void 0) {
3308
+ state.buffer.me = {
3309
+ type: "full",
3310
+ data: __spreadValues({}, state.me.current)
3311
+ };
3312
+ tryFlushing();
3313
+ }
3314
+ state.lastConnectionId = state.connection.current.id;
3315
+ if (state.root) {
3316
+ state.buffer.messages.push({ type: 200 /* FETCH_STORAGE */ });
3317
+ }
3318
+ tryFlushing();
3319
+ } else {
3320
+ }
3321
+ }
3322
+ function heartbeat() {
3323
+ if (state.socket === null) {
3324
+ return;
3325
+ }
3326
+ clearTimeout(state.timeoutHandles.pongTimeout);
3327
+ state.timeoutHandles.pongTimeout = effects.schedulePongTimeout();
3328
+ if (state.socket.readyState === state.socket.OPEN) {
3329
+ state.socket.send("ping");
3330
+ }
3331
+ }
3332
+ function pongTimeout() {
3333
+ log("Pong timeout. Trying to reconnect.");
3334
+ reconnect();
3335
+ }
3336
+ function reconnect() {
3337
+ if (state.socket) {
3338
+ state.socket.removeEventListener("open", onOpen);
3339
+ state.socket.removeEventListener("message", onMessage);
3340
+ state.socket.removeEventListener("close", onClose);
3341
+ state.socket.removeEventListener("error", onError);
3342
+ state.socket.close();
3343
+ state.socket = null;
3344
+ }
3345
+ updateConnection({ state: "unavailable" }, batchUpdates);
3346
+ clearTimeout(state.timeoutHandles.pongTimeout);
3347
+ if (state.timeoutHandles.flush) {
3348
+ clearTimeout(state.timeoutHandles.flush);
3349
+ }
3350
+ clearTimeout(state.timeoutHandles.reconnect);
3351
+ clearInterval(state.intervalHandles.heartbeat);
3352
+ connect();
3353
+ }
3354
+ function applyAndSendOfflineOps(offlineOps, batchedUpdatesWrapper) {
3355
+ if (offlineOps.size === 0) {
3356
+ return;
3357
+ }
3358
+ const messages = [];
3359
+ const ops = Array.from(offlineOps.values());
3360
+ const result = apply(ops, true);
3361
+ messages.push({
3362
+ type: 201 /* UPDATE_STORAGE */,
3363
+ ops
3364
+ });
3365
+ notify(result.updates, batchedUpdatesWrapper);
3366
+ effects.send(messages);
3367
+ }
3368
+ function tryFlushing() {
3369
+ const storageOps = state.buffer.storageOperations;
3370
+ if (storageOps.length > 0) {
3371
+ storageOps.forEach((op) => {
3372
+ state.offlineOperations.set(nn(op.opId), op);
3373
+ });
3374
+ }
3375
+ if (state.socket === null || state.socket.readyState !== state.socket.OPEN) {
3376
+ state.buffer.storageOperations = [];
3377
+ return;
3378
+ }
3379
+ const now = Date.now();
3380
+ const elapsedTime = now - state.lastFlushTime;
3381
+ if (elapsedTime > config.throttleDelay) {
3382
+ const messages = flushDataToMessages(state);
3383
+ if (messages.length === 0) {
3384
+ return;
3385
+ }
3386
+ effects.send(messages);
3387
+ state.buffer = {
3388
+ messages: [],
3389
+ storageOperations: [],
3390
+ me: null
3391
+ };
3392
+ state.lastFlushTime = now;
3393
+ } else {
3394
+ if (state.timeoutHandles.flush !== null) {
3395
+ clearTimeout(state.timeoutHandles.flush);
3396
+ }
3397
+ state.timeoutHandles.flush = effects.delayFlush(
3398
+ config.throttleDelay - (now - state.lastFlushTime)
3399
+ );
3400
+ }
3401
+ }
3402
+ function flushDataToMessages(state2) {
3403
+ const messages = [];
3404
+ if (state2.buffer.me) {
3405
+ messages.push(
3406
+ state2.buffer.me.type === "full" ? {
3407
+ type: 100 /* UPDATE_PRESENCE */,
3408
+ targetActor: -1,
3409
+ data: state2.buffer.me.data
3410
+ } : {
3411
+ type: 100 /* UPDATE_PRESENCE */,
3412
+ data: state2.buffer.me.data
3413
+ }
3414
+ );
3415
+ }
3416
+ for (const event of state2.buffer.messages) {
3417
+ messages.push(event);
3418
+ }
3419
+ if (state2.buffer.storageOperations.length > 0) {
3420
+ messages.push({
3421
+ type: 201 /* UPDATE_STORAGE */,
3422
+ ops: state2.buffer.storageOperations
3423
+ });
3424
+ }
3425
+ return messages;
3426
+ }
3427
+ function disconnect() {
3428
+ if (state.socket) {
3429
+ state.socket.removeEventListener("open", onOpen);
3430
+ state.socket.removeEventListener("message", onMessage);
3431
+ state.socket.removeEventListener("close", onClose);
3432
+ state.socket.removeEventListener("error", onError);
3433
+ state.socket.close();
3434
+ state.socket = null;
3435
+ }
3436
+ batchUpdates(() => {
3437
+ updateConnection({ state: "closed" }, doNotBatchUpdates);
3438
+ if (state.timeoutHandles.flush) {
3439
+ clearTimeout(state.timeoutHandles.flush);
3440
+ }
3441
+ clearTimeout(state.timeoutHandles.reconnect);
3442
+ clearTimeout(state.timeoutHandles.pongTimeout);
3443
+ clearInterval(state.intervalHandles.heartbeat);
3444
+ state.others.clearOthers();
3445
+ notify({ others: [{ type: "reset" }] }, doNotBatchUpdates);
3446
+ Object.values(eventHub).forEach((eventSource) => eventSource.clear());
3447
+ });
3448
+ }
3449
+ function getPresence() {
3450
+ return state.me.current;
3451
+ }
3452
+ function getOthers() {
3453
+ return state.others.current;
3454
+ }
3455
+ function broadcastEvent(event, options = {
3456
+ shouldQueueEventIfNotReady: false
3457
+ }) {
3458
+ if (state.socket === null && !options.shouldQueueEventIfNotReady) {
3459
+ return;
3460
+ }
3461
+ state.buffer.messages.push({
3462
+ type: 103 /* BROADCAST_EVENT */,
3463
+ event
3464
+ });
3465
+ tryFlushing();
3466
+ }
3467
+ function dispatchOps(ops) {
3468
+ state.buffer.storageOperations.push(...ops);
3469
+ tryFlushing();
3470
+ }
3471
+ let _getInitialStatePromise = null;
3472
+ let _getInitialStateResolver = null;
3473
+ function startLoadingStorage() {
3474
+ if (_getInitialStatePromise === null) {
3475
+ state.buffer.messages.push({ type: 200 /* FETCH_STORAGE */ });
3476
+ tryFlushing();
3477
+ _getInitialStatePromise = new Promise(
3478
+ (resolve) => _getInitialStateResolver = resolve
3479
+ );
3480
+ }
3481
+ return _getInitialStatePromise;
3482
+ }
3483
+ function getStorageSnapshot() {
3484
+ const root = state.root;
3485
+ if (root !== void 0) {
3486
+ return root;
3487
+ } else {
3488
+ startLoadingStorage();
3489
+ return null;
3490
+ }
3491
+ }
3492
+ function getStorage() {
3493
+ return __async(this, null, function* () {
3494
+ if (state.root) {
3495
+ return Promise.resolve({
3496
+ root: state.root
3497
+ });
3498
+ }
3499
+ yield startLoadingStorage();
3500
+ return {
3501
+ root: nn(state.root)
3502
+ };
3503
+ });
3504
+ }
3505
+ function undo() {
3506
+ if (state.activeBatch) {
3507
+ throw new Error("undo is not allowed during a batch");
3508
+ }
3509
+ const historyOps = state.undoStack.pop();
3510
+ if (historyOps === void 0) {
3511
+ return;
3512
+ }
3513
+ state.pausedHistory = null;
3514
+ const result = apply(historyOps, true);
3515
+ batchUpdates(() => {
3516
+ notify(result.updates, doNotBatchUpdates);
3517
+ state.redoStack.push(result.reverse);
3518
+ onHistoryChange(doNotBatchUpdates);
3519
+ });
3520
+ for (const op of historyOps) {
3521
+ if (op.type !== "presence") {
3522
+ state.buffer.storageOperations.push(op);
3523
+ }
3524
+ }
3525
+ tryFlushing();
3526
+ }
3527
+ function canUndo() {
3528
+ return state.undoStack.length > 0;
3529
+ }
3530
+ function redo() {
3531
+ if (state.activeBatch) {
3532
+ throw new Error("redo is not allowed during a batch");
3533
+ }
3534
+ const historyOps = state.redoStack.pop();
3535
+ if (historyOps === void 0) {
3536
+ return;
3537
+ }
3538
+ state.pausedHistory = null;
3539
+ const result = apply(historyOps, true);
3540
+ batchUpdates(() => {
3541
+ notify(result.updates, doNotBatchUpdates);
3542
+ state.undoStack.push(result.reverse);
3543
+ onHistoryChange(doNotBatchUpdates);
3544
+ });
3545
+ for (const op of historyOps) {
3546
+ if (op.type !== "presence") {
3547
+ state.buffer.storageOperations.push(op);
3548
+ }
3549
+ }
3550
+ tryFlushing();
3551
+ }
3552
+ function canRedo() {
3553
+ return state.redoStack.length > 0;
3554
+ }
3555
+ function batch(callback) {
3556
+ if (state.activeBatch) {
3557
+ return callback();
3558
+ }
3559
+ let rv = void 0;
3560
+ batchUpdates(() => {
3561
+ state.activeBatch = {
3562
+ ops: [],
3563
+ updates: {
3564
+ storageUpdates: /* @__PURE__ */ new Map(),
3565
+ presence: false,
3566
+ others: []
3567
+ },
3568
+ reverseOps: []
3569
+ };
3570
+ try {
3571
+ rv = callback();
3572
+ } finally {
3573
+ const currentBatch = state.activeBatch;
3574
+ state.activeBatch = null;
3575
+ if (currentBatch.reverseOps.length > 0) {
3576
+ addToUndoStack(currentBatch.reverseOps, doNotBatchUpdates);
3577
+ }
3578
+ if (currentBatch.ops.length > 0) {
3579
+ state.redoStack = [];
3580
+ }
3581
+ if (currentBatch.ops.length > 0) {
3582
+ dispatchOps(currentBatch.ops);
3583
+ }
3584
+ notify(currentBatch.updates, doNotBatchUpdates);
3585
+ tryFlushing();
3586
+ }
3587
+ });
3588
+ return rv;
3589
+ }
3590
+ function pauseHistory() {
3591
+ state.pausedHistory = [];
3592
+ }
3593
+ function resumeHistory() {
3594
+ const historyOps = state.pausedHistory;
3595
+ state.pausedHistory = null;
3596
+ if (historyOps !== null && historyOps.length > 0) {
3597
+ _addToRealUndoStack(historyOps, batchUpdates);
3598
+ }
3599
+ }
3600
+ function simulateSocketClose() {
3601
+ if (state.socket) {
3602
+ state.socket = null;
3603
+ }
3604
+ }
3605
+ function simulateSendCloseEvent(event) {
3606
+ onClose(event);
3607
+ }
3608
+ return {
3609
+ onClose,
3610
+ onMessage,
3611
+ authenticationSuccess,
3612
+ heartbeat,
3613
+ onNavigatorOnline,
3614
+ simulateSocketClose,
3615
+ simulateSendCloseEvent,
3616
+ onVisibilityChange,
3617
+ getUndoStack: () => state.undoStack,
3618
+ getItemsCount: () => state.nodes.size,
3619
+ connect,
3620
+ disconnect,
3621
+ subscribe,
3622
+ updatePresence,
3623
+ broadcastEvent,
3624
+ batch,
3625
+ undo,
3626
+ redo,
3627
+ canUndo,
3628
+ canRedo,
3629
+ pauseHistory,
3630
+ resumeHistory,
3631
+ getStorage,
3632
+ getStorageSnapshot,
3633
+ events: {
3634
+ customEvent: eventHub.customEvent.observable,
3635
+ others: eventHub.others.observable,
3636
+ me: eventHub.me.observable,
3637
+ error: eventHub.error.observable,
3638
+ connection: eventHub.connection.observable,
3639
+ storage: eventHub.storage.observable,
3640
+ history: eventHub.history.observable,
3641
+ storageDidLoad: eventHub.storageDidLoad.observable
3642
+ },
3643
+ getConnectionState,
3644
+ isSelfAware: () => isConnectionSelfAware(state.connection.current),
3645
+ getSelf: () => self.current,
3646
+ getPresence,
3647
+ getOthers
3648
+ };
3649
+ }
3650
+ function defaultState(initialPresence, initialStorage) {
3651
+ const others = new OthersRef();
3652
+ const connection = new ValueRef({ state: "closed" });
3653
+ return {
3654
+ token: null,
3655
+ lastConnectionId: null,
3656
+ socket: null,
3657
+ numberOfRetry: 0,
3658
+ lastFlushTime: 0,
3659
+ timeoutHandles: {
3660
+ flush: null,
3661
+ reconnect: 0,
3662
+ pongTimeout: 0
3663
+ },
3664
+ buffer: {
3665
+ me: {
3666
+ type: "full",
3667
+ data: initialPresence
3668
+ },
3669
+ messages: [],
3670
+ storageOperations: []
3671
+ },
3672
+ intervalHandles: {
3673
+ heartbeat: 0
3674
+ },
3675
+ connection,
3676
+ me: new MeRef(initialPresence),
3677
+ others,
3678
+ initialStorage,
3679
+ idFactory: null,
3680
+ clock: 0,
3681
+ opClock: 0,
3682
+ nodes: /* @__PURE__ */ new Map(),
3683
+ root: void 0,
3684
+ undoStack: [],
3685
+ redoStack: [],
3686
+ pausedHistory: null,
3687
+ activeBatch: null,
3688
+ offlineOperations: /* @__PURE__ */ new Map()
3689
+ };
3690
+ }
3691
+ function createRoom(options, config) {
3692
+ const { initialPresence, initialStorage } = options;
3693
+ const state = defaultState(
3694
+ typeof initialPresence === "function" ? initialPresence(config.roomId) : initialPresence,
3695
+ typeof initialStorage === "function" ? initialStorage(config.roomId) : initialStorage
3696
+ );
3697
+ const machine = makeStateMachine(
3698
+ state,
3699
+ config
3700
+ );
3701
+ const room = {
3702
+ id: config.roomId,
3703
+ getConnectionState: machine.getConnectionState,
3704
+ isSelfAware: machine.isSelfAware,
3705
+ getSelf: machine.getSelf,
3706
+ subscribe: machine.subscribe,
3707
+ getPresence: machine.getPresence,
3708
+ updatePresence: machine.updatePresence,
3709
+ getOthers: machine.getOthers,
3710
+ broadcastEvent: machine.broadcastEvent,
3711
+ getStorage: machine.getStorage,
3712
+ getStorageSnapshot: machine.getStorageSnapshot,
3713
+ events: machine.events,
3714
+ batch: machine.batch,
3715
+ history: {
3716
+ undo: machine.undo,
3717
+ redo: machine.redo,
3718
+ canUndo: machine.canUndo,
3719
+ canRedo: machine.canRedo,
3720
+ pause: machine.pauseHistory,
3721
+ resume: machine.resumeHistory
3722
+ },
3723
+ __INTERNAL_DO_NOT_USE: {
3724
+ simulateCloseWebsocket: machine.simulateSocketClose,
3725
+ simulateSendCloseEvent: machine.simulateSendCloseEvent
3726
+ }
3727
+ };
3728
+ return {
3729
+ connect: machine.connect,
3730
+ disconnect: machine.disconnect,
3731
+ onNavigatorOnline: machine.onNavigatorOnline,
3732
+ onVisibilityChange: machine.onVisibilityChange,
3733
+ room
3734
+ };
3735
+ }
3736
+ var LiveblocksError = class extends Error {
3737
+ constructor(message, code) {
3738
+ super(message);
3739
+ this.code = code;
3740
+ }
3741
+ };
3742
+ function prepareCreateWebSocket(liveblocksServer, WebSocketPolyfill) {
3743
+ if (typeof window === "undefined" && WebSocketPolyfill === void 0) {
3744
+ throw new Error(
3745
+ "To use Liveblocks client in a non-dom environment, you need to provide a WebSocket polyfill."
3746
+ );
3747
+ }
3748
+ const ws = WebSocketPolyfill || WebSocket;
3749
+ return (token) => {
3750
+ return new ws(
3751
+ `${liveblocksServer}/?token=${token}&version=${true ? "0.18.3-test1" : "dev"}`
3752
+ );
3753
+ };
3754
+ }
3755
+ function prepareAuthEndpoint(authentication, fetchPolyfill) {
3756
+ if (authentication.type === "public") {
3757
+ if (typeof window === "undefined" && fetchPolyfill === void 0) {
3758
+ throw new Error(
3759
+ "To use Liveblocks client in a non-dom environment with a publicApiKey, you need to provide a fetch polyfill."
3760
+ );
3761
+ }
3762
+ return (room) => fetchAuthEndpoint(fetchPolyfill || fetch, authentication.url, {
3763
+ room,
3764
+ publicApiKey: authentication.publicApiKey
3765
+ });
3766
+ }
3767
+ if (authentication.type === "private") {
3768
+ if (typeof window === "undefined" && fetchPolyfill === void 0) {
3769
+ throw new Error(
3770
+ "To use Liveblocks client in a non-dom environment with a url as auth endpoint, you need to provide a fetch polyfill."
3771
+ );
3772
+ }
3773
+ return (room) => fetchAuthEndpoint(fetchPolyfill || fetch, authentication.url, {
3774
+ room
3775
+ });
3776
+ }
3777
+ if (authentication.type === "custom") {
3778
+ return (room) => __async(this, null, function* () {
3779
+ const response = yield authentication.callback(room);
3780
+ if (!response || !response.token) {
3781
+ throw new Error(
3782
+ 'Authentication error. We expect the authentication callback to return a token, but it does not. Hint: the return value should look like: { token: "..." }'
3783
+ );
3784
+ }
3785
+ return response;
3786
+ });
3787
+ }
3788
+ throw new Error("Internal error. Unexpected authentication type");
3789
+ }
3790
+ function fetchAuthEndpoint(fetch2, endpoint, body) {
3791
+ return __async(this, null, function* () {
3792
+ const res = yield fetch2(endpoint, {
3793
+ method: "POST",
3794
+ headers: {
3795
+ "Content-Type": "application/json"
3796
+ },
3797
+ body: JSON.stringify(body)
3798
+ });
3799
+ if (!res.ok) {
3800
+ throw new AuthenticationError(
3801
+ `Expected a status 200 but got ${res.status} when doing a POST request on "${endpoint}"`
3802
+ );
3803
+ }
3804
+ let data;
3805
+ try {
3806
+ data = yield res.json();
3807
+ } catch (er) {
3808
+ throw new AuthenticationError(
3809
+ `Expected a JSON response when doing a POST request on "${endpoint}". ${er}`
3810
+ );
3811
+ }
3812
+ if (!isPlainObject(data) || typeof data.token !== "string") {
3813
+ throw new AuthenticationError(
3814
+ `Expected a JSON response of the form \`{ token: "..." }\` when doing a POST request on "${endpoint}", but got ${JSON.stringify(
3815
+ data
3816
+ )}`
3817
+ );
3818
+ }
3819
+ const { token } = data;
3820
+ return { token };
3821
+ });
3822
+ }
3823
+ var AuthenticationError = class extends Error {
3824
+ constructor(message) {
3825
+ super(message);
3826
+ }
3827
+ };
3828
+
3829
+ // src/client.ts
3830
+ function createClient(options) {
3831
+ const clientOptions = options;
3832
+ const throttleDelay = getThrottleDelayFromOptions(options);
3833
+ const rooms = /* @__PURE__ */ new Map();
3834
+ function getRoom(roomId) {
3835
+ const internalRoom = rooms.get(roomId);
3836
+ return internalRoom ? internalRoom.room : null;
3837
+ }
3838
+ function enter(roomId, options2) {
3839
+ var _a, _b;
3840
+ const shouldConnect = options2.shouldInitiallyConnect === void 0 ? true : options2.shouldInitiallyConnect;
3841
+ let internalRoom = rooms.get(roomId);
3842
+ if (internalRoom) {
3843
+ return internalRoom.room;
3844
+ }
3845
+ deprecateIf(
3846
+ options2.initialPresence === null || options2.initialPresence === void 0,
3847
+ "Please provide an initial presence value for the current user when entering the room."
3848
+ );
3849
+ internalRoom = createRoom(
3850
+ {
3851
+ initialPresence: (_a = options2.initialPresence) != null ? _a : {},
3852
+ initialStorage: options2.initialStorage
3853
+ },
3854
+ {
3855
+ roomId,
3856
+ throttleDelay,
3857
+ polyfills: clientOptions.polyfills,
3858
+ WebSocketPolyfill: clientOptions.WebSocketPolyfill,
3859
+ fetchPolyfill: clientOptions.fetchPolyfill,
3860
+ unstable_batchedUpdates: options2 == null ? void 0 : options2.unstable_batchedUpdates,
3861
+ liveblocksServer: (clientOptions == null ? void 0 : clientOptions.liveblocksServer) || "wss://api.liveblocks.io/v6",
3862
+ authentication: prepareAuthentication(clientOptions, roomId)
3863
+ }
3864
+ );
3865
+ rooms.set(
3866
+ roomId,
3867
+ internalRoom
3868
+ );
3869
+ if (shouldConnect) {
3870
+ if (typeof atob === "undefined") {
3871
+ if (((_b = clientOptions.polyfills) == null ? void 0 : _b.atob) === void 0) {
3872
+ throw new Error(
3873
+ "You need to polyfill atob to use the client in your environment. Please follow the instructions at https://liveblocks.io/docs/errors/liveblocks-client/atob-polyfill"
3874
+ );
3875
+ }
3876
+ global.atob = clientOptions.polyfills.atob;
3877
+ }
3878
+ internalRoom.connect();
3879
+ }
3880
+ return internalRoom.room;
3881
+ }
3882
+ function leave(roomId) {
3883
+ const room = rooms.get(roomId);
3884
+ if (room) {
3885
+ room.disconnect();
3886
+ rooms.delete(roomId);
3887
+ }
3888
+ }
3889
+ if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
3890
+ window.addEventListener("online", () => {
3891
+ for (const [, room] of rooms) {
3892
+ room.onNavigatorOnline();
3893
+ }
3894
+ });
3895
+ }
3896
+ if (typeof document !== "undefined") {
3897
+ document.addEventListener("visibilitychange", () => {
3898
+ for (const [, room] of rooms) {
3899
+ room.onVisibilityChange(document.visibilityState);
3900
+ }
3901
+ });
3902
+ }
3903
+ return {
3904
+ getRoom,
3905
+ enter,
3906
+ leave
3907
+ };
3908
+ }
3909
+ function getThrottleDelayFromOptions(options) {
3910
+ if (options.throttle === void 0) {
3911
+ return 100;
3912
+ }
3913
+ if (typeof options.throttle !== "number" || options.throttle < 80 || options.throttle > 1e3) {
3914
+ throw new Error("throttle should be a number between 80 and 1000.");
3915
+ }
3916
+ return options.throttle;
3917
+ }
3918
+ function prepareAuthentication(clientOptions, roomId) {
3919
+ const { publicApiKey, authEndpoint } = clientOptions;
3920
+ if (authEndpoint !== void 0 && publicApiKey !== void 0) {
3921
+ throw new Error(
3922
+ "You cannot use both publicApiKey and authEndpoint. Please use either publicApiKey or authEndpoint, but not both. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient"
3923
+ );
3924
+ }
3925
+ if (typeof publicApiKey === "string") {
3926
+ if (publicApiKey.startsWith("sk_")) {
3927
+ throw new Error(
3928
+ "Invalid publicApiKey. You are using the secret key which is not supported. Please use the public key instead. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientPublicKey"
3929
+ );
3930
+ } else if (!publicApiKey.startsWith("pk_")) {
3931
+ throw new Error(
3932
+ "Invalid key. Please use the public key format: pk_<public key>. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientPublicKey"
3933
+ );
3934
+ }
3935
+ return {
3936
+ type: "public",
3937
+ publicApiKey,
3938
+ url: buildLiveblocksPublicAuthorizeEndpoint(clientOptions, roomId)
3939
+ };
3940
+ }
3941
+ if (typeof authEndpoint === "string") {
3942
+ return {
3943
+ type: "private",
3944
+ url: authEndpoint
3945
+ };
3946
+ } else if (typeof authEndpoint === "function") {
3947
+ return {
3948
+ type: "custom",
3949
+ callback: authEndpoint
3950
+ };
3951
+ } else if (authEndpoint !== void 0) {
3952
+ throw new Error(
3953
+ "authEndpoint must be a string or a function. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientAuthEndpoint"
3954
+ );
3955
+ }
3956
+ throw new Error(
3957
+ "Invalid Liveblocks client options. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient"
3958
+ );
3959
+ }
3960
+ function buildLiveblocksPublicAuthorizeEndpoint(options, roomId) {
3961
+ if (options.publicAuthorizeEndpoint) {
3962
+ return options.publicAuthorizeEndpoint.replace("{roomId}", roomId);
3963
+ }
3964
+ return `https://api.liveblocks.io/v2/rooms/${encodeURIComponent(
3965
+ roomId
3966
+ )}/public/authorize`;
3967
+ }
3968
+
3969
+ // src/immutable.ts
3970
+ function lsonObjectToJson(obj) {
3971
+ const result = {};
3972
+ for (const key in obj) {
3973
+ const val = obj[key];
3974
+ if (val !== void 0) {
3975
+ result[key] = lsonToJson(val);
3976
+ }
3977
+ }
3978
+ return result;
3979
+ }
3980
+ function liveObjectToJson(liveObject) {
3981
+ return lsonObjectToJson(liveObject.toObject());
3982
+ }
3983
+ function liveMapToJson(map) {
3984
+ const result = {};
3985
+ for (const [key, value] of map.entries()) {
3986
+ result[key] = lsonToJson(value);
3987
+ }
3988
+ return result;
3989
+ }
3990
+ function lsonListToJson(value) {
3991
+ return value.map(lsonToJson);
3992
+ }
3993
+ function liveListToJson(value) {
3994
+ return lsonListToJson(value.toArray());
3995
+ }
3996
+ function lsonToJson(value) {
3997
+ if (value instanceof LiveObject) {
3998
+ return liveObjectToJson(value);
3999
+ } else if (value instanceof LiveList) {
4000
+ return liveListToJson(value);
4001
+ } else if (value instanceof LiveMap) {
4002
+ return liveMapToJson(value);
4003
+ } else if (value instanceof LiveRegister) {
4004
+ return value.data;
4005
+ }
4006
+ if (Array.isArray(value)) {
4007
+ return lsonListToJson(value);
4008
+ } else if (isPlainObject(value)) {
4009
+ return lsonObjectToJson(value);
4010
+ }
4011
+ return value;
4012
+ }
4013
+ function deepLiveify(value) {
4014
+ if (Array.isArray(value)) {
4015
+ return new LiveList(value.map(deepLiveify));
4016
+ } else if (isPlainObject(value)) {
4017
+ const init = {};
4018
+ for (const key in value) {
4019
+ const val = value[key];
4020
+ if (val === void 0) {
4021
+ continue;
4022
+ }
4023
+ init[key] = deepLiveify(val);
4024
+ }
4025
+ return new LiveObject(init);
4026
+ } else {
4027
+ return value;
4028
+ }
4029
+ }
4030
+ function patchLiveList(liveList, prev, next) {
4031
+ let i = 0;
4032
+ let prevEnd = prev.length - 1;
4033
+ let nextEnd = next.length - 1;
4034
+ let prevNode = prev[0];
4035
+ let nextNode = next[0];
4036
+ outer: {
4037
+ while (prevNode === nextNode) {
4038
+ ++i;
4039
+ if (i > prevEnd || i > nextEnd) {
4040
+ break outer;
4041
+ }
4042
+ prevNode = prev[i];
4043
+ nextNode = next[i];
4044
+ }
4045
+ prevNode = prev[prevEnd];
4046
+ nextNode = next[nextEnd];
4047
+ while (prevNode === nextNode) {
4048
+ prevEnd--;
4049
+ nextEnd--;
4050
+ if (i > prevEnd || i > nextEnd) {
4051
+ break outer;
4052
+ }
4053
+ prevNode = prev[prevEnd];
4054
+ nextNode = next[nextEnd];
4055
+ }
4056
+ }
4057
+ if (i > prevEnd) {
4058
+ if (i <= nextEnd) {
4059
+ while (i <= nextEnd) {
4060
+ liveList.insert(deepLiveify(next[i]), i);
4061
+ i++;
4062
+ }
4063
+ }
4064
+ } else if (i > nextEnd) {
4065
+ let localI = i;
4066
+ while (localI <= prevEnd) {
4067
+ liveList.delete(i);
4068
+ localI++;
4069
+ }
4070
+ } else {
4071
+ while (i <= prevEnd && i <= nextEnd) {
4072
+ prevNode = prev[i];
4073
+ nextNode = next[i];
4074
+ const liveListNode = liveList.get(i);
4075
+ if (isLiveObject(liveListNode) && isPlainObject(prevNode) && isPlainObject(nextNode)) {
4076
+ patchLiveObject(liveListNode, prevNode, nextNode);
4077
+ } else {
4078
+ liveList.set(i, deepLiveify(nextNode));
4079
+ }
4080
+ i++;
4081
+ }
4082
+ while (i <= nextEnd) {
4083
+ liveList.insert(deepLiveify(next[i]), i);
4084
+ i++;
4085
+ }
4086
+ let localI = i;
4087
+ while (localI <= prevEnd) {
4088
+ liveList.delete(i);
4089
+ localI++;
4090
+ }
4091
+ }
4092
+ }
4093
+ function patchLiveObjectKey(liveObject, key, prev, next) {
4094
+ if (process.env.NODE_ENV !== "production") {
4095
+ const nonSerializableValue = findNonSerializableValue(next);
4096
+ if (nonSerializableValue) {
4097
+ error(
4098
+ `New state path: '${nonSerializableValue.path}' value: '${nonSerializableValue.value}' is not serializable.
4099
+ Only serializable value can be synced with Liveblocks.`
4100
+ );
4101
+ return;
4102
+ }
4103
+ }
4104
+ const value = liveObject.get(key);
4105
+ if (next === void 0) {
4106
+ liveObject.delete(key);
4107
+ } else if (value === void 0) {
4108
+ liveObject.set(key, deepLiveify(next));
4109
+ } else if (prev === next) {
4110
+ return;
4111
+ } else if (isLiveList(value) && Array.isArray(prev) && Array.isArray(next)) {
4112
+ patchLiveList(value, prev, next);
4113
+ } else if (isLiveObject(value) && isPlainObject(prev) && isPlainObject(next)) {
4114
+ patchLiveObject(value, prev, next);
4115
+ } else {
4116
+ liveObject.set(key, deepLiveify(next));
4117
+ }
4118
+ }
4119
+ function patchLiveObject(root, prev, next) {
4120
+ const updates = {};
4121
+ for (const key in next) {
4122
+ patchLiveObjectKey(root, key, prev[key], next[key]);
4123
+ }
4124
+ for (const key in prev) {
4125
+ if (next[key] === void 0) {
4126
+ root.delete(key);
4127
+ }
4128
+ }
4129
+ if (Object.keys(updates).length > 0) {
4130
+ root.update(updates);
4131
+ }
4132
+ }
4133
+ function getParentsPath(node) {
4134
+ const path = [];
4135
+ while (node.parent.type === "HasParent") {
4136
+ if (isLiveList(node.parent.node)) {
4137
+ path.push(node.parent.node._indexOfPosition(node.parent.key));
4138
+ } else {
4139
+ path.push(node.parent.key);
4140
+ }
4141
+ node = node.parent.node;
4142
+ }
4143
+ return path;
4144
+ }
4145
+ function legacy_patchImmutableObject(state, updates) {
4146
+ return updates.reduce(
4147
+ (state2, update) => legacy_patchImmutableObjectWithUpdate(state2, update),
4148
+ state
4149
+ );
4150
+ }
4151
+ function legacy_patchImmutableObjectWithUpdate(state, update) {
4152
+ const path = getParentsPath(update.node);
4153
+ return legacy_patchImmutableNode(state, path, update);
4154
+ }
4155
+ function legacy_patchImmutableNode(state, path, update) {
4156
+ var _a, _b, _c, _d;
4157
+ const pathItem = path.pop();
4158
+ if (pathItem === void 0) {
4159
+ switch (update.type) {
4160
+ case "LiveObject": {
4161
+ if (state === null || typeof state !== "object" || Array.isArray(state)) {
4162
+ throw new Error(
4163
+ "Internal: received update on LiveObject but state was not an object"
4164
+ );
4165
+ }
4166
+ const newState = Object.assign({}, state);
4167
+ for (const key in update.updates) {
4168
+ if (((_a = update.updates[key]) == null ? void 0 : _a.type) === "update") {
4169
+ const val = update.node.get(key);
4170
+ if (val !== void 0) {
4171
+ newState[key] = lsonToJson(val);
4172
+ }
4173
+ } else if (((_b = update.updates[key]) == null ? void 0 : _b.type) === "delete") {
4174
+ delete newState[key];
4175
+ }
4176
+ }
4177
+ return newState;
4178
+ }
4179
+ case "LiveList": {
4180
+ if (!Array.isArray(state)) {
4181
+ throw new Error(
4182
+ "Internal: received update on LiveList but state was not an array"
4183
+ );
4184
+ }
4185
+ let newState = state.map((x) => x);
4186
+ for (const listUpdate of update.updates) {
4187
+ if (listUpdate.type === "set") {
4188
+ newState = newState.map(
4189
+ (item, index) => index === listUpdate.index ? lsonToJson(listUpdate.item) : item
4190
+ );
4191
+ } else if (listUpdate.type === "insert") {
4192
+ if (listUpdate.index === newState.length) {
4193
+ newState.push(lsonToJson(listUpdate.item));
4194
+ } else {
4195
+ newState = [
4196
+ ...newState.slice(0, listUpdate.index),
4197
+ lsonToJson(listUpdate.item),
4198
+ ...newState.slice(listUpdate.index)
4199
+ ];
4200
+ }
4201
+ } else if (listUpdate.type === "delete") {
4202
+ newState.splice(listUpdate.index, 1);
4203
+ } else if (listUpdate.type === "move") {
4204
+ if (listUpdate.previousIndex > listUpdate.index) {
4205
+ newState = [
4206
+ ...newState.slice(0, listUpdate.index),
4207
+ lsonToJson(listUpdate.item),
4208
+ ...newState.slice(listUpdate.index, listUpdate.previousIndex),
4209
+ ...newState.slice(listUpdate.previousIndex + 1)
4210
+ ];
4211
+ } else {
4212
+ newState = [
4213
+ ...newState.slice(0, listUpdate.previousIndex),
4214
+ ...newState.slice(
4215
+ listUpdate.previousIndex + 1,
4216
+ listUpdate.index + 1
4217
+ ),
4218
+ lsonToJson(listUpdate.item),
4219
+ ...newState.slice(listUpdate.index + 1)
4220
+ ];
4221
+ }
4222
+ }
4223
+ }
4224
+ return newState;
4225
+ }
4226
+ case "LiveMap": {
4227
+ if (state === null || typeof state !== "object" || Array.isArray(state)) {
4228
+ throw new Error(
4229
+ "Internal: received update on LiveMap but state was not an object"
4230
+ );
4231
+ }
4232
+ const newState = Object.assign({}, state);
4233
+ for (const key in update.updates) {
4234
+ if (((_c = update.updates[key]) == null ? void 0 : _c.type) === "update") {
4235
+ const value = update.node.get(key);
4236
+ if (value !== void 0) {
4237
+ newState[key] = lsonToJson(value);
4238
+ }
4239
+ } else if (((_d = update.updates[key]) == null ? void 0 : _d.type) === "delete") {
4240
+ delete newState[key];
4241
+ }
4242
+ }
4243
+ return newState;
4244
+ }
4245
+ }
4246
+ }
4247
+ if (Array.isArray(state)) {
4248
+ const newArray = [...state];
4249
+ newArray[pathItem] = legacy_patchImmutableNode(
4250
+ state[pathItem],
4251
+ path,
4252
+ update
4253
+ );
4254
+ return newArray;
4255
+ } else if (state !== null && typeof state === "object") {
4256
+ const node = state[pathItem];
4257
+ if (node === void 0) {
4258
+ return state;
4259
+ } else {
4260
+ return __spreadProps(__spreadValues({}, state), {
4261
+ [pathItem]: legacy_patchImmutableNode(node, path, update)
4262
+ });
4263
+ }
4264
+ } else {
4265
+ return state;
4266
+ }
4267
+ }
4268
+
4269
+ // src/shallow.ts
4270
+ function shallowArray(xs, ys) {
4271
+ if (xs.length !== ys.length) {
4272
+ return false;
4273
+ }
4274
+ for (let i = 0; i < xs.length; i++) {
4275
+ if (!Object.is(xs[i], ys[i])) {
4276
+ return false;
4277
+ }
4278
+ }
4279
+ return true;
4280
+ }
4281
+ function shallowObj(objA, objB) {
4282
+ if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null || Object.prototype.toString.call(objA) !== "[object Object]" || Object.prototype.toString.call(objB) !== "[object Object]") {
4283
+ return false;
4284
+ }
4285
+ const keysA = Object.keys(objA);
4286
+ if (keysA.length !== Object.keys(objB).length) {
4287
+ return false;
4288
+ }
4289
+ return keysA.every(
4290
+ (key) => Object.prototype.hasOwnProperty.call(objB, key) && Object.is(objA[key], objB[key])
4291
+ );
4292
+ }
4293
+ function shallow(a, b) {
4294
+ if (Object.is(a, b)) {
4295
+ return true;
4296
+ }
4297
+ const isArrayA = Array.isArray(a);
4298
+ const isArrayB = Array.isArray(b);
4299
+ if (isArrayA || isArrayB) {
4300
+ if (!isArrayA || !isArrayB) {
4301
+ return false;
4302
+ }
4303
+ return shallowArray(a, b);
4304
+ }
4305
+ return shallowObj(a, b);
4306
+ }
4307
+
4308
+
4309
+
4310
+
4311
+
4312
+
4313
+
4314
+
4315
+
4316
+
4317
+
4318
+
4319
+
4320
+
4321
+
4322
+
4323
+
4324
+
4325
+
4326
+
4327
+
4328
+
4329
+
4330
+
4331
+
4332
+
4333
+
4334
+
4335
+
4336
+
4337
+
4338
+
4339
+
4340
+
4341
+
4342
+ exports.ClientMsgCode = ClientMsgCode; exports.CrdtType = CrdtType; exports.LiveList = LiveList; exports.LiveMap = LiveMap; exports.LiveObject = LiveObject; exports.OpCode = OpCode; exports.ServerMsgCode = ServerMsgCode; exports.WebsocketCloseCodes = WebsocketCloseCodes; exports.asArrayWithLegacyMethods = asArrayWithLegacyMethods; exports.assertNever = assertNever; exports.b64decode = b64decode; exports.comparePosition = comparePosition; exports.createClient = createClient; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.errorIf = errorIf; exports.freeze = freeze; exports.isAppOnlyAuthToken = isAppOnlyAuthToken; exports.isAuthToken = isAuthToken; exports.isChildCrdt = isChildCrdt; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isPlainObject = isPlainObject; exports.isRoomAuthToken = isRoomAuthToken; exports.isRootCrdt = isRootCrdt; exports.legacy_patchImmutableObject = legacy_patchImmutableObject; exports.lsonToJson = lsonToJson; exports.makePosition = makePosition; exports.nn = nn; exports.patchLiveObjectKey = patchLiveObjectKey; exports.shallow = shallow; exports.throwUsageError = throwUsageError; exports.tryParseJson = tryParseJson;