@yorkie-js/react 0.6.34 → 0.6.35

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.
@@ -7844,6 +7844,95 @@ __publicField(_PushPullChangesResponse, "fields", proto3.util.newFieldList(() =>
7844
7844
  { no: 1, name: "change_pack", kind: "message", T: ChangePack$1 }
7845
7845
  ]));
7846
7846
  let PushPullChangesResponse = _PushPullChangesResponse;
7847
+ const _BroadcastRequest = class _BroadcastRequest extends Message {
7848
+ constructor(data) {
7849
+ super();
7850
+ /**
7851
+ * @generated from field: string client_id = 1;
7852
+ */
7853
+ __publicField(this, "clientId", "");
7854
+ /**
7855
+ * @generated from field: string document_id = 2;
7856
+ */
7857
+ __publicField(this, "documentId", "");
7858
+ /**
7859
+ * @generated from field: string topic = 3;
7860
+ */
7861
+ __publicField(this, "topic", "");
7862
+ /**
7863
+ * @generated from field: bytes payload = 4;
7864
+ */
7865
+ __publicField(this, "payload", new Uint8Array(0));
7866
+ proto3.util.initPartial(data, this);
7867
+ }
7868
+ static fromBinary(bytes, options) {
7869
+ return new _BroadcastRequest().fromBinary(bytes, options);
7870
+ }
7871
+ static fromJson(jsonValue, options) {
7872
+ return new _BroadcastRequest().fromJson(jsonValue, options);
7873
+ }
7874
+ static fromJsonString(jsonString, options) {
7875
+ return new _BroadcastRequest().fromJsonString(jsonString, options);
7876
+ }
7877
+ static equals(a, b) {
7878
+ return proto3.util.equals(_BroadcastRequest, a, b);
7879
+ }
7880
+ };
7881
+ __publicField(_BroadcastRequest, "runtime", proto3);
7882
+ __publicField(_BroadcastRequest, "typeName", "yorkie.v1.BroadcastRequest");
7883
+ __publicField(_BroadcastRequest, "fields", proto3.util.newFieldList(() => [
7884
+ {
7885
+ no: 1,
7886
+ name: "client_id",
7887
+ kind: "scalar",
7888
+ T: 9
7889
+ /* ScalarType.STRING */
7890
+ },
7891
+ {
7892
+ no: 2,
7893
+ name: "document_id",
7894
+ kind: "scalar",
7895
+ T: 9
7896
+ /* ScalarType.STRING */
7897
+ },
7898
+ {
7899
+ no: 3,
7900
+ name: "topic",
7901
+ kind: "scalar",
7902
+ T: 9
7903
+ /* ScalarType.STRING */
7904
+ },
7905
+ {
7906
+ no: 4,
7907
+ name: "payload",
7908
+ kind: "scalar",
7909
+ T: 12
7910
+ /* ScalarType.BYTES */
7911
+ }
7912
+ ]));
7913
+ let BroadcastRequest = _BroadcastRequest;
7914
+ const _BroadcastResponse = class _BroadcastResponse extends Message {
7915
+ constructor(data) {
7916
+ super();
7917
+ proto3.util.initPartial(data, this);
7918
+ }
7919
+ static fromBinary(bytes, options) {
7920
+ return new _BroadcastResponse().fromBinary(bytes, options);
7921
+ }
7922
+ static fromJson(jsonValue, options) {
7923
+ return new _BroadcastResponse().fromJson(jsonValue, options);
7924
+ }
7925
+ static fromJsonString(jsonString, options) {
7926
+ return new _BroadcastResponse().fromJsonString(jsonString, options);
7927
+ }
7928
+ static equals(a, b) {
7929
+ return proto3.util.equals(_BroadcastResponse, a, b);
7930
+ }
7931
+ };
7932
+ __publicField(_BroadcastResponse, "runtime", proto3);
7933
+ __publicField(_BroadcastResponse, "typeName", "yorkie.v1.BroadcastResponse");
7934
+ __publicField(_BroadcastResponse, "fields", proto3.util.newFieldList(() => []));
7935
+ let BroadcastResponse = _BroadcastResponse;
7847
7936
  const _AttachPresenceRequest = class _AttachPresenceRequest extends Message {
7848
7937
  constructor(data) {
7849
7938
  super();
@@ -8083,6 +8172,10 @@ let RefreshPresenceRequest = _RefreshPresenceRequest;
8083
8172
  const _RefreshPresenceResponse = class _RefreshPresenceResponse extends Message {
8084
8173
  constructor(data) {
8085
8174
  super();
8175
+ /**
8176
+ * @generated from field: int64 count = 1;
8177
+ */
8178
+ __publicField(this, "count", protoInt64.zero);
8086
8179
  proto3.util.initPartial(data, this);
8087
8180
  }
8088
8181
  static fromBinary(bytes, options) {
@@ -8100,7 +8193,15 @@ const _RefreshPresenceResponse = class _RefreshPresenceResponse extends Message
8100
8193
  };
8101
8194
  __publicField(_RefreshPresenceResponse, "runtime", proto3);
8102
8195
  __publicField(_RefreshPresenceResponse, "typeName", "yorkie.v1.RefreshPresenceResponse");
8103
- __publicField(_RefreshPresenceResponse, "fields", proto3.util.newFieldList(() => []));
8196
+ __publicField(_RefreshPresenceResponse, "fields", proto3.util.newFieldList(() => [
8197
+ {
8198
+ no: 1,
8199
+ name: "count",
8200
+ kind: "scalar",
8201
+ T: 3
8202
+ /* ScalarType.INT64 */
8203
+ }
8204
+ ]));
8104
8205
  let RefreshPresenceResponse = _RefreshPresenceResponse;
8105
8206
  const _WatchPresenceRequest = class _WatchPresenceRequest extends Message {
8106
8207
  constructor(data) {
@@ -8221,95 +8322,6 @@ __publicField(_WatchPresenceInitialized, "fields", proto3.util.newFieldList(() =
8221
8322
  }
8222
8323
  ]));
8223
8324
  let WatchPresenceInitialized = _WatchPresenceInitialized;
8224
- const _BroadcastRequest = class _BroadcastRequest extends Message {
8225
- constructor(data) {
8226
- super();
8227
- /**
8228
- * @generated from field: string client_id = 1;
8229
- */
8230
- __publicField(this, "clientId", "");
8231
- /**
8232
- * @generated from field: string document_id = 2;
8233
- */
8234
- __publicField(this, "documentId", "");
8235
- /**
8236
- * @generated from field: string topic = 3;
8237
- */
8238
- __publicField(this, "topic", "");
8239
- /**
8240
- * @generated from field: bytes payload = 4;
8241
- */
8242
- __publicField(this, "payload", new Uint8Array(0));
8243
- proto3.util.initPartial(data, this);
8244
- }
8245
- static fromBinary(bytes, options) {
8246
- return new _BroadcastRequest().fromBinary(bytes, options);
8247
- }
8248
- static fromJson(jsonValue, options) {
8249
- return new _BroadcastRequest().fromJson(jsonValue, options);
8250
- }
8251
- static fromJsonString(jsonString, options) {
8252
- return new _BroadcastRequest().fromJsonString(jsonString, options);
8253
- }
8254
- static equals(a, b) {
8255
- return proto3.util.equals(_BroadcastRequest, a, b);
8256
- }
8257
- };
8258
- __publicField(_BroadcastRequest, "runtime", proto3);
8259
- __publicField(_BroadcastRequest, "typeName", "yorkie.v1.BroadcastRequest");
8260
- __publicField(_BroadcastRequest, "fields", proto3.util.newFieldList(() => [
8261
- {
8262
- no: 1,
8263
- name: "client_id",
8264
- kind: "scalar",
8265
- T: 9
8266
- /* ScalarType.STRING */
8267
- },
8268
- {
8269
- no: 2,
8270
- name: "document_id",
8271
- kind: "scalar",
8272
- T: 9
8273
- /* ScalarType.STRING */
8274
- },
8275
- {
8276
- no: 3,
8277
- name: "topic",
8278
- kind: "scalar",
8279
- T: 9
8280
- /* ScalarType.STRING */
8281
- },
8282
- {
8283
- no: 4,
8284
- name: "payload",
8285
- kind: "scalar",
8286
- T: 12
8287
- /* ScalarType.BYTES */
8288
- }
8289
- ]));
8290
- let BroadcastRequest = _BroadcastRequest;
8291
- const _BroadcastResponse = class _BroadcastResponse extends Message {
8292
- constructor(data) {
8293
- super();
8294
- proto3.util.initPartial(data, this);
8295
- }
8296
- static fromBinary(bytes, options) {
8297
- return new _BroadcastResponse().fromBinary(bytes, options);
8298
- }
8299
- static fromJson(jsonValue, options) {
8300
- return new _BroadcastResponse().fromJson(jsonValue, options);
8301
- }
8302
- static fromJsonString(jsonString, options) {
8303
- return new _BroadcastResponse().fromJsonString(jsonString, options);
8304
- }
8305
- static equals(a, b) {
8306
- return proto3.util.equals(_BroadcastResponse, a, b);
8307
- }
8308
- };
8309
- __publicField(_BroadcastResponse, "runtime", proto3);
8310
- __publicField(_BroadcastResponse, "typeName", "yorkie.v1.BroadcastResponse");
8311
- __publicField(_BroadcastResponse, "fields", proto3.util.newFieldList(() => []));
8312
- let BroadcastResponse = _BroadcastResponse;
8313
8325
  const YorkieService = {
8314
8326
  typeName: "yorkie.v1.YorkieService",
8315
8327
  methods: {
@@ -8376,6 +8388,15 @@ const YorkieService = {
8376
8388
  O: WatchDocumentResponse,
8377
8389
  kind: MethodKind.ServerStreaming
8378
8390
  },
8391
+ /**
8392
+ * @generated from rpc yorkie.v1.YorkieService.Broadcast
8393
+ */
8394
+ broadcast: {
8395
+ name: "Broadcast",
8396
+ I: BroadcastRequest,
8397
+ O: BroadcastResponse,
8398
+ kind: MethodKind.Unary
8399
+ },
8379
8400
  /**
8380
8401
  * @generated from rpc yorkie.v1.YorkieService.AttachPresence
8381
8402
  */
@@ -8411,15 +8432,6 @@ const YorkieService = {
8411
8432
  I: WatchPresenceRequest,
8412
8433
  O: WatchPresenceResponse,
8413
8434
  kind: MethodKind.ServerStreaming
8414
- },
8415
- /**
8416
- * @generated from rpc yorkie.v1.YorkieService.Broadcast
8417
- */
8418
- broadcast: {
8419
- name: "Broadcast",
8420
- I: BroadcastRequest,
8421
- O: BroadcastResponse,
8422
- kind: MethodKind.Unary
8423
8435
  }
8424
8436
  }
8425
8437
  };
@@ -9128,9 +9140,30 @@ class ElementRHT {
9128
9140
  }
9129
9141
  return node;
9130
9142
  }
9143
+ /**
9144
+ * `deepcopy` creates a deep copy of this ElementRHT.
9145
+ */
9146
+ deepcopy() {
9147
+ const clone = ElementRHT.create();
9148
+ for (const [, node] of this.nodeMapByCreatedAt) {
9149
+ clone.nodeMapByCreatedAt.set(
9150
+ node.getValue().getCreatedAt().toIDString(),
9151
+ ElementRHTNode.of(node.getStrKey(), node.getValue().deepcopy())
9152
+ );
9153
+ }
9154
+ for (const [key, node] of this.nodeMapByKey) {
9155
+ clone.nodeMapByKey.set(
9156
+ key,
9157
+ clone.nodeMapByCreatedAt.get(
9158
+ node.getValue().getCreatedAt().toIDString()
9159
+ )
9160
+ );
9161
+ }
9162
+ return clone;
9163
+ }
9131
9164
  // eslint-disable-next-line jsdoc/require-jsdoc
9132
9165
  *[Symbol.iterator]() {
9133
- for (const [, node] of this.nodeMapByKey) {
9166
+ for (const [, node] of this.nodeMapByCreatedAt) {
9134
9167
  yield node;
9135
9168
  }
9136
9169
  }
@@ -9264,12 +9297,12 @@ class CRDTObject extends CRDTContainer {
9264
9297
  */
9265
9298
  toSortedJSON() {
9266
9299
  var _a2;
9267
- const keys = Array();
9300
+ const keys = /* @__PURE__ */ new Set();
9268
9301
  for (const [key] of this) {
9269
- keys.push(key);
9302
+ keys.add(key);
9270
9303
  }
9271
9304
  const json = [];
9272
- for (const key of keys.sort()) {
9305
+ for (const key of Array.from(keys).sort()) {
9273
9306
  const node = (_a2 = this.memberNodes.get(key)) == null ? void 0 : _a2.getValue();
9274
9307
  json.push(`"${escapeString(key)}":${node.toSortedJSON()}`);
9275
9308
  }
@@ -9286,14 +9319,9 @@ class CRDTObject extends CRDTContainer {
9286
9319
  */
9287
9320
  deepcopy() {
9288
9321
  const clone = CRDTObject.create(this.getCreatedAt());
9289
- for (const node of this.memberNodes) {
9290
- clone.memberNodes.set(
9291
- node.getStrKey(),
9292
- node.getValue().deepcopy(),
9293
- this.getPositionedAt()
9294
- );
9295
- }
9296
- clone.remove(this.getRemovedAt());
9322
+ clone.memberNodes = this.memberNodes.deepcopy();
9323
+ clone.setRemovedAt(this.getRemovedAt());
9324
+ clone.setMovedAt(this.getMovedAt());
9297
9325
  return clone;
9298
9326
  }
9299
9327
  /**
@@ -9314,14 +9342,11 @@ class CRDTObject extends CRDTContainer {
9314
9342
  * `[Symbol.iterator]` returns an iterator for the entries in this object.
9315
9343
  */
9316
9344
  *[Symbol.iterator]() {
9317
- const keySet = /* @__PURE__ */ new Set();
9318
9345
  for (const node of this.memberNodes) {
9319
- if (!keySet.has(node.getStrKey())) {
9320
- keySet.add(node.getStrKey());
9321
- if (!node.isRemoved()) {
9322
- yield [node.getStrKey(), node.getValue()];
9323
- }
9346
+ if (node.isRemoved()) {
9347
+ continue;
9324
9348
  }
9349
+ yield [node.getStrKey(), node.getValue()];
9325
9350
  }
9326
9351
  }
9327
9352
  }
@@ -11537,7 +11562,8 @@ class CRDTArray extends CRDTContainer {
11537
11562
  node.getValue().deepcopy()
11538
11563
  );
11539
11564
  }
11540
- clone.remove(this.getRemovedAt());
11565
+ clone.setRemovedAt(this.getRemovedAt());
11566
+ clone.setMovedAt(this.getMovedAt());
11541
11567
  return clone;
11542
11568
  }
11543
11569
  }
@@ -12546,12 +12572,13 @@ class CRDTText extends CRDTElement {
12546
12572
  * `deepcopy` copies itself deeply.
12547
12573
  */
12548
12574
  deepcopy() {
12549
- const text = new CRDTText(
12575
+ const clone = new CRDTText(
12550
12576
  this.rgaTreeSplit.deepcopy(),
12551
12577
  this.getCreatedAt()
12552
12578
  );
12553
- text.remove(this.getRemovedAt());
12554
- return text;
12579
+ clone.setRemovedAt(this.getRemovedAt());
12580
+ clone.setMovedAt(this.getMovedAt());
12581
+ return clone;
12555
12582
  }
12556
12583
  /**
12557
12584
  * `findIndexesFromRange` returns pair of integer offsets of the given range.
@@ -12782,15 +12809,15 @@ class StyleOperation extends Operation {
12782
12809
  const ElementPaddingSize = 2;
12783
12810
  const DefaultRootType = "root";
12784
12811
  const DefaultTextType = "text";
12785
- function addSizeOfLeftSiblings(parent, offset) {
12812
+ function addSizeOfLeftSiblings(parent, offset, includeRemoved = false) {
12786
12813
  let acc = 0;
12787
- const siblings = parent.children;
12814
+ const siblings = includeRemoved ? parent.allChildren : parent.children;
12788
12815
  for (let i = 0; i < offset; i++) {
12789
12816
  const leftSibling = siblings[i];
12790
- if (!leftSibling || leftSibling.isRemoved) {
12817
+ if (!leftSibling || !includeRemoved && leftSibling.isRemoved) {
12791
12818
  continue;
12792
12819
  }
12793
- acc += leftSibling.paddedSize;
12820
+ acc += leftSibling.paddedSize(includeRemoved);
12794
12821
  }
12795
12822
  return acc;
12796
12823
  }
@@ -12799,44 +12826,55 @@ class IndexTreeNode {
12799
12826
  __publicField(this, "type");
12800
12827
  __publicField(this, "parent");
12801
12828
  __publicField(this, "_children");
12802
- __publicField(this, "size");
12829
+ __publicField(this, "visibleSize");
12830
+ __publicField(this, "totalSize");
12803
12831
  this.type = type;
12804
- this.size = 0;
12832
+ this.visibleSize = 0;
12833
+ this.totalSize = 0;
12805
12834
  this._children = children;
12806
12835
  if (this.isText && this._children.length > 0) {
12807
12836
  throw new YorkieError(Code.ErrRefused, "Text node cannot have children");
12808
12837
  }
12809
12838
  }
12810
12839
  /**
12811
- * `updateAncestorsSize` updates the size of the ancestors. It is used when
12812
- * the size of the node is changed.
12840
+ * `updateAncestorsSize` updates the size of the ancestors.
12841
+ * It is used when the size of the node is changed.
12842
+ * If includeRemoved is true, it updates ancestors totalSize including removed nodes.
12813
12843
  */
12814
- updateAncestorsSize() {
12844
+ updateAncestorsSize(delta, includeRemoved = false) {
12815
12845
  let parent = this.parent;
12816
- const sign = this.isRemoved ? -1 : 1;
12817
12846
  while (parent) {
12818
- parent.size += this.paddedSize * sign;
12819
- if (parent.isRemoved) {
12820
- break;
12847
+ if (includeRemoved) {
12848
+ parent.totalSize += delta;
12849
+ } else {
12850
+ parent.visibleSize += delta;
12851
+ if (parent.isRemoved) {
12852
+ break;
12853
+ }
12821
12854
  }
12822
12855
  parent = parent.parent;
12823
12856
  }
12824
12857
  }
12825
12858
  /**
12826
- * `updateDescendantsSize` updates the size of the descendants. It is used when
12859
+ * `UpdateDescendantsSize` updates the size of the descendants. It is used when
12827
12860
  * the tree is newly created and the size of the descendants is not calculated.
12861
+ * If includeRemoved is true, it includes removed nodes in the calculation.
12828
12862
  */
12829
- updateDescendantsSize() {
12863
+ updateDescendantsSize(includeRemoved = false) {
12830
12864
  let size = 0;
12831
12865
  for (const child of this._children) {
12832
- const childSize = child.updateDescendantsSize();
12833
- if (child.isRemoved) {
12866
+ const childSize = child.updateDescendantsSize(includeRemoved);
12867
+ if (!includeRemoved && child.isRemoved) {
12834
12868
  continue;
12835
12869
  }
12836
12870
  size += childSize;
12837
12871
  }
12838
- this.size += size;
12839
- return this.paddedSize;
12872
+ if (includeRemoved) {
12873
+ this.totalSize += size;
12874
+ } else {
12875
+ this.visibleSize += size;
12876
+ }
12877
+ return this.paddedSize(includeRemoved);
12840
12878
  }
12841
12879
  /**
12842
12880
  * `isText` returns true if the node is a text node.
@@ -12845,10 +12883,18 @@ class IndexTreeNode {
12845
12883
  return this.type === DefaultTextType;
12846
12884
  }
12847
12885
  /**
12848
- * `paddedSize` returns the size of the node including padding size.
12886
+ * `paddedSize` returns the length of the node including padding.
12887
+ * If includeRemoved is true, it includes removed nodes in the calculation.
12849
12888
  */
12850
- get paddedSize() {
12851
- return this.size + (this.isText ? 0 : ElementPaddingSize);
12889
+ paddedSize(includeRemoved = false) {
12890
+ let size = this.visibleSize;
12891
+ if (includeRemoved) {
12892
+ size = this.totalSize;
12893
+ }
12894
+ if (!this.isText) {
12895
+ size += ElementPaddingSize;
12896
+ }
12897
+ return size;
12852
12898
  }
12853
12899
  /**
12854
12900
  * `isAncenstorOf` returns true if the node is an ancestor of the given node.
@@ -12883,7 +12929,7 @@ class IndexTreeNode {
12883
12929
  */
12884
12930
  splitText(offset, absOffset) {
12885
12931
  const diff = { data: 0, meta: 0 };
12886
- if (offset === 0 || offset === this.size) {
12932
+ if (offset === 0 || offset === this.visibleSize) {
12887
12933
  return [void 0, diff];
12888
12934
  }
12889
12935
  const leftValue = this.value.slice(0, offset);
@@ -12941,7 +12987,8 @@ class IndexTreeNode {
12941
12987
  this._children.push(...newNode);
12942
12988
  for (const node of newNode) {
12943
12989
  node.parent = this;
12944
- node.updateAncestorsSize();
12990
+ node.updateAncestorsSize(node.paddedSize());
12991
+ node.updateAncestorsSize(node.paddedSize(true), true);
12945
12992
  }
12946
12993
  }
12947
12994
  /**
@@ -12969,7 +13016,8 @@ class IndexTreeNode {
12969
13016
  throw new YorkieError(Code.ErrInvalidArgument, "child not found");
12970
13017
  }
12971
13018
  this.insertAtInternal(newNode, offset);
12972
- newNode.updateAncestorsSize();
13019
+ newNode.updateAncestorsSize(newNode.paddedSize());
13020
+ newNode.updateAncestorsSize(newNode.paddedSize(true), true);
12973
13021
  }
12974
13022
  /**
12975
13023
  * `insertAfter` inserts the given node after the given child.
@@ -12983,7 +13031,8 @@ class IndexTreeNode {
12983
13031
  throw new YorkieError(Code.ErrInvalidArgument, "child not found");
12984
13032
  }
12985
13033
  this.insertAtInternal(newNode, offset + 1);
12986
- newNode.updateAncestorsSize();
13034
+ newNode.updateAncestorsSize(newNode.paddedSize());
13035
+ newNode.updateAncestorsSize(newNode.paddedSize(true), true);
12987
13036
  }
12988
13037
  /**
12989
13038
  * `insertAt` inserts the given node at the given offset.
@@ -12993,10 +13042,12 @@ class IndexTreeNode {
12993
13042
  throw new YorkieError(Code.ErrRefused, "Text node cannot have children");
12994
13043
  }
12995
13044
  this.insertAtInternal(newNode, offset);
12996
- newNode.updateAncestorsSize();
13045
+ newNode.updateAncestorsSize(newNode.paddedSize());
13046
+ newNode.updateAncestorsSize(newNode.paddedSize(true), true);
12997
13047
  }
12998
13048
  /**
12999
13049
  * `removeChild` removes the given child.
13050
+ * In this method, the child is physically removed from the tree.
13000
13051
  */
13001
13052
  removeChild(child) {
13002
13053
  if (this.isText) {
@@ -13007,6 +13058,7 @@ class IndexTreeNode {
13007
13058
  throw new YorkieError(Code.ErrInvalidArgument, "child not found");
13008
13059
  }
13009
13060
  this._children.splice(offset, 1);
13061
+ child.updateAncestorsSize(-child.paddedSize(true), true);
13010
13062
  child.parent = void 0;
13011
13063
  }
13012
13064
  /**
@@ -13017,17 +13069,26 @@ class IndexTreeNode {
13017
13069
  const prvSize = this.getDataSize();
13018
13070
  const clone = this.cloneElement(issueTimeTicket);
13019
13071
  this.parent.insertAfterInternal(clone, this);
13020
- clone.updateAncestorsSize();
13072
+ clone.updateAncestorsSize(clone.paddedSize());
13073
+ clone.updateAncestorsSize(clone.paddedSize(true), true);
13021
13074
  const leftChildren = this.children.slice(0, offset);
13022
13075
  const rightChildren = this.children.slice(offset);
13023
13076
  this._children = leftChildren;
13024
13077
  clone._children = rightChildren;
13025
- this.size = this._children.reduce(
13026
- (acc, child) => acc + child.paddedSize,
13078
+ this.visibleSize = this._children.reduce(
13079
+ (acc, child) => acc + child.paddedSize(),
13080
+ 0
13081
+ );
13082
+ this.totalSize = this._children.reduce(
13083
+ (acc, child) => acc + child.paddedSize(true),
13084
+ 0
13085
+ );
13086
+ clone.visibleSize = clone._children.reduce(
13087
+ (acc, child) => acc + child.paddedSize(true),
13027
13088
  0
13028
13089
  );
13029
- clone.size = clone._children.reduce(
13030
- (acc, child) => acc + child.paddedSize,
13090
+ clone.totalSize = clone._children.reduce(
13091
+ (acc, child) => acc + child.paddedSize(true),
13031
13092
  0
13032
13093
  );
13033
13094
  for (const child of clone._children) {
@@ -13064,12 +13125,15 @@ class IndexTreeNode {
13064
13125
  }
13065
13126
  /**
13066
13127
  * findOffset returns the offset of the given node in the children.
13067
- * It excludes the removed nodes.
13128
+ * If includeRemoved is true, it includes removed nodes in the calculation.
13068
13129
  */
13069
- findOffset(node) {
13130
+ findOffset(node, includeRemoved = false) {
13070
13131
  if (this.isText) {
13071
13132
  throw new YorkieError(Code.ErrRefused, "Text node cannot have children");
13072
13133
  }
13134
+ if (includeRemoved) {
13135
+ return this._children.indexOf(node);
13136
+ }
13073
13137
  if (node.isRemoved) {
13074
13138
  const index = this._children.indexOf(node);
13075
13139
  const refined = this.allChildren.splice(0, index).filter((node2) => !node2.isRemoved).length;
@@ -13114,35 +13178,38 @@ var TokenType = /* @__PURE__ */ ((TokenType2) => {
13114
13178
  TokenType2["Text"] = "Text";
13115
13179
  return TokenType2;
13116
13180
  })(TokenType || {});
13117
- function tokensBetween(root, from, to, callback) {
13181
+ function tokensBetween(root, from, to, callback, includeRemoved = false) {
13118
13182
  if (from > to) {
13119
13183
  throw new YorkieError(
13120
13184
  Code.ErrInvalidArgument,
13121
13185
  `from is greater than to: ${from} > ${to}`
13122
13186
  );
13123
13187
  }
13124
- if (from > root.size) {
13188
+ const rootSize = includeRemoved ? root.totalSize : root.visibleSize;
13189
+ if (from > rootSize) {
13125
13190
  throw new YorkieError(
13126
13191
  Code.ErrInvalidArgument,
13127
- `from is out of range: ${from} > ${root.size}`
13192
+ `from is out of range: ${from} > ${rootSize}`
13128
13193
  );
13129
13194
  }
13130
- if (to > root.size) {
13195
+ if (to > rootSize) {
13131
13196
  throw new YorkieError(
13132
13197
  Code.ErrInvalidArgument,
13133
- `to is out of range: ${to} > ${root.size}`
13198
+ `to is out of range: ${to} > ${rootSize}`
13134
13199
  );
13135
13200
  }
13136
13201
  if (from === to) {
13137
13202
  return;
13138
13203
  }
13139
13204
  let pos = 0;
13140
- for (const child of root.children) {
13141
- if (from - child.paddedSize < pos && pos < to) {
13205
+ const children = includeRemoved ? root._children : root.children;
13206
+ for (const child of children) {
13207
+ if (from - child.paddedSize(includeRemoved) < pos && pos < to) {
13142
13208
  const fromChild = child.isText ? from - pos : from - pos - 1;
13143
13209
  const toChild = child.isText ? to - pos : to - pos - 1;
13210
+ const childSize = includeRemoved ? child.totalSize : child.visibleSize;
13144
13211
  const startContained = !child.isText && fromChild < 0;
13145
- const endContained = !child.isText && toChild > child.size;
13212
+ const endContained = !child.isText && toChild > childSize;
13146
13213
  if (child.isText || startContained) {
13147
13214
  callback(
13148
13215
  [
@@ -13156,8 +13223,9 @@ function tokensBetween(root, from, to, callback) {
13156
13223
  tokensBetween(
13157
13224
  child,
13158
13225
  Math.max(0, fromChild),
13159
- Math.min(toChild, child.size),
13160
- callback
13226
+ Math.min(toChild, childSize),
13227
+ callback,
13228
+ includeRemoved
13161
13229
  );
13162
13230
  if (endContained) {
13163
13231
  callback([
@@ -13167,7 +13235,7 @@ function tokensBetween(root, from, to, callback) {
13167
13235
  ], endContained);
13168
13236
  }
13169
13237
  }
13170
- pos += child.paddedSize;
13238
+ pos += child.paddedSize(includeRemoved);
13171
13239
  }
13172
13240
  }
13173
13241
  function traverse(node, callback, depth = 0) {
@@ -13183,10 +13251,10 @@ function traverseAll(node, callback, depth = 0) {
13183
13251
  callback(node, depth);
13184
13252
  }
13185
13253
  function findTreePos(node, index, preferText = true) {
13186
- if (index > node.size) {
13254
+ if (index > node.visibleSize) {
13187
13255
  throw new YorkieError(
13188
13256
  Code.ErrInvalidArgument,
13189
- `index is out of range: ${index} > ${node.size}`
13257
+ `index is out of range: ${index} > ${node.visibleSize}`
13190
13258
  );
13191
13259
  }
13192
13260
  if (node.isText) {
@@ -13195,20 +13263,20 @@ function findTreePos(node, index, preferText = true) {
13195
13263
  let offset = 0;
13196
13264
  let pos = 0;
13197
13265
  for (const child of node.children) {
13198
- if (preferText && child.isText && child.size >= index - pos) {
13266
+ if (preferText && child.isText && child.visibleSize >= index - pos) {
13199
13267
  return findTreePos(child, index - pos, preferText);
13200
13268
  }
13201
13269
  if (index === pos) {
13202
13270
  return { node, offset };
13203
13271
  }
13204
- if (!preferText && child.paddedSize === index - pos) {
13272
+ if (!preferText && child.paddedSize() === index - pos) {
13205
13273
  return { node, offset: offset + 1 };
13206
13274
  }
13207
- if (child.paddedSize > index - pos) {
13275
+ if (child.paddedSize() > index - pos) {
13208
13276
  const skipOpenSize = 1;
13209
13277
  return findTreePos(child, index - pos - skipOpenSize, preferText);
13210
13278
  }
13211
- pos += child.paddedSize;
13279
+ pos += child.paddedSize();
13212
13280
  offset += 1;
13213
13281
  }
13214
13282
  return { node, offset };
@@ -13220,13 +13288,13 @@ function findLeftmost(node) {
13220
13288
  return findLeftmost(node.children[0]);
13221
13289
  }
13222
13290
  function findTextPos(node, pathElement) {
13223
- if (node.size < pathElement) {
13291
+ if (node.visibleSize < pathElement) {
13224
13292
  throw new YorkieError(Code.ErrInvalidArgument, "unacceptable path");
13225
13293
  }
13226
13294
  for (let i = 0; i < node.children.length; i++) {
13227
13295
  const child = node.children[i];
13228
- if (child.size < pathElement) {
13229
- pathElement -= child.size;
13296
+ if (child.visibleSize < pathElement) {
13297
+ pathElement -= child.visibleSize;
13230
13298
  } else {
13231
13299
  node = child;
13232
13300
  break;
@@ -13241,9 +13309,10 @@ class IndexTree {
13241
13309
  }
13242
13310
  /**
13243
13311
  * `tokensBetween` returns the tokens between the given range.
13312
+ * If includeRemoved is true, it includes removed nodes in the calculation.
13244
13313
  */
13245
- tokensBetween(from, to, callback) {
13246
- tokensBetween(this.root, from, to, callback);
13314
+ tokensBetween(from, to, callback, includeRemoved = false) {
13315
+ tokensBetween(this.root, from, to, callback, includeRemoved);
13247
13316
  }
13248
13317
  /**
13249
13318
  * `traverse` traverses the tree with postorder traversal.
@@ -13342,7 +13411,7 @@ class IndexTree {
13342
13411
  * `getSize` returns the size of the tree.
13343
13412
  */
13344
13413
  get size() {
13345
- return this.root.size;
13414
+ return this.root.visibleSize;
13346
13415
  }
13347
13416
  /**
13348
13417
  * `findPostorderRight` finds right node of the given tree position with
@@ -13351,7 +13420,7 @@ class IndexTree {
13351
13420
  findPostorderRight(treePos) {
13352
13421
  const { node, offset } = treePos;
13353
13422
  if (node.isText) {
13354
- if (node.size === offset) {
13423
+ if (node.visibleSize === offset) {
13355
13424
  const nextSibling = node.nextSibling;
13356
13425
  if (nextSibling) {
13357
13426
  return nextSibling;
@@ -13367,8 +13436,9 @@ class IndexTree {
13367
13436
  }
13368
13437
  /**
13369
13438
  * `indexOf` returns the index of the given tree position.
13439
+ * If includeRemoved is true, it includes removed nodes in the calculation.
13370
13440
  */
13371
- indexOf(pos) {
13441
+ indexOf(pos, includeRemoved = false) {
13372
13442
  let { node } = pos;
13373
13443
  const { offset } = pos;
13374
13444
  let size = 0;
@@ -13376,22 +13446,22 @@ class IndexTree {
13376
13446
  if (node.isText) {
13377
13447
  size += offset;
13378
13448
  const parent = node.parent;
13379
- const offsetOfNode = parent.findOffset(node);
13449
+ const offsetOfNode = parent.findOffset(node, includeRemoved);
13380
13450
  if (offsetOfNode === -1) {
13381
13451
  throw new YorkieError(Code.ErrInvalidArgument, "invalid pos");
13382
13452
  }
13383
- size += addSizeOfLeftSiblings(parent, offsetOfNode);
13453
+ size += addSizeOfLeftSiblings(parent, offsetOfNode, includeRemoved);
13384
13454
  node = node.parent;
13385
13455
  } else {
13386
- size += addSizeOfLeftSiblings(node, offset);
13456
+ size += addSizeOfLeftSiblings(node, offset, includeRemoved);
13387
13457
  }
13388
13458
  while (node == null ? void 0 : node.parent) {
13389
13459
  const parent = node.parent;
13390
- const offsetOfNode = parent.findOffset(node);
13460
+ const offsetOfNode = parent.findOffset(node, includeRemoved);
13391
13461
  if (offsetOfNode === -1) {
13392
13462
  throw new YorkieError(Code.ErrInvalidArgument, "invalid pos");
13393
13463
  }
13394
- size += addSizeOfLeftSiblings(parent, offsetOfNode);
13464
+ size += addSizeOfLeftSiblings(parent, offsetOfNode, includeRemoved);
13395
13465
  depth++;
13396
13466
  node = node.parent;
13397
13467
  }
@@ -13948,7 +14018,8 @@ class CRDTTreeNode extends IndexTreeNode {
13948
14018
  const clone = new CRDTTreeNode(this.id, this.type);
13949
14019
  clone.removedAt = this.removedAt;
13950
14020
  clone._value = this._value;
13951
- clone.size = this.size;
14021
+ clone.visibleSize = this.visibleSize;
14022
+ clone.totalSize = this.totalSize;
13952
14023
  clone.attrs = (_a2 = this.attrs) == null ? void 0 : _a2.deepcopy();
13953
14024
  clone._children = this._children.map((child) => {
13954
14025
  const childClone = child.deepcopy();
@@ -13982,7 +14053,8 @@ class CRDTTreeNode extends IndexTreeNode {
13982
14053
  );
13983
14054
  }
13984
14055
  this._value = v;
13985
- this.size = v.length;
14056
+ this.visibleSize = v.length;
14057
+ this.totalSize = v.length;
13986
14058
  }
13987
14059
  /**
13988
14060
  * `isRemoved` returns whether the node is removed or not.
@@ -13994,13 +14066,15 @@ class CRDTTreeNode extends IndexTreeNode {
13994
14066
  * `remove` marks the node as removed.
13995
14067
  */
13996
14068
  remove(removedAt) {
13997
- const alived = !this.removedAt;
13998
- if (!this.removedAt || this.removedAt.compare(removedAt) > 0) {
14069
+ if (!this.removedAt) {
13999
14070
  this.removedAt = removedAt;
14071
+ this.updateAncestorsSize(-this.paddedSize());
14072
+ return true;
14000
14073
  }
14001
- if (alived) {
14002
- this.updateAncestorsSize();
14074
+ if (removedAt.after(this.removedAt)) {
14075
+ this.removedAt = removedAt;
14003
14076
  }
14077
+ return false;
14004
14078
  }
14005
14079
  /**
14006
14080
  * `cloneText` clones this text node with the given offset.
@@ -14058,9 +14132,17 @@ class CRDTTreeNode extends IndexTreeNode {
14058
14132
  /**
14059
14133
  * `canDelete` checks if node is able to delete.
14060
14134
  */
14061
- canDelete(editedAt, clientLamportAtChange) {
14062
- const nodeExisted = this.getCreatedAt().getLamport() <= clientLamportAtChange;
14063
- return nodeExisted && (!this.removedAt || editedAt.after(this.removedAt));
14135
+ canDelete(editedAt, creationKnown, tombstoneKnown) {
14136
+ if (!creationKnown) {
14137
+ return false;
14138
+ }
14139
+ if (!this.removedAt) {
14140
+ return true;
14141
+ }
14142
+ if (!tombstoneKnown && (editedAt == null ? void 0 : editedAt.after(this.removedAt))) {
14143
+ return true;
14144
+ }
14145
+ return false;
14064
14146
  }
14065
14147
  /**
14066
14148
  * `canStyle` checks if node is able to style.
@@ -14099,7 +14181,7 @@ class CRDTTreeNode extends IndexTreeNode {
14099
14181
  getDataSize() {
14100
14182
  const dataSize = { data: 0, meta: 0 };
14101
14183
  if (this.isText) {
14102
- dataSize.data += this.size * 2;
14184
+ dataSize.data += this.visibleSize * 2;
14103
14185
  }
14104
14186
  if (this.id) {
14105
14187
  dataSize.meta += TimeTicketSize;
@@ -14176,14 +14258,14 @@ function toTestTreeNode(node) {
14176
14258
  return {
14177
14259
  type: currentNode.type,
14178
14260
  value: currentNode.value,
14179
- size: currentNode.size,
14261
+ visibleSize: currentNode.visibleSize,
14180
14262
  isRemoved: currentNode.isRemoved
14181
14263
  };
14182
14264
  }
14183
14265
  return {
14184
14266
  type: node.type,
14185
14267
  children: node.children.map(toTestTreeNode),
14186
- size: node.size,
14268
+ visibleSize: node.visibleSize,
14187
14269
  isRemoved: node.isRemoved
14188
14270
  };
14189
14271
  }
@@ -14411,18 +14493,25 @@ class CRDTTree extends CRDTElement {
14411
14493
  toBeMovedToFromParents.push(child);
14412
14494
  }
14413
14495
  }
14414
- const actorID = node.getCreatedAt().getActorID();
14415
- let clientLamportAtChange = MaxLamport;
14416
- if (versionVector != void 0) {
14417
- clientLamportAtChange = versionVector.get(actorID) ? versionVector.get(actorID) : 0n;
14496
+ const isLocal = versionVector === void 0;
14497
+ let creationKnown = false;
14498
+ const createdAtVV = versionVector == null ? void 0 : versionVector.get(
14499
+ node.id.getCreatedAt().getActorID()
14500
+ );
14501
+ creationKnown = isLocal || createdAtVV !== void 0 && createdAtVV >= node.id.getCreatedAt().getLamport();
14502
+ let tombstoneKnown = false;
14503
+ if (node.removedAt) {
14504
+ const removedAtVV = versionVector == null ? void 0 : versionVector.get(node.removedAt.getActorID());
14505
+ tombstoneKnown = isLocal || removedAtVV !== void 0 && removedAtVV >= node.removedAt.getLamport();
14418
14506
  }
14419
- if (node.canDelete(editedAt, clientLamportAtChange) || nodesToBeRemoved.includes(node.parent)) {
14507
+ if (node.canDelete(editedAt, creationKnown, tombstoneKnown) || nodesToBeRemoved.includes(node.parent)) {
14420
14508
  if (tokenType === TokenType.Text || tokenType === TokenType.Start) {
14421
14509
  nodesToBeRemoved.push(node);
14422
14510
  }
14423
14511
  tokensToBeRemoved.push([node, tokenType]);
14424
14512
  }
14425
- }
14513
+ },
14514
+ true
14426
14515
  );
14427
14516
  const changes = this.makeDeletionChanges(
14428
14517
  tokensToBeRemoved,
@@ -14508,7 +14597,7 @@ class CRDTTree extends CRDTElement {
14508
14597
  editT(range, contents, splitLevel, editedAt, issueTimeTicket) {
14509
14598
  const fromPos = this.findPos(range[0]);
14510
14599
  const toPos = this.findPos(range[1]);
14511
- this.edit(
14600
+ return this.edit(
14512
14601
  [fromPos, toPos],
14513
14602
  contents,
14514
14603
  splitLevel,
@@ -14668,7 +14757,7 @@ class CRDTTree extends CRDTElement {
14668
14757
  const nodeInfo = {
14669
14758
  type: node.type,
14670
14759
  parent: parentNode == null ? void 0 : parentNode.id.toTestString(),
14671
- size: node.size,
14760
+ size: node.visibleSize,
14672
14761
  id: node.id.toTestString(),
14673
14762
  removedAt: (_a2 = node.removedAt) == null ? void 0 : _a2.toTestString(),
14674
14763
  insPrev: (_b2 = node.insPrevID) == null ? void 0 : _b2.toTestString(),
@@ -14715,7 +14804,10 @@ class CRDTTree extends CRDTElement {
14715
14804
  */
14716
14805
  deepcopy() {
14717
14806
  const root = this.getRoot();
14718
- return new CRDTTree(root.deepcopy(), this.getCreatedAt());
14807
+ const tree = new CRDTTree(root.deepcopy(), this.getCreatedAt());
14808
+ tree.setRemovedAt(this.getRemovedAt());
14809
+ tree.setMovedAt(this.getMovedAt());
14810
+ return tree;
14719
14811
  }
14720
14812
  /**
14721
14813
  * `toPath` converts the given CRDTTreeNodeID to the path of the tree.
@@ -14729,13 +14821,14 @@ class CRDTTree extends CRDTElement {
14729
14821
  }
14730
14822
  /**
14731
14823
  * `toIndex` converts the given CRDTTreeNodeID to the index of the tree.
14824
+ * If includeRemoved is true, it includes removed nodes in the calculation.
14732
14825
  */
14733
- toIndex(parentNode, leftNode) {
14734
- const treePos = this.toTreePos(parentNode, leftNode);
14826
+ toIndex(parentNode, leftNode, includeRemoved = false) {
14827
+ const treePos = this.toTreePos(parentNode, leftNode, includeRemoved);
14735
14828
  if (!treePos) {
14736
14829
  return -1;
14737
14830
  }
14738
- return this.indexTree.indexOf(treePos);
14831
+ return this.indexTree.indexOf(treePos, includeRemoved);
14739
14832
  }
14740
14833
  /**
14741
14834
  * `indexToPath` converts the given tree index to path.
@@ -14788,26 +14881,28 @@ class CRDTTree extends CRDTElement {
14788
14881
  }
14789
14882
  /**
14790
14883
  * `traverseInPosRange` traverses the tree in the given position range.
14884
+ * If includeRemoved is true, it includes removed nodes in the calculation.
14791
14885
  */
14792
- traverseInPosRange(fromParent, fromLeft, toParent, toLeft, callback) {
14793
- const fromIdx = this.toIndex(fromParent, fromLeft);
14794
- const toIdx = this.toIndex(toParent, toLeft);
14795
- return this.indexTree.tokensBetween(fromIdx, toIdx, callback);
14886
+ traverseInPosRange(fromParent, fromLeft, toParent, toLeft, callback, includeRemoved = false) {
14887
+ const fromIdx = this.toIndex(fromParent, fromLeft, includeRemoved);
14888
+ const toIdx = this.toIndex(toParent, toLeft, includeRemoved);
14889
+ this.indexTree.tokensBetween(fromIdx, toIdx, callback, includeRemoved);
14796
14890
  }
14797
14891
  /**
14798
14892
  * `toTreePos` converts the given nodes to the position of the IndexTree.
14893
+ * If includeRemoved is true, it includes removed nodes in the calculation.
14799
14894
  */
14800
- toTreePos(parentNode, leftNode) {
14895
+ toTreePos(parentNode, leftNode, includeRemoved = false) {
14801
14896
  if (!parentNode || !leftNode) {
14802
14897
  return;
14803
14898
  }
14804
- if (parentNode.isRemoved) {
14899
+ if (!includeRemoved && parentNode.isRemoved) {
14805
14900
  let childNode;
14806
14901
  while (parentNode.isRemoved) {
14807
14902
  childNode = parentNode;
14808
14903
  parentNode = childNode.parent;
14809
14904
  }
14810
- const offset2 = parentNode.findOffset(childNode);
14905
+ const offset2 = parentNode.findOffset(childNode, includeRemoved);
14811
14906
  return {
14812
14907
  node: parentNode,
14813
14908
  offset: offset2
@@ -14819,12 +14914,12 @@ class CRDTTree extends CRDTElement {
14819
14914
  offset: 0
14820
14915
  };
14821
14916
  }
14822
- let offset = parentNode.findOffset(leftNode);
14823
- if (!leftNode.isRemoved) {
14917
+ let offset = parentNode.findOffset(leftNode, includeRemoved);
14918
+ if (includeRemoved || !leftNode.isRemoved) {
14824
14919
  if (leftNode.isText) {
14825
14920
  return {
14826
14921
  node: leftNode,
14827
- offset: leftNode.paddedSize
14922
+ offset: leftNode.paddedSize(includeRemoved)
14828
14923
  };
14829
14924
  }
14830
14925
  offset++;
@@ -15967,13 +16062,16 @@ class RGATreeSplitNode extends SplayNode {
15967
16062
  /**
15968
16063
  * `canDelete` checks if node is able to delete.
15969
16064
  */
15970
- canRemove(creationKnown) {
16065
+ canRemove(editedAt, creationKnown, tombstoneKnown) {
15971
16066
  if (!creationKnown) {
15972
16067
  return false;
15973
16068
  }
15974
16069
  if (!this.removedAt) {
15975
16070
  return true;
15976
16071
  }
16072
+ if (!tombstoneKnown && (editedAt == null ? void 0 : editedAt.after(this.removedAt))) {
16073
+ return true;
16074
+ }
15977
16075
  return false;
15978
16076
  }
15979
16077
  /**
@@ -15992,12 +16090,12 @@ class RGATreeSplitNode extends SplayNode {
15992
16090
  /**
15993
16091
  * `remove` removes the node of the given edited time.
15994
16092
  */
15995
- remove(removedAt, tombstoneKnown) {
16093
+ remove(removedAt) {
15996
16094
  if (!this.removedAt) {
15997
16095
  this.removedAt = removedAt;
15998
16096
  return;
15999
16097
  }
16000
- if (!tombstoneKnown && removedAt.after(this.removedAt)) {
16098
+ if (removedAt.after(this.removedAt)) {
16001
16099
  this.removedAt = removedAt;
16002
16100
  }
16003
16101
  }
@@ -16334,13 +16432,31 @@ class RGATreeSplit {
16334
16432
  if (!candidates.length) {
16335
16433
  return [[], /* @__PURE__ */ new Map()];
16336
16434
  }
16337
- const isLocal = vector === void 0;
16435
+ const isLocal = vector === void 0 || vector.size() === 0;
16338
16436
  const nodesToRemove = [];
16339
16437
  const nodesToKeep = [];
16340
16438
  const [leftEdge, rightEdge] = this.findEdgesOfCandidates(candidates);
16341
16439
  nodesToKeep.push(leftEdge);
16342
16440
  for (const node of candidates) {
16343
- if (node.canRemove(isLocal || vector.afterOrEqual(node.getCreatedAt()))) {
16441
+ let creationKnown = false;
16442
+ if (isLocal) {
16443
+ creationKnown = true;
16444
+ } else {
16445
+ const createdAtVV = vector == null ? void 0 : vector.get(node.getCreatedAt().getActorID());
16446
+ if (createdAtVV && createdAtVV >= node.getCreatedAt().getLamport()) {
16447
+ creationKnown = true;
16448
+ }
16449
+ }
16450
+ let tombstoneKnown = false;
16451
+ if (node.getRemovedAt()) {
16452
+ const removedAtVV = vector == null ? void 0 : vector.get(node.getRemovedAt().getActorID());
16453
+ if (isLocal) {
16454
+ tombstoneKnown = true;
16455
+ } else if (removedAtVV && removedAtVV >= node.getRemovedAt().getLamport()) {
16456
+ tombstoneKnown = true;
16457
+ }
16458
+ }
16459
+ if (node.canRemove(editedAt, creationKnown, tombstoneKnown)) {
16344
16460
  nodesToRemove.push(node);
16345
16461
  } else {
16346
16462
  nodesToKeep.push(node);
@@ -16351,10 +16467,7 @@ class RGATreeSplit {
16351
16467
  const removedNodes = /* @__PURE__ */ new Map();
16352
16468
  for (const node of nodesToRemove) {
16353
16469
  removedNodes.set(node.getID().toIDString(), node);
16354
- node.remove(
16355
- editedAt,
16356
- node.isRemoved() && (isLocal || vector.afterOrEqual(node.getRemovedAt()))
16357
- );
16470
+ node.remove(editedAt);
16358
16471
  }
16359
16472
  this.deleteIndexNodes(nodesToKeep);
16360
16473
  return [changes, removedNodes];
@@ -16536,13 +16649,14 @@ class CRDTCounter extends CRDTElement {
16536
16649
  * `deepcopy` copies itself deeply.
16537
16650
  */
16538
16651
  deepcopy() {
16539
- const counter = CRDTCounter.create(
16652
+ const clone = CRDTCounter.create(
16540
16653
  this.valueType,
16541
16654
  this.value,
16542
16655
  this.getCreatedAt()
16543
16656
  );
16544
- counter.setMovedAt(this.getMovedAt());
16545
- return counter;
16657
+ clone.setRemovedAt(this.getRemovedAt());
16658
+ clone.setMovedAt(this.getMovedAt());
16659
+ return clone;
16546
16660
  }
16547
16661
  /**
16548
16662
  * `getType` returns the type of the value.
@@ -17719,6 +17833,7 @@ function fromTreeNodes(pbTreeNodes) {
17719
17833
  depthTable.set(pbTreeNodes[i].depth, nodes[i]);
17720
17834
  }
17721
17835
  root.updateDescendantsSize();
17836
+ root.updateDescendantsSize(true);
17722
17837
  return CRDTTree.create(root, InitialTimeTicket).getRoot();
17723
17838
  }
17724
17839
  function fromRHT(pbRHT) {
@@ -18206,108 +18321,6 @@ function uuid() {
18206
18321
  return v.toString(16);
18207
18322
  });
18208
18323
  }
18209
- class Attachment {
18210
- constructor(reconnectStreamDelay, resource, resourceID, syncMode, unsubscribeBroadcastEvent) {
18211
- __publicField(this, "resource");
18212
- __publicField(this, "resourceID");
18213
- __publicField(this, "syncMode");
18214
- __publicField(this, "changeEventReceived");
18215
- __publicField(this, "lastHeartbeatTime");
18216
- __publicField(this, "reconnectStreamDelay");
18217
- __publicField(this, "cancelled");
18218
- __publicField(this, "watchStream");
18219
- __publicField(this, "watchLoopTimerID");
18220
- __publicField(this, "watchAbortController");
18221
- __publicField(this, "unsubscribeBroadcastEvent");
18222
- this.reconnectStreamDelay = reconnectStreamDelay;
18223
- this.resource = resource;
18224
- this.resourceID = resourceID;
18225
- this.syncMode = syncMode;
18226
- this.changeEventReceived = syncMode !== void 0 ? false : void 0;
18227
- this.lastHeartbeatTime = Date.now();
18228
- this.cancelled = false;
18229
- this.unsubscribeBroadcastEvent = unsubscribeBroadcastEvent;
18230
- }
18231
- /**
18232
- * `changeSyncMode` changes the sync mode of the document.
18233
- */
18234
- changeSyncMode(syncMode) {
18235
- this.syncMode = syncMode;
18236
- }
18237
- /**
18238
- * `needRealtimeSync` returns whether the resource needs to be synced in real time.
18239
- * Only applicable to Document resources with syncMode defined.
18240
- */
18241
- needRealtimeSync() {
18242
- if (this.syncMode === void 0) {
18243
- return false;
18244
- }
18245
- if (this.syncMode === SyncMode.RealtimeSyncOff) {
18246
- return false;
18247
- }
18248
- if (this.syncMode === SyncMode.RealtimePushOnly) {
18249
- return this.resource.hasLocalChanges();
18250
- }
18251
- return this.syncMode !== SyncMode.Manual && (this.resource.hasLocalChanges() || (this.changeEventReceived ?? false));
18252
- }
18253
- /**
18254
- * `needSync` determines if the attachment needs sync.
18255
- * This includes both document sync and presence heartbeat.
18256
- */
18257
- needSync(heartbeatInterval) {
18258
- if (this.syncMode !== void 0) {
18259
- return this.needRealtimeSync();
18260
- }
18261
- return Date.now() - this.lastHeartbeatTime >= heartbeatInterval;
18262
- }
18263
- /**
18264
- * `updateHeartbeatTime` updates the last heartbeat time.
18265
- */
18266
- updateHeartbeatTime() {
18267
- this.lastHeartbeatTime = Date.now();
18268
- }
18269
- /**
18270
- * `runWatchLoop` runs the watch loop.
18271
- */
18272
- async runWatchLoop(watchStreamCreator) {
18273
- const doLoop = async () => {
18274
- if (this.watchStream) {
18275
- return Promise.resolve();
18276
- }
18277
- if (this.watchLoopTimerID) {
18278
- clearTimeout(this.watchLoopTimerID);
18279
- this.watchLoopTimerID = void 0;
18280
- }
18281
- try {
18282
- [this.watchStream, this.watchAbortController] = await watchStreamCreator(() => {
18283
- this.watchStream = void 0;
18284
- this.watchAbortController = void 0;
18285
- if (!this.cancelled) {
18286
- this.watchLoopTimerID = setTimeout(
18287
- doLoop,
18288
- this.reconnectStreamDelay
18289
- );
18290
- }
18291
- });
18292
- } catch {
18293
- }
18294
- };
18295
- await doLoop();
18296
- }
18297
- /**
18298
- * `cancelWatchStream` cancels the watch stream.
18299
- */
18300
- cancelWatchStream() {
18301
- this.cancelled = true;
18302
- if (this.watchStream && this.watchAbortController) {
18303
- this.watchAbortController.abort();
18304
- this.watchStream = void 0;
18305
- this.watchAbortController = void 0;
18306
- }
18307
- clearTimeout(this.watchLoopTimerID);
18308
- this.watchLoopTimerID = void 0;
18309
- }
18310
- }
18311
18324
  const Noop = () => {
18312
18325
  };
18313
18326
  class ObserverProxy {
@@ -20640,6 +20653,18 @@ class CRDTRoot {
20640
20653
  acc(diff) {
20641
20654
  addDataSizes(this.docSize.live, diff);
20642
20655
  }
20656
+ /**
20657
+ * `getGCElementPairs` returns an iterator for all GC element pairs.
20658
+ * This is similar to Go's GCElementPairMap() functionality.
20659
+ */
20660
+ *getGCElementPairs() {
20661
+ for (const createdAt of this.gcElementSetByCreatedAt) {
20662
+ const pair = this.elementPairMapByCreatedAt.get(createdAt);
20663
+ if (pair) {
20664
+ yield pair;
20665
+ }
20666
+ }
20667
+ }
20643
20668
  }
20644
20669
  class DocPresence {
20645
20670
  constructor(changeContext, presence) {
@@ -21594,6 +21619,13 @@ class Document {
21594
21619
  getGarbageLen() {
21595
21620
  return this.root.getGarbageLen();
21596
21621
  }
21622
+ /**
21623
+ * `getRootCRDT` returns the CRDTRoot for testing purposes.
21624
+ * This method is intended for internal testing only.
21625
+ */
21626
+ getRootCRDT() {
21627
+ return this.root;
21628
+ }
21597
21629
  /**
21598
21630
  * `getGarbageLenFromClone` returns the length of elements should be purged from clone.
21599
21631
  */
@@ -22167,6 +22199,108 @@ class Document {
22167
22199
  this.publish(events);
22168
22200
  }
22169
22201
  }
22202
+ class Attachment {
22203
+ constructor(reconnectStreamDelay, resource, resourceID, syncMode, unsubscribeBroadcastEvent) {
22204
+ __publicField(this, "resource");
22205
+ __publicField(this, "resourceID");
22206
+ __publicField(this, "syncMode");
22207
+ __publicField(this, "changeEventReceived");
22208
+ __publicField(this, "lastHeartbeatTime");
22209
+ __publicField(this, "reconnectStreamDelay");
22210
+ __publicField(this, "cancelled");
22211
+ __publicField(this, "watchStream");
22212
+ __publicField(this, "watchLoopTimerID");
22213
+ __publicField(this, "watchAbortController");
22214
+ __publicField(this, "unsubscribeBroadcastEvent");
22215
+ this.reconnectStreamDelay = reconnectStreamDelay;
22216
+ this.resource = resource;
22217
+ this.resourceID = resourceID;
22218
+ this.syncMode = syncMode;
22219
+ this.changeEventReceived = syncMode !== void 0 ? false : void 0;
22220
+ this.lastHeartbeatTime = Date.now();
22221
+ this.cancelled = false;
22222
+ this.unsubscribeBroadcastEvent = unsubscribeBroadcastEvent;
22223
+ }
22224
+ /**
22225
+ * `changeSyncMode` changes the sync mode of the document.
22226
+ */
22227
+ changeSyncMode(syncMode) {
22228
+ this.syncMode = syncMode;
22229
+ }
22230
+ /**
22231
+ * `needRealtimeSync` returns whether the resource needs to be synced in real time.
22232
+ * Only applicable to Document resources with syncMode defined.
22233
+ */
22234
+ needRealtimeSync() {
22235
+ if (this.syncMode === SyncMode.RealtimeSyncOff) {
22236
+ return false;
22237
+ }
22238
+ if (this.syncMode === SyncMode.RealtimePushOnly) {
22239
+ return this.resource.hasLocalChanges();
22240
+ }
22241
+ return this.syncMode !== SyncMode.Manual && (this.resource.hasLocalChanges() || (this.changeEventReceived ?? false));
22242
+ }
22243
+ /**
22244
+ * `needSync` determines if the attachment needs sync.
22245
+ * This includes both document sync and presence heartbeat.
22246
+ */
22247
+ needSync(heartbeatInterval) {
22248
+ if (this.resource instanceof Document) {
22249
+ return this.needRealtimeSync();
22250
+ }
22251
+ if (this.syncMode === SyncMode.Manual) {
22252
+ return false;
22253
+ }
22254
+ return Date.now() - this.lastHeartbeatTime >= heartbeatInterval;
22255
+ }
22256
+ /**
22257
+ * `updateHeartbeatTime` updates the last heartbeat time.
22258
+ */
22259
+ updateHeartbeatTime() {
22260
+ this.lastHeartbeatTime = Date.now();
22261
+ }
22262
+ /**
22263
+ * `runWatchLoop` runs the watch loop.
22264
+ */
22265
+ async runWatchLoop(watchStreamCreator) {
22266
+ const doLoop = async () => {
22267
+ if (this.watchStream) {
22268
+ return Promise.resolve();
22269
+ }
22270
+ if (this.watchLoopTimerID) {
22271
+ clearTimeout(this.watchLoopTimerID);
22272
+ this.watchLoopTimerID = void 0;
22273
+ }
22274
+ try {
22275
+ [this.watchStream, this.watchAbortController] = await watchStreamCreator(() => {
22276
+ this.watchStream = void 0;
22277
+ this.watchAbortController = void 0;
22278
+ if (!this.cancelled) {
22279
+ this.watchLoopTimerID = setTimeout(
22280
+ doLoop,
22281
+ this.reconnectStreamDelay
22282
+ );
22283
+ }
22284
+ });
22285
+ } catch {
22286
+ }
22287
+ };
22288
+ await doLoop();
22289
+ }
22290
+ /**
22291
+ * `cancelWatchStream` cancels the watch stream.
22292
+ */
22293
+ cancelWatchStream() {
22294
+ this.cancelled = true;
22295
+ if (this.watchStream && this.watchAbortController) {
22296
+ this.watchAbortController.abort();
22297
+ this.watchStream = void 0;
22298
+ this.watchAbortController = void 0;
22299
+ }
22300
+ clearTimeout(this.watchLoopTimerID);
22301
+ this.watchLoopTimerID = void 0;
22302
+ }
22303
+ }
22170
22304
  function createAuthInterceptor(apiKey, token) {
22171
22305
  let currentToken = token;
22172
22306
  const setToken = (token2) => {
@@ -22187,7 +22321,7 @@ function createAuthInterceptor(apiKey, token) {
22187
22321
  };
22188
22322
  }
22189
22323
  const name$1 = "@yorkie-js/sdk";
22190
- const version$1 = "0.6.34";
22324
+ const version$1 = "0.6.35";
22191
22325
  const pkg$1 = {
22192
22326
  name: name$1,
22193
22327
  version: version$1
@@ -22509,7 +22643,7 @@ class Client {
22509
22643
  */
22510
22644
  attach(resource, opts) {
22511
22645
  if (resource instanceof Presence) {
22512
- return this.attachPresence(resource);
22646
+ return this.attachPresence(resource, opts);
22513
22647
  } else {
22514
22648
  return this.attachDocument(resource, opts);
22515
22649
  }
@@ -22674,7 +22808,7 @@ class Client {
22674
22808
  * `attach` attaches the given presence counter to this client.
22675
22809
  * It tells the server that this client will track the presence count.
22676
22810
  */
22677
- async attachPresence(presence) {
22811
+ async attachPresence(presence, opts = {}) {
22678
22812
  if (!this.isActive()) {
22679
22813
  throw new YorkieError(
22680
22814
  Code.ErrClientNotActivated,
@@ -22700,15 +22834,19 @@ class Client {
22700
22834
  presence.setPresenceID(res.presenceId);
22701
22835
  presence.updateCount(Number(res.count), 0);
22702
22836
  presence.applyStatus(PresenceStatus.Attached);
22837
+ const syncMode = opts.isRealtime !== false ? "realtime" : "manual";
22703
22838
  const attachment = new Attachment(
22704
22839
  this.reconnectStreamDelay,
22705
22840
  presence,
22706
- res.presenceId
22841
+ res.presenceId,
22842
+ syncMode
22707
22843
  );
22708
22844
  this.attachmentMap.set(presence.getKey(), attachment);
22709
- await this.runWatchLoop(presence.getKey());
22845
+ if (syncMode === "realtime") {
22846
+ await this.runWatchLoop(presence.getKey());
22847
+ }
22710
22848
  logger.info(
22711
- `[AP] c:"${this.getKey()}" attaches p:"${presence.getKey()}" count:${presence.getCount()}`
22849
+ `[AP] c:"${this.getKey()}" attaches p:"${presence.getKey()}" mode:${syncMode} count:${presence.getCount()}`
22712
22850
  );
22713
22851
  return presence;
22714
22852
  } catch (err) {
@@ -22796,23 +22934,39 @@ class Client {
22796
22934
  return doc;
22797
22935
  }
22798
22936
  /**
22799
- * `sync` pushes local changes of the attached documents to the server and
22800
- * receives changes of the remote replica from the server then apply them to
22801
- * local documents.
22937
+ * `sync` implementation that handles both Document and Presence.
22802
22938
  */
22803
- sync(doc) {
22939
+ sync(resource) {
22804
22940
  if (!this.isActive()) {
22805
22941
  throw new YorkieError(
22806
22942
  Code.ErrClientNotActivated,
22807
22943
  `${this.key} is not active`
22808
22944
  );
22809
22945
  }
22810
- if (doc) {
22811
- const attachment = this.attachmentMap.get(doc.getKey());
22946
+ if (resource instanceof Presence) {
22947
+ const attachment = this.attachmentMap.get(
22948
+ resource.getKey()
22949
+ );
22950
+ if (!attachment) {
22951
+ throw new YorkieError(
22952
+ Code.ErrDocumentNotAttached,
22953
+ `${resource.getKey()} is not attached`
22954
+ );
22955
+ }
22956
+ return this.enqueueTask(async () => {
22957
+ return this.syncInternal(attachment).catch(async (err) => {
22958
+ logger.error(`[SY] c:"${this.getKey()}" err :`, err);
22959
+ await this.handleConnectError(err);
22960
+ throw err;
22961
+ });
22962
+ });
22963
+ }
22964
+ if (resource instanceof Document) {
22965
+ const attachment = this.attachmentMap.get(resource.getKey());
22812
22966
  if (!attachment) {
22813
22967
  throw new YorkieError(
22814
22968
  Code.ErrDocumentNotAttached,
22815
- `${doc.getKey()} is not attached`
22969
+ `${resource.getKey()} is not attached`
22816
22970
  );
22817
22971
  }
22818
22972
  return this.enqueueTask(async () => {
@@ -23334,7 +23488,7 @@ class Client {
23334
23488
  const { resource } = attachment;
23335
23489
  if (resource instanceof Presence) {
23336
23490
  try {
23337
- await this.rpcClient.refreshPresence(
23491
+ const res = await this.rpcClient.refreshPresence(
23338
23492
  {
23339
23493
  clientId: this.id,
23340
23494
  presenceId: resource.getPresenceID(),
@@ -23346,9 +23500,10 @@ class Client {
23346
23500
  }
23347
23501
  }
23348
23502
  );
23503
+ resource.updateCount(Number(res.count), 0);
23349
23504
  attachment.updateHeartbeatTime();
23350
23505
  logger.debug(
23351
- `[RP] c:"${this.getKey()}" refreshes p:"${resource.getKey()}"`
23506
+ `[RP] c:"${this.getKey()}" refreshes p:"${resource.getKey()}" mode:${attachment.syncMode}`
23352
23507
  );
23353
23508
  } catch (err) {
23354
23509
  logger.error(`[RP] c:"${this.getKey()}" err :`, err);
@@ -23482,7 +23637,7 @@ if (typeof globalThis !== "undefined") {
23482
23637
  };
23483
23638
  }
23484
23639
  const name = "@yorkie-js/react";
23485
- const version = "0.6.34";
23640
+ const version = "0.6.35";
23486
23641
  const pkg = {
23487
23642
  name,
23488
23643
  version