@liveblocks/core 3.13.0-rc1 → 3.13.0-rc3

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-rc1";
9
+ var PKG_VERSION = "3.13.0-rc3";
10
10
  var PKG_FORMAT = "cjs";
11
11
 
12
12
  // src/dupe-detection.ts
@@ -1606,6 +1606,7 @@ function createApiClient({
1606
1606
  comment: {
1607
1607
  id: commentId,
1608
1608
  body: options.body,
1609
+ metadata: options.commentMetadata,
1609
1610
  attachmentIds: options.attachmentIds
1610
1611
  },
1611
1612
  metadata: options.metadata
@@ -1659,6 +1660,16 @@ function createApiClient({
1659
1660
  options.metadata
1660
1661
  );
1661
1662
  }
1663
+ async function editCommentMetadata(options) {
1664
+ return await httpClient.post(
1665
+ url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}/metadata`,
1666
+ await authManager.getAuthValue({
1667
+ requestedScope: "comments:read",
1668
+ roomId: options.roomId
1669
+ }),
1670
+ options.metadata
1671
+ );
1672
+ }
1662
1673
  async function createComment(options) {
1663
1674
  const commentId = _nullishCoalesce(options.commentId, () => ( createCommentId()));
1664
1675
  const comment = await httpClient.post(
@@ -1670,6 +1681,7 @@ function createApiClient({
1670
1681
  {
1671
1682
  id: commentId,
1672
1683
  body: options.body,
1684
+ metadata: options.metadata,
1673
1685
  attachmentIds: options.attachmentIds
1674
1686
  }
1675
1687
  );
@@ -1684,7 +1696,8 @@ function createApiClient({
1684
1696
  }),
1685
1697
  {
1686
1698
  body: options.body,
1687
- attachmentIds: options.attachmentIds
1699
+ attachmentIds: options.attachmentIds,
1700
+ metadata: options.metadata
1688
1701
  }
1689
1702
  );
1690
1703
  return convertToCommentData(comment);
@@ -2426,6 +2439,7 @@ function createApiClient({
2426
2439
  editThreadMetadata,
2427
2440
  createComment,
2428
2441
  editComment,
2442
+ editCommentMetadata,
2429
2443
  deleteComment,
2430
2444
  addReaction,
2431
2445
  removeReaction,
@@ -3090,7 +3104,7 @@ var ServerMsgCode = Object.freeze({
3090
3104
  BROADCASTED_EVENT: 103,
3091
3105
  ROOM_STATE: 104,
3092
3106
  // For Storage
3093
- INITIAL_STORAGE_STATE: 200,
3107
+ STORAGE_STATE: 200,
3094
3108
  UPDATE_STORAGE: 201,
3095
3109
  // For Yjs Docs
3096
3110
  UPDATE_YDOC: 300,
@@ -3104,6 +3118,7 @@ var ServerMsgCode = Object.freeze({
3104
3118
  COMMENT_DELETED: 404,
3105
3119
  COMMENT_REACTION_ADDED: 405,
3106
3120
  COMMENT_REACTION_REMOVED: 406,
3121
+ COMMENT_METADATA_UPDATED: 409,
3107
3122
  // Error codes
3108
3123
  REJECT_STORAGE_OP: 299
3109
3124
  // Sent if a mutation was not allowed on the server (i.e. due to permissions, limit exceeded, etc)
@@ -5922,9 +5937,7 @@ var OpCode = Object.freeze({
5922
5937
  DELETE_CRDT: 5,
5923
5938
  DELETE_OBJECT_KEY: 6,
5924
5939
  CREATE_MAP: 7,
5925
- CREATE_REGISTER: 8,
5926
- ACK: 9
5927
- // Will only appear in v8+
5940
+ CREATE_REGISTER: 8
5928
5941
  });
5929
5942
  function isAckOp(op) {
5930
5943
  return op.type === OpCode.DELETE_CRDT && op.id === "ACK";
@@ -7581,7 +7594,20 @@ function isRootCrdt(id, _) {
7581
7594
  }
7582
7595
  var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7583
7596
  #map;
7584
- #propToLastUpdate;
7597
+ /**
7598
+ * Tracks unacknowledged local changes per property to preserve optimistic
7599
+ * updates. Maps property keys to their pending operation IDs.
7600
+ *
7601
+ * INVARIANT: Only locally-generated opIds are ever stored here. Remote opIds
7602
+ * are only compared against (to detect ACKs), never stored.
7603
+ *
7604
+ * When a local change is made, the opId is stored here. When a remote op
7605
+ * arrives for the same key:
7606
+ * - If no entry exists → apply remote op
7607
+ * - If opId matches → it's an ACK, clear the entry
7608
+ * - If opId differs → ignore remote op to preserve optimistic update
7609
+ */
7610
+ #unackedOpsByKey;
7585
7611
  /**
7586
7612
  * Enable or disable detection of too large LiveObjects.
7587
7613
  * When enabled, throws an error if LiveObject static data exceeds 128KB, which
@@ -7624,7 +7650,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7624
7650
  }
7625
7651
  constructor(obj = {}) {
7626
7652
  super();
7627
- this.#propToLastUpdate = /* @__PURE__ */ new Map();
7653
+ this.#unackedOpsByKey = /* @__PURE__ */ new Map();
7628
7654
  const o = compactObject(obj);
7629
7655
  for (const key of Object.keys(o)) {
7630
7656
  const value = o[key];
@@ -7698,16 +7724,16 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7698
7724
  const { id, opId, parentKey: key } = op;
7699
7725
  const child = creationOpToLson(op);
7700
7726
  if (this._pool.getNode(id) !== void 0) {
7701
- if (this.#propToLastUpdate.get(key) === opId) {
7702
- this.#propToLastUpdate.delete(key);
7727
+ if (this.#unackedOpsByKey.get(key) === opId) {
7728
+ this.#unackedOpsByKey.delete(key);
7703
7729
  }
7704
7730
  return { modified: false };
7705
7731
  }
7706
7732
  if (source === 0 /* LOCAL */) {
7707
- this.#propToLastUpdate.set(key, nn(opId));
7708
- } else if (this.#propToLastUpdate.get(key) === void 0) {
7709
- } else if (this.#propToLastUpdate.get(key) === opId) {
7710
- this.#propToLastUpdate.delete(key);
7733
+ this.#unackedOpsByKey.set(key, nn(opId));
7734
+ } else if (this.#unackedOpsByKey.get(key) === void 0) {
7735
+ } else if (this.#unackedOpsByKey.get(key) === opId) {
7736
+ this.#unackedOpsByKey.delete(key);
7711
7737
  return { modified: false };
7712
7738
  } else {
7713
7739
  return { modified: false };
@@ -7835,11 +7861,11 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7835
7861
  continue;
7836
7862
  }
7837
7863
  if (isLocal) {
7838
- this.#propToLastUpdate.set(key, nn(op.opId));
7839
- } else if (this.#propToLastUpdate.get(key) === void 0) {
7864
+ this.#unackedOpsByKey.set(key, nn(op.opId));
7865
+ } else if (this.#unackedOpsByKey.get(key) === void 0) {
7840
7866
  isModified = true;
7841
- } else if (this.#propToLastUpdate.get(key) === op.opId) {
7842
- this.#propToLastUpdate.delete(key);
7867
+ } else if (this.#unackedOpsByKey.get(key) === op.opId) {
7868
+ this.#unackedOpsByKey.delete(key);
7843
7869
  continue;
7844
7870
  } else {
7845
7871
  continue;
@@ -7871,7 +7897,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7871
7897
  if (oldValue === void 0) {
7872
7898
  return { modified: false };
7873
7899
  }
7874
- if (!isLocal && this.#propToLastUpdate.get(key) !== void 0) {
7900
+ if (!isLocal && this.#unackedOpsByKey.get(key) !== void 0) {
7875
7901
  return { modified: false };
7876
7902
  }
7877
7903
  const id = nn(this._id);
@@ -8059,12 +8085,12 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8059
8085
  (op) => op.parentId === this._id
8060
8086
  );
8061
8087
  if (createCrdtOp) {
8062
- this.#propToLastUpdate.set(key, nn(createCrdtOp.opId));
8088
+ this.#unackedOpsByKey.set(key, nn(createCrdtOp.opId));
8063
8089
  }
8064
8090
  ops.push(...newAttachChildOps);
8065
8091
  } else {
8066
8092
  updatedProps[key] = newValue;
8067
- this.#propToLastUpdate.set(key, opId);
8093
+ this.#unackedOpsByKey.set(key, opId);
8068
8094
  }
8069
8095
  this.#map.set(key, newValue);
8070
8096
  this.invalidate();
@@ -8662,6 +8688,8 @@ function defaultMessageFromContext(context) {
8662
8688
  return "Could not delete thread";
8663
8689
  case "EDIT_THREAD_METADATA_ERROR":
8664
8690
  return "Could not edit thread metadata";
8691
+ case "EDIT_COMMENT_METADATA_ERROR":
8692
+ return "Could not edit comment metadata";
8665
8693
  case "MARK_THREAD_AS_RESOLVED_ERROR":
8666
8694
  return "Could not mark thread as resolved";
8667
8695
  case "MARK_THREAD_AS_UNRESOLVED_ERROR":
@@ -9165,13 +9193,13 @@ function createRoom(options, config) {
9165
9193
  presence: false
9166
9194
  };
9167
9195
  const createdNodeIds = /* @__PURE__ */ new Set();
9168
- const ops = rawOps.map((op) => {
9196
+ const ops = isLocal ? rawOps.map((op) => {
9169
9197
  if (op.type !== "presence" && !op.opId) {
9170
9198
  return { ...op, opId: context.pool.generateOpId() };
9171
9199
  } else {
9172
9200
  return op;
9173
9201
  }
9174
- });
9202
+ }) : Array.from(rawOps);
9175
9203
  for (const op of ops) {
9176
9204
  if (op.type === "presence") {
9177
9205
  const reverse = {
@@ -9195,10 +9223,11 @@ function createRoom(options, config) {
9195
9223
  let source;
9196
9224
  if (isLocal) {
9197
9225
  source = 0 /* LOCAL */;
9226
+ } else if (op.opId !== void 0) {
9227
+ context.unacknowledgedOps.delete(op.opId);
9228
+ source = 2 /* OURS */;
9198
9229
  } else {
9199
- const opId = nn(op.opId);
9200
- const deleted = context.unacknowledgedOps.delete(opId);
9201
- source = deleted ? 2 /* OURS */ : 1 /* THEIRS */;
9230
+ source = 1 /* THEIRS */;
9202
9231
  }
9203
9232
  const applyOpResult = applyOp(op, source);
9204
9233
  if (applyOpResult.modified) {
@@ -9475,7 +9504,7 @@ function createRoom(options, config) {
9475
9504
  updates.others.push(onRoomStateMessage(message));
9476
9505
  break;
9477
9506
  }
9478
- case ServerMsgCode.INITIAL_STORAGE_STATE: {
9507
+ case ServerMsgCode.STORAGE_STATE: {
9479
9508
  processInitialStorage(message);
9480
9509
  break;
9481
9510
  }
@@ -9517,7 +9546,8 @@ function createRoom(options, config) {
9517
9546
  case ServerMsgCode.COMMENT_REACTION_REMOVED:
9518
9547
  case ServerMsgCode.COMMENT_CREATED:
9519
9548
  case ServerMsgCode.COMMENT_EDITED:
9520
- case ServerMsgCode.COMMENT_DELETED: {
9549
+ case ServerMsgCode.COMMENT_DELETED:
9550
+ case ServerMsgCode.COMMENT_METADATA_UPDATED: {
9521
9551
  eventHub.comments.notify(message);
9522
9552
  break;
9523
9553
  }
@@ -9633,7 +9663,7 @@ function createRoom(options, config) {
9633
9663
  async function streamStorage() {
9634
9664
  if (!managedSocket.authValue) return;
9635
9665
  const items = await httpClient.streamStorage({ roomId });
9636
- processInitialStorage({ type: ServerMsgCode.INITIAL_STORAGE_STATE, items });
9666
+ processInitialStorage({ type: ServerMsgCode.STORAGE_STATE, items });
9637
9667
  }
9638
9668
  function refreshStorage(options2) {
9639
9669
  const messages = context.buffer.messages;
@@ -9869,6 +9899,7 @@ function createRoom(options, config) {
9869
9899
  commentId: options2.commentId,
9870
9900
  metadata: options2.metadata,
9871
9901
  body: options2.body,
9902
+ commentMetadata: options2.commentMetadata,
9872
9903
  attachmentIds: options2.attachmentIds
9873
9904
  });
9874
9905
  }
@@ -9881,6 +9912,18 @@ function createRoom(options, config) {
9881
9912
  }) {
9882
9913
  return httpClient.editThreadMetadata({ roomId, threadId, metadata });
9883
9914
  }
9915
+ async function editCommentMetadata({
9916
+ threadId,
9917
+ commentId,
9918
+ metadata
9919
+ }) {
9920
+ return httpClient.editCommentMetadata({
9921
+ roomId,
9922
+ threadId,
9923
+ commentId,
9924
+ metadata
9925
+ });
9926
+ }
9884
9927
  async function markThreadAsResolved(threadId) {
9885
9928
  return httpClient.markThreadAsResolved({ roomId, threadId });
9886
9929
  }
@@ -9902,6 +9945,7 @@ function createRoom(options, config) {
9902
9945
  threadId: options2.threadId,
9903
9946
  commentId: options2.commentId,
9904
9947
  body: options2.body,
9948
+ metadata: options2.metadata,
9905
9949
  attachmentIds: options2.attachmentIds
9906
9950
  });
9907
9951
  }
@@ -9911,6 +9955,7 @@ function createRoom(options, config) {
9911
9955
  threadId: options2.threadId,
9912
9956
  commentId: options2.commentId,
9913
9957
  body: options2.body,
9958
+ metadata: options2.metadata,
9914
9959
  attachmentIds: options2.attachmentIds
9915
9960
  });
9916
9961
  }
@@ -10098,6 +10143,7 @@ function createRoom(options, config) {
10098
10143
  unsubscribeFromThread,
10099
10144
  createComment,
10100
10145
  editComment,
10146
+ editCommentMetadata,
10101
10147
  deleteComment,
10102
10148
  addReaction,
10103
10149
  removeReaction,