reptree 0.6.0 → 0.7.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/README.md CHANGED
@@ -33,9 +33,10 @@ const qa = company.newNamedChild("qa");
33
33
  // Create a vertex in another vertex
34
34
  const alice = qa.newChild();
35
35
 
36
- // Set properties
36
+ // Set properties (supports any JSON-serializable values)
37
37
  alice.setProperty("name", "Alice");
38
38
  alice.setProperty("age", 32);
39
+ alice.setProperty("meta", { department: "QA", skills: ["cypress", "playwright"], flags: { lead: false } });
39
40
 
40
41
  // Move the vertex inside a different vertex
41
42
  alice.moveTo(devs);
@@ -89,8 +90,7 @@ const logoFile = imagesFolder.newNamedChild("logo.png");
89
90
  logoFile.setProperties({
90
91
  type: "file",
91
92
  size: 15360,
92
- dimensions: "512x512",
93
- format: "png",
93
+ meta: { dimensions: "512x512", format: "png" },
94
94
  s3Path: "s3://my-bucket/images/logo.png",
95
95
  });
96
96
 
package/dist/index.cjs CHANGED
@@ -385,7 +385,7 @@ var TreeState = class {
385
385
  }
386
386
  };
387
387
 
388
- // src/uuid.ts
388
+ // src/utils/uuid.ts
389
389
  var removeDashes = (guid) => guid.replace(/-/g, "");
390
390
  function uuid() {
391
391
  return removeDashes(crypto.randomUUID());
@@ -555,7 +555,7 @@ var Vertex = class _Vertex {
555
555
  if (props && typeof props === "object" && "children" in props) {
556
556
  throw new Error("Passing children inside props is not supported at the moment");
557
557
  }
558
- const normalized = _Vertex.normalizePropsForCreation(props, name);
558
+ const normalized = _Vertex.normalizePropsForCreation(props);
559
559
  return this.tree.newNamedVertex(this.id, name, normalized);
560
560
  }
561
561
  setProperty(key, value) {
@@ -634,21 +634,32 @@ var Vertex = class _Vertex {
634
634
  * - Filters unsupported field types with a console warning
635
635
  * - When a name param is provided to newNamedChild, ignores conflicting name in props
636
636
  */
637
- static normalizePropsForCreation(props, explicitName) {
637
+ static normalizePropsForCreation(props) {
638
638
  if (!props) return null;
639
639
  const input = props;
640
640
  const out = {};
641
641
  const skipped = [];
642
+ const isJsonValue2 = (v) => {
643
+ if (v === null) return true;
644
+ const t = typeof v;
645
+ if (t === "string" || t === "number" || t === "boolean") return true;
646
+ if (Array.isArray(v)) return v.every(isJsonValue2);
647
+ if (t === "object") {
648
+ const proto = Object.getPrototypeOf(v);
649
+ if (proto !== Object.prototype && proto !== null) return false;
650
+ for (const val of Object.values(v)) {
651
+ if (!isJsonValue2(val)) return false;
652
+ }
653
+ return true;
654
+ }
655
+ return false;
656
+ };
642
657
  for (const [rawKey, rawValue] of Object.entries(input)) {
643
658
  if (rawValue === void 0) {
644
659
  continue;
645
660
  }
646
661
  if (rawKey === "children") continue;
647
662
  let key = rawKey;
648
- if (rawKey === "name" && explicitName !== void 0) {
649
- console.warn('newNamedChild: "name" in props is ignored because a name argument was provided');
650
- continue;
651
- }
652
663
  let value = rawValue;
653
664
  if (key === "_c") {
654
665
  if (value instanceof Date) {
@@ -659,23 +670,14 @@ var Vertex = class _Vertex {
659
670
  continue;
660
671
  }
661
672
  }
662
- const isPrimitive = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean";
663
- if (Array.isArray(value)) {
664
- if (!value.every(isPrimitive)) {
665
- skipped.push(rawKey);
666
- continue;
667
- }
668
- } else if (typeof value === "object" && value !== null) {
669
- skipped.push(rawKey);
670
- continue;
671
- } else if (!isPrimitive(value)) {
673
+ if (!isJsonValue2(value)) {
672
674
  skipped.push(rawKey);
673
675
  continue;
674
676
  }
675
677
  out[key] = value;
676
678
  }
677
679
  if (skipped.length > 0) {
678
- console.warn(`Some fields were skipped due to unsupported types: ${skipped.join(", ")}`);
680
+ throw new Error(`Unsupported property types for keys: ${skipped.join(", ")}`);
679
681
  }
680
682
  return Object.keys(out).length > 0 ? out : null;
681
683
  }
@@ -866,6 +868,61 @@ var StateVector = class _StateVector {
866
868
  }
867
869
  };
868
870
 
871
+ // src/utils/deepEqual.ts
872
+ function deepEqual(a, b) {
873
+ if (a === b) return true;
874
+ if (a === null || b === null) return a === b;
875
+ const ta = typeof a;
876
+ const tb = typeof b;
877
+ if (ta !== tb) return false;
878
+ if (ta !== "object") return false;
879
+ const aIsArr = Array.isArray(a);
880
+ const bIsArr = Array.isArray(b);
881
+ if (aIsArr || bIsArr) {
882
+ if (!(aIsArr && bIsArr)) return false;
883
+ if (a.length !== b.length) return false;
884
+ for (let i = 0; i < a.length; i++) {
885
+ if (!deepEqual(a[i], b[i])) return false;
886
+ }
887
+ return true;
888
+ }
889
+ const aProto = Object.getPrototypeOf(a);
890
+ const bProto = Object.getPrototypeOf(b);
891
+ if (aProto !== Object.prototype && aProto !== null || bProto !== Object.prototype && bProto !== null) {
892
+ return false;
893
+ }
894
+ const aKeys = Object.keys(a);
895
+ const bKeys = Object.keys(b);
896
+ if (aKeys.length !== bKeys.length) return false;
897
+ for (const key of aKeys) {
898
+ if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
899
+ if (!deepEqual(a[key], b[key])) return false;
900
+ }
901
+ return true;
902
+ }
903
+
904
+ // src/utils/isJsonValue.ts
905
+ function isJsonValue(v) {
906
+ if (v === void 0) return true;
907
+ if (v === null) return true;
908
+ const t = typeof v;
909
+ if (t === "string" || t === "number" || t === "boolean") return true;
910
+ if (t === "bigint" || t === "function" || t === "symbol") return false;
911
+ if (Array.isArray(v)) return v.every(isJsonValue);
912
+ if (t === "object") {
913
+ if (v instanceof Date) return false;
914
+ if (v instanceof Map || v instanceof Set || v instanceof RegExp) return false;
915
+ if (ArrayBuffer.isView(v)) return false;
916
+ const proto = Object.getPrototypeOf(v);
917
+ if (proto !== Object.prototype && proto !== null) return false;
918
+ for (const val of Object.values(v)) {
919
+ if (!isJsonValue(val)) return false;
920
+ }
921
+ return true;
922
+ }
923
+ return false;
924
+ }
925
+
869
926
  // src/RepTree.ts
870
927
  var _RepTree = class _RepTree {
871
928
  /**
@@ -1032,6 +1089,9 @@ var _RepTree = class _RepTree {
1032
1089
  this.moveVertex(vertexId, _RepTree.NULL_VERTEX_ID);
1033
1090
  }
1034
1091
  setTransientVertexProperty(vertexId, key, value) {
1092
+ if (!isJsonValue(value)) {
1093
+ throw new Error(`Unsupported transient property value for key "${key}"`);
1094
+ }
1035
1095
  this.lamportClock++;
1036
1096
  const op = newSetTransientVertexPropertyOp(this.lamportClock, this.peerId, vertexId, key, value);
1037
1097
  this.localOps.push(op);
@@ -1057,6 +1117,29 @@ var _RepTree = class _RepTree {
1057
1117
  vertex.clearAllTransientProperties();
1058
1118
  }
1059
1119
  setVertexProperty(vertexId, key, value) {
1120
+ const isJsonValue2 = (v) => {
1121
+ if (v === void 0) return true;
1122
+ if (v === null) return true;
1123
+ const t = typeof v;
1124
+ if (t === "string" || t === "number" || t === "boolean") return true;
1125
+ if (t === "bigint" || t === "function" || t === "symbol") return false;
1126
+ if (Array.isArray(v)) return v.every(isJsonValue2);
1127
+ if (t === "object") {
1128
+ if (v instanceof Date) return false;
1129
+ if (v instanceof Map || v instanceof Set || v instanceof RegExp) return false;
1130
+ if (ArrayBuffer.isView(v)) return false;
1131
+ const proto = Object.getPrototypeOf(v);
1132
+ if (proto !== Object.prototype && proto !== null) return false;
1133
+ for (const val of Object.values(v)) {
1134
+ if (!isJsonValue2(val)) return false;
1135
+ }
1136
+ return true;
1137
+ }
1138
+ return false;
1139
+ };
1140
+ if (!isJsonValue2(value)) {
1141
+ throw new Error(`Unsupported property value for key "${key}"`);
1142
+ }
1060
1143
  this.lamportClock++;
1061
1144
  const op = newSetVertexPropertyOp(this.lamportClock, this.peerId, vertexId, key, value);
1062
1145
  this.localOps.push(op);
@@ -1218,12 +1301,8 @@ var _RepTree = class _RepTree {
1218
1301
  }
1219
1302
  for (const propA of propertiesA) {
1220
1303
  const propB = propertiesB.find((p) => p.key === propA.key);
1221
- if (!propB) {
1222
- return false;
1223
- }
1224
- if (propA.value !== propB.value) {
1225
- return false;
1226
- }
1304
+ if (!propB) return false;
1305
+ if (!deepEqual(propA.value, propB.value)) return false;
1227
1306
  }
1228
1307
  }
1229
1308
  for (const childId of childrenA) {
@@ -1353,7 +1432,6 @@ var _RepTree = class _RepTree {
1353
1432
  }
1354
1433
  }
1355
1434
  }
1356
- // Non-LWW modify-property flow removed
1357
1435
  applyOperation(op) {
1358
1436
  if (isMoveVertexOp(op)) {
1359
1437
  this.applyMove(op);