reptree 0.2.3 → 0.3.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 +24 -6
- package/dist/index.cjs +322 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -4
- package/dist/index.d.ts +46 -4
- package/dist/index.js +321 -28
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ npm install reptree
|
|
|
26
26
|
### Reactive vertex with Zod (optional)
|
|
27
27
|
|
|
28
28
|
```ts
|
|
29
|
-
import { RepTree
|
|
29
|
+
import { RepTree } from 'reptree';
|
|
30
30
|
import { z } from 'zod';
|
|
31
31
|
|
|
32
32
|
const tree = new RepTree('peer1');
|
|
@@ -35,16 +35,25 @@ const v = root.newChild();
|
|
|
35
35
|
|
|
36
36
|
const Person = z.object({ name: z.string(), age: z.number().int().min(0) });
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
const person = bindVertex(tree, v.id, Person);
|
|
40
|
-
|
|
41
|
-
// Or via instance method on Vertex
|
|
42
|
-
// const person = v.bind(Person);
|
|
38
|
+
const person = v.bind(Person);
|
|
43
39
|
|
|
44
40
|
person.name = 'Alice'; // validated and persisted
|
|
45
41
|
person.age = 33; // validated and persisted
|
|
46
42
|
```
|
|
47
43
|
|
|
44
|
+
#### Aliases for internal fields
|
|
45
|
+
|
|
46
|
+
- `name` ↔ `_n`
|
|
47
|
+
- `createdAt` ↔ `_c` (Date exposed, ISO stored)
|
|
48
|
+
|
|
49
|
+
These aliases are applied by default when using `vertex.bind()`.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
person.name = 'Alice'; // writes _n
|
|
53
|
+
person.createdAt = new Date(); // writes _c (ISO)
|
|
54
|
+
console.log(person.createdAt instanceof Date); // true
|
|
55
|
+
```
|
|
56
|
+
|
|
48
57
|
For more, see `docs/reactive-vertices.md`.
|
|
49
58
|
|
|
50
59
|
```typescript
|
|
@@ -98,6 +107,15 @@ const ops = tree.getAllOps();
|
|
|
98
107
|
otherTree.merge(ops);
|
|
99
108
|
```
|
|
100
109
|
|
|
110
|
+
### Creating children with normalized props
|
|
111
|
+
|
|
112
|
+
`vertex.newChild(props)` and `vertex.newNamedChild(name, props)` accept plain objects. RepTree will:
|
|
113
|
+
|
|
114
|
+
- Map `name` → `_n`, `createdAt` (Date) → `_c` (ISO)
|
|
115
|
+
- Filter unsupported types (non-primitive objects except Y.Doc)
|
|
116
|
+
- Ignore `props.name` if `newNamedChild` has an explicit `name`
|
|
117
|
+
- Forbid nested children in props for now
|
|
118
|
+
|
|
101
119
|
## Yjs Integration
|
|
102
120
|
|
|
103
121
|
RepTree supports [Yjs](https://github.com/yjs/yjs) documents as vertex properties, enabling real-time collaborative editing with a variety of shared data types:
|
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
Vertex: () => Vertex,
|
|
37
37
|
VertexState: () => VertexState,
|
|
38
38
|
bindVertex: () => bindVertex,
|
|
39
|
+
defaultAliases: () => defaultAliases,
|
|
39
40
|
isAnyPropertyOp: () => isAnyPropertyOp,
|
|
40
41
|
isLWWPropertyOp: () => isLWWPropertyOp,
|
|
41
42
|
isModifyPropertyOp: () => isModifyPropertyOp,
|
|
@@ -404,19 +405,217 @@ function uuid() {
|
|
|
404
405
|
}
|
|
405
406
|
|
|
406
407
|
// src/reactive.ts
|
|
407
|
-
|
|
408
|
+
var defaultAliases = [
|
|
409
|
+
{ publicKey: "name", internalKey: "_n" },
|
|
410
|
+
{
|
|
411
|
+
publicKey: "createdAt",
|
|
412
|
+
internalKey: "_c",
|
|
413
|
+
toPublic: (v) => typeof v === "string" ? new Date(v) : v,
|
|
414
|
+
toInternal: (v) => v instanceof Date ? v.toISOString() : v
|
|
415
|
+
}
|
|
416
|
+
];
|
|
417
|
+
function buildAliasMaps(aliases) {
|
|
418
|
+
const publicToInternal = /* @__PURE__ */ new Map();
|
|
419
|
+
const internalToPublic = /* @__PURE__ */ new Map();
|
|
420
|
+
for (const rule of aliases) {
|
|
421
|
+
publicToInternal.set(rule.publicKey, rule);
|
|
422
|
+
internalToPublic.set(rule.internalKey, rule);
|
|
423
|
+
}
|
|
424
|
+
return { publicToInternal, internalToPublic };
|
|
425
|
+
}
|
|
426
|
+
function toPublicObject(tree, id, internalToPublic) {
|
|
408
427
|
const obj = {};
|
|
409
|
-
for (const { key, value } of tree.getVertexProperties(id))
|
|
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
|
+
}
|
|
410
437
|
return obj;
|
|
411
438
|
}
|
|
412
|
-
|
|
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
|
+
function bindVertex(tree, id, schemaOrOptions) {
|
|
444
|
+
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
|
+
const options = isOptions ? schemaOrOptions : { schema: schemaOrOptions };
|
|
446
|
+
const schema = options.schema;
|
|
447
|
+
const aliases = options.aliases ?? defaultAliases;
|
|
448
|
+
const includeInternalKeys = options.includeInternalKeys ?? false;
|
|
449
|
+
const { publicToInternal, internalToPublic } = buildAliasMaps(aliases);
|
|
450
|
+
const cachedMethods = /* @__PURE__ */ new Map();
|
|
413
451
|
return new Proxy({}, {
|
|
414
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);
|
|
589
|
+
}
|
|
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
|
+
});
|
|
596
|
+
}
|
|
597
|
+
return cachedMethods.get(prop);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
415
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;
|
|
605
|
+
}
|
|
416
606
|
return tree.getVertexProperty(id, prop);
|
|
417
607
|
},
|
|
418
608
|
set(_target, prop, value) {
|
|
419
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;
|
|
618
|
+
}
|
|
420
619
|
if (schema?.shape && schema.shape[prop]) {
|
|
421
620
|
const field = schema.shape[prop];
|
|
422
621
|
if (field.safeParse) {
|
|
@@ -425,7 +624,7 @@ function bindVertex(tree, id, schema) {
|
|
|
425
624
|
value = res.data ?? value;
|
|
426
625
|
}
|
|
427
626
|
} else if (schema?.safeParse) {
|
|
428
|
-
const next = { ...
|
|
627
|
+
const next = { ...toPublicObject(tree, id, internalToPublic), [prop]: value };
|
|
429
628
|
const res = schema.safeParse(next);
|
|
430
629
|
if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);
|
|
431
630
|
const parsed = res.data;
|
|
@@ -433,20 +632,49 @@ function bindVertex(tree, id, schema) {
|
|
|
433
632
|
value = parsed[prop];
|
|
434
633
|
}
|
|
435
634
|
}
|
|
635
|
+
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
|
+
}
|
|
436
641
|
tree.setVertexProperty(id, prop, value);
|
|
437
642
|
return true;
|
|
438
643
|
},
|
|
439
644
|
deleteProperty(_target, prop) {
|
|
440
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)) {
|
|
653
|
+
return true;
|
|
654
|
+
}
|
|
655
|
+
const rule = publicToInternal.get(prop);
|
|
656
|
+
if (rule) {
|
|
657
|
+
tree.setVertexProperty(id, rule.internalKey, void 0);
|
|
658
|
+
return true;
|
|
659
|
+
}
|
|
441
660
|
tree.setVertexProperty(id, prop, void 0);
|
|
442
661
|
return true;
|
|
443
662
|
},
|
|
444
663
|
has(_target, prop) {
|
|
445
664
|
if (typeof prop !== "string") return false;
|
|
446
|
-
|
|
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;
|
|
447
670
|
},
|
|
448
671
|
ownKeys() {
|
|
449
|
-
|
|
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);
|
|
450
678
|
},
|
|
451
679
|
getOwnPropertyDescriptor() {
|
|
452
680
|
return { enumerable: true, configurable: true };
|
|
@@ -455,7 +683,8 @@ function bindVertex(tree, id, schema) {
|
|
|
455
683
|
}
|
|
456
684
|
|
|
457
685
|
// src/Vertex.ts
|
|
458
|
-
var
|
|
686
|
+
var Y = __toESM(require("yjs"), 1);
|
|
687
|
+
var Vertex = class _Vertex {
|
|
459
688
|
constructor(tree, state) {
|
|
460
689
|
this.tree = tree;
|
|
461
690
|
this.state = state;
|
|
@@ -501,12 +730,18 @@ var Vertex = class {
|
|
|
501
730
|
return this.children.map((v) => v.getAsTypedObject());
|
|
502
731
|
}
|
|
503
732
|
newChild(props) {
|
|
504
|
-
|
|
505
|
-
|
|
733
|
+
if (props && typeof props === "object" && "children" in props) {
|
|
734
|
+
throw new Error("Passing children inside props is not supported at the moment");
|
|
735
|
+
}
|
|
736
|
+
const normalized = _Vertex.normalizePropsForCreation(props);
|
|
737
|
+
return this.tree.newVertex(this.id, normalized);
|
|
506
738
|
}
|
|
507
739
|
newNamedChild(name, props) {
|
|
508
|
-
|
|
509
|
-
|
|
740
|
+
if (props && typeof props === "object" && "children" in props) {
|
|
741
|
+
throw new Error("Passing children inside props is not supported at the moment");
|
|
742
|
+
}
|
|
743
|
+
const normalized = _Vertex.normalizePropsForCreation(props, name);
|
|
744
|
+
return this.tree.newNamedVertex(this.id, name, normalized);
|
|
510
745
|
}
|
|
511
746
|
setProperty(key, value) {
|
|
512
747
|
const existingValue = this.getProperty(key, false);
|
|
@@ -572,9 +807,67 @@ var Vertex = class {
|
|
|
572
807
|
moveTo(parent) {
|
|
573
808
|
this.tree.moveVertex(this.id, parent.id);
|
|
574
809
|
}
|
|
575
|
-
/** Returns a live reactive object bound to this vertex.
|
|
576
|
-
bind(
|
|
577
|
-
return bindVertex(this.tree, this.id,
|
|
810
|
+
/** Returns a live reactive object bound to this vertex. Accepts schema or options. */
|
|
811
|
+
bind(schemaOrOptions) {
|
|
812
|
+
return bindVertex(this.tree, this.id, schemaOrOptions);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Normalizes an input props object for vertex creation:
|
|
816
|
+
* - Aliases name -> _n, createdAt -> _c (Date -> ISO string)
|
|
817
|
+
* - Filters unsupported field types with a console warning
|
|
818
|
+
* - When a name param is provided to newNamedChild, ignores conflicting name in props
|
|
819
|
+
*/
|
|
820
|
+
static normalizePropsForCreation(props, explicitName) {
|
|
821
|
+
if (!props) return null;
|
|
822
|
+
const input = props;
|
|
823
|
+
const out = {};
|
|
824
|
+
const skipped = [];
|
|
825
|
+
for (const [rawKey, rawValue] of Object.entries(input)) {
|
|
826
|
+
if (rawValue === void 0) {
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
if (rawKey === "children") continue;
|
|
830
|
+
let key = rawKey;
|
|
831
|
+
if (rawKey === "name") {
|
|
832
|
+
if (explicitName !== void 0) {
|
|
833
|
+
console.warn('newNamedChild: "name" in props is ignored because a name argument was provided');
|
|
834
|
+
continue;
|
|
835
|
+
}
|
|
836
|
+
key = "_n";
|
|
837
|
+
} else if (rawKey === "createdAt") {
|
|
838
|
+
key = "_c";
|
|
839
|
+
}
|
|
840
|
+
let value = rawValue;
|
|
841
|
+
if (key === "_c") {
|
|
842
|
+
if (value instanceof Date) {
|
|
843
|
+
value = value.toISOString();
|
|
844
|
+
} else if (typeof value === "string") {
|
|
845
|
+
} else {
|
|
846
|
+
skipped.push(rawKey);
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
const isPrimitive = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean";
|
|
851
|
+
if (Array.isArray(value)) {
|
|
852
|
+
if (!value.every(isPrimitive)) {
|
|
853
|
+
skipped.push(rawKey);
|
|
854
|
+
continue;
|
|
855
|
+
}
|
|
856
|
+
} else if (typeof value === "object" && value !== null) {
|
|
857
|
+
if (!(value instanceof Y.Doc)) {
|
|
858
|
+
skipped.push(rawKey);
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
} else if (!isPrimitive(value)) {
|
|
862
|
+
skipped.push(rawKey);
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
out[key] = value;
|
|
866
|
+
}
|
|
867
|
+
if (skipped.length > 0) {
|
|
868
|
+
console.warn(`Some fields were skipped due to unsupported types: ${skipped.join(", ")}`);
|
|
869
|
+
}
|
|
870
|
+
return Object.keys(out).length > 0 ? out : null;
|
|
578
871
|
}
|
|
579
872
|
};
|
|
580
873
|
|
|
@@ -764,7 +1057,7 @@ var StateVector = class _StateVector {
|
|
|
764
1057
|
};
|
|
765
1058
|
|
|
766
1059
|
// src/RepTree.ts
|
|
767
|
-
var
|
|
1060
|
+
var Y2 = __toESM(require("yjs"), 1);
|
|
768
1061
|
var _RepTree = class _RepTree {
|
|
769
1062
|
/**
|
|
770
1063
|
* @param peerId - The peer ID of the current client. Should be unique across all peers.
|
|
@@ -926,8 +1219,8 @@ var _RepTree = class _RepTree {
|
|
|
926
1219
|
setTransientVertexProperty(vertexId, key, value) {
|
|
927
1220
|
this.lamportClock++;
|
|
928
1221
|
let opValue;
|
|
929
|
-
if (value instanceof
|
|
930
|
-
const state =
|
|
1222
|
+
if (value instanceof Y2.Doc) {
|
|
1223
|
+
const state = Y2.encodeStateAsUpdate(value);
|
|
931
1224
|
opValue = {
|
|
932
1225
|
type: "yjs",
|
|
933
1226
|
value: state
|
|
@@ -943,8 +1236,8 @@ var _RepTree = class _RepTree {
|
|
|
943
1236
|
setVertexProperty(vertexId, key, value) {
|
|
944
1237
|
this.lamportClock++;
|
|
945
1238
|
let opValue;
|
|
946
|
-
if (value instanceof
|
|
947
|
-
const state =
|
|
1239
|
+
if (value instanceof Y2.Doc) {
|
|
1240
|
+
const state = Y2.encodeStateAsUpdate(value);
|
|
948
1241
|
opValue = {
|
|
949
1242
|
type: "yjs",
|
|
950
1243
|
value: state
|
|
@@ -1116,10 +1409,10 @@ var _RepTree = class _RepTree {
|
|
|
1116
1409
|
if (!propB) {
|
|
1117
1410
|
return false;
|
|
1118
1411
|
}
|
|
1119
|
-
if (propA.value instanceof
|
|
1120
|
-
const snapshotA =
|
|
1121
|
-
const snapshotB =
|
|
1122
|
-
if (!
|
|
1412
|
+
if (propA.value instanceof Y2.Doc && propB.value instanceof Y2.Doc) {
|
|
1413
|
+
const snapshotA = Y2.snapshot(propA.value);
|
|
1414
|
+
const snapshotB = Y2.snapshot(propB.value);
|
|
1415
|
+
if (!Y2.equalSnapshots(snapshotA, snapshotB)) {
|
|
1123
1416
|
return false;
|
|
1124
1417
|
}
|
|
1125
1418
|
} else if (propA.value !== propB.value) {
|
|
@@ -1223,7 +1516,7 @@ var _RepTree = class _RepTree {
|
|
|
1223
1516
|
const propertyKey = `${key}@${vertexId}`;
|
|
1224
1517
|
if (this.yjsObservers.has(propertyKey)) {
|
|
1225
1518
|
const existingDoc = this.getVertexProperty(vertexId, key);
|
|
1226
|
-
if (existingDoc instanceof
|
|
1519
|
+
if (existingDoc instanceof Y2.Doc) {
|
|
1227
1520
|
existingDoc.off("update", this.yjsObservers.get(propertyKey));
|
|
1228
1521
|
}
|
|
1229
1522
|
this.yjsObservers.delete(propertyKey);
|
|
@@ -1303,13 +1596,13 @@ var _RepTree = class _RepTree {
|
|
|
1303
1596
|
throw new Error("Unknown CRDT type");
|
|
1304
1597
|
}
|
|
1305
1598
|
const ydoc = targetVertex.getProperty(op.key);
|
|
1306
|
-
if (ydoc instanceof
|
|
1307
|
-
|
|
1599
|
+
if (ydoc instanceof Y2.Doc) {
|
|
1600
|
+
Y2.applyUpdate(ydoc, crdtValue.value);
|
|
1308
1601
|
} else {
|
|
1309
|
-
const newDoc = new
|
|
1602
|
+
const newDoc = new Y2.Doc();
|
|
1310
1603
|
this.setupYjsObserver(newDoc, op.targetId, op.key);
|
|
1311
1604
|
this.state.setProperty(op.targetId, op.key, newDoc);
|
|
1312
|
-
|
|
1605
|
+
Y2.applyUpdate(newDoc, crdtValue.value);
|
|
1313
1606
|
}
|
|
1314
1607
|
this.propertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);
|
|
1315
1608
|
this.reportOpAsApplied(op);
|
|
@@ -1437,6 +1730,7 @@ var RepTree = _RepTree;
|
|
|
1437
1730
|
Vertex,
|
|
1438
1731
|
VertexState,
|
|
1439
1732
|
bindVertex,
|
|
1733
|
+
defaultAliases,
|
|
1440
1734
|
isAnyPropertyOp,
|
|
1441
1735
|
isLWWPropertyOp,
|
|
1442
1736
|
isModifyPropertyOp,
|