reptree 0.2.2 → 0.2.4
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 +46 -0
- package/dist/index.cjs +305 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +303 -19
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -89,6 +89,54 @@ declare function newMoveVertexOp(clock: number, peerId: string, targetId: string
|
|
|
89
89
|
declare function newSetVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty;
|
|
90
90
|
declare function newSetTransientVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty;
|
|
91
91
|
|
|
92
|
+
type FieldSchemaLike = {
|
|
93
|
+
safeParse?: (input: unknown) => {
|
|
94
|
+
success: true;
|
|
95
|
+
data: unknown;
|
|
96
|
+
} | {
|
|
97
|
+
success: false;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
type SchemaLike<T> = {
|
|
101
|
+
safeParse?: (input: unknown) => {
|
|
102
|
+
success: true;
|
|
103
|
+
data: T;
|
|
104
|
+
} | {
|
|
105
|
+
success: false;
|
|
106
|
+
};
|
|
107
|
+
parse?: (input: unknown) => T;
|
|
108
|
+
shape?: Record<string, FieldSchemaLike>;
|
|
109
|
+
};
|
|
110
|
+
type AliasRule = {
|
|
111
|
+
publicKey: string;
|
|
112
|
+
internalKey: string;
|
|
113
|
+
toPublic?: (value: unknown) => unknown;
|
|
114
|
+
toInternal?: (value: unknown) => unknown;
|
|
115
|
+
};
|
|
116
|
+
declare const defaultAliases: AliasRule[];
|
|
117
|
+
type BindOptions<T> = {
|
|
118
|
+
schema?: SchemaLike<T>;
|
|
119
|
+
aliases?: AliasRule[];
|
|
120
|
+
includeInternalKeys?: boolean;
|
|
121
|
+
};
|
|
122
|
+
type BindedVertex<T> = T & {
|
|
123
|
+
/**
|
|
124
|
+
* Create a transient proxy that can be used to write transient properties.
|
|
125
|
+
*/
|
|
126
|
+
useTransient(fn: (t: T) => void): void;
|
|
127
|
+
/**
|
|
128
|
+
* Promote transient properties to persistent.
|
|
129
|
+
*/
|
|
130
|
+
commitTransients(): void;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Returns a live object that proxies reads/writes to a vertex.
|
|
134
|
+
* - Reads reflect the latest CRDT state.
|
|
135
|
+
* - Writes persist to the CRDT.
|
|
136
|
+
* - If a schema is provided, writes are validated. If a field schema exists in `schema.shape`, field-level validation is applied.
|
|
137
|
+
*/
|
|
138
|
+
declare function bindVertex<T extends Record<string, unknown>>(tree: RepTree, id: string, schemaOrOptions?: SchemaLike<T> | BindOptions<T>): BindedVertex<T>;
|
|
139
|
+
|
|
92
140
|
/**
|
|
93
141
|
* A wrapper class for VertexState that provides a more convenient API
|
|
94
142
|
* for working with vertices in a RepTree.
|
|
@@ -124,6 +172,15 @@ declare class Vertex {
|
|
|
124
172
|
observeChildrenAsTypedArray<T>(listener: (children: T[]) => void): () => void;
|
|
125
173
|
delete(): void;
|
|
126
174
|
moveTo(parent: Vertex): void;
|
|
175
|
+
/** Returns a live reactive object bound to this vertex. Accepts schema or options. */
|
|
176
|
+
bind<T extends Record<string, unknown>>(schemaOrOptions?: SchemaLike<T> | BindOptions<T>): BindedVertex<T>;
|
|
177
|
+
/**
|
|
178
|
+
* Normalizes an input props object for vertex creation:
|
|
179
|
+
* - Aliases name -> _n, createdAt -> _c (Date -> ISO string)
|
|
180
|
+
* - Filters unsupported field types with a console warning
|
|
181
|
+
* - When a name param is provided to newNamedChild, ignores conflicting name in props
|
|
182
|
+
*/
|
|
183
|
+
private static normalizePropsForCreation;
|
|
127
184
|
}
|
|
128
185
|
|
|
129
186
|
/**
|
|
@@ -236,6 +293,12 @@ declare class RepTree {
|
|
|
236
293
|
* When enabled, rebuilds the state vector from existing operations if needed
|
|
237
294
|
*/
|
|
238
295
|
set stateVectorEnabled(value: boolean);
|
|
296
|
+
/**
|
|
297
|
+
* Parses the vertex properties with a provided schema that has a `parse` method (e.g., Zod schema)
|
|
298
|
+
*/
|
|
299
|
+
parseVertex<T>(vertexId: string, schema: {
|
|
300
|
+
parse: (data: unknown) => T;
|
|
301
|
+
}): T;
|
|
239
302
|
}
|
|
240
303
|
|
|
241
304
|
declare class TreeState {
|
|
@@ -321,4 +384,4 @@ declare class StateVector {
|
|
|
321
384
|
|
|
322
385
|
declare function uuid(): string;
|
|
323
386
|
|
|
324
|
-
export { type CRDTType, type MoveVertex, type OpId, type OpIdRange, RepTree, type SetVertexProperty, StateVector, TreeState, type TreeVertexId, type TreeVertexProperty, Vertex, type VertexChangeEvent, type VertexChildrenChangeEvent, type VertexMoveEvent, type VertexOperation, type VertexPropertyChangeEvent, type VertexPropertyType, type VertexPropertyTypeInOperation, VertexState, isAnyPropertyOp, isLWWPropertyOp, isModifyPropertyOp, isMoveVertexOp, newMoveVertexOp, newSetTransientVertexPropertyOp, newSetVertexPropertyOp, uuid };
|
|
387
|
+
export { type AliasRule, type BindOptions, type BindedVertex, type CRDTType, type MoveVertex, type OpId, type OpIdRange, RepTree, type SchemaLike, type SetVertexProperty, StateVector, TreeState, type TreeVertexId, type TreeVertexProperty, Vertex, type VertexChangeEvent, type VertexChildrenChangeEvent, type VertexMoveEvent, type VertexOperation, type VertexPropertyChangeEvent, type VertexPropertyType, type VertexPropertyTypeInOperation, VertexState, bindVertex, defaultAliases, isAnyPropertyOp, isLWWPropertyOp, isModifyPropertyOp, isMoveVertexOp, newMoveVertexOp, newSetTransientVertexPropertyOp, newSetVertexPropertyOp, uuid };
|
package/dist/index.js
CHANGED
|
@@ -354,8 +354,211 @@ function uuid() {
|
|
|
354
354
|
return removeDashes(crypto.randomUUID());
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
+
// src/reactive.ts
|
|
358
|
+
var defaultAliases = [
|
|
359
|
+
{ publicKey: "name", internalKey: "_n" },
|
|
360
|
+
{
|
|
361
|
+
publicKey: "createdAt",
|
|
362
|
+
internalKey: "_c",
|
|
363
|
+
toPublic: (v) => typeof v === "string" ? new Date(v) : v,
|
|
364
|
+
toInternal: (v) => v instanceof Date ? v.toISOString() : v
|
|
365
|
+
}
|
|
366
|
+
];
|
|
367
|
+
function buildAliasMaps(aliases) {
|
|
368
|
+
const publicToInternal = /* @__PURE__ */ new Map();
|
|
369
|
+
const internalToPublic = /* @__PURE__ */ new Map();
|
|
370
|
+
for (const rule of aliases) {
|
|
371
|
+
publicToInternal.set(rule.publicKey, rule);
|
|
372
|
+
internalToPublic.set(rule.internalKey, rule);
|
|
373
|
+
}
|
|
374
|
+
return { publicToInternal, internalToPublic };
|
|
375
|
+
}
|
|
376
|
+
function toPublicObject(tree, id, internalToPublic) {
|
|
377
|
+
const obj = {};
|
|
378
|
+
for (const { key, value } of tree.getVertexProperties(id)) {
|
|
379
|
+
const rule = internalToPublic.get(key);
|
|
380
|
+
if (rule) {
|
|
381
|
+
const converted = rule.toPublic ? rule.toPublic(value) : value;
|
|
382
|
+
obj[rule.publicKey] = converted;
|
|
383
|
+
} else {
|
|
384
|
+
obj[key] = value;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return obj;
|
|
388
|
+
}
|
|
389
|
+
var RESERVED_METHOD_USE_TRANSIENT = "useTransient";
|
|
390
|
+
var RESERVED_METHOD_COMMIT_TRANSIENTS = "commitTransients";
|
|
391
|
+
function bindVertex(tree, id, schemaOrOptions) {
|
|
392
|
+
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"));
|
|
393
|
+
const options = isOptions ? schemaOrOptions : { schema: schemaOrOptions };
|
|
394
|
+
const schema = options.schema;
|
|
395
|
+
const aliases = options.aliases ?? defaultAliases;
|
|
396
|
+
const includeInternalKeys = options.includeInternalKeys ?? false;
|
|
397
|
+
const { publicToInternal, internalToPublic } = buildAliasMaps(aliases);
|
|
398
|
+
return new Proxy({}, {
|
|
399
|
+
get(_target, prop) {
|
|
400
|
+
if (prop === RESERVED_METHOD_USE_TRANSIENT) {
|
|
401
|
+
return (fn) => {
|
|
402
|
+
const transientProxy = new Proxy({}, {
|
|
403
|
+
get(_t, p) {
|
|
404
|
+
if (typeof p !== "string") return void 0;
|
|
405
|
+
const rule2 = publicToInternal.get(p);
|
|
406
|
+
if (rule2) {
|
|
407
|
+
const raw = tree.getVertexProperty(id, rule2.internalKey);
|
|
408
|
+
return rule2.toPublic ? rule2.toPublic(raw) : raw;
|
|
409
|
+
}
|
|
410
|
+
return tree.getVertexProperty(id, p);
|
|
411
|
+
},
|
|
412
|
+
set(_t, p, value) {
|
|
413
|
+
if (typeof p !== "string") return true;
|
|
414
|
+
if (schema?.shape && schema.shape[p]) {
|
|
415
|
+
const field = schema.shape[p];
|
|
416
|
+
if (field.safeParse) {
|
|
417
|
+
const res = field.safeParse(value);
|
|
418
|
+
if (!res.success) throw new Error(`Invalid value for ${String(p)}`);
|
|
419
|
+
value = res.data ?? value;
|
|
420
|
+
}
|
|
421
|
+
} else if (schema?.safeParse) {
|
|
422
|
+
const next = { ...toPublicObject(tree, id, internalToPublic), [p]: value };
|
|
423
|
+
const res = schema.safeParse(next);
|
|
424
|
+
if (!res.success) throw new Error(`Invalid value for ${String(p)}`);
|
|
425
|
+
const parsed = res.data;
|
|
426
|
+
if (parsed && Object.prototype.hasOwnProperty.call(parsed, p)) {
|
|
427
|
+
value = parsed[p];
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
const rule2 = publicToInternal.get(p);
|
|
431
|
+
if (rule2) {
|
|
432
|
+
const converted = rule2.toInternal ? rule2.toInternal(value) : value;
|
|
433
|
+
tree.setTransientVertexProperty(id, rule2.internalKey, converted);
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
tree.setTransientVertexProperty(id, p, value);
|
|
437
|
+
return true;
|
|
438
|
+
},
|
|
439
|
+
deleteProperty(_t, p) {
|
|
440
|
+
if (typeof p !== "string") return true;
|
|
441
|
+
const rule2 = publicToInternal.get(p);
|
|
442
|
+
if (rule2) {
|
|
443
|
+
tree.setTransientVertexProperty(id, rule2.internalKey, void 0);
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
tree.setTransientVertexProperty(id, p, void 0);
|
|
447
|
+
return true;
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
fn(transientProxy);
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
if (prop === RESERVED_METHOD_COMMIT_TRANSIENTS) {
|
|
454
|
+
return () => {
|
|
455
|
+
const entries = tree.getVertexProperties(id);
|
|
456
|
+
const currentPublic = schema?.safeParse ? toPublicObject(tree, id, internalToPublic) : void 0;
|
|
457
|
+
for (const { key: internalKey, value: overlayValue } of entries) {
|
|
458
|
+
const persistentValue = tree.getVertexProperty(id, internalKey, false);
|
|
459
|
+
if (overlayValue === persistentValue) continue;
|
|
460
|
+
const aliasRule = internalToPublic.get(internalKey);
|
|
461
|
+
const publicKey = aliasRule ? aliasRule.publicKey : internalKey;
|
|
462
|
+
const publicValue = aliasRule && aliasRule.toPublic ? aliasRule.toPublic(overlayValue) : overlayValue;
|
|
463
|
+
let valueToPersistInternal = overlayValue;
|
|
464
|
+
if (schema?.shape && schema.shape[publicKey]) {
|
|
465
|
+
const field = schema.shape[publicKey];
|
|
466
|
+
if (field.safeParse) {
|
|
467
|
+
const res = field.safeParse(publicValue);
|
|
468
|
+
if (!res.success) throw new Error(`Invalid value for ${String(publicKey)}`);
|
|
469
|
+
const coerced = res.data;
|
|
470
|
+
const maybeInternal = aliasRule && aliasRule.toInternal ? aliasRule.toInternal(coerced) : coerced;
|
|
471
|
+
valueToPersistInternal = maybeInternal;
|
|
472
|
+
}
|
|
473
|
+
} else if (schema?.safeParse && currentPublic) {
|
|
474
|
+
const nextPublic = { ...currentPublic, [publicKey]: publicValue };
|
|
475
|
+
const res = schema.safeParse(nextPublic);
|
|
476
|
+
if (!res.success) throw new Error("Invalid values for commitTransients");
|
|
477
|
+
const parsed = res.data;
|
|
478
|
+
const parsedPublic = Object.prototype.hasOwnProperty.call(parsed, publicKey) ? parsed[publicKey] : publicValue;
|
|
479
|
+
const maybeInternal = aliasRule && aliasRule.toInternal ? aliasRule.toInternal(parsedPublic) : parsedPublic;
|
|
480
|
+
valueToPersistInternal = maybeInternal;
|
|
481
|
+
}
|
|
482
|
+
tree.setVertexProperty(id, internalKey, valueToPersistInternal);
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
if (typeof prop !== "string") return void 0;
|
|
487
|
+
const rule = publicToInternal.get(prop);
|
|
488
|
+
if (rule) {
|
|
489
|
+
const raw = tree.getVertexProperty(id, rule.internalKey);
|
|
490
|
+
return rule.toPublic ? rule.toPublic(raw) : raw;
|
|
491
|
+
}
|
|
492
|
+
return tree.getVertexProperty(id, prop);
|
|
493
|
+
},
|
|
494
|
+
set(_target, prop, value) {
|
|
495
|
+
if (typeof prop !== "string") return true;
|
|
496
|
+
if (prop === RESERVED_METHOD_USE_TRANSIENT || prop === RESERVED_METHOD_COMMIT_TRANSIENTS) {
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
499
|
+
if (schema?.shape && schema.shape[prop]) {
|
|
500
|
+
const field = schema.shape[prop];
|
|
501
|
+
if (field.safeParse) {
|
|
502
|
+
const res = field.safeParse(value);
|
|
503
|
+
if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);
|
|
504
|
+
value = res.data ?? value;
|
|
505
|
+
}
|
|
506
|
+
} else if (schema?.safeParse) {
|
|
507
|
+
const next = { ...toPublicObject(tree, id, internalToPublic), [prop]: value };
|
|
508
|
+
const res = schema.safeParse(next);
|
|
509
|
+
if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);
|
|
510
|
+
const parsed = res.data;
|
|
511
|
+
if (parsed && Object.prototype.hasOwnProperty.call(parsed, prop)) {
|
|
512
|
+
value = parsed[prop];
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
const rule = publicToInternal.get(prop);
|
|
516
|
+
if (rule) {
|
|
517
|
+
const converted = rule.toInternal ? rule.toInternal(value) : value;
|
|
518
|
+
tree.setVertexProperty(id, rule.internalKey, converted);
|
|
519
|
+
return true;
|
|
520
|
+
}
|
|
521
|
+
tree.setVertexProperty(id, prop, value);
|
|
522
|
+
return true;
|
|
523
|
+
},
|
|
524
|
+
deleteProperty(_target, prop) {
|
|
525
|
+
if (typeof prop !== "string") return true;
|
|
526
|
+
if (prop === RESERVED_METHOD_USE_TRANSIENT || prop === RESERVED_METHOD_COMMIT_TRANSIENTS) {
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
const rule = publicToInternal.get(prop);
|
|
530
|
+
if (rule) {
|
|
531
|
+
tree.setVertexProperty(id, rule.internalKey, void 0);
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
tree.setVertexProperty(id, prop, void 0);
|
|
535
|
+
return true;
|
|
536
|
+
},
|
|
537
|
+
has(_target, prop) {
|
|
538
|
+
if (typeof prop !== "string") return false;
|
|
539
|
+
if (schema?.shape && Object.prototype.hasOwnProperty.call(schema.shape, prop)) return true;
|
|
540
|
+
if (includeInternalKeys) {
|
|
541
|
+
return publicToInternal.has(prop) || internalToPublic.has(prop);
|
|
542
|
+
}
|
|
543
|
+
return false;
|
|
544
|
+
},
|
|
545
|
+
ownKeys() {
|
|
546
|
+
const keys = /* @__PURE__ */ new Set();
|
|
547
|
+
for (const k of Object.keys(schema?.shape ?? {})) keys.add(k);
|
|
548
|
+
if (includeInternalKeys) {
|
|
549
|
+
for (const rule of aliases) keys.add(rule.internalKey);
|
|
550
|
+
}
|
|
551
|
+
return Array.from(keys);
|
|
552
|
+
},
|
|
553
|
+
getOwnPropertyDescriptor() {
|
|
554
|
+
return { enumerable: true, configurable: true };
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
|
|
357
559
|
// src/Vertex.ts
|
|
358
|
-
|
|
560
|
+
import * as Y from "yjs";
|
|
561
|
+
var Vertex = class _Vertex {
|
|
359
562
|
constructor(tree, state) {
|
|
360
563
|
this.tree = tree;
|
|
361
564
|
this.state = state;
|
|
@@ -401,12 +604,18 @@ var Vertex = class {
|
|
|
401
604
|
return this.children.map((v) => v.getAsTypedObject());
|
|
402
605
|
}
|
|
403
606
|
newChild(props) {
|
|
404
|
-
|
|
405
|
-
|
|
607
|
+
if (props && typeof props === "object" && "children" in props) {
|
|
608
|
+
throw new Error("Passing children inside props is not supported at the moment");
|
|
609
|
+
}
|
|
610
|
+
const normalized = _Vertex.normalizePropsForCreation(props);
|
|
611
|
+
return this.tree.newVertex(this.id, normalized);
|
|
406
612
|
}
|
|
407
613
|
newNamedChild(name, props) {
|
|
408
|
-
|
|
409
|
-
|
|
614
|
+
if (props && typeof props === "object" && "children" in props) {
|
|
615
|
+
throw new Error("Passing children inside props is not supported at the moment");
|
|
616
|
+
}
|
|
617
|
+
const normalized = _Vertex.normalizePropsForCreation(props, name);
|
|
618
|
+
return this.tree.newNamedVertex(this.id, name, normalized);
|
|
410
619
|
}
|
|
411
620
|
setProperty(key, value) {
|
|
412
621
|
const existingValue = this.getProperty(key, false);
|
|
@@ -472,6 +681,68 @@ var Vertex = class {
|
|
|
472
681
|
moveTo(parent) {
|
|
473
682
|
this.tree.moveVertex(this.id, parent.id);
|
|
474
683
|
}
|
|
684
|
+
/** Returns a live reactive object bound to this vertex. Accepts schema or options. */
|
|
685
|
+
bind(schemaOrOptions) {
|
|
686
|
+
return bindVertex(this.tree, this.id, schemaOrOptions);
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Normalizes an input props object for vertex creation:
|
|
690
|
+
* - Aliases name -> _n, createdAt -> _c (Date -> ISO string)
|
|
691
|
+
* - Filters unsupported field types with a console warning
|
|
692
|
+
* - When a name param is provided to newNamedChild, ignores conflicting name in props
|
|
693
|
+
*/
|
|
694
|
+
static normalizePropsForCreation(props, explicitName) {
|
|
695
|
+
if (!props) return null;
|
|
696
|
+
const input = props;
|
|
697
|
+
const out = {};
|
|
698
|
+
const skipped = [];
|
|
699
|
+
for (const [rawKey, rawValue] of Object.entries(input)) {
|
|
700
|
+
if (rawValue === void 0) {
|
|
701
|
+
continue;
|
|
702
|
+
}
|
|
703
|
+
if (rawKey === "children") continue;
|
|
704
|
+
let key = rawKey;
|
|
705
|
+
if (rawKey === "name") {
|
|
706
|
+
if (explicitName !== void 0) {
|
|
707
|
+
console.warn('newNamedChild: "name" in props is ignored because a name argument was provided');
|
|
708
|
+
continue;
|
|
709
|
+
}
|
|
710
|
+
key = "_n";
|
|
711
|
+
} else if (rawKey === "createdAt") {
|
|
712
|
+
key = "_c";
|
|
713
|
+
}
|
|
714
|
+
let value = rawValue;
|
|
715
|
+
if (key === "_c") {
|
|
716
|
+
if (value instanceof Date) {
|
|
717
|
+
value = value.toISOString();
|
|
718
|
+
} else if (typeof value === "string") {
|
|
719
|
+
} else {
|
|
720
|
+
skipped.push(rawKey);
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
const isPrimitive = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean";
|
|
725
|
+
if (Array.isArray(value)) {
|
|
726
|
+
if (!value.every(isPrimitive)) {
|
|
727
|
+
skipped.push(rawKey);
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
} else if (typeof value === "object" && value !== null) {
|
|
731
|
+
if (!(value instanceof Y.Doc)) {
|
|
732
|
+
skipped.push(rawKey);
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
} else if (!isPrimitive(value)) {
|
|
736
|
+
skipped.push(rawKey);
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
out[key] = value;
|
|
740
|
+
}
|
|
741
|
+
if (skipped.length > 0) {
|
|
742
|
+
console.warn(`Some fields were skipped due to unsupported types: ${skipped.join(", ")}`);
|
|
743
|
+
}
|
|
744
|
+
return Object.keys(out).length > 0 ? out : null;
|
|
745
|
+
}
|
|
475
746
|
};
|
|
476
747
|
|
|
477
748
|
// src/StateVector.ts
|
|
@@ -660,7 +931,7 @@ var StateVector = class _StateVector {
|
|
|
660
931
|
};
|
|
661
932
|
|
|
662
933
|
// src/RepTree.ts
|
|
663
|
-
import * as
|
|
934
|
+
import * as Y2 from "yjs";
|
|
664
935
|
var _RepTree = class _RepTree {
|
|
665
936
|
/**
|
|
666
937
|
* @param peerId - The peer ID of the current client. Should be unique across all peers.
|
|
@@ -822,8 +1093,8 @@ var _RepTree = class _RepTree {
|
|
|
822
1093
|
setTransientVertexProperty(vertexId, key, value) {
|
|
823
1094
|
this.lamportClock++;
|
|
824
1095
|
let opValue;
|
|
825
|
-
if (value instanceof
|
|
826
|
-
const state =
|
|
1096
|
+
if (value instanceof Y2.Doc) {
|
|
1097
|
+
const state = Y2.encodeStateAsUpdate(value);
|
|
827
1098
|
opValue = {
|
|
828
1099
|
type: "yjs",
|
|
829
1100
|
value: state
|
|
@@ -839,8 +1110,8 @@ var _RepTree = class _RepTree {
|
|
|
839
1110
|
setVertexProperty(vertexId, key, value) {
|
|
840
1111
|
this.lamportClock++;
|
|
841
1112
|
let opValue;
|
|
842
|
-
if (value instanceof
|
|
843
|
-
const state =
|
|
1113
|
+
if (value instanceof Y2.Doc) {
|
|
1114
|
+
const state = Y2.encodeStateAsUpdate(value);
|
|
844
1115
|
opValue = {
|
|
845
1116
|
type: "yjs",
|
|
846
1117
|
value: state
|
|
@@ -1012,10 +1283,10 @@ var _RepTree = class _RepTree {
|
|
|
1012
1283
|
if (!propB) {
|
|
1013
1284
|
return false;
|
|
1014
1285
|
}
|
|
1015
|
-
if (propA.value instanceof
|
|
1016
|
-
const snapshotA =
|
|
1017
|
-
const snapshotB =
|
|
1018
|
-
if (!
|
|
1286
|
+
if (propA.value instanceof Y2.Doc && propB.value instanceof Y2.Doc) {
|
|
1287
|
+
const snapshotA = Y2.snapshot(propA.value);
|
|
1288
|
+
const snapshotB = Y2.snapshot(propB.value);
|
|
1289
|
+
if (!Y2.equalSnapshots(snapshotA, snapshotB)) {
|
|
1019
1290
|
return false;
|
|
1020
1291
|
}
|
|
1021
1292
|
} else if (propA.value !== propB.value) {
|
|
@@ -1119,7 +1390,7 @@ var _RepTree = class _RepTree {
|
|
|
1119
1390
|
const propertyKey = `${key}@${vertexId}`;
|
|
1120
1391
|
if (this.yjsObservers.has(propertyKey)) {
|
|
1121
1392
|
const existingDoc = this.getVertexProperty(vertexId, key);
|
|
1122
|
-
if (existingDoc instanceof
|
|
1393
|
+
if (existingDoc instanceof Y2.Doc) {
|
|
1123
1394
|
existingDoc.off("update", this.yjsObservers.get(propertyKey));
|
|
1124
1395
|
}
|
|
1125
1396
|
this.yjsObservers.delete(propertyKey);
|
|
@@ -1199,13 +1470,13 @@ var _RepTree = class _RepTree {
|
|
|
1199
1470
|
throw new Error("Unknown CRDT type");
|
|
1200
1471
|
}
|
|
1201
1472
|
const ydoc = targetVertex.getProperty(op.key);
|
|
1202
|
-
if (ydoc instanceof
|
|
1203
|
-
|
|
1473
|
+
if (ydoc instanceof Y2.Doc) {
|
|
1474
|
+
Y2.applyUpdate(ydoc, crdtValue.value);
|
|
1204
1475
|
} else {
|
|
1205
|
-
const newDoc = new
|
|
1476
|
+
const newDoc = new Y2.Doc();
|
|
1206
1477
|
this.setupYjsObserver(newDoc, op.targetId, op.key);
|
|
1207
1478
|
this.state.setProperty(op.targetId, op.key, newDoc);
|
|
1208
|
-
|
|
1479
|
+
Y2.applyUpdate(newDoc, crdtValue.value);
|
|
1209
1480
|
}
|
|
1210
1481
|
this.propertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);
|
|
1211
1482
|
this.reportOpAsApplied(op);
|
|
@@ -1311,6 +1582,17 @@ var _RepTree = class _RepTree {
|
|
|
1311
1582
|
this.stateVector = new StateVector();
|
|
1312
1583
|
}
|
|
1313
1584
|
}
|
|
1585
|
+
/**
|
|
1586
|
+
* Parses the vertex properties with a provided schema that has a `parse` method (e.g., Zod schema)
|
|
1587
|
+
*/
|
|
1588
|
+
parseVertex(vertexId, schema) {
|
|
1589
|
+
const propsArray = this.getVertexProperties(vertexId);
|
|
1590
|
+
const propsObject = {};
|
|
1591
|
+
for (const { key, value } of propsArray) {
|
|
1592
|
+
propsObject[key] = value;
|
|
1593
|
+
}
|
|
1594
|
+
return schema.parse(propsObject);
|
|
1595
|
+
}
|
|
1314
1596
|
};
|
|
1315
1597
|
_RepTree.NULL_VERTEX_ID = "0";
|
|
1316
1598
|
var RepTree = _RepTree;
|
|
@@ -1320,6 +1602,8 @@ export {
|
|
|
1320
1602
|
TreeState,
|
|
1321
1603
|
Vertex,
|
|
1322
1604
|
VertexState,
|
|
1605
|
+
bindVertex,
|
|
1606
|
+
defaultAliases,
|
|
1323
1607
|
isAnyPropertyOp,
|
|
1324
1608
|
isLWWPropertyOp,
|
|
1325
1609
|
isModifyPropertyOp,
|