@yorkie-js/sdk 0.7.6 → 0.7.7

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.
@@ -3716,6 +3716,19 @@ declare function isDate(value: any): value is YSONDate {
3716
3716
  );
3717
3717
  }
3718
3718
 
3719
+ /**
3720
+ * `isDedupCounter` checks if a value is a YSONDedupCounter object.
3721
+ */
3722
+ declare function isDedupCounter(value: any): value is YSONDedupCounter {
3723
+ return (
3724
+ typeof value === 'object' &&
3725
+ value !== null &&
3726
+ value.type === 'DedupCounter' &&
3727
+ typeof value.value === 'object' &&
3728
+ typeof value.registers === 'string'
3729
+ );
3730
+ }
3731
+
3719
3732
  /**
3720
3733
  * `isDocEventForReplay` checks if an event can be used to replay a document.
3721
3734
  */
@@ -3783,7 +3796,8 @@ declare function isObject(value: any): value is { [key: string]: YSONValue } {
3783
3796
  !isLong(value) &&
3784
3797
  !isDate(value) &&
3785
3798
  !isBinData(value) &&
3786
- !isCounter(value)
3799
+ !isCounter(value) &&
3800
+ !isDedupCounter(value)
3787
3801
  );
3788
3802
  }
3789
3803
 
@@ -7019,6 +7033,7 @@ declare namespace YSON {
7019
7033
  YSONDate as Date,
7020
7034
  YSONBinData as BinData,
7021
7035
  YSONCounter as Counter,
7036
+ YSONDedupCounter as DedupCounter,
7022
7037
  isText,
7023
7038
  isTree,
7024
7039
  isInt,
@@ -7026,6 +7041,7 @@ declare namespace YSON {
7026
7041
  isDate,
7027
7042
  isBinData,
7028
7043
  isCounter,
7044
+ isDedupCounter,
7029
7045
  isObject,
7030
7046
  parse,
7031
7047
  textToString,
@@ -7073,6 +7089,21 @@ declare interface YSONDate {
7073
7089
  value: string;
7074
7090
  }
7075
7091
 
7092
+ /**
7093
+ * `YSONDedupCounter` represents a DedupCounter CRDT that uses HyperLogLog
7094
+ * to count unique actors.
7095
+ *
7096
+ * @example
7097
+ * ```typescript
7098
+ * { type: 'DedupCounter', value: { type: 'Int', value: 15 }, registers: 'AQID...' }
7099
+ * ```
7100
+ */
7101
+ declare interface YSONDedupCounter {
7102
+ type: 'DedupCounter';
7103
+ value: YSONInt;
7104
+ registers: string;
7105
+ }
7106
+
7076
7107
  /**
7077
7108
  * `YSONInt` represents a 32-bit integer.
7078
7109
  *
@@ -7209,6 +7240,7 @@ declare type YSONValue =
7209
7240
  | YSONDate
7210
7241
  | YSONBinData
7211
7242
  | YSONCounter
7243
+ | YSONDedupCounter
7212
7244
  | { [key: string]: YSONValue }
7213
7245
  | Array<YSONValue>;
7214
7246
 
@@ -11130,6 +11130,32 @@ class IndexTreeNode {
11130
11130
  }
11131
11131
  actualRight.push(child);
11132
11132
  }
11133
+ if (versionVector) {
11134
+ const movedToLeft = [];
11135
+ const remaining = [];
11136
+ let boundaryReached = false;
11137
+ for (const child of actualRight) {
11138
+ if (!boundaryReached) {
11139
+ if (child.insPrevID !== void 0 && !child.isText) {
11140
+ remaining.push(child);
11141
+ continue;
11142
+ }
11143
+ const actorID = child.id.getCreatedAt().getActorID();
11144
+ const knownLamport = versionVector.get(actorID);
11145
+ if (knownLamport === void 0 || knownLamport < child.id.getCreatedAt().getLamport()) {
11146
+ movedToLeft.push(child);
11147
+ continue;
11148
+ }
11149
+ }
11150
+ boundaryReached = true;
11151
+ remaining.push(child);
11152
+ }
11153
+ if (movedToLeft.length > 0) {
11154
+ left.push(...movedToLeft);
11155
+ actualRight.length = 0;
11156
+ actualRight.push(...remaining);
11157
+ }
11158
+ }
11133
11159
  this._children = left;
11134
11160
  clone._children = actualRight;
11135
11161
  this.visibleSize = this._children.reduce(
@@ -11906,8 +11932,14 @@ class CRDTTreeNode extends IndexTreeNode {
11906
11932
  split.insPrevID = this.id;
11907
11933
  if (this.insNextID) {
11908
11934
  const insNext = tree.findFloorNode(this.insNextID);
11909
- insNext.insPrevID = split.id;
11910
11935
  split.insNextID = this.insNextID;
11936
+ if (insNext) {
11937
+ insNext.insPrevID = split.id;
11938
+ if (!this.isText && insNext.parent && !insNext.isRemoved && insNext.parent !== split.parent && split.allChildren.length === 0) {
11939
+ split.parent.detachChild(split);
11940
+ insNext.parent.insertBefore(split, insNext);
11941
+ }
11942
+ }
11911
11943
  }
11912
11944
  this.insNextID = split.id;
11913
11945
  tree.registerNode(split);
@@ -12131,7 +12163,7 @@ class CRDTTree extends CRDTElement {
12131
12163
  * given node, advancing past element-type split siblings that the editing
12132
12164
  * client did not know about (not in versionVector).
12133
12165
  */
12134
- advancePastUnknownSplitSiblings(node, versionVector) {
12166
+ advancePastUnknownSplitSiblings(node, versionVector, relaxParentCheck = false, skipActorID) {
12135
12167
  if (!versionVector || !node) {
12136
12168
  return node;
12137
12169
  }
@@ -12141,10 +12173,13 @@ class CRDTTree extends CRDTElement {
12141
12173
  if (!next || next.isText) {
12142
12174
  break;
12143
12175
  }
12144
- if (next.parent !== current.parent) {
12176
+ if (!relaxParentCheck && next.parent !== current.parent) {
12145
12177
  break;
12146
12178
  }
12147
12179
  const actorID = next.id.getCreatedAt().getActorID();
12180
+ if (skipActorID !== void 0 && actorID === skipActorID) {
12181
+ break;
12182
+ }
12148
12183
  const knownLamport = versionVector.get(actorID);
12149
12184
  if (knownLamport !== void 0 && knownLamport >= next.id.getCreatedAt().getLamport()) {
12150
12185
  break;
@@ -12485,6 +12520,23 @@ class CRDTTree extends CRDTElement {
12485
12520
  addDataSizes(diff, diffTo, diffFrom);
12486
12521
  const fromLeft = fromLeftRaw !== fromParent ? this.advancePastUnknownSplitSiblings(fromLeftRaw, versionVector) : fromLeftRaw;
12487
12522
  const toLeft = toLeftRaw !== toParent ? this.advancePastUnknownSplitSiblings(toLeftRaw, versionVector) : toLeftRaw;
12523
+ let collectFromParent = fromParent;
12524
+ let collectFromLeft = fromLeft;
12525
+ if (fromLeft !== fromParent && fromParent !== toParent) {
12526
+ let current = fromLeft;
12527
+ while (current.insNextID) {
12528
+ const next = this.findFloorNode(current.insNextID);
12529
+ if (!next || next.isText) {
12530
+ break;
12531
+ }
12532
+ if (next.parent && next.parent === toParent) {
12533
+ collectFromLeft = next;
12534
+ collectFromParent = toParent;
12535
+ break;
12536
+ }
12537
+ current = next;
12538
+ }
12539
+ }
12488
12540
  const fromIdx = this.toIndex(fromParent, fromLeft);
12489
12541
  const fromPath = this.toPath(fromParent, fromLeft);
12490
12542
  const nodesToBeRemoved = [];
@@ -12493,8 +12545,8 @@ class CRDTTree extends CRDTElement {
12493
12545
  const toBeMergedNodes = [];
12494
12546
  const preTombstoned = /* @__PURE__ */ new Set();
12495
12547
  this.traverseInPosRange(
12496
- fromParent,
12497
- fromLeft,
12548
+ collectFromParent,
12549
+ collectFromLeft,
12498
12550
  toParent,
12499
12551
  toLeft,
12500
12552
  ([node, tokenType], ended) => {
@@ -12598,9 +12650,20 @@ class CRDTTree extends CRDTElement {
12598
12650
  let parent = fromParent;
12599
12651
  let left = fromLeft;
12600
12652
  while (splitCount < splitLevel) {
12653
+ if (left !== parent) {
12654
+ left = this.advancePastUnknownSplitSiblings(
12655
+ left,
12656
+ versionVector,
12657
+ true,
12658
+ editedAt.getActorID()
12659
+ );
12660
+ if (left.parent && left.parent !== parent) {
12661
+ parent = left.parent;
12662
+ }
12663
+ }
12601
12664
  parent.split(
12602
12665
  this,
12603
- parent.findOffset(left, true) + 1,
12666
+ left !== parent ? parent.findOffset(left, true) + 1 : 0,
12604
12667
  issueTimeTicket,
12605
12668
  versionVector
12606
12669
  );
@@ -13207,10 +13270,10 @@ class TreeEditOperation extends Operation {
13207
13270
  );
13208
13271
  this.lastToIdx = preEditFromIdx + removedSize;
13209
13272
  let reverseOp;
13210
- const isPureL1Split = this.splitLevel === 1 && !this.contents?.length && removedNodes.length === 0;
13273
+ const isPureSplit = this.splitLevel > 0 && !this.contents?.length && removedNodes.length === 0;
13211
13274
  if (this.splitLevel === 0) {
13212
13275
  reverseOp = this.toReverseOperation(tree, removedNodes, preEditFromIdx);
13213
- } else if (isPureL1Split) {
13276
+ } else if (isPureSplit) {
13214
13277
  reverseOp = this.toSplitReverseOperation(tree, preEditFromIdx);
13215
13278
  }
13216
13279
  root.acc(diff);
@@ -20811,7 +20874,7 @@ function createAuthInterceptor(apiKey, token) {
20811
20874
  };
20812
20875
  }
20813
20876
  const name = "@yorkie-js/sdk";
20814
- const version = "0.7.6";
20877
+ const version = "0.7.7";
20815
20878
  const pkg = {
20816
20879
  name,
20817
20880
  version
@@ -22527,8 +22590,11 @@ function isBinData(value) {
22527
22590
  function isCounter(value) {
22528
22591
  return typeof value === "object" && value !== null && value.type === "Counter" && typeof value.value === "object";
22529
22592
  }
22593
+ function isDedupCounter(value) {
22594
+ return typeof value === "object" && value !== null && value.type === "DedupCounter" && typeof value.value === "object" && typeof value.registers === "string";
22595
+ }
22530
22596
  function isObject(value) {
22531
- return typeof value === "object" && value !== null && !Array.isArray(value) && !isText(value) && !isTree(value) && !isInt(value) && !isLong(value) && !isDate(value) && !isBinData(value) && !isCounter(value);
22597
+ return typeof value === "object" && value !== null && !Array.isArray(value) && !isText(value) && !isTree(value) && !isInt(value) && !isLong(value) && !isDate(value) && !isBinData(value) && !isCounter(value) && !isDedupCounter(value);
22532
22598
  }
22533
22599
  function parse(yson) {
22534
22600
  try {
@@ -22544,6 +22610,12 @@ function parse(yson) {
22544
22610
  }
22545
22611
  function preprocessYSON(yson) {
22546
22612
  let result = yson;
22613
+ result = result.replace(
22614
+ /DedupCounter\(Int\((-?\d+)\),"([^"]+)"\)/g,
22615
+ (_, value, registers) => {
22616
+ return `{"__yson_type":"DedupCounter","__yson_data":{"__yson_type":"Int","__yson_data":${value}},"__yson_registers":"${registers}"}`;
22617
+ }
22618
+ );
22547
22619
  result = result.replace(
22548
22620
  /Counter\((Int|Long)\((-?\d+)\)\)/g,
22549
22621
  (_, type, value) => {
@@ -22604,6 +22676,20 @@ function postprocessValue(value) {
22604
22676
  value: value.__yson_data
22605
22677
  };
22606
22678
  }
22679
+ if (value.__yson_type === "DedupCounter" && typeof value.__yson_data === "object" && typeof value.__yson_registers === "string") {
22680
+ const counterValue = postprocessValue(value.__yson_data);
22681
+ if (typeof counterValue === "object" && counterValue !== null && "type" in counterValue && counterValue.type === "Int") {
22682
+ return {
22683
+ type: "DedupCounter",
22684
+ value: counterValue,
22685
+ registers: value.__yson_registers
22686
+ };
22687
+ }
22688
+ throw new YorkieError(
22689
+ Code.ErrInvalidArgument,
22690
+ "DedupCounter must contain Int"
22691
+ );
22692
+ }
22607
22693
  if (value.__yson_type === "Counter" && typeof value.__yson_data === "object") {
22608
22694
  const counterValue = postprocessValue(value.__yson_data);
22609
22695
  if (typeof counterValue === "object" && counterValue !== null && "type" in counterValue && (counterValue.type === "Int" || counterValue.type === "Long")) {
@@ -22692,6 +22778,7 @@ const YSON = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty
22692
22778
  isBinData,
22693
22779
  isCounter,
22694
22780
  isDate,
22781
+ isDedupCounter,
22695
22782
  isInt,
22696
22783
  isLong,
22697
22784
  isObject,