reptree 0.3.0 → 0.4.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/dist/index.cjs CHANGED
@@ -187,6 +187,12 @@ var VertexState = class {
187
187
  removeTransientProperty(key) {
188
188
  this.transientProperties = this.transientProperties.filter((p) => p.key !== key);
189
189
  }
190
+ getTransientProperties() {
191
+ return this.transientProperties;
192
+ }
193
+ clearAllTransientProperties() {
194
+ this.transientProperties = [];
195
+ }
190
196
  };
191
197
 
192
198
  // src/TreeState.ts
@@ -423,263 +429,124 @@ function buildAliasMaps(aliases) {
423
429
  }
424
430
  return { publicToInternal, internalToPublic };
425
431
  }
426
- function toPublicObject(tree, id, internalToPublic) {
427
- const obj = {};
428
- for (const { key, value } of tree.getVertexProperties(id)) {
429
- const rule = internalToPublic.get(key);
430
- if (rule) {
431
- const converted = rule.toPublic ? rule.toPublic(value) : value;
432
- obj[rule.publicKey] = converted;
433
- } else {
434
- obj[key] = value;
435
- }
436
- }
437
- return obj;
438
- }
439
- var RESERVED_METHOD_USE_TRANSIENT = "useTransient";
440
- var RESERVED_METHOD_COMMIT_TRANSIENTS = "commitTransients";
441
- var VERTEX_PROPS = ["$id", "$parentId", "$parent", "$children", "$childrenIds"];
442
- var VERTEX_METHODS = ["$moveTo", "$delete", "$observe", "$observeChildren", "$newChild", "$newNamedChild"];
443
432
  function bindVertex(tree, id, schemaOrOptions) {
444
433
  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"));
445
434
  const options = isOptions ? schemaOrOptions : { schema: schemaOrOptions };
446
435
  const schema = options.schema;
447
436
  const aliases = options.aliases ?? defaultAliases;
448
- const includeInternalKeys = options.includeInternalKeys ?? false;
449
- const { publicToInternal, internalToPublic } = buildAliasMaps(aliases);
450
- const cachedMethods = /* @__PURE__ */ new Map();
451
- return new Proxy({}, {
452
- get(_target, prop) {
453
- if (prop === RESERVED_METHOD_USE_TRANSIENT) {
454
- return (fn) => {
455
- const transientProxy = new Proxy({}, {
456
- get(_t, p) {
457
- if (typeof p !== "string") return void 0;
458
- const rule2 = publicToInternal.get(p);
459
- if (rule2) {
460
- const raw = tree.getVertexProperty(id, rule2.internalKey);
461
- return rule2.toPublic ? rule2.toPublic(raw) : raw;
462
- }
463
- return tree.getVertexProperty(id, p);
464
- },
465
- set(_t, p, value) {
466
- if (typeof p !== "string") return true;
467
- if (schema?.shape && schema.shape[p]) {
468
- const field = schema.shape[p];
469
- if (field.safeParse) {
470
- const res = field.safeParse(value);
471
- if (!res.success) throw new Error(`Invalid value for ${String(p)}`);
472
- value = res.data ?? value;
473
- }
474
- } else if (schema?.safeParse) {
475
- const next = { ...toPublicObject(tree, id, internalToPublic), [p]: value };
476
- const res = schema.safeParse(next);
477
- if (!res.success) throw new Error(`Invalid value for ${String(p)}`);
478
- const parsed = res.data;
479
- if (parsed && Object.prototype.hasOwnProperty.call(parsed, p)) {
480
- value = parsed[p];
481
- }
482
- }
483
- const rule2 = publicToInternal.get(p);
484
- if (rule2) {
485
- const converted = rule2.toInternal ? rule2.toInternal(value) : value;
486
- tree.setTransientVertexProperty(id, rule2.internalKey, converted);
487
- return true;
488
- }
489
- tree.setTransientVertexProperty(id, p, value);
490
- return true;
491
- },
492
- deleteProperty(_t, p) {
493
- if (typeof p !== "string") return true;
494
- const rule2 = publicToInternal.get(p);
495
- if (rule2) {
496
- tree.setTransientVertexProperty(id, rule2.internalKey, void 0);
497
- return true;
498
- }
499
- tree.setTransientVertexProperty(id, p, void 0);
500
- return true;
501
- }
502
- });
503
- fn(transientProxy);
504
- };
505
- }
506
- if (prop === RESERVED_METHOD_COMMIT_TRANSIENTS) {
507
- return () => {
508
- const entries = tree.getVertexProperties(id);
509
- const currentPublic = schema?.safeParse ? toPublicObject(tree, id, internalToPublic) : void 0;
510
- for (const { key: internalKey, value: overlayValue } of entries) {
511
- const persistentValue = tree.getVertexProperty(id, internalKey, false);
512
- if (overlayValue === persistentValue) continue;
513
- const aliasRule = internalToPublic.get(internalKey);
514
- const publicKey = aliasRule ? aliasRule.publicKey : internalKey;
515
- const publicValue = aliasRule && aliasRule.toPublic ? aliasRule.toPublic(overlayValue) : overlayValue;
516
- let valueToPersistInternal = overlayValue;
517
- if (schema?.shape && schema.shape[publicKey]) {
518
- const field = schema.shape[publicKey];
519
- if (field.safeParse) {
520
- const res = field.safeParse(publicValue);
521
- if (!res.success) throw new Error(`Invalid value for ${String(publicKey)}`);
522
- const coerced = res.data;
523
- const maybeInternal = aliasRule && aliasRule.toInternal ? aliasRule.toInternal(coerced) : coerced;
524
- valueToPersistInternal = maybeInternal;
525
- }
526
- } else if (schema?.safeParse && currentPublic) {
527
- const nextPublic = { ...currentPublic, [publicKey]: publicValue };
528
- const res = schema.safeParse(nextPublic);
529
- if (!res.success) throw new Error("Invalid values for commitTransients");
530
- const parsed = res.data;
531
- const parsedPublic = Object.prototype.hasOwnProperty.call(parsed, publicKey) ? parsed[publicKey] : publicValue;
532
- const maybeInternal = aliasRule && aliasRule.toInternal ? aliasRule.toInternal(parsedPublic) : parsedPublic;
533
- valueToPersistInternal = maybeInternal;
534
- }
535
- tree.setVertexProperty(id, internalKey, valueToPersistInternal);
536
- }
537
- };
538
- }
539
- if (typeof prop === "string") {
540
- if (prop === "$id") return id;
541
- if (prop === "$parentId") return tree.getVertex(id)?.parentId ?? null;
542
- if (prop === "$parent") {
543
- const vertex = tree.getVertex(id);
544
- return vertex?.parent;
545
- }
546
- if (prop === "$children") return tree.getChildren(id);
547
- if (prop === "$childrenIds") return tree.getChildrenIds(id);
548
- if (prop === "$moveTo") {
549
- if (!cachedMethods.has(prop)) {
550
- cachedMethods.set(prop, (parent) => {
551
- const parentId = typeof parent === "object" && parent !== null ? parent.id || parent.$id : parent;
552
- tree.moveVertex(id, parentId);
553
- });
554
- }
555
- return cachedMethods.get(prop);
556
- }
557
- if (prop === "$delete") {
558
- if (!cachedMethods.has(prop)) {
559
- cachedMethods.set(prop, () => tree.deleteVertex(id));
560
- }
561
- return cachedMethods.get(prop);
562
- }
563
- if (prop === "$observe") {
564
- if (!cachedMethods.has(prop)) {
565
- cachedMethods.set(prop, (listener) => tree.observe(id, listener));
566
- }
567
- return cachedMethods.get(prop);
568
- }
569
- if (prop === "$observeChildren") {
570
- if (!cachedMethods.has(prop)) {
571
- cachedMethods.set(prop, (listener) => {
572
- return tree.observe(id, (events) => {
573
- if (events.some((e) => e.type === "children")) {
574
- listener(tree.getChildren(id));
575
- }
576
- });
577
- });
578
- }
579
- return cachedMethods.get(prop);
580
- }
581
- if (prop === "$newChild") {
582
- if (!cachedMethods.has(prop)) {
583
- cachedMethods.set(prop, (props) => {
584
- const vertex = tree.getVertex(id);
585
- return vertex?.newChild(props);
586
- });
587
- }
588
- return cachedMethods.get(prop);
437
+ const { publicToInternal } = buildAliasMaps(aliases);
438
+ const obj = {};
439
+ Object.defineProperties(obj, {
440
+ $vertex: { get: () => tree.getVertex(id), enumerable: false, configurable: true },
441
+ $id: { get: () => id, enumerable: false, configurable: true },
442
+ $parentId: { get: () => tree.getVertex(id)?.parentId ?? null, enumerable: false, configurable: true },
443
+ $parent: { get: () => tree.getVertex(id)?.parent, enumerable: false, configurable: true },
444
+ $children: { get: () => tree.getChildren(id), enumerable: false, configurable: true },
445
+ $childrenIds: { get: () => tree.getChildrenIds(id), enumerable: false, configurable: true },
446
+ $moveTo: {
447
+ value: (parent) => {
448
+ const parentId = typeof parent === "object" && parent !== null ? parent.id || parent.$id : parent;
449
+ tree.moveVertex(id, parentId);
450
+ },
451
+ enumerable: false,
452
+ configurable: true,
453
+ writable: false
454
+ },
455
+ $delete: { value: () => tree.deleteVertex(id), enumerable: false, configurable: true, writable: false },
456
+ $observe: { value: (listener) => tree.observe(id, listener), enumerable: false, configurable: true, writable: false },
457
+ $observeChildren: {
458
+ value: (listener) => tree.observe(id, (events) => {
459
+ if (events.some((e) => e.type === "children")) {
460
+ listener(tree.getChildren(id));
589
461
  }
590
- if (prop === "$newNamedChild") {
591
- if (!cachedMethods.has(prop)) {
592
- cachedMethods.set(prop, (name, props) => {
593
- const vertex = tree.getVertex(id);
594
- return vertex?.newNamedChild(name, props);
595
- });
462
+ }),
463
+ enumerable: false,
464
+ configurable: true,
465
+ writable: false
466
+ },
467
+ $newChild: { value: (props) => tree.getVertex(id).newChild(props), enumerable: false, configurable: true, writable: false },
468
+ $newNamedChild: { value: (name, props) => tree.getVertex(id).newNamedChild(name, props), enumerable: false, configurable: true, writable: false },
469
+ $useTransients: {
470
+ value: function(fn) {
471
+ const transientProxy = new Proxy({}, {
472
+ set(_, prop, value) {
473
+ if (typeof prop === "string") {
474
+ const rule = publicToInternal.get(prop);
475
+ const internalKey = rule?.internalKey ?? prop;
476
+ const internalValue = rule?.toInternal ? rule.toInternal(value) : value;
477
+ tree.setTransientVertexProperty(id, internalKey, internalValue);
478
+ }
479
+ return true;
480
+ },
481
+ get(_, prop) {
482
+ if (typeof prop !== "string") return void 0;
483
+ const rule = publicToInternal.get(prop);
484
+ const internalKey = rule?.internalKey ?? prop;
485
+ const rawValue = tree.getVertexProperty(id, internalKey, true);
486
+ return rule?.toPublic ? rule.toPublic(rawValue) : rawValue;
596
487
  }
597
- return cachedMethods.get(prop);
488
+ });
489
+ fn(transientProxy);
490
+ },
491
+ enumerable: false,
492
+ configurable: true,
493
+ writable: false
494
+ },
495
+ $commitTransients: { value: () => tree.commitTransients(id), enumerable: false, configurable: true, writable: false },
496
+ equals: {
497
+ value: function(other) {
498
+ if (other && typeof other === "object" && "$id" in other) {
499
+ return other.$id === id;
598
500
  }
501
+ return false;
502
+ },
503
+ enumerable: false,
504
+ configurable: true,
505
+ writable: false
506
+ }
507
+ });
508
+ const proxy = new Proxy(obj, {
509
+ get(target, prop, receiver) {
510
+ if (typeof prop !== "string") {
511
+ return Reflect.get(target, prop, receiver);
599
512
  }
600
- if (typeof prop !== "string") return void 0;
601
- const rule = publicToInternal.get(prop);
602
- if (rule) {
603
- const raw = tree.getVertexProperty(id, rule.internalKey);
604
- return rule.toPublic ? rule.toPublic(raw) : raw;
513
+ if (prop in target) {
514
+ return Reflect.get(target, prop, receiver);
605
515
  }
606
- return tree.getVertexProperty(id, prop);
516
+ const rule = publicToInternal.get(prop);
517
+ const internalKey = rule?.internalKey ?? prop;
518
+ const rawValue = tree.getVertexProperty(id, internalKey, true);
519
+ return rule?.toPublic ? rule.toPublic(rawValue) : rawValue;
607
520
  },
608
- set(_target, prop, value) {
609
- if (typeof prop !== "string") return true;
610
- if (prop === RESERVED_METHOD_USE_TRANSIENT || prop === RESERVED_METHOD_COMMIT_TRANSIENTS) {
611
- return true;
612
- }
613
- if (VERTEX_PROPS.includes(prop)) {
614
- return true;
615
- }
616
- if (VERTEX_METHODS.includes(prop)) {
617
- return true;
521
+ set(target, prop, value) {
522
+ if (typeof prop !== "string") {
523
+ return Reflect.set(target, prop, value);
618
524
  }
619
525
  if (schema?.shape && schema.shape[prop]) {
620
526
  const field = schema.shape[prop];
621
527
  if (field.safeParse) {
622
528
  const res = field.safeParse(value);
623
- if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);
624
- value = res.data ?? value;
625
- }
626
- } else if (schema?.safeParse) {
627
- const next = { ...toPublicObject(tree, id, internalToPublic), [prop]: value };
628
- const res = schema.safeParse(next);
629
- if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);
630
- const parsed = res.data;
631
- if (parsed && Object.prototype.hasOwnProperty.call(parsed, prop)) {
632
- value = parsed[prop];
529
+ if (!res.success) throw new Error(`Invalid value for ${prop}`);
530
+ value = res.data;
633
531
  }
634
532
  }
635
533
  const rule = publicToInternal.get(prop);
636
- if (rule) {
637
- const converted = rule.toInternal ? rule.toInternal(value) : value;
638
- tree.setVertexProperty(id, rule.internalKey, converted);
639
- return true;
640
- }
641
- tree.setVertexProperty(id, prop, value);
534
+ const internalKey = rule?.internalKey ?? prop;
535
+ const internalValue = rule?.toInternal ? rule.toInternal(value) : value;
536
+ tree.setVertexProperty(id, internalKey, internalValue);
642
537
  return true;
643
538
  },
644
539
  deleteProperty(_target, prop) {
645
- if (typeof prop !== "string") return true;
646
- if (prop === RESERVED_METHOD_USE_TRANSIENT || prop === RESERVED_METHOD_COMMIT_TRANSIENTS) {
647
- return true;
648
- }
649
- if (VERTEX_PROPS.includes(prop)) {
650
- return true;
651
- }
652
- if (VERTEX_METHODS.includes(prop)) {
540
+ if (typeof prop !== "string") {
653
541
  return true;
654
542
  }
655
543
  const rule = publicToInternal.get(prop);
656
- if (rule) {
657
- tree.setVertexProperty(id, rule.internalKey, void 0);
658
- return true;
659
- }
660
- tree.setVertexProperty(id, prop, void 0);
544
+ const internalKey = rule?.internalKey ?? prop;
545
+ tree.setVertexProperty(id, internalKey, void 0);
661
546
  return true;
662
- },
663
- has(_target, prop) {
664
- if (typeof prop !== "string") return false;
665
- if (schema?.shape && Object.prototype.hasOwnProperty.call(schema.shape, prop)) return true;
666
- if (includeInternalKeys) {
667
- return publicToInternal.has(prop) || internalToPublic.has(prop);
668
- }
669
- return false;
670
- },
671
- ownKeys() {
672
- const keys = /* @__PURE__ */ new Set();
673
- for (const k of Object.keys(schema?.shape ?? {})) keys.add(k);
674
- if (includeInternalKeys) {
675
- for (const rule of aliases) keys.add(rule.internalKey);
676
- }
677
- return Array.from(keys);
678
- },
679
- getOwnPropertyDescriptor() {
680
- return { enumerable: true, configurable: true };
681
547
  }
682
548
  });
549
+ return proxy;
683
550
  }
684
551
 
685
552
  // src/Vertex.ts
@@ -757,6 +624,9 @@ var Vertex = class _Vertex {
757
624
  }
758
625
  this.tree.setTransientVertexProperty(this.id, key, value);
759
626
  }
627
+ commitTransients() {
628
+ this.tree.commitTransients(this.id);
629
+ }
760
630
  setProperties(props) {
761
631
  for (const [key, value] of Object.entries(props)) {
762
632
  this.setProperty(key, value);
@@ -1233,6 +1103,20 @@ var _RepTree = class _RepTree {
1233
1103
  this.localOps.push(op);
1234
1104
  this.applyProperty(op);
1235
1105
  }
1106
+ commitTransients(vertexId) {
1107
+ const vertex = this.state.getVertex(vertexId);
1108
+ if (!vertex) {
1109
+ return;
1110
+ }
1111
+ const transientProps = vertex.getTransientProperties();
1112
+ for (const prop of transientProps) {
1113
+ this.setVertexProperty(vertexId, prop.key, prop.value);
1114
+ }
1115
+ for (const prop of transientProps) {
1116
+ this.transientPropertiesAndTheirOpIds.delete(`${prop.key}@${vertexId}`);
1117
+ }
1118
+ vertex.clearAllTransientProperties();
1119
+ }
1236
1120
  setVertexProperty(vertexId, key, value) {
1237
1121
  this.lamportClock++;
1238
1122
  let opValue;