@liveblocks/core 3.13.0-vincent3 → 3.13.0

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.cjs CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
 
7
7
  // src/version.ts
8
8
  var PKG_NAME = "@liveblocks/core";
9
- var PKG_VERSION = "3.13.0-vincent3";
9
+ var PKG_VERSION = "3.13.0";
10
10
  var PKG_FORMAT = "cjs";
11
11
 
12
12
  // src/dupe-detection.ts
@@ -251,6 +251,19 @@ function findLastIndex(arr, predicate) {
251
251
  }
252
252
  return -1;
253
253
  }
254
+ function partition(iterable, predicate) {
255
+ const good = [];
256
+ const bad = [];
257
+ let index = 0;
258
+ for (const item of iterable) {
259
+ if (predicate(item, index++)) {
260
+ good.push(item);
261
+ } else {
262
+ bad.push(item);
263
+ }
264
+ }
265
+ return [good, bad];
266
+ }
254
267
 
255
268
  // src/lib/signals.ts
256
269
  var kSinks = Symbol("kSinks");
@@ -1606,6 +1619,7 @@ function createApiClient({
1606
1619
  comment: {
1607
1620
  id: commentId,
1608
1621
  body: options.body,
1622
+ metadata: options.commentMetadata,
1609
1623
  attachmentIds: options.attachmentIds
1610
1624
  },
1611
1625
  metadata: options.metadata
@@ -1659,6 +1673,16 @@ function createApiClient({
1659
1673
  options.metadata
1660
1674
  );
1661
1675
  }
1676
+ async function editCommentMetadata(options) {
1677
+ return await httpClient.post(
1678
+ url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}/metadata`,
1679
+ await authManager.getAuthValue({
1680
+ requestedScope: "comments:read",
1681
+ roomId: options.roomId
1682
+ }),
1683
+ options.metadata
1684
+ );
1685
+ }
1662
1686
  async function createComment(options) {
1663
1687
  const commentId = _nullishCoalesce(options.commentId, () => ( createCommentId()));
1664
1688
  const comment = await httpClient.post(
@@ -1670,6 +1694,7 @@ function createApiClient({
1670
1694
  {
1671
1695
  id: commentId,
1672
1696
  body: options.body,
1697
+ metadata: options.metadata,
1673
1698
  attachmentIds: options.attachmentIds
1674
1699
  }
1675
1700
  );
@@ -1684,7 +1709,8 @@ function createApiClient({
1684
1709
  }),
1685
1710
  {
1686
1711
  body: options.body,
1687
- attachmentIds: options.attachmentIds
1712
+ attachmentIds: options.attachmentIds,
1713
+ metadata: options.metadata
1688
1714
  }
1689
1715
  );
1690
1716
  return convertToCommentData(comment);
@@ -2426,6 +2452,7 @@ function createApiClient({
2426
2452
  editThreadMetadata,
2427
2453
  createComment,
2428
2454
  editComment,
2455
+ editCommentMetadata,
2429
2456
  deleteComment,
2430
2457
  addReaction,
2431
2458
  removeReaction,
@@ -3090,12 +3117,7 @@ var ServerMsgCode = Object.freeze({
3090
3117
  BROADCASTED_EVENT: 103,
3091
3118
  ROOM_STATE: 104,
3092
3119
  // For Storage
3093
- STORAGE_STATE_V7: 200,
3094
- // Only sent in V7
3095
- STORAGE_CHUNK: 210,
3096
- // Used in V8+
3097
- STORAGE_STREAM_END: 211,
3098
- // Used in V8+
3120
+ STORAGE_STATE: 200,
3099
3121
  UPDATE_STORAGE: 201,
3100
3122
  // For Yjs Docs
3101
3123
  UPDATE_YDOC: 300,
@@ -3109,6 +3131,7 @@ var ServerMsgCode = Object.freeze({
3109
3131
  COMMENT_DELETED: 404,
3110
3132
  COMMENT_REACTION_ADDED: 405,
3111
3133
  COMMENT_REACTION_REMOVED: 406,
3134
+ COMMENT_METADATA_UPDATED: 409,
3112
3135
  // Error codes
3113
3136
  REJECT_STORAGE_OP: 299
3114
3137
  // Sent if a mutation was not allowed on the server (i.e. due to permissions, limit exceeded, etc)
@@ -6094,6 +6117,19 @@ var AbstractCrdt = class {
6094
6117
  }
6095
6118
  this.#pool = void 0;
6096
6119
  }
6120
+ /**
6121
+ * Serializes this CRDT and all its children into a list of creation ops
6122
+ * with opIds. Used for forward operations that will be sent over the wire
6123
+ * immediately. Each op gets a unique opId for server acknowledgement.
6124
+ *
6125
+ * @internal
6126
+ */
6127
+ _toOpsWithOpId(parentId, parentKey, pool) {
6128
+ return this._toOps(parentId, parentKey).map((op) => ({
6129
+ opId: pool.generateOpId(),
6130
+ ...op
6131
+ }));
6132
+ }
6097
6133
  /** This caches the result of the last .toImmutable() call for this Live node. */
6098
6134
  #cachedImmutable;
6099
6135
  #cachedTreeNodeKey;
@@ -6145,57 +6181,6 @@ var CrdtType = Object.freeze({
6145
6181
  MAP: 2,
6146
6182
  REGISTER: 3
6147
6183
  });
6148
- function isRootNode(node) {
6149
- return node[0] === "root";
6150
- }
6151
- function isRootCrdt(id, _) {
6152
- return id === "root";
6153
- }
6154
- function* compactNodesToNodeStream(nodes) {
6155
- for (const node of nodes) {
6156
- const id = node[0];
6157
- if (isRootNode(node)) {
6158
- yield [id, { type: CrdtType.OBJECT, data: node[1] }];
6159
- continue;
6160
- }
6161
- switch (node[1]) {
6162
- case CrdtType.OBJECT:
6163
- yield [id, { type: CrdtType.OBJECT, parentId: node[2], parentKey: node[3], data: node[4] }];
6164
- break;
6165
- case CrdtType.LIST:
6166
- yield [id, { type: CrdtType.LIST, parentId: node[2], parentKey: node[3] }];
6167
- break;
6168
- case CrdtType.MAP:
6169
- yield [id, { type: CrdtType.MAP, parentId: node[2], parentKey: node[3] }];
6170
- break;
6171
- case CrdtType.REGISTER:
6172
- yield [id, { type: CrdtType.REGISTER, parentId: node[2], parentKey: node[3], data: node[4] }];
6173
- break;
6174
- }
6175
- }
6176
- }
6177
- function* nodeStreamToCompactNodes(nodes) {
6178
- for (const [id, node] of nodes) {
6179
- switch (node.type) {
6180
- case CrdtType.OBJECT:
6181
- if (isRootCrdt(id, node)) {
6182
- yield [id, node.data];
6183
- } else {
6184
- yield [id, CrdtType.OBJECT, node.parentId, node.parentKey, node.data];
6185
- }
6186
- break;
6187
- case CrdtType.LIST:
6188
- yield [id, CrdtType.LIST, node.parentId, node.parentKey];
6189
- break;
6190
- case CrdtType.MAP:
6191
- yield [id, CrdtType.MAP, node.parentId, node.parentKey];
6192
- break;
6193
- case CrdtType.REGISTER:
6194
- yield [id, CrdtType.REGISTER, node.parentId, node.parentKey, node.data];
6195
- break;
6196
- }
6197
- }
6198
- }
6199
6184
 
6200
6185
  // src/crdts/LiveRegister.ts
6201
6186
  var LiveRegister = class _LiveRegister extends AbstractCrdt {
@@ -6214,7 +6199,7 @@ var LiveRegister = class _LiveRegister extends AbstractCrdt {
6214
6199
  return register;
6215
6200
  }
6216
6201
  /** @internal */
6217
- _toOps(parentId, parentKey, pool) {
6202
+ _toOps(parentId, parentKey) {
6218
6203
  if (this._id === void 0) {
6219
6204
  throw new Error(
6220
6205
  "Cannot serialize register if parentId or parentKey is undefined"
@@ -6223,7 +6208,6 @@ var LiveRegister = class _LiveRegister extends AbstractCrdt {
6223
6208
  return [
6224
6209
  {
6225
6210
  type: OpCode.CREATE_REGISTER,
6226
- opId: _optionalChain([pool, 'optionalAccess', _115 => _115.generateOpId, 'call', _116 => _116()]),
6227
6211
  id: this._id,
6228
6212
  parentId,
6229
6213
  parentKey,
@@ -6322,14 +6306,13 @@ var LiveList = class _LiveList extends AbstractCrdt {
6322
6306
  * This is quite unintuitive and should disappear as soon as
6323
6307
  * we introduce an explicit LiveList.Set operation
6324
6308
  */
6325
- _toOps(parentId, parentKey, pool) {
6309
+ _toOps(parentId, parentKey) {
6326
6310
  if (this._id === void 0) {
6327
6311
  throw new Error("Cannot serialize item is not attached");
6328
6312
  }
6329
6313
  const ops = [];
6330
6314
  const op = {
6331
6315
  id: this._id,
6332
- opId: _optionalChain([pool, 'optionalAccess', _117 => _117.generateOpId, 'call', _118 => _118()]),
6333
6316
  type: OpCode.CREATE_LIST,
6334
6317
  parentId,
6335
6318
  parentKey
@@ -6338,13 +6321,9 @@ var LiveList = class _LiveList extends AbstractCrdt {
6338
6321
  for (const item of this.#items) {
6339
6322
  const parentKey2 = item._getParentKeyOrThrow();
6340
6323
  const childOps = HACK_addIntentAndDeletedIdToOperation(
6341
- item._toOps(this._id, parentKey2, pool),
6324
+ item._toOps(this._id, parentKey2),
6342
6325
  void 0
6343
6326
  );
6344
- const childOpId = childOps[0].opId;
6345
- if (childOpId !== void 0) {
6346
- this.#unacknowledgedSets.set(parentKey2, childOpId);
6347
- }
6348
6327
  ops.push(...childOps);
6349
6328
  }
6350
6329
  return ops;
@@ -6600,7 +6579,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6600
6579
  #applyInsertUndoRedo(op) {
6601
6580
  const { id, parentKey: key } = op;
6602
6581
  const child = creationOpToLiveNode(op);
6603
- if (_optionalChain([this, 'access', _119 => _119._pool, 'optionalAccess', _120 => _120.getNode, 'call', _121 => _121(id)]) !== void 0) {
6582
+ if (_optionalChain([this, 'access', _115 => _115._pool, 'optionalAccess', _116 => _116.getNode, 'call', _117 => _117(id)]) !== void 0) {
6604
6583
  return { modified: false };
6605
6584
  }
6606
6585
  child._attach(id, nn(this._pool));
@@ -6608,8 +6587,8 @@ var LiveList = class _LiveList extends AbstractCrdt {
6608
6587
  const existingItemIndex = this._indexOfPosition(key);
6609
6588
  let newKey = key;
6610
6589
  if (existingItemIndex !== -1) {
6611
- const before2 = _optionalChain([this, 'access', _122 => _122.#items, 'access', _123 => _123[existingItemIndex], 'optionalAccess', _124 => _124._parentPos]);
6612
- const after2 = _optionalChain([this, 'access', _125 => _125.#items, 'access', _126 => _126[existingItemIndex + 1], 'optionalAccess', _127 => _127._parentPos]);
6590
+ const before2 = _optionalChain([this, 'access', _118 => _118.#items, 'access', _119 => _119[existingItemIndex], 'optionalAccess', _120 => _120._parentPos]);
6591
+ const after2 = _optionalChain([this, 'access', _121 => _121.#items, 'access', _122 => _122[existingItemIndex + 1], 'optionalAccess', _123 => _123._parentPos]);
6613
6592
  newKey = makePosition(before2, after2);
6614
6593
  child._setParentLink(this, newKey);
6615
6594
  }
@@ -6623,7 +6602,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6623
6602
  #applySetUndoRedo(op) {
6624
6603
  const { id, parentKey: key } = op;
6625
6604
  const child = creationOpToLiveNode(op);
6626
- if (_optionalChain([this, 'access', _128 => _128._pool, 'optionalAccess', _129 => _129.getNode, 'call', _130 => _130(id)]) !== void 0) {
6605
+ if (_optionalChain([this, 'access', _124 => _124._pool, 'optionalAccess', _125 => _125.getNode, 'call', _126 => _126(id)]) !== void 0) {
6627
6606
  return { modified: false };
6628
6607
  }
6629
6608
  this.#unacknowledgedSets.set(key, nn(op.opId));
@@ -6636,7 +6615,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6636
6615
  existingItem._detach();
6637
6616
  this.#items[indexOfItemWithSameKey] = child;
6638
6617
  const reverse = HACK_addIntentAndDeletedIdToOperation(
6639
- existingItem._toOps(nn(this._id), key, this._pool),
6618
+ existingItem._toOps(nn(this._id), key),
6640
6619
  op.id
6641
6620
  );
6642
6621
  const delta = [setDelta(indexOfItemWithSameKey, child)];
@@ -6692,7 +6671,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6692
6671
  _detachChild(child) {
6693
6672
  if (child) {
6694
6673
  const parentKey = nn(child._parentKey);
6695
- const reverse = child._toOps(nn(this._id), parentKey, this._pool);
6674
+ const reverse = child._toOps(nn(this._id), parentKey);
6696
6675
  const indexToDelete = this.#items.indexOf(child);
6697
6676
  if (indexToDelete === -1) {
6698
6677
  return {
@@ -6744,7 +6723,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6744
6723
  } else {
6745
6724
  this.#items[existingItemIndex]._setParentLink(
6746
6725
  this,
6747
- makePosition(newKey, _optionalChain([this, 'access', _131 => _131.#items, 'access', _132 => _132[existingItemIndex + 1], 'optionalAccess', _133 => _133._parentPos]))
6726
+ makePosition(newKey, _optionalChain([this, 'access', _127 => _127.#items, 'access', _128 => _128[existingItemIndex + 1], 'optionalAccess', _129 => _129._parentPos]))
6748
6727
  );
6749
6728
  const previousIndex = this.#items.indexOf(child);
6750
6729
  child._setParentLink(this, newKey);
@@ -6769,7 +6748,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6769
6748
  if (existingItemIndex !== -1) {
6770
6749
  this.#items[existingItemIndex]._setParentLink(
6771
6750
  this,
6772
- makePosition(newKey, _optionalChain([this, 'access', _134 => _134.#items, 'access', _135 => _135[existingItemIndex + 1], 'optionalAccess', _136 => _136._parentPos]))
6751
+ makePosition(newKey, _optionalChain([this, 'access', _130 => _130.#items, 'access', _131 => _131[existingItemIndex + 1], 'optionalAccess', _132 => _132._parentPos]))
6773
6752
  );
6774
6753
  }
6775
6754
  child._setParentLink(this, newKey);
@@ -6788,7 +6767,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6788
6767
  if (existingItemIndex !== -1) {
6789
6768
  this.#items[existingItemIndex]._setParentLink(
6790
6769
  this,
6791
- makePosition(newKey, _optionalChain([this, 'access', _137 => _137.#items, 'access', _138 => _138[existingItemIndex + 1], 'optionalAccess', _139 => _139._parentPos]))
6770
+ makePosition(newKey, _optionalChain([this, 'access', _133 => _133.#items, 'access', _134 => _134[existingItemIndex + 1], 'optionalAccess', _135 => _135._parentPos]))
6792
6771
  );
6793
6772
  }
6794
6773
  child._setParentLink(this, newKey);
@@ -6816,7 +6795,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6816
6795
  if (existingItemIndex !== -1) {
6817
6796
  actualNewKey = makePosition(
6818
6797
  newKey,
6819
- _optionalChain([this, 'access', _140 => _140.#items, 'access', _141 => _141[existingItemIndex + 1], 'optionalAccess', _142 => _142._parentPos])
6798
+ _optionalChain([this, 'access', _136 => _136.#items, 'access', _137 => _137[existingItemIndex + 1], 'optionalAccess', _138 => _138._parentPos])
6820
6799
  );
6821
6800
  }
6822
6801
  child._setParentLink(this, actualNewKey);
@@ -6874,7 +6853,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6874
6853
  * @param element The element to add to the end of the LiveList.
6875
6854
  */
6876
6855
  push(element) {
6877
- _optionalChain([this, 'access', _143 => _143._pool, 'optionalAccess', _144 => _144.assertStorageIsWritable, 'call', _145 => _145()]);
6856
+ _optionalChain([this, 'access', _139 => _139._pool, 'optionalAccess', _140 => _140.assertStorageIsWritable, 'call', _141 => _141()]);
6878
6857
  return this.insert(element, this.length);
6879
6858
  }
6880
6859
  /**
@@ -6883,7 +6862,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6883
6862
  * @param index The index at which you want to insert the element.
6884
6863
  */
6885
6864
  insert(element, index) {
6886
- _optionalChain([this, 'access', _146 => _146._pool, 'optionalAccess', _147 => _147.assertStorageIsWritable, 'call', _148 => _148()]);
6865
+ _optionalChain([this, 'access', _142 => _142._pool, 'optionalAccess', _143 => _143.assertStorageIsWritable, 'call', _144 => _144()]);
6887
6866
  if (index < 0 || index > this.#items.length) {
6888
6867
  throw new Error(
6889
6868
  `Cannot insert list item at index "${index}". index should be between 0 and ${this.#items.length}`
@@ -6899,7 +6878,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6899
6878
  const id = this._pool.generateId();
6900
6879
  value._attach(id, this._pool);
6901
6880
  this._pool.dispatch(
6902
- value._toOps(this._id, position, this._pool),
6881
+ value._toOpsWithOpId(this._id, position, this._pool),
6903
6882
  [{ type: OpCode.DELETE_CRDT, id }],
6904
6883
  /* @__PURE__ */ new Map([
6905
6884
  [this._id, makeUpdate(this, [insertDelta(index, value)])]
@@ -6913,7 +6892,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6913
6892
  * @param targetIndex The index where the element should be after moving.
6914
6893
  */
6915
6894
  move(index, targetIndex) {
6916
- _optionalChain([this, 'access', _149 => _149._pool, 'optionalAccess', _150 => _150.assertStorageIsWritable, 'call', _151 => _151()]);
6895
+ _optionalChain([this, 'access', _145 => _145._pool, 'optionalAccess', _146 => _146.assertStorageIsWritable, 'call', _147 => _147()]);
6917
6896
  if (targetIndex < 0) {
6918
6897
  throw new Error("targetIndex cannot be less than 0");
6919
6898
  }
@@ -6971,7 +6950,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6971
6950
  * @param index The index of the element to delete
6972
6951
  */
6973
6952
  delete(index) {
6974
- _optionalChain([this, 'access', _152 => _152._pool, 'optionalAccess', _153 => _153.assertStorageIsWritable, 'call', _154 => _154()]);
6953
+ _optionalChain([this, 'access', _148 => _148._pool, 'optionalAccess', _149 => _149.assertStorageIsWritable, 'call', _150 => _150()]);
6975
6954
  if (index < 0 || index >= this.#items.length) {
6976
6955
  throw new Error(
6977
6956
  `Cannot delete list item at index "${index}". index should be between 0 and ${this.#items.length - 1}`
@@ -7004,7 +6983,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7004
6983
  }
7005
6984
  }
7006
6985
  clear() {
7007
- _optionalChain([this, 'access', _155 => _155._pool, 'optionalAccess', _156 => _156.assertStorageIsWritable, 'call', _157 => _157()]);
6986
+ _optionalChain([this, 'access', _151 => _151._pool, 'optionalAccess', _152 => _152.assertStorageIsWritable, 'call', _153 => _153()]);
7008
6987
  if (this._pool) {
7009
6988
  const ops = [];
7010
6989
  const reverseOps = [];
@@ -7038,7 +7017,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7038
7017
  }
7039
7018
  }
7040
7019
  set(index, item) {
7041
- _optionalChain([this, 'access', _158 => _158._pool, 'optionalAccess', _159 => _159.assertStorageIsWritable, 'call', _160 => _160()]);
7020
+ _optionalChain([this, 'access', _154 => _154._pool, 'optionalAccess', _155 => _155.assertStorageIsWritable, 'call', _156 => _156()]);
7042
7021
  if (index < 0 || index >= this.#items.length) {
7043
7022
  throw new Error(
7044
7023
  `Cannot set list item at index "${index}". index should be between 0 and ${this.#items.length - 1}`
@@ -7058,12 +7037,12 @@ var LiveList = class _LiveList extends AbstractCrdt {
7058
7037
  const storageUpdates = /* @__PURE__ */ new Map();
7059
7038
  storageUpdates.set(this._id, makeUpdate(this, [setDelta(index, value)]));
7060
7039
  const ops = HACK_addIntentAndDeletedIdToOperation(
7061
- value._toOps(this._id, position, this._pool),
7040
+ value._toOpsWithOpId(this._id, position, this._pool),
7062
7041
  existingId
7063
7042
  );
7064
7043
  this.#unacknowledgedSets.set(position, nn(ops[0].opId));
7065
7044
  const reverseOps = HACK_addIntentAndDeletedIdToOperation(
7066
- existingItem._toOps(this._id, position, void 0),
7045
+ existingItem._toOps(this._id, position),
7067
7046
  id
7068
7047
  );
7069
7048
  this._pool.dispatch(ops, reverseOps, storageUpdates);
@@ -7184,7 +7163,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7184
7163
  #shiftItemPosition(index, key) {
7185
7164
  const shiftedPosition = makePosition(
7186
7165
  key,
7187
- this.#items.length > index + 1 ? _optionalChain([this, 'access', _161 => _161.#items, 'access', _162 => _162[index + 1], 'optionalAccess', _163 => _163._parentPos]) : void 0
7166
+ this.#items.length > index + 1 ? _optionalChain([this, 'access', _157 => _157.#items, 'access', _158 => _158[index + 1], 'optionalAccess', _159 => _159._parentPos]) : void 0
7188
7167
  );
7189
7168
  this.#items[index]._setParentLink(this, shiftedPosition);
7190
7169
  }
@@ -7302,21 +7281,20 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7302
7281
  }
7303
7282
  }
7304
7283
  /** @internal */
7305
- _toOps(parentId, parentKey, pool) {
7284
+ _toOps(parentId, parentKey) {
7306
7285
  if (this._id === void 0) {
7307
7286
  throw new Error("Cannot serialize item is not attached");
7308
7287
  }
7309
7288
  const ops = [];
7310
7289
  const op = {
7311
7290
  id: this._id,
7312
- opId: _optionalChain([pool, 'optionalAccess', _164 => _164.generateOpId, 'call', _165 => _165()]),
7313
7291
  type: OpCode.CREATE_MAP,
7314
7292
  parentId,
7315
7293
  parentKey
7316
7294
  };
7317
7295
  ops.push(op);
7318
7296
  for (const [key, value] of this.#map) {
7319
- ops.push(...value._toOps(this._id, key, pool));
7297
+ ops.push(...value._toOps(this._id, key));
7320
7298
  }
7321
7299
  return ops;
7322
7300
  }
@@ -7400,7 +7378,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7400
7378
  _detachChild(child) {
7401
7379
  const id = nn(this._id);
7402
7380
  const parentKey = nn(child._parentKey);
7403
- const reverse = child._toOps(id, parentKey, this._pool);
7381
+ const reverse = child._toOps(id, parentKey);
7404
7382
  for (const [key, value] of this.#map) {
7405
7383
  if (value === child) {
7406
7384
  this.#map.delete(key);
@@ -7449,7 +7427,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7449
7427
  * @param value The value of the element to add. Should be serializable to JSON.
7450
7428
  */
7451
7429
  set(key, value) {
7452
- _optionalChain([this, 'access', _166 => _166._pool, 'optionalAccess', _167 => _167.assertStorageIsWritable, 'call', _168 => _168()]);
7430
+ _optionalChain([this, 'access', _160 => _160._pool, 'optionalAccess', _161 => _161.assertStorageIsWritable, 'call', _162 => _162()]);
7453
7431
  const oldValue = this.#map.get(key);
7454
7432
  if (oldValue) {
7455
7433
  oldValue._detach();
@@ -7467,10 +7445,10 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7467
7445
  type: "LiveMap",
7468
7446
  updates: { [key]: { type: "update" } }
7469
7447
  });
7470
- const ops = item._toOps(this._id, key, this._pool);
7448
+ const ops = item._toOpsWithOpId(this._id, key, this._pool);
7471
7449
  this.#unacknowledgedSet.set(key, nn(ops[0].opId));
7472
7450
  this._pool.dispatch(
7473
- item._toOps(this._id, key, this._pool),
7451
+ ops,
7474
7452
  oldValue ? oldValue._toOps(this._id, key) : [{ type: OpCode.DELETE_CRDT, id }],
7475
7453
  storageUpdates
7476
7454
  );
@@ -7495,7 +7473,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7495
7473
  * @returns true if an element existed and has been removed, or false if the element does not exist.
7496
7474
  */
7497
7475
  delete(key) {
7498
- _optionalChain([this, 'access', _169 => _169._pool, 'optionalAccess', _170 => _170.assertStorageIsWritable, 'call', _171 => _171()]);
7476
+ _optionalChain([this, 'access', _163 => _163._pool, 'optionalAccess', _164 => _164.assertStorageIsWritable, 'call', _165 => _165()]);
7499
7477
  const item = this.#map.get(key);
7500
7478
  if (item === void 0) {
7501
7479
  return false;
@@ -7630,12 +7608,25 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7630
7608
 
7631
7609
  // src/crdts/LiveObject.ts
7632
7610
  var MAX_LIVE_OBJECT_SIZE = 128 * 1024;
7633
- function isRootCrdt2(id, _) {
7611
+ function isRootCrdt(id, _) {
7634
7612
  return id === "root";
7635
7613
  }
7636
7614
  var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7637
7615
  #map;
7638
- #propToLastUpdate;
7616
+ /**
7617
+ * Tracks unacknowledged local changes per property to preserve optimistic
7618
+ * updates. Maps property keys to their pending operation IDs.
7619
+ *
7620
+ * INVARIANT: Only locally-generated opIds are ever stored here. Remote opIds
7621
+ * are only compared against (to detect ACKs), never stored.
7622
+ *
7623
+ * When a local change is made, the opId is stored here. When a remote op
7624
+ * arrives for the same key:
7625
+ * - If no entry exists → apply remote op
7626
+ * - If opId matches → it's an ACK, clear the entry
7627
+ * - If opId differs → ignore remote op to preserve optimistic update
7628
+ */
7629
+ #unackedOpsByKey;
7639
7630
  /**
7640
7631
  * Enable or disable detection of too large LiveObjects.
7641
7632
  * When enabled, throws an error if LiveObject static data exceeds 128KB, which
@@ -7650,7 +7641,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7650
7641
  const parentToChildren = /* @__PURE__ */ new Map();
7651
7642
  let root = null;
7652
7643
  for (const [id, crdt] of items) {
7653
- if (isRootCrdt2(id, crdt)) {
7644
+ if (isRootCrdt(id, crdt)) {
7654
7645
  root = crdt;
7655
7646
  } else {
7656
7647
  const tuple = [id, crdt];
@@ -7668,8 +7659,8 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7668
7659
  return [root, parentToChildren];
7669
7660
  }
7670
7661
  /** @private Do not use this API directly */
7671
- static _fromItems(nodes, pool) {
7672
- const [root, parentToChildren] = _LiveObject.#buildRootAndParentToChildren(nodes);
7662
+ static _fromItems(items, pool) {
7663
+ const [root, parentToChildren] = _LiveObject.#buildRootAndParentToChildren(items);
7673
7664
  return _LiveObject._deserialize(
7674
7665
  ["root", root],
7675
7666
  parentToChildren,
@@ -7678,7 +7669,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7678
7669
  }
7679
7670
  constructor(obj = {}) {
7680
7671
  super();
7681
- this.#propToLastUpdate = /* @__PURE__ */ new Map();
7672
+ this.#unackedOpsByKey = /* @__PURE__ */ new Map();
7682
7673
  const o = compactObject(obj);
7683
7674
  for (const key of Object.keys(o)) {
7684
7675
  const value = o[key];
@@ -7689,16 +7680,14 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7689
7680
  this.#map = new Map(Object.entries(o));
7690
7681
  }
7691
7682
  /** @internal */
7692
- _toOps(parentId, parentKey, pool) {
7683
+ _toOps(parentId, parentKey) {
7693
7684
  if (this._id === void 0) {
7694
7685
  throw new Error("Cannot serialize item is not attached");
7695
7686
  }
7696
- const opId = _optionalChain([pool, 'optionalAccess', _172 => _172.generateOpId, 'call', _173 => _173()]);
7697
7687
  const ops = [];
7698
7688
  const op = {
7699
7689
  type: OpCode.CREATE_OBJECT,
7700
7690
  id: this._id,
7701
- opId,
7702
7691
  parentId,
7703
7692
  parentKey,
7704
7693
  data: {}
@@ -7706,7 +7695,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7706
7695
  ops.push(op);
7707
7696
  for (const [key, value] of this.#map) {
7708
7697
  if (isLiveNode(value)) {
7709
- ops.push(...value._toOps(this._id, key, pool));
7698
+ ops.push(...value._toOps(this._id, key));
7710
7699
  } else {
7711
7700
  op.data[key] = value;
7712
7701
  }
@@ -7752,16 +7741,16 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7752
7741
  const { id, opId, parentKey: key } = op;
7753
7742
  const child = creationOpToLson(op);
7754
7743
  if (this._pool.getNode(id) !== void 0) {
7755
- if (this.#propToLastUpdate.get(key) === opId) {
7756
- this.#propToLastUpdate.delete(key);
7744
+ if (this.#unackedOpsByKey.get(key) === opId) {
7745
+ this.#unackedOpsByKey.delete(key);
7757
7746
  }
7758
7747
  return { modified: false };
7759
7748
  }
7760
7749
  if (source === 0 /* LOCAL */) {
7761
- this.#propToLastUpdate.set(key, nn(opId));
7762
- } else if (this.#propToLastUpdate.get(key) === void 0) {
7763
- } else if (this.#propToLastUpdate.get(key) === opId) {
7764
- this.#propToLastUpdate.delete(key);
7750
+ this.#unackedOpsByKey.set(key, nn(opId));
7751
+ } else if (this.#unackedOpsByKey.get(key) === void 0) {
7752
+ } else if (this.#unackedOpsByKey.get(key) === opId) {
7753
+ this.#unackedOpsByKey.delete(key);
7765
7754
  return { modified: false };
7766
7755
  } else {
7767
7756
  return { modified: false };
@@ -7803,7 +7792,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7803
7792
  if (child) {
7804
7793
  const id = nn(this._id);
7805
7794
  const parentKey = nn(child._parentKey);
7806
- const reverse = child._toOps(id, parentKey, this._pool);
7795
+ const reverse = child._toOps(id, parentKey);
7807
7796
  for (const [key, value] of this.#map) {
7808
7797
  if (value === child) {
7809
7798
  this.#map.delete(key);
@@ -7889,11 +7878,11 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7889
7878
  continue;
7890
7879
  }
7891
7880
  if (isLocal) {
7892
- this.#propToLastUpdate.set(key, nn(op.opId));
7893
- } else if (this.#propToLastUpdate.get(key) === void 0) {
7881
+ this.#unackedOpsByKey.set(key, nn(op.opId));
7882
+ } else if (this.#unackedOpsByKey.get(key) === void 0) {
7894
7883
  isModified = true;
7895
- } else if (this.#propToLastUpdate.get(key) === op.opId) {
7896
- this.#propToLastUpdate.delete(key);
7884
+ } else if (this.#unackedOpsByKey.get(key) === op.opId) {
7885
+ this.#unackedOpsByKey.delete(key);
7897
7886
  continue;
7898
7887
  } else {
7899
7888
  continue;
@@ -7925,7 +7914,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7925
7914
  if (oldValue === void 0) {
7926
7915
  return { modified: false };
7927
7916
  }
7928
- if (!isLocal && this.#propToLastUpdate.get(key) !== void 0) {
7917
+ if (!isLocal && this.#unackedOpsByKey.get(key) !== void 0) {
7929
7918
  return { modified: false };
7930
7919
  }
7931
7920
  const id = nn(this._id);
@@ -7967,7 +7956,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7967
7956
  * @param value The value of the property to add
7968
7957
  */
7969
7958
  set(key, value) {
7970
- _optionalChain([this, 'access', _174 => _174._pool, 'optionalAccess', _175 => _175.assertStorageIsWritable, 'call', _176 => _176()]);
7959
+ _optionalChain([this, 'access', _166 => _166._pool, 'optionalAccess', _167 => _167.assertStorageIsWritable, 'call', _168 => _168()]);
7971
7960
  this.update({ [key]: value });
7972
7961
  }
7973
7962
  /**
@@ -7982,7 +7971,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7982
7971
  * @param key The key of the property to delete
7983
7972
  */
7984
7973
  delete(key) {
7985
- _optionalChain([this, 'access', _177 => _177._pool, 'optionalAccess', _178 => _178.assertStorageIsWritable, 'call', _179 => _179()]);
7974
+ _optionalChain([this, 'access', _169 => _169._pool, 'optionalAccess', _170 => _170.assertStorageIsWritable, 'call', _171 => _171()]);
7986
7975
  const keyAsString = key;
7987
7976
  const oldValue = this.#map.get(keyAsString);
7988
7977
  if (oldValue === void 0) {
@@ -8037,7 +8026,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8037
8026
  * @param patch The object used to overrides properties
8038
8027
  */
8039
8028
  update(patch) {
8040
- _optionalChain([this, 'access', _180 => _180._pool, 'optionalAccess', _181 => _181.assertStorageIsWritable, 'call', _182 => _182()]);
8029
+ _optionalChain([this, 'access', _172 => _172._pool, 'optionalAccess', _173 => _173.assertStorageIsWritable, 'call', _174 => _174()]);
8041
8030
  if (_LiveObject.detectLargeObjects) {
8042
8031
  const data = {};
8043
8032
  for (const [key, value] of this.#map) {
@@ -8108,17 +8097,21 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8108
8097
  if (isLiveNode(newValue)) {
8109
8098
  newValue._setParentLink(this, key);
8110
8099
  newValue._attach(this._pool.generateId(), this._pool);
8111
- const newAttachChildOps = newValue._toOps(this._id, key, this._pool);
8100
+ const newAttachChildOps = newValue._toOpsWithOpId(
8101
+ this._id,
8102
+ key,
8103
+ this._pool
8104
+ );
8112
8105
  const createCrdtOp = newAttachChildOps.find(
8113
8106
  (op) => op.parentId === this._id
8114
8107
  );
8115
8108
  if (createCrdtOp) {
8116
- this.#propToLastUpdate.set(key, nn(createCrdtOp.opId));
8109
+ this.#unackedOpsByKey.set(key, nn(createCrdtOp.opId));
8117
8110
  }
8118
8111
  ops.push(...newAttachChildOps);
8119
8112
  } else {
8120
8113
  updatedProps[key] = newValue;
8121
- this.#propToLastUpdate.set(key, opId);
8114
+ this.#unackedOpsByKey.set(key, opId);
8122
8115
  }
8123
8116
  this.#map.set(key, newValue);
8124
8117
  this.invalidate();
@@ -8288,7 +8281,10 @@ function getTreesDiffOperations(currentItems, newItems) {
8288
8281
  const ops = [];
8289
8282
  currentItems.forEach((_, id) => {
8290
8283
  if (!newItems.get(id)) {
8291
- ops.push({ type: OpCode.DELETE_CRDT, id });
8284
+ ops.push({
8285
+ type: OpCode.DELETE_CRDT,
8286
+ id
8287
+ });
8292
8288
  }
8293
8289
  });
8294
8290
  newItems.forEach((crdt, id) => {
@@ -8713,6 +8709,8 @@ function defaultMessageFromContext(context) {
8713
8709
  return "Could not delete thread";
8714
8710
  case "EDIT_THREAD_METADATA_ERROR":
8715
8711
  return "Could not edit thread metadata";
8712
+ case "EDIT_COMMENT_METADATA_ERROR":
8713
+ return "Could not edit comment metadata";
8716
8714
  case "MARK_THREAD_AS_RESOLVED_ERROR":
8717
8715
  return "Could not mark thread as resolved";
8718
8716
  case "MARK_THREAD_AS_UNRESOLVED_ERROR":
@@ -8774,33 +8772,18 @@ function installBackgroundTabSpy() {
8774
8772
  const doc = typeof document !== "undefined" ? document : void 0;
8775
8773
  const inBackgroundSince = { current: null };
8776
8774
  function onVisibilityChange() {
8777
- if (_optionalChain([doc, 'optionalAccess', _183 => _183.visibilityState]) === "hidden") {
8775
+ if (_optionalChain([doc, 'optionalAccess', _175 => _175.visibilityState]) === "hidden") {
8778
8776
  inBackgroundSince.current = _nullishCoalesce(inBackgroundSince.current, () => ( Date.now()));
8779
8777
  } else {
8780
8778
  inBackgroundSince.current = null;
8781
8779
  }
8782
8780
  }
8783
- _optionalChain([doc, 'optionalAccess', _184 => _184.addEventListener, 'call', _185 => _185("visibilitychange", onVisibilityChange)]);
8781
+ _optionalChain([doc, 'optionalAccess', _176 => _176.addEventListener, 'call', _177 => _177("visibilitychange", onVisibilityChange)]);
8784
8782
  const unsub = () => {
8785
- _optionalChain([doc, 'optionalAccess', _186 => _186.removeEventListener, 'call', _187 => _187("visibilitychange", onVisibilityChange)]);
8783
+ _optionalChain([doc, 'optionalAccess', _178 => _178.removeEventListener, 'call', _179 => _179("visibilitychange", onVisibilityChange)]);
8786
8784
  };
8787
8785
  return [inBackgroundSince, unsub];
8788
8786
  }
8789
- function makePartialNodeMap() {
8790
- let map = /* @__PURE__ */ new Map();
8791
- return {
8792
- append(chunk2) {
8793
- for (const [id, node] of chunk2) {
8794
- map.set(id, node);
8795
- }
8796
- },
8797
- clear() {
8798
- const result = map;
8799
- map = /* @__PURE__ */ new Map();
8800
- return result;
8801
- }
8802
- };
8803
- }
8804
8787
  function createRoom(options, config) {
8805
8788
  const roomId = config.roomId;
8806
8789
  const initialPresence = options.initialPresence;
@@ -8861,7 +8844,6 @@ function createRoom(options, config) {
8861
8844
  activeBatch: null,
8862
8845
  unacknowledgedOps: /* @__PURE__ */ new Map()
8863
8846
  };
8864
- const partialNodes = makePartialNodeMap();
8865
8847
  let lastTokenKey;
8866
8848
  function onStatusDidChange(newStatus) {
8867
8849
  const authValue = managedSocket.authValue;
@@ -8966,7 +8948,7 @@ function createRoom(options, config) {
8966
8948
  }
8967
8949
  }
8968
8950
  function isStorageWritable() {
8969
- const scopes = _optionalChain([context, 'access', _188 => _188.dynamicSessionInfoSig, 'access', _189 => _189.get, 'call', _190 => _190(), 'optionalAccess', _191 => _191.scopes]);
8951
+ const scopes = _optionalChain([context, 'access', _180 => _180.dynamicSessionInfoSig, 'access', _181 => _181.get, 'call', _182 => _182(), 'optionalAccess', _183 => _183.scopes]);
8970
8952
  return scopes !== void 0 ? canWriteStorage(scopes) : true;
8971
8953
  }
8972
8954
  const eventHub = {
@@ -9097,7 +9079,7 @@ function createRoom(options, config) {
9097
9079
  // be stuck in "synchronizing" forever).
9098
9080
  case "experimental-fallback-to-http": {
9099
9081
  warn("Message is too large for websockets, so sending over HTTP instead");
9100
- const nonce = _nullishCoalesce(_optionalChain([context, 'access', _192 => _192.dynamicSessionInfoSig, 'access', _193 => _193.get, 'call', _194 => _194(), 'optionalAccess', _195 => _195.nonce]), () => ( raise("Session is not authorized to send message over HTTP")));
9082
+ const nonce = _nullishCoalesce(_optionalChain([context, 'access', _184 => _184.dynamicSessionInfoSig, 'access', _185 => _185.get, 'call', _186 => _186(), 'optionalAccess', _187 => _187.nonce]), () => ( raise("Session is not authorized to send message over HTTP")));
9101
9083
  void httpClient.sendMessagesOverHTTP({ roomId, nonce, messages }).then((resp) => {
9102
9084
  if (!resp.ok && resp.status === 403) {
9103
9085
  managedSocket.reconnect();
@@ -9143,13 +9125,16 @@ function createRoom(options, config) {
9143
9125
  self,
9144
9126
  (me) => me !== null ? userToTreeNode("Me", me) : null
9145
9127
  );
9146
- function createOrUpdateRootFromMessage(nodes) {
9128
+ function createOrUpdateRootFromMessage(message) {
9129
+ if (message.items.length === 0) {
9130
+ throw new Error("Internal error: cannot load storage without items");
9131
+ }
9147
9132
  if (context.root !== void 0) {
9148
- updateRoot(new Map(nodes));
9133
+ updateRoot(message.items);
9149
9134
  } else {
9150
- context.root = LiveObject._fromItems(nodes, context.pool);
9135
+ context.root = LiveObject._fromItems(message.items, context.pool);
9151
9136
  }
9152
- const canWrite = _nullishCoalesce(_optionalChain([self, 'access', _196 => _196.get, 'call', _197 => _197(), 'optionalAccess', _198 => _198.canWrite]), () => ( true));
9137
+ const canWrite = _nullishCoalesce(_optionalChain([self, 'access', _188 => _188.get, 'call', _189 => _189(), 'optionalAccess', _190 => _190.canWrite]), () => ( true));
9153
9138
  const stackSizeBefore = context.undoStack.length;
9154
9139
  for (const key in context.initialStorage) {
9155
9140
  if (context.root.get(key) === void 0) {
@@ -9164,10 +9149,7 @@ function createRoom(options, config) {
9164
9149
  }
9165
9150
  context.undoStack.length = stackSizeBefore;
9166
9151
  }
9167
- function updateRoot(nodes) {
9168
- if (nodes.size === 0) {
9169
- throw new Error("Internal error: cannot load storage without items");
9170
- }
9152
+ function updateRoot(items) {
9171
9153
  if (context.root === void 0) {
9172
9154
  return;
9173
9155
  }
@@ -9175,26 +9157,22 @@ function createRoom(options, config) {
9175
9157
  for (const [id, node] of context.pool.nodes) {
9176
9158
  currentItems.set(id, node._serialize());
9177
9159
  }
9178
- const ops = getTreesDiffOperations(currentItems, nodes);
9179
- const result = applyOps(
9180
- ops,
9181
- /* isLocal */
9182
- false
9183
- );
9160
+ const ops = getTreesDiffOperations(currentItems, new Map(items));
9161
+ const result = applyRemoteOps(ops);
9184
9162
  notify(result.updates);
9185
9163
  }
9186
- function _addToRealUndoStack(historyOps) {
9164
+ function _addToRealUndoStack(frames) {
9187
9165
  if (context.undoStack.length >= 50) {
9188
9166
  context.undoStack.shift();
9189
9167
  }
9190
- context.undoStack.push(historyOps);
9168
+ context.undoStack.push(frames);
9191
9169
  onHistoryChange();
9192
9170
  }
9193
- function addToUndoStack(historyOps) {
9171
+ function addToUndoStack(frames) {
9194
9172
  if (context.pausedHistory !== null) {
9195
- context.pausedHistory.pushLeft(historyOps);
9173
+ context.pausedHistory.pushLeft(frames);
9196
9174
  } else {
9197
- _addToRealUndoStack(historyOps);
9175
+ _addToRealUndoStack(frames);
9198
9176
  }
9199
9177
  }
9200
9178
  function notify(updates) {
@@ -9225,69 +9203,85 @@ function createRoom(options, config) {
9225
9203
  "Internal. Tried to get connection id but connection was never open"
9226
9204
  );
9227
9205
  }
9228
- function applyOps(rawOps, isLocal) {
9206
+ function applyLocalOps(frames) {
9207
+ const [pframes, ops] = partition(
9208
+ frames,
9209
+ (f) => f.type === "presence"
9210
+ );
9211
+ const opsWithOpIds = ops.map(
9212
+ (op) => op.opId === void 0 ? { ...op, opId: context.pool.generateOpId() } : op
9213
+ );
9214
+ const { reverse, updates } = applyOps(
9215
+ pframes,
9216
+ opsWithOpIds,
9217
+ /* isLocal */
9218
+ true
9219
+ );
9220
+ return { opsToEmit: opsWithOpIds, reverse, updates };
9221
+ }
9222
+ function applyRemoteOps(ops) {
9223
+ return applyOps(
9224
+ [],
9225
+ ops,
9226
+ /* isLocal */
9227
+ false
9228
+ );
9229
+ }
9230
+ function applyOps(pframes, ops, isLocal) {
9229
9231
  const output = {
9230
9232
  reverse: new Deque(),
9231
9233
  storageUpdates: /* @__PURE__ */ new Map(),
9232
9234
  presence: false
9233
9235
  };
9234
- const createdNodeIds = /* @__PURE__ */ new Set();
9235
- const ops = rawOps.map((op) => {
9236
- if (op.type !== "presence" && !op.opId) {
9237
- return { ...op, opId: context.pool.generateOpId() };
9236
+ for (const pf of pframes) {
9237
+ const reverse = {
9238
+ type: "presence",
9239
+ data: {}
9240
+ };
9241
+ for (const key in pf.data) {
9242
+ reverse.data[key] = context.myPresence.get()[key];
9243
+ }
9244
+ context.myPresence.patch(pf.data);
9245
+ if (context.buffer.presenceUpdates === null) {
9246
+ context.buffer.presenceUpdates = { type: "partial", data: pf.data };
9238
9247
  } else {
9239
- return op;
9248
+ for (const key in pf.data) {
9249
+ context.buffer.presenceUpdates.data[key] = pf.data[key];
9250
+ }
9240
9251
  }
9241
- });
9252
+ output.reverse.pushLeft(reverse);
9253
+ output.presence = true;
9254
+ }
9255
+ const createdNodeIds = /* @__PURE__ */ new Set();
9242
9256
  for (const op of ops) {
9243
- if (op.type === "presence") {
9244
- const reverse = {
9245
- type: "presence",
9246
- data: {}
9247
- };
9248
- for (const key in op.data) {
9249
- reverse.data[key] = context.myPresence.get()[key];
9250
- }
9251
- context.myPresence.patch(op.data);
9252
- if (context.buffer.presenceUpdates === null) {
9253
- context.buffer.presenceUpdates = { type: "partial", data: op.data };
9254
- } else {
9255
- for (const key in op.data) {
9256
- context.buffer.presenceUpdates.data[key] = op.data[key];
9257
- }
9258
- }
9259
- output.reverse.pushLeft(reverse);
9260
- output.presence = true;
9257
+ let source;
9258
+ if (isLocal) {
9259
+ source = 0 /* LOCAL */;
9260
+ } else if (op.opId !== void 0) {
9261
+ context.unacknowledgedOps.delete(op.opId);
9262
+ source = 2 /* OURS */;
9261
9263
  } else {
9262
- let source;
9263
- if (isLocal) {
9264
- source = 0 /* LOCAL */;
9265
- } else {
9266
- const opId = nn(op.opId);
9267
- const deleted = context.unacknowledgedOps.delete(opId);
9268
- source = deleted ? 2 /* OURS */ : 1 /* THEIRS */;
9264
+ source = 1 /* THEIRS */;
9265
+ }
9266
+ const applyOpResult = applyOp(op, source);
9267
+ if (applyOpResult.modified) {
9268
+ const nodeId = applyOpResult.modified.node._id;
9269
+ if (!(nodeId && createdNodeIds.has(nodeId))) {
9270
+ output.storageUpdates.set(
9271
+ nn(applyOpResult.modified.node._id),
9272
+ mergeStorageUpdates(
9273
+ output.storageUpdates.get(nn(applyOpResult.modified.node._id)),
9274
+ applyOpResult.modified
9275
+ )
9276
+ );
9277
+ output.reverse.pushLeft(applyOpResult.reverse);
9269
9278
  }
9270
- const applyOpResult = applyOp(op, source);
9271
- if (applyOpResult.modified) {
9272
- const nodeId = applyOpResult.modified.node._id;
9273
- if (!(nodeId && createdNodeIds.has(nodeId))) {
9274
- output.storageUpdates.set(
9275
- nn(applyOpResult.modified.node._id),
9276
- mergeStorageUpdates(
9277
- output.storageUpdates.get(nn(applyOpResult.modified.node._id)),
9278
- applyOpResult.modified
9279
- )
9280
- );
9281
- output.reverse.pushLeft(applyOpResult.reverse);
9282
- }
9283
- if (op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_OBJECT) {
9284
- createdNodeIds.add(nn(op.id));
9285
- }
9279
+ if (op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_OBJECT) {
9280
+ createdNodeIds.add(op.id);
9286
9281
  }
9287
9282
  }
9288
9283
  }
9289
9284
  return {
9290
- ops,
9291
9285
  reverse: Array.from(output.reverse),
9292
9286
  updates: {
9293
9287
  storageUpdates: output.storageUpdates,
@@ -9356,7 +9350,7 @@ function createRoom(options, config) {
9356
9350
  }
9357
9351
  context.myPresence.patch(patch);
9358
9352
  if (context.activeBatch) {
9359
- if (_optionalChain([options2, 'optionalAccess', _199 => _199.addToHistory])) {
9353
+ if (_optionalChain([options2, 'optionalAccess', _191 => _191.addToHistory])) {
9360
9354
  context.activeBatch.reverseOps.pushLeft({
9361
9355
  type: "presence",
9362
9356
  data: oldValues
@@ -9365,7 +9359,7 @@ function createRoom(options, config) {
9365
9359
  context.activeBatch.updates.presence = true;
9366
9360
  } else {
9367
9361
  flushNowOrSoon();
9368
- if (_optionalChain([options2, 'optionalAccess', _200 => _200.addToHistory])) {
9362
+ if (_optionalChain([options2, 'optionalAccess', _192 => _192.addToHistory])) {
9369
9363
  addToUndoStack([{ type: "presence", data: oldValues }]);
9370
9364
  }
9371
9365
  notify({ presence: true });
@@ -9472,20 +9466,16 @@ function createRoom(options, config) {
9472
9466
  return compact([parseServerMessage(data)]);
9473
9467
  }
9474
9468
  }
9475
- function applyAndSendOps(offlineOps) {
9476
- if (offlineOps.size === 0) {
9469
+ function applyAndSendOfflineOps(unackedOps) {
9470
+ if (unackedOps.size === 0) {
9477
9471
  return;
9478
9472
  }
9479
9473
  const messages = [];
9480
- const inOps = Array.from(offlineOps.values());
9481
- const result = applyOps(
9482
- inOps,
9483
- /* isLocal */
9484
- true
9485
- );
9474
+ const inOps = Array.from(unackedOps.values());
9475
+ const result = applyLocalOps(inOps);
9486
9476
  messages.push({
9487
9477
  type: ClientMsgCode.UPDATE_STORAGE,
9488
- ops: result.ops
9478
+ ops: result.opsToEmit
9489
9479
  });
9490
9480
  notify(result.updates);
9491
9481
  sendMessages(messages);
@@ -9542,18 +9532,12 @@ function createRoom(options, config) {
9542
9532
  updates.others.push(onRoomStateMessage(message));
9543
9533
  break;
9544
9534
  }
9545
- case ServerMsgCode.STORAGE_CHUNK:
9546
- partialNodes.append(compactNodesToNodeStream(message.nodes));
9547
- break;
9548
- case ServerMsgCode.STORAGE_STREAM_END:
9549
- processInitialStorage(partialNodes.clear());
9535
+ case ServerMsgCode.STORAGE_STATE: {
9536
+ processInitialStorage(message);
9550
9537
  break;
9538
+ }
9551
9539
  case ServerMsgCode.UPDATE_STORAGE: {
9552
- const applyResult = applyOps(
9553
- message.ops,
9554
- /* isLocal */
9555
- false
9556
- );
9540
+ const applyResult = applyRemoteOps(message.ops);
9557
9541
  for (const [key, value] of applyResult.updates.storageUpdates) {
9558
9542
  updates.storageUpdates.set(
9559
9543
  key,
@@ -9586,12 +9570,11 @@ function createRoom(options, config) {
9586
9570
  case ServerMsgCode.COMMENT_REACTION_REMOVED:
9587
9571
  case ServerMsgCode.COMMENT_CREATED:
9588
9572
  case ServerMsgCode.COMMENT_EDITED:
9589
- case ServerMsgCode.COMMENT_DELETED: {
9573
+ case ServerMsgCode.COMMENT_DELETED:
9574
+ case ServerMsgCode.COMMENT_METADATA_UPDATED: {
9590
9575
  eventHub.comments.notify(message);
9591
9576
  break;
9592
9577
  }
9593
- case ServerMsgCode.STORAGE_STATE_V7:
9594
- // No longer used in V8
9595
9578
  default:
9596
9579
  break;
9597
9580
  }
@@ -9602,7 +9585,7 @@ function createRoom(options, config) {
9602
9585
  const storageOps = context.buffer.storageOperations;
9603
9586
  if (storageOps.length > 0) {
9604
9587
  for (const op of storageOps) {
9605
- context.unacknowledgedOps.set(nn(op.opId), op);
9588
+ context.unacknowledgedOps.set(op.opId, op);
9606
9589
  }
9607
9590
  notifyStorageStatus();
9608
9591
  }
@@ -9693,18 +9676,18 @@ function createRoom(options, config) {
9693
9676
  }
9694
9677
  let _getStorage$ = null;
9695
9678
  let _resolveStoragePromise = null;
9696
- function processInitialStorage(nodes) {
9679
+ function processInitialStorage(message) {
9697
9680
  const unacknowledgedOps = new Map(context.unacknowledgedOps);
9698
- createOrUpdateRootFromMessage(nodes);
9699
- applyAndSendOps(unacknowledgedOps);
9700
- _optionalChain([_resolveStoragePromise, 'optionalCall', _201 => _201()]);
9681
+ createOrUpdateRootFromMessage(message);
9682
+ applyAndSendOfflineOps(unacknowledgedOps);
9683
+ _optionalChain([_resolveStoragePromise, 'optionalCall', _193 => _193()]);
9701
9684
  notifyStorageStatus();
9702
9685
  eventHub.storageDidLoad.notify();
9703
9686
  }
9704
9687
  async function streamStorage() {
9705
9688
  if (!managedSocket.authValue) return;
9706
- const nodes = new Map(await httpClient.streamStorage({ roomId }));
9707
- processInitialStorage(nodes);
9689
+ const items = await httpClient.streamStorage({ roomId });
9690
+ processInitialStorage({ type: ServerMsgCode.STORAGE_STATE, items });
9708
9691
  }
9709
9692
  function refreshStorage(options2) {
9710
9693
  const messages = context.buffer.messages;
@@ -9712,7 +9695,6 @@ function createRoom(options, config) {
9712
9695
  void streamStorage();
9713
9696
  } else if (!messages.some((msg) => msg.type === ClientMsgCode.FETCH_STORAGE)) {
9714
9697
  messages.push({ type: ClientMsgCode.FETCH_STORAGE });
9715
- partialNodes.clear();
9716
9698
  }
9717
9699
  if (options2.flush) {
9718
9700
  flushNowOrSoon();
@@ -9765,23 +9747,17 @@ function createRoom(options, config) {
9765
9747
  if (context.activeBatch) {
9766
9748
  throw new Error("undo is not allowed during a batch");
9767
9749
  }
9768
- const historyOps = context.undoStack.pop();
9769
- if (historyOps === void 0) {
9750
+ const frames = context.undoStack.pop();
9751
+ if (frames === void 0) {
9770
9752
  return;
9771
9753
  }
9772
9754
  context.pausedHistory = null;
9773
- const result = applyOps(
9774
- historyOps,
9775
- /* isLocal */
9776
- true
9777
- );
9755
+ const result = applyLocalOps(frames);
9778
9756
  notify(result.updates);
9779
9757
  context.redoStack.push(result.reverse);
9780
9758
  onHistoryChange();
9781
- for (const op of result.ops) {
9782
- if (op.type !== "presence") {
9783
- context.buffer.storageOperations.push(op);
9784
- }
9759
+ for (const op of result.opsToEmit) {
9760
+ context.buffer.storageOperations.push(op);
9785
9761
  }
9786
9762
  flushNowOrSoon();
9787
9763
  }
@@ -9789,23 +9765,17 @@ function createRoom(options, config) {
9789
9765
  if (context.activeBatch) {
9790
9766
  throw new Error("redo is not allowed during a batch");
9791
9767
  }
9792
- const historyOps = context.redoStack.pop();
9793
- if (historyOps === void 0) {
9768
+ const frames = context.redoStack.pop();
9769
+ if (frames === void 0) {
9794
9770
  return;
9795
9771
  }
9796
9772
  context.pausedHistory = null;
9797
- const result = applyOps(
9798
- historyOps,
9799
- /* isLocal */
9800
- true
9801
- );
9773
+ const result = applyLocalOps(frames);
9802
9774
  notify(result.updates);
9803
9775
  context.undoStack.push(result.reverse);
9804
9776
  onHistoryChange();
9805
- for (const op of result.ops) {
9806
- if (op.type !== "presence") {
9807
- context.buffer.storageOperations.push(op);
9808
- }
9777
+ for (const op of result.opsToEmit) {
9778
+ context.buffer.storageOperations.push(op);
9809
9779
  }
9810
9780
  flushNowOrSoon();
9811
9781
  }
@@ -9852,10 +9822,10 @@ function createRoom(options, config) {
9852
9822
  }
9853
9823
  }
9854
9824
  function resumeHistory() {
9855
- const historyOps = context.pausedHistory;
9825
+ const frames = context.pausedHistory;
9856
9826
  context.pausedHistory = null;
9857
- if (historyOps !== null && historyOps.length > 0) {
9858
- _addToRealUndoStack(Array.from(historyOps));
9827
+ if (frames !== null && frames.length > 0) {
9828
+ _addToRealUndoStack(Array.from(frames));
9859
9829
  }
9860
9830
  }
9861
9831
  const syncSourceForStorage = config.createSyncSource();
@@ -9927,8 +9897,8 @@ function createRoom(options, config) {
9927
9897
  async function getThreads(options2) {
9928
9898
  return httpClient.getThreads({
9929
9899
  roomId,
9930
- query: _optionalChain([options2, 'optionalAccess', _202 => _202.query]),
9931
- cursor: _optionalChain([options2, 'optionalAccess', _203 => _203.cursor])
9900
+ query: _optionalChain([options2, 'optionalAccess', _194 => _194.query]),
9901
+ cursor: _optionalChain([options2, 'optionalAccess', _195 => _195.cursor])
9932
9902
  });
9933
9903
  }
9934
9904
  async function getThread(threadId) {
@@ -9941,6 +9911,7 @@ function createRoom(options, config) {
9941
9911
  commentId: options2.commentId,
9942
9912
  metadata: options2.metadata,
9943
9913
  body: options2.body,
9914
+ commentMetadata: options2.commentMetadata,
9944
9915
  attachmentIds: options2.attachmentIds
9945
9916
  });
9946
9917
  }
@@ -9953,6 +9924,18 @@ function createRoom(options, config) {
9953
9924
  }) {
9954
9925
  return httpClient.editThreadMetadata({ roomId, threadId, metadata });
9955
9926
  }
9927
+ async function editCommentMetadata({
9928
+ threadId,
9929
+ commentId,
9930
+ metadata
9931
+ }) {
9932
+ return httpClient.editCommentMetadata({
9933
+ roomId,
9934
+ threadId,
9935
+ commentId,
9936
+ metadata
9937
+ });
9938
+ }
9956
9939
  async function markThreadAsResolved(threadId) {
9957
9940
  return httpClient.markThreadAsResolved({ roomId, threadId });
9958
9941
  }
@@ -9974,6 +9957,7 @@ function createRoom(options, config) {
9974
9957
  threadId: options2.threadId,
9975
9958
  commentId: options2.commentId,
9976
9959
  body: options2.body,
9960
+ metadata: options2.metadata,
9977
9961
  attachmentIds: options2.attachmentIds
9978
9962
  });
9979
9963
  }
@@ -9983,6 +9967,7 @@ function createRoom(options, config) {
9983
9967
  threadId: options2.threadId,
9984
9968
  commentId: options2.commentId,
9985
9969
  body: options2.body,
9970
+ metadata: options2.metadata,
9986
9971
  attachmentIds: options2.attachmentIds
9987
9972
  });
9988
9973
  }
@@ -10035,7 +10020,7 @@ function createRoom(options, config) {
10035
10020
  function getSubscriptionSettings(options2) {
10036
10021
  return httpClient.getSubscriptionSettings({
10037
10022
  roomId,
10038
- signal: _optionalChain([options2, 'optionalAccess', _204 => _204.signal])
10023
+ signal: _optionalChain([options2, 'optionalAccess', _196 => _196.signal])
10039
10024
  });
10040
10025
  }
10041
10026
  function updateSubscriptionSettings(settings) {
@@ -10057,7 +10042,7 @@ function createRoom(options, config) {
10057
10042
  {
10058
10043
  [kInternal]: {
10059
10044
  get presenceBuffer() {
10060
- return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _205 => _205.buffer, 'access', _206 => _206.presenceUpdates, 'optionalAccess', _207 => _207.data]), () => ( null)));
10045
+ return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _197 => _197.buffer, 'access', _198 => _198.presenceUpdates, 'optionalAccess', _199 => _199.data]), () => ( null)));
10061
10046
  },
10062
10047
  // prettier-ignore
10063
10048
  get undoStack() {
@@ -10072,9 +10057,9 @@ function createRoom(options, config) {
10072
10057
  return context.yjsProvider;
10073
10058
  },
10074
10059
  setYjsProvider(newProvider) {
10075
- _optionalChain([context, 'access', _208 => _208.yjsProvider, 'optionalAccess', _209 => _209.off, 'call', _210 => _210("status", yjsStatusDidChange)]);
10060
+ _optionalChain([context, 'access', _200 => _200.yjsProvider, 'optionalAccess', _201 => _201.off, 'call', _202 => _202("status", yjsStatusDidChange)]);
10076
10061
  context.yjsProvider = newProvider;
10077
- _optionalChain([newProvider, 'optionalAccess', _211 => _211.on, 'call', _212 => _212("status", yjsStatusDidChange)]);
10062
+ _optionalChain([newProvider, 'optionalAccess', _203 => _203.on, 'call', _204 => _204("status", yjsStatusDidChange)]);
10078
10063
  context.yjsProviderDidChange.notify();
10079
10064
  },
10080
10065
  yjsProviderDidChange: context.yjsProviderDidChange.observable,
@@ -10120,7 +10105,7 @@ function createRoom(options, config) {
10120
10105
  source.dispose();
10121
10106
  }
10122
10107
  eventHub.roomWillDestroy.notify();
10123
- _optionalChain([context, 'access', _213 => _213.yjsProvider, 'optionalAccess', _214 => _214.off, 'call', _215 => _215("status", yjsStatusDidChange)]);
10108
+ _optionalChain([context, 'access', _205 => _205.yjsProvider, 'optionalAccess', _206 => _206.off, 'call', _207 => _207("status", yjsStatusDidChange)]);
10124
10109
  syncSourceForStorage.destroy();
10125
10110
  syncSourceForYjs.destroy();
10126
10111
  uninstallBgTabSpy();
@@ -10170,6 +10155,7 @@ function createRoom(options, config) {
10170
10155
  unsubscribeFromThread,
10171
10156
  createComment,
10172
10157
  editComment,
10158
+ editCommentMetadata,
10173
10159
  deleteComment,
10174
10160
  addReaction,
10175
10161
  removeReaction,
@@ -10270,7 +10256,7 @@ function makeClassicSubscribeFn(roomId, events, errorEvents) {
10270
10256
  }
10271
10257
  if (isLiveNode(first)) {
10272
10258
  const node = first;
10273
- if (_optionalChain([options, 'optionalAccess', _216 => _216.isDeep])) {
10259
+ if (_optionalChain([options, 'optionalAccess', _208 => _208.isDeep])) {
10274
10260
  const storageCallback = second;
10275
10261
  return subscribeToLiveStructureDeeply(node, storageCallback);
10276
10262
  } else {
@@ -10302,7 +10288,7 @@ function makeCreateSocketDelegateForRoom(roomId, baseUrl, WebSocketPolyfill, eng
10302
10288
  }
10303
10289
  const url2 = new URL(baseUrl);
10304
10290
  url2.protocol = url2.protocol === "http:" ? "ws" : "wss";
10305
- url2.pathname = "/v8";
10291
+ url2.pathname = "/v7";
10306
10292
  url2.searchParams.set("roomId", roomId);
10307
10293
  if (authValue.type === "secret") {
10308
10294
  url2.searchParams.set("tok", authValue.token.raw);
@@ -10353,8 +10339,8 @@ function createClient(options) {
10353
10339
  const userId = token.k === "sec-legacy" /* SECRET_LEGACY */ ? token.id : token.uid;
10354
10340
  currentUserId.set(() => userId);
10355
10341
  });
10356
- const fetchPolyfill = _optionalChain([clientOptions, 'access', _217 => _217.polyfills, 'optionalAccess', _218 => _218.fetch]) || /* istanbul ignore next */
10357
- _optionalChain([globalThis, 'access', _219 => _219.fetch, 'optionalAccess', _220 => _220.bind, 'call', _221 => _221(globalThis)]);
10342
+ const fetchPolyfill = _optionalChain([clientOptions, 'access', _209 => _209.polyfills, 'optionalAccess', _210 => _210.fetch]) || /* istanbul ignore next */
10343
+ _optionalChain([globalThis, 'access', _211 => _211.fetch, 'optionalAccess', _212 => _212.bind, 'call', _213 => _213(globalThis)]);
10358
10344
  const httpClient = createApiClient({
10359
10345
  baseUrl,
10360
10346
  fetchPolyfill,
@@ -10372,7 +10358,7 @@ function createClient(options) {
10372
10358
  delegates: {
10373
10359
  createSocket: makeCreateSocketDelegateForAi(
10374
10360
  baseUrl,
10375
- _optionalChain([clientOptions, 'access', _222 => _222.polyfills, 'optionalAccess', _223 => _223.WebSocket])
10361
+ _optionalChain([clientOptions, 'access', _214 => _214.polyfills, 'optionalAccess', _215 => _215.WebSocket])
10376
10362
  ),
10377
10363
  authenticate: async () => {
10378
10364
  const resp = await authManager.getAuthValue({
@@ -10434,7 +10420,7 @@ function createClient(options) {
10434
10420
  createSocket: makeCreateSocketDelegateForRoom(
10435
10421
  roomId,
10436
10422
  baseUrl,
10437
- _optionalChain([clientOptions, 'access', _224 => _224.polyfills, 'optionalAccess', _225 => _225.WebSocket]),
10423
+ _optionalChain([clientOptions, 'access', _216 => _216.polyfills, 'optionalAccess', _217 => _217.WebSocket]),
10438
10424
  options2.engine
10439
10425
  ),
10440
10426
  authenticate: makeAuthDelegateForRoom(roomId, authManager)
@@ -10459,7 +10445,7 @@ function createClient(options) {
10459
10445
  const shouldConnect = _nullishCoalesce(options2.autoConnect, () => ( true));
10460
10446
  if (shouldConnect) {
10461
10447
  if (typeof atob === "undefined") {
10462
- if (_optionalChain([clientOptions, 'access', _226 => _226.polyfills, 'optionalAccess', _227 => _227.atob]) === void 0) {
10448
+ if (_optionalChain([clientOptions, 'access', _218 => _218.polyfills, 'optionalAccess', _219 => _219.atob]) === void 0) {
10463
10449
  throw new Error(
10464
10450
  "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"
10465
10451
  );
@@ -10471,7 +10457,7 @@ function createClient(options) {
10471
10457
  return leaseRoom(newRoomDetails);
10472
10458
  }
10473
10459
  function getRoom(roomId) {
10474
- const room = _optionalChain([roomsById, 'access', _228 => _228.get, 'call', _229 => _229(roomId), 'optionalAccess', _230 => _230.room]);
10460
+ const room = _optionalChain([roomsById, 'access', _220 => _220.get, 'call', _221 => _221(roomId), 'optionalAccess', _222 => _222.room]);
10475
10461
  return room ? room : null;
10476
10462
  }
10477
10463
  function logout() {
@@ -10487,7 +10473,7 @@ function createClient(options) {
10487
10473
  const batchedResolveUsers = new Batch(
10488
10474
  async (batchedUserIds) => {
10489
10475
  const userIds = batchedUserIds.flat();
10490
- const users = await _optionalChain([resolveUsers, 'optionalCall', _231 => _231({ userIds })]);
10476
+ const users = await _optionalChain([resolveUsers, 'optionalCall', _223 => _223({ userIds })]);
10491
10477
  warnOnceIf(
10492
10478
  !resolveUsers,
10493
10479
  "Set the resolveUsers option in createClient to specify user info."
@@ -10504,7 +10490,7 @@ function createClient(options) {
10504
10490
  const batchedResolveRoomsInfo = new Batch(
10505
10491
  async (batchedRoomIds) => {
10506
10492
  const roomIds = batchedRoomIds.flat();
10507
- const roomsInfo = await _optionalChain([resolveRoomsInfo, 'optionalCall', _232 => _232({ roomIds })]);
10493
+ const roomsInfo = await _optionalChain([resolveRoomsInfo, 'optionalCall', _224 => _224({ roomIds })]);
10508
10494
  warnOnceIf(
10509
10495
  !resolveRoomsInfo,
10510
10496
  "Set the resolveRoomsInfo option in createClient to specify room info."
@@ -10521,7 +10507,7 @@ function createClient(options) {
10521
10507
  const batchedResolveGroupsInfo = new Batch(
10522
10508
  async (batchedGroupIds) => {
10523
10509
  const groupIds = batchedGroupIds.flat();
10524
- const groupsInfo = await _optionalChain([resolveGroupsInfo, 'optionalCall', _233 => _233({ groupIds })]);
10510
+ const groupsInfo = await _optionalChain([resolveGroupsInfo, 'optionalCall', _225 => _225({ groupIds })]);
10525
10511
  warnOnceIf(
10526
10512
  !resolveGroupsInfo,
10527
10513
  "Set the resolveGroupsInfo option in createClient to specify group info."
@@ -10577,7 +10563,7 @@ function createClient(options) {
10577
10563
  }
10578
10564
  };
10579
10565
  const win = typeof window !== "undefined" ? window : void 0;
10580
- _optionalChain([win, 'optionalAccess', _234 => _234.addEventListener, 'call', _235 => _235("beforeunload", maybePreventClose)]);
10566
+ _optionalChain([win, 'optionalAccess', _226 => _226.addEventListener, 'call', _227 => _227("beforeunload", maybePreventClose)]);
10581
10567
  }
10582
10568
  async function getNotificationSettings(options2) {
10583
10569
  const plainSettings = await httpClient.getNotificationSettings(options2);
@@ -10704,7 +10690,7 @@ var commentBodyElementsTypes = {
10704
10690
  mention: "inline"
10705
10691
  };
10706
10692
  function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
10707
- if (!body || !_optionalChain([body, 'optionalAccess', _236 => _236.content])) {
10693
+ if (!body || !_optionalChain([body, 'optionalAccess', _228 => _228.content])) {
10708
10694
  return;
10709
10695
  }
10710
10696
  const element = typeof elementOrVisitor === "string" ? elementOrVisitor : void 0;
@@ -10714,13 +10700,13 @@ function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
10714
10700
  for (const block of body.content) {
10715
10701
  if (type === "all" || type === "block") {
10716
10702
  if (guard(block)) {
10717
- _optionalChain([visitor, 'optionalCall', _237 => _237(block)]);
10703
+ _optionalChain([visitor, 'optionalCall', _229 => _229(block)]);
10718
10704
  }
10719
10705
  }
10720
10706
  if (type === "all" || type === "inline") {
10721
10707
  for (const inline of block.children) {
10722
10708
  if (guard(inline)) {
10723
- _optionalChain([visitor, 'optionalCall', _238 => _238(inline)]);
10709
+ _optionalChain([visitor, 'optionalCall', _230 => _230(inline)]);
10724
10710
  }
10725
10711
  }
10726
10712
  }
@@ -10890,7 +10876,7 @@ var stringifyCommentBodyPlainElements = {
10890
10876
  text: ({ element }) => element.text,
10891
10877
  link: ({ element }) => _nullishCoalesce(element.text, () => ( element.url)),
10892
10878
  mention: ({ element, user, group }) => {
10893
- return `@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _239 => _239.name]), () => ( _optionalChain([group, 'optionalAccess', _240 => _240.name]))), () => ( element.id))}`;
10879
+ return `@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _231 => _231.name]), () => ( _optionalChain([group, 'optionalAccess', _232 => _232.name]))), () => ( element.id))}`;
10894
10880
  }
10895
10881
  };
10896
10882
  var stringifyCommentBodyHtmlElements = {
@@ -10920,7 +10906,7 @@ var stringifyCommentBodyHtmlElements = {
10920
10906
  return html`<a href="${href}" target="_blank" rel="noopener noreferrer">${element.text ? html`${element.text}` : element.url}</a>`;
10921
10907
  },
10922
10908
  mention: ({ element, user, group }) => {
10923
- return html`<span data-mention>@${_optionalChain([user, 'optionalAccess', _241 => _241.name]) ? html`${_optionalChain([user, 'optionalAccess', _242 => _242.name])}` : _optionalChain([group, 'optionalAccess', _243 => _243.name]) ? html`${_optionalChain([group, 'optionalAccess', _244 => _244.name])}` : element.id}</span>`;
10909
+ return html`<span data-mention>@${_optionalChain([user, 'optionalAccess', _233 => _233.name]) ? html`${_optionalChain([user, 'optionalAccess', _234 => _234.name])}` : _optionalChain([group, 'optionalAccess', _235 => _235.name]) ? html`${_optionalChain([group, 'optionalAccess', _236 => _236.name])}` : element.id}</span>`;
10924
10910
  }
10925
10911
  };
10926
10912
  var stringifyCommentBodyMarkdownElements = {
@@ -10950,20 +10936,20 @@ var stringifyCommentBodyMarkdownElements = {
10950
10936
  return markdown`[${_nullishCoalesce(element.text, () => ( element.url))}](${href})`;
10951
10937
  },
10952
10938
  mention: ({ element, user, group }) => {
10953
- return markdown`@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _245 => _245.name]), () => ( _optionalChain([group, 'optionalAccess', _246 => _246.name]))), () => ( element.id))}`;
10939
+ return markdown`@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _237 => _237.name]), () => ( _optionalChain([group, 'optionalAccess', _238 => _238.name]))), () => ( element.id))}`;
10954
10940
  }
10955
10941
  };
10956
10942
  async function stringifyCommentBody(body, options) {
10957
- const format = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _247 => _247.format]), () => ( "plain"));
10958
- const separator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _248 => _248.separator]), () => ( (format === "markdown" ? "\n\n" : "\n")));
10943
+ const format = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _239 => _239.format]), () => ( "plain"));
10944
+ const separator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _240 => _240.separator]), () => ( (format === "markdown" ? "\n\n" : "\n")));
10959
10945
  const elements = {
10960
10946
  ...format === "html" ? stringifyCommentBodyHtmlElements : format === "markdown" ? stringifyCommentBodyMarkdownElements : stringifyCommentBodyPlainElements,
10961
- ..._optionalChain([options, 'optionalAccess', _249 => _249.elements])
10947
+ ..._optionalChain([options, 'optionalAccess', _241 => _241.elements])
10962
10948
  };
10963
10949
  const { users: resolvedUsers, groups: resolvedGroupsInfo } = await resolveMentionsInCommentBody(
10964
10950
  body,
10965
- _optionalChain([options, 'optionalAccess', _250 => _250.resolveUsers]),
10966
- _optionalChain([options, 'optionalAccess', _251 => _251.resolveGroupsInfo])
10951
+ _optionalChain([options, 'optionalAccess', _242 => _242.resolveUsers]),
10952
+ _optionalChain([options, 'optionalAccess', _243 => _243.resolveGroupsInfo])
10967
10953
  );
10968
10954
  const blocks = body.content.flatMap((block, blockIndex) => {
10969
10955
  switch (block.type) {
@@ -11250,12 +11236,12 @@ function legacy_patchImmutableNode(state, path, update) {
11250
11236
  }
11251
11237
  const newState = Object.assign({}, state);
11252
11238
  for (const key in update.updates) {
11253
- if (_optionalChain([update, 'access', _252 => _252.updates, 'access', _253 => _253[key], 'optionalAccess', _254 => _254.type]) === "update") {
11239
+ if (_optionalChain([update, 'access', _244 => _244.updates, 'access', _245 => _245[key], 'optionalAccess', _246 => _246.type]) === "update") {
11254
11240
  const val = update.node.get(key);
11255
11241
  if (val !== void 0) {
11256
11242
  newState[key] = lsonToJson(val);
11257
11243
  }
11258
- } else if (_optionalChain([update, 'access', _255 => _255.updates, 'access', _256 => _256[key], 'optionalAccess', _257 => _257.type]) === "delete") {
11244
+ } else if (_optionalChain([update, 'access', _247 => _247.updates, 'access', _248 => _248[key], 'optionalAccess', _249 => _249.type]) === "delete") {
11259
11245
  delete newState[key];
11260
11246
  }
11261
11247
  }
@@ -11316,12 +11302,12 @@ function legacy_patchImmutableNode(state, path, update) {
11316
11302
  }
11317
11303
  const newState = Object.assign({}, state);
11318
11304
  for (const key in update.updates) {
11319
- if (_optionalChain([update, 'access', _258 => _258.updates, 'access', _259 => _259[key], 'optionalAccess', _260 => _260.type]) === "update") {
11305
+ if (_optionalChain([update, 'access', _250 => _250.updates, 'access', _251 => _251[key], 'optionalAccess', _252 => _252.type]) === "update") {
11320
11306
  const value = update.node.get(key);
11321
11307
  if (value !== void 0) {
11322
11308
  newState[key] = lsonToJson(value);
11323
11309
  }
11324
- } else if (_optionalChain([update, 'access', _261 => _261.updates, 'access', _262 => _262[key], 'optionalAccess', _263 => _263.type]) === "delete") {
11310
+ } else if (_optionalChain([update, 'access', _253 => _253.updates, 'access', _254 => _254[key], 'optionalAccess', _255 => _255.type]) === "delete") {
11325
11311
  delete newState[key];
11326
11312
  }
11327
11313
  }
@@ -11401,9 +11387,9 @@ function makePoller(callback, intervalMs, options) {
11401
11387
  const startTime = performance.now();
11402
11388
  const doc = typeof document !== "undefined" ? document : void 0;
11403
11389
  const win = typeof window !== "undefined" ? window : void 0;
11404
- const maxStaleTimeMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _264 => _264.maxStaleTimeMs]), () => ( Number.POSITIVE_INFINITY));
11390
+ const maxStaleTimeMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _256 => _256.maxStaleTimeMs]), () => ( Number.POSITIVE_INFINITY));
11405
11391
  const context = {
11406
- inForeground: _optionalChain([doc, 'optionalAccess', _265 => _265.visibilityState]) !== "hidden",
11392
+ inForeground: _optionalChain([doc, 'optionalAccess', _257 => _257.visibilityState]) !== "hidden",
11407
11393
  lastSuccessfulPollAt: startTime,
11408
11394
  count: 0,
11409
11395
  backoff: 0
@@ -11484,11 +11470,11 @@ function makePoller(callback, intervalMs, options) {
11484
11470
  pollNowIfStale();
11485
11471
  }
11486
11472
  function onVisibilityChange() {
11487
- setInForeground(_optionalChain([doc, 'optionalAccess', _266 => _266.visibilityState]) !== "hidden");
11473
+ setInForeground(_optionalChain([doc, 'optionalAccess', _258 => _258.visibilityState]) !== "hidden");
11488
11474
  }
11489
- _optionalChain([doc, 'optionalAccess', _267 => _267.addEventListener, 'call', _268 => _268("visibilitychange", onVisibilityChange)]);
11490
- _optionalChain([win, 'optionalAccess', _269 => _269.addEventListener, 'call', _270 => _270("online", onVisibilityChange)]);
11491
- _optionalChain([win, 'optionalAccess', _271 => _271.addEventListener, 'call', _272 => _272("focus", pollNowIfStale)]);
11475
+ _optionalChain([doc, 'optionalAccess', _259 => _259.addEventListener, 'call', _260 => _260("visibilitychange", onVisibilityChange)]);
11476
+ _optionalChain([win, 'optionalAccess', _261 => _261.addEventListener, 'call', _262 => _262("online", onVisibilityChange)]);
11477
+ _optionalChain([win, 'optionalAccess', _263 => _263.addEventListener, 'call', _264 => _264("focus", pollNowIfStale)]);
11492
11478
  fsm.start();
11493
11479
  return {
11494
11480
  inc,
@@ -11620,6 +11606,5 @@ detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
11620
11606
 
11621
11607
 
11622
11608
 
11623
-
11624
- exports.ClientMsgCode = ClientMsgCode; exports.CrdtType = CrdtType; exports.DefaultMap = DefaultMap; exports.Deque = Deque; exports.DerivedSignal = DerivedSignal; exports.HttpError = HttpError; exports.LiveList = LiveList; exports.LiveMap = LiveMap; exports.LiveObject = LiveObject; exports.LiveblocksError = LiveblocksError; exports.MENTION_CHARACTER = MENTION_CHARACTER; exports.MutableSignal = MutableSignal; exports.OpCode = OpCode; exports.Permission = Permission; exports.Promise_withResolvers = Promise_withResolvers; exports.ServerMsgCode = ServerMsgCode; exports.Signal = Signal; exports.SortedList = SortedList; exports.TextEditorType = TextEditorType; exports.WebsocketCloseCodes = WebsocketCloseCodes; exports.asPos = asPos; exports.assert = assert; exports.assertNever = assertNever; exports.autoRetry = autoRetry; exports.b64decode = b64decode; exports.batch = batch; exports.checkBounds = checkBounds; exports.chunk = chunk; exports.cloneLson = cloneLson; exports.compactObject = compactObject; exports.console = fancy_console_exports; exports.convertToCommentData = convertToCommentData; exports.convertToCommentUserReaction = convertToCommentUserReaction; exports.convertToGroupData = convertToGroupData; exports.convertToInboxNotificationData = convertToInboxNotificationData; exports.convertToSubscriptionData = convertToSubscriptionData; exports.convertToThreadData = convertToThreadData; exports.convertToUserSubscriptionData = convertToUserSubscriptionData; exports.createClient = createClient; exports.createCommentAttachmentId = createCommentAttachmentId; exports.createCommentId = createCommentId; exports.createInboxNotificationId = createInboxNotificationId; exports.createManagedPool = createManagedPool; exports.createNotificationSettings = createNotificationSettings; exports.createThreadId = createThreadId; exports.defineAiTool = defineAiTool; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.detectDupes = detectDupes; exports.entries = entries; exports.errorIf = errorIf; exports.findLastIndex = findLastIndex; exports.freeze = freeze; exports.generateUrl = generateUrl; exports.getMentionsFromCommentBody = getMentionsFromCommentBody; exports.getSubscriptionKey = getSubscriptionKey; exports.html = html; exports.htmlSafe = htmlSafe; exports.isCommentBodyLink = isCommentBodyLink; exports.isCommentBodyMention = isCommentBodyMention; exports.isCommentBodyText = isCommentBodyText; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isLiveNode = isLiveNode; exports.isNotificationChannelEnabled = isNotificationChannelEnabled; exports.isNumberOperator = isNumberOperator; exports.isPlainObject = isPlainObject; exports.isStartsWithOperator = isStartsWithOperator; exports.isUrl = isUrl; exports.kInternal = kInternal; exports.keys = keys; exports.legacy_patchImmutableObject = legacy_patchImmutableObject; exports.lsonToJson = lsonToJson; exports.makeAbortController = makeAbortController; exports.makeEventSource = makeEventSource; exports.makePoller = makePoller; exports.makePosition = makePosition; exports.mapValues = mapValues; exports.memoizeOnSuccess = memoizeOnSuccess; exports.nanoid = nanoid; exports.nn = nn; exports.nodeStreamToCompactNodes = nodeStreamToCompactNodes; exports.objectToQuery = objectToQuery; exports.patchLiveObjectKey = patchLiveObjectKey; exports.patchNotificationSettings = patchNotificationSettings; exports.raise = raise; exports.resolveMentionsInCommentBody = resolveMentionsInCommentBody; exports.sanitizeUrl = sanitizeUrl; exports.shallow = shallow; exports.shallow2 = shallow2; exports.stableStringify = stableStringify; exports.stringifyCommentBody = stringifyCommentBody; exports.throwUsageError = throwUsageError; exports.toPlainLson = toPlainLson; exports.tryParseJson = tryParseJson; exports.url = url; exports.urljoin = urljoin; exports.wait = wait; exports.warnOnce = warnOnce; exports.warnOnceIf = warnOnceIf; exports.withTimeout = withTimeout;
11609
+ exports.ClientMsgCode = ClientMsgCode; exports.CrdtType = CrdtType; exports.DefaultMap = DefaultMap; exports.Deque = Deque; exports.DerivedSignal = DerivedSignal; exports.HttpError = HttpError; exports.LiveList = LiveList; exports.LiveMap = LiveMap; exports.LiveObject = LiveObject; exports.LiveblocksError = LiveblocksError; exports.MENTION_CHARACTER = MENTION_CHARACTER; exports.MutableSignal = MutableSignal; exports.OpCode = OpCode; exports.Permission = Permission; exports.Promise_withResolvers = Promise_withResolvers; exports.ServerMsgCode = ServerMsgCode; exports.Signal = Signal; exports.SortedList = SortedList; exports.TextEditorType = TextEditorType; exports.WebsocketCloseCodes = WebsocketCloseCodes; exports.asPos = asPos; exports.assert = assert; exports.assertNever = assertNever; exports.autoRetry = autoRetry; exports.b64decode = b64decode; exports.batch = batch; exports.checkBounds = checkBounds; exports.chunk = chunk; exports.cloneLson = cloneLson; exports.compactObject = compactObject; exports.console = fancy_console_exports; exports.convertToCommentData = convertToCommentData; exports.convertToCommentUserReaction = convertToCommentUserReaction; exports.convertToGroupData = convertToGroupData; exports.convertToInboxNotificationData = convertToInboxNotificationData; exports.convertToSubscriptionData = convertToSubscriptionData; exports.convertToThreadData = convertToThreadData; exports.convertToUserSubscriptionData = convertToUserSubscriptionData; exports.createClient = createClient; exports.createCommentAttachmentId = createCommentAttachmentId; exports.createCommentId = createCommentId; exports.createInboxNotificationId = createInboxNotificationId; exports.createManagedPool = createManagedPool; exports.createNotificationSettings = createNotificationSettings; exports.createThreadId = createThreadId; exports.defineAiTool = defineAiTool; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.detectDupes = detectDupes; exports.entries = entries; exports.errorIf = errorIf; exports.findLastIndex = findLastIndex; exports.freeze = freeze; exports.generateUrl = generateUrl; exports.getMentionsFromCommentBody = getMentionsFromCommentBody; exports.getSubscriptionKey = getSubscriptionKey; exports.html = html; exports.htmlSafe = htmlSafe; exports.isCommentBodyLink = isCommentBodyLink; exports.isCommentBodyMention = isCommentBodyMention; exports.isCommentBodyText = isCommentBodyText; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isLiveNode = isLiveNode; exports.isNotificationChannelEnabled = isNotificationChannelEnabled; exports.isNumberOperator = isNumberOperator; exports.isPlainObject = isPlainObject; exports.isStartsWithOperator = isStartsWithOperator; exports.isUrl = isUrl; exports.kInternal = kInternal; exports.keys = keys; exports.legacy_patchImmutableObject = legacy_patchImmutableObject; exports.lsonToJson = lsonToJson; exports.makeAbortController = makeAbortController; exports.makeEventSource = makeEventSource; exports.makePoller = makePoller; exports.makePosition = makePosition; exports.mapValues = mapValues; exports.memoizeOnSuccess = memoizeOnSuccess; exports.nanoid = nanoid; exports.nn = nn; exports.objectToQuery = objectToQuery; exports.patchLiveObjectKey = patchLiveObjectKey; exports.patchNotificationSettings = patchNotificationSettings; exports.raise = raise; exports.resolveMentionsInCommentBody = resolveMentionsInCommentBody; exports.sanitizeUrl = sanitizeUrl; exports.shallow = shallow; exports.shallow2 = shallow2; exports.stableStringify = stableStringify; exports.stringifyCommentBody = stringifyCommentBody; exports.throwUsageError = throwUsageError; exports.toPlainLson = toPlainLson; exports.tryParseJson = tryParseJson; exports.url = url; exports.urljoin = urljoin; exports.wait = wait; exports.warnOnce = warnOnce; exports.warnOnceIf = warnOnceIf; exports.withTimeout = withTimeout;
11625
11610
  //# sourceMappingURL=index.cjs.map