reptree 0.5.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
@@ -26,7 +26,6 @@ __export(index_exports, {
26
26
  Vertex: () => Vertex,
27
27
  VertexState: () => VertexState,
28
28
  bindVertex: () => bindVertex,
29
- defaultAliases: () => defaultAliases,
30
29
  isAnyPropertyOp: () => isAnyPropertyOp,
31
30
  isMoveVertexOp: () => isMoveVertexOp,
32
31
  newMoveVertexOp: () => newMoveVertexOp,
@@ -355,7 +354,7 @@ var TreeState = class {
355
354
  const vertex = this.getVertex(vertexId);
356
355
  if (vertex) {
357
356
  for (const prop of vertex.getAllProperties()) {
358
- if (prop.key === "_n") {
357
+ if (prop.key === "name") {
359
358
  vertexName = prop.value;
360
359
  }
361
360
  const propPrefix = indent + (isLast ? " " : "\u2502 ") + "\u2022 ";
@@ -368,8 +367,8 @@ var TreeState = class {
368
367
  const sortedChildren = [...children].sort((a, b) => {
369
368
  const vertexA = this.getVertex(a);
370
369
  const vertexB = this.getVertex(b);
371
- const nameA = vertexA?.getProperty("_n");
372
- const nameB = vertexB?.getProperty("_n");
370
+ const nameA = vertexA?.getProperty("name");
371
+ const nameB = vertexB?.getProperty("name");
373
372
  if (nameA && nameB) {
374
373
  return nameA.localeCompare(nameB);
375
374
  }
@@ -386,37 +385,17 @@ var TreeState = class {
386
385
  }
387
386
  };
388
387
 
389
- // src/uuid.ts
388
+ // src/utils/uuid.ts
390
389
  var removeDashes = (guid) => guid.replace(/-/g, "");
391
390
  function uuid() {
392
391
  return removeDashes(crypto.randomUUID());
393
392
  }
394
393
 
395
394
  // src/reactive.ts
396
- var defaultAliases = [
397
- { publicKey: "name", internalKey: "_n" },
398
- {
399
- publicKey: "createdAt",
400
- internalKey: "_c",
401
- toPublic: (v) => typeof v === "string" ? new Date(v) : v,
402
- toInternal: (v) => v instanceof Date ? v.toISOString() : v
403
- }
404
- ];
405
- function buildAliasMaps(aliases) {
406
- const publicToInternal = /* @__PURE__ */ new Map();
407
- const internalToPublic = /* @__PURE__ */ new Map();
408
- for (const rule of aliases) {
409
- publicToInternal.set(rule.publicKey, rule);
410
- internalToPublic.set(rule.internalKey, rule);
411
- }
412
- return { publicToInternal, internalToPublic };
413
- }
414
395
  function bindVertex(tree, id, schemaOrOptions) {
415
- const isOptions = typeof schemaOrOptions === "object" && schemaOrOptions !== null && (Object.prototype.hasOwnProperty.call(schemaOrOptions, "aliases") || Object.prototype.hasOwnProperty.call(schemaOrOptions, "includeInternalKeys") || Object.prototype.hasOwnProperty.call(schemaOrOptions, "schema"));
396
+ const isOptions = typeof schemaOrOptions === "object" && schemaOrOptions !== null && (Object.prototype.hasOwnProperty.call(schemaOrOptions, "includeInternalKeys") || Object.prototype.hasOwnProperty.call(schemaOrOptions, "schema"));
416
397
  const options = isOptions ? schemaOrOptions : { schema: schemaOrOptions };
417
398
  const schema = options.schema;
418
- const aliases = options.aliases ?? defaultAliases;
419
- const { publicToInternal } = buildAliasMaps(aliases);
420
399
  const obj = {};
421
400
  Object.defineProperties(obj, {
422
401
  $vertex: { get: () => tree.getVertex(id), enumerable: false, configurable: true },
@@ -453,19 +432,14 @@ function bindVertex(tree, id, schemaOrOptions) {
453
432
  const transientProxy = new Proxy({}, {
454
433
  set(_, prop, value) {
455
434
  if (typeof prop === "string") {
456
- const rule = publicToInternal.get(prop);
457
- const internalKey = rule?.internalKey ?? prop;
458
- const internalValue = rule?.toInternal ? rule.toInternal(value) : value;
459
- tree.setTransientVertexProperty(id, internalKey, internalValue);
435
+ tree.setTransientVertexProperty(id, prop, value);
460
436
  }
461
437
  return true;
462
438
  },
463
439
  get(_, prop) {
464
440
  if (typeof prop !== "string") return void 0;
465
- const rule = publicToInternal.get(prop);
466
- const internalKey = rule?.internalKey ?? prop;
467
- const rawValue = tree.getVertexProperty(id, internalKey, true);
468
- return rule?.toPublic ? rule.toPublic(rawValue) : rawValue;
441
+ const rawValue = tree.getVertexProperty(id, prop, true);
442
+ return rawValue;
469
443
  }
470
444
  });
471
445
  fn(transientProxy);
@@ -495,10 +469,8 @@ function bindVertex(tree, id, schemaOrOptions) {
495
469
  if (prop in target) {
496
470
  return Reflect.get(target, prop, receiver);
497
471
  }
498
- const rule = publicToInternal.get(prop);
499
- const internalKey = rule?.internalKey ?? prop;
500
- const rawValue = tree.getVertexProperty(id, internalKey, true);
501
- return rule?.toPublic ? rule.toPublic(rawValue) : rawValue;
472
+ const rawValue = tree.getVertexProperty(id, prop, true);
473
+ return rawValue;
502
474
  },
503
475
  set(target, prop, value) {
504
476
  if (typeof prop !== "string") {
@@ -512,19 +484,14 @@ function bindVertex(tree, id, schemaOrOptions) {
512
484
  value = res.data;
513
485
  }
514
486
  }
515
- const rule = publicToInternal.get(prop);
516
- const internalKey = rule?.internalKey ?? prop;
517
- const internalValue = rule?.toInternal ? rule.toInternal(value) : value;
518
- tree.setVertexProperty(id, internalKey, internalValue);
487
+ tree.setVertexProperty(id, prop, value);
519
488
  return true;
520
489
  },
521
490
  deleteProperty(_target, prop) {
522
491
  if (typeof prop !== "string") {
523
492
  return true;
524
493
  }
525
- const rule = publicToInternal.get(prop);
526
- const internalKey = rule?.internalKey ?? prop;
527
- tree.setVertexProperty(id, internalKey, void 0);
494
+ tree.setVertexProperty(id, prop, void 0);
528
495
  return true;
529
496
  }
530
497
  });
@@ -541,10 +508,10 @@ var Vertex = class _Vertex {
541
508
  return this.state.id;
542
509
  }
543
510
  get name() {
544
- return this.getProperty("_n");
511
+ return this.getProperty("name");
545
512
  }
546
513
  set name(name) {
547
- this.tree.setVertexProperty(this.id, "_n", name);
514
+ this.tree.setVertexProperty(this.id, "name", name);
548
515
  }
549
516
  get createdAt() {
550
517
  const createdAt = this.getProperty("_c");
@@ -588,7 +555,7 @@ var Vertex = class _Vertex {
588
555
  if (props && typeof props === "object" && "children" in props) {
589
556
  throw new Error("Passing children inside props is not supported at the moment");
590
557
  }
591
- const normalized = _Vertex.normalizePropsForCreation(props, name);
558
+ const normalized = _Vertex.normalizePropsForCreation(props);
592
559
  return this.tree.newNamedVertex(this.id, name, normalized);
593
560
  }
594
561
  setProperty(key, value) {
@@ -664,30 +631,35 @@ var Vertex = class _Vertex {
664
631
  }
665
632
  /**
666
633
  * Normalizes an input props object for vertex creation:
667
- * - Aliases name -> _n, createdAt -> _c (Date -> ISO string)
668
634
  * - Filters unsupported field types with a console warning
669
635
  * - When a name param is provided to newNamedChild, ignores conflicting name in props
670
636
  */
671
- static normalizePropsForCreation(props, explicitName) {
637
+ static normalizePropsForCreation(props) {
672
638
  if (!props) return null;
673
639
  const input = props;
674
640
  const out = {};
675
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
+ };
676
657
  for (const [rawKey, rawValue] of Object.entries(input)) {
677
658
  if (rawValue === void 0) {
678
659
  continue;
679
660
  }
680
661
  if (rawKey === "children") continue;
681
662
  let key = rawKey;
682
- if (rawKey === "name") {
683
- if (explicitName !== void 0) {
684
- console.warn('newNamedChild: "name" in props is ignored because a name argument was provided');
685
- continue;
686
- }
687
- key = "_n";
688
- } else if (rawKey === "createdAt") {
689
- key = "_c";
690
- }
691
663
  let value = rawValue;
692
664
  if (key === "_c") {
693
665
  if (value instanceof Date) {
@@ -698,23 +670,14 @@ var Vertex = class _Vertex {
698
670
  continue;
699
671
  }
700
672
  }
701
- const isPrimitive = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean";
702
- if (Array.isArray(value)) {
703
- if (!value.every(isPrimitive)) {
704
- skipped.push(rawKey);
705
- continue;
706
- }
707
- } else if (typeof value === "object" && value !== null) {
708
- skipped.push(rawKey);
709
- continue;
710
- } else if (!isPrimitive(value)) {
673
+ if (!isJsonValue2(value)) {
711
674
  skipped.push(rawKey);
712
675
  continue;
713
676
  }
714
677
  out[key] = value;
715
678
  }
716
679
  if (skipped.length > 0) {
717
- console.warn(`Some fields were skipped due to unsupported types: ${skipped.join(", ")}`);
680
+ throw new Error(`Unsupported property types for keys: ${skipped.join(", ")}`);
718
681
  }
719
682
  return Object.keys(out).length > 0 ? out : null;
720
683
  }
@@ -905,6 +868,61 @@ var StateVector = class _StateVector {
905
868
  }
906
869
  };
907
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
+
908
926
  // src/RepTree.ts
909
927
  var _RepTree = class _RepTree {
910
928
  /**
@@ -1054,7 +1072,7 @@ var _RepTree = class _RepTree {
1054
1072
  if (typedProps) {
1055
1073
  this.setVertexProperties(vertexId, typedProps);
1056
1074
  }
1057
- this.setVertexProperty(vertexId, "_n", name);
1075
+ this.setVertexProperty(vertexId, "name", name);
1058
1076
  const vertex = this.state.getVertex(vertexId);
1059
1077
  if (!vertex) {
1060
1078
  throw new Error("Failed to create named vertex");
@@ -1071,6 +1089,9 @@ var _RepTree = class _RepTree {
1071
1089
  this.moveVertex(vertexId, _RepTree.NULL_VERTEX_ID);
1072
1090
  }
1073
1091
  setTransientVertexProperty(vertexId, key, value) {
1092
+ if (!isJsonValue(value)) {
1093
+ throw new Error(`Unsupported transient property value for key "${key}"`);
1094
+ }
1074
1095
  this.lamportClock++;
1075
1096
  const op = newSetTransientVertexPropertyOp(this.lamportClock, this.peerId, vertexId, key, value);
1076
1097
  this.localOps.push(op);
@@ -1096,6 +1117,29 @@ var _RepTree = class _RepTree {
1096
1117
  vertex.clearAllTransientProperties();
1097
1118
  }
1098
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
+ }
1099
1143
  this.lamportClock++;
1100
1144
  const op = newSetVertexPropertyOp(this.lamportClock, this.peerId, vertexId, key, value);
1101
1145
  this.localOps.push(op);
@@ -1128,7 +1172,7 @@ var _RepTree = class _RepTree {
1128
1172
  const targetName = path[0];
1129
1173
  const children = this.getChildren(vertex.id);
1130
1174
  for (const child of children) {
1131
- if (child.getProperty("_n") === targetName) {
1175
+ if (child.getProperty("name") === targetName) {
1132
1176
  return this.getVertexByPathArray(child, path.slice(1));
1133
1177
  }
1134
1178
  }
@@ -1257,12 +1301,8 @@ var _RepTree = class _RepTree {
1257
1301
  }
1258
1302
  for (const propA of propertiesA) {
1259
1303
  const propB = propertiesB.find((p) => p.key === propA.key);
1260
- if (!propB) {
1261
- return false;
1262
- }
1263
- if (propA.value !== propB.value) {
1264
- return false;
1265
- }
1304
+ if (!propB) return false;
1305
+ if (!deepEqual(propA.value, propB.value)) return false;
1266
1306
  }
1267
1307
  }
1268
1308
  for (const childId of childrenA) {
@@ -1392,7 +1432,6 @@ var _RepTree = class _RepTree {
1392
1432
  }
1393
1433
  }
1394
1434
  }
1395
- // Non-LWW modify-property flow removed
1396
1435
  applyOperation(op) {
1397
1436
  if (isMoveVertexOp(op)) {
1398
1437
  this.applyMove(op);
@@ -1516,7 +1555,6 @@ var RepTree = _RepTree;
1516
1555
  Vertex,
1517
1556
  VertexState,
1518
1557
  bindVertex,
1519
- defaultAliases,
1520
1558
  isAnyPropertyOp,
1521
1559
  isMoveVertexOp,
1522
1560
  newMoveVertexOp,