reptree 0.2.2 → 0.2.3

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.d.cts CHANGED
@@ -89,6 +89,32 @@ 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
+ /**
111
+ * Returns a live object that proxies reads/writes to a vertex.
112
+ * - Reads reflect the latest CRDT state.
113
+ * - Writes persist to the CRDT.
114
+ * - If a schema is provided, writes are validated. If a field schema exists in `schema.shape`, field-level validation is applied.
115
+ */
116
+ declare function bindVertex<T extends Record<string, unknown>>(tree: RepTree, id: string, schema?: SchemaLike<T>): T;
117
+
92
118
  /**
93
119
  * A wrapper class for VertexState that provides a more convenient API
94
120
  * for working with vertices in a RepTree.
@@ -124,6 +150,8 @@ declare class Vertex {
124
150
  observeChildrenAsTypedArray<T>(listener: (children: T[]) => void): () => void;
125
151
  delete(): void;
126
152
  moveTo(parent: Vertex): void;
153
+ /** Returns a live reactive object bound to this vertex. Optional schema validates writes. */
154
+ bind<T extends Record<string, unknown>>(schema?: SchemaLike<T>): T;
127
155
  }
128
156
 
129
157
  /**
@@ -236,6 +264,12 @@ declare class RepTree {
236
264
  * When enabled, rebuilds the state vector from existing operations if needed
237
265
  */
238
266
  set stateVectorEnabled(value: boolean);
267
+ /**
268
+ * Parses the vertex properties with a provided schema that has a `parse` method (e.g., Zod schema)
269
+ */
270
+ parseVertex<T>(vertexId: string, schema: {
271
+ parse: (data: unknown) => T;
272
+ }): T;
239
273
  }
240
274
 
241
275
  declare class TreeState {
@@ -321,4 +355,4 @@ declare class StateVector {
321
355
 
322
356
  declare function uuid(): string;
323
357
 
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 };
358
+ 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, bindVertex, isAnyPropertyOp, isLWWPropertyOp, isModifyPropertyOp, isMoveVertexOp, newMoveVertexOp, newSetTransientVertexPropertyOp, newSetVertexPropertyOp, uuid };
package/dist/index.d.ts CHANGED
@@ -89,6 +89,32 @@ 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
+ /**
111
+ * Returns a live object that proxies reads/writes to a vertex.
112
+ * - Reads reflect the latest CRDT state.
113
+ * - Writes persist to the CRDT.
114
+ * - If a schema is provided, writes are validated. If a field schema exists in `schema.shape`, field-level validation is applied.
115
+ */
116
+ declare function bindVertex<T extends Record<string, unknown>>(tree: RepTree, id: string, schema?: SchemaLike<T>): T;
117
+
92
118
  /**
93
119
  * A wrapper class for VertexState that provides a more convenient API
94
120
  * for working with vertices in a RepTree.
@@ -124,6 +150,8 @@ declare class Vertex {
124
150
  observeChildrenAsTypedArray<T>(listener: (children: T[]) => void): () => void;
125
151
  delete(): void;
126
152
  moveTo(parent: Vertex): void;
153
+ /** Returns a live reactive object bound to this vertex. Optional schema validates writes. */
154
+ bind<T extends Record<string, unknown>>(schema?: SchemaLike<T>): T;
127
155
  }
128
156
 
129
157
  /**
@@ -236,6 +264,12 @@ declare class RepTree {
236
264
  * When enabled, rebuilds the state vector from existing operations if needed
237
265
  */
238
266
  set stateVectorEnabled(value: boolean);
267
+ /**
268
+ * Parses the vertex properties with a provided schema that has a `parse` method (e.g., Zod schema)
269
+ */
270
+ parseVertex<T>(vertexId: string, schema: {
271
+ parse: (data: unknown) => T;
272
+ }): T;
239
273
  }
240
274
 
241
275
  declare class TreeState {
@@ -321,4 +355,4 @@ declare class StateVector {
321
355
 
322
356
  declare function uuid(): string;
323
357
 
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 };
358
+ 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, bindVertex, isAnyPropertyOp, isLWWPropertyOp, isModifyPropertyOp, isMoveVertexOp, newMoveVertexOp, newSetTransientVertexPropertyOp, newSetVertexPropertyOp, uuid };
package/dist/index.js CHANGED
@@ -354,6 +354,57 @@ function uuid() {
354
354
  return removeDashes(crypto.randomUUID());
355
355
  }
356
356
 
357
+ // src/reactive.ts
358
+ function toObject(tree, id) {
359
+ const obj = {};
360
+ for (const { key, value } of tree.getVertexProperties(id)) obj[key] = value;
361
+ return obj;
362
+ }
363
+ function bindVertex(tree, id, schema) {
364
+ return new Proxy({}, {
365
+ get(_target, prop) {
366
+ if (typeof prop !== "string") return void 0;
367
+ return tree.getVertexProperty(id, prop);
368
+ },
369
+ set(_target, prop, value) {
370
+ if (typeof prop !== "string") return true;
371
+ if (schema?.shape && schema.shape[prop]) {
372
+ const field = schema.shape[prop];
373
+ if (field.safeParse) {
374
+ const res = field.safeParse(value);
375
+ if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);
376
+ value = res.data ?? value;
377
+ }
378
+ } else if (schema?.safeParse) {
379
+ const next = { ...toObject(tree, id), [prop]: value };
380
+ const res = schema.safeParse(next);
381
+ if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);
382
+ const parsed = res.data;
383
+ if (parsed && Object.prototype.hasOwnProperty.call(parsed, prop)) {
384
+ value = parsed[prop];
385
+ }
386
+ }
387
+ tree.setVertexProperty(id, prop, value);
388
+ return true;
389
+ },
390
+ deleteProperty(_target, prop) {
391
+ if (typeof prop !== "string") return true;
392
+ tree.setVertexProperty(id, prop, void 0);
393
+ return true;
394
+ },
395
+ has(_target, prop) {
396
+ if (typeof prop !== "string") return false;
397
+ return !!schema?.shape && Object.prototype.hasOwnProperty.call(schema.shape, prop);
398
+ },
399
+ ownKeys() {
400
+ return Object.keys(schema?.shape ?? {});
401
+ },
402
+ getOwnPropertyDescriptor() {
403
+ return { enumerable: true, configurable: true };
404
+ }
405
+ });
406
+ }
407
+
357
408
  // src/Vertex.ts
358
409
  var Vertex = class {
359
410
  constructor(tree, state) {
@@ -472,6 +523,10 @@ var Vertex = class {
472
523
  moveTo(parent) {
473
524
  this.tree.moveVertex(this.id, parent.id);
474
525
  }
526
+ /** Returns a live reactive object bound to this vertex. Optional schema validates writes. */
527
+ bind(schema) {
528
+ return bindVertex(this.tree, this.id, schema);
529
+ }
475
530
  };
476
531
 
477
532
  // src/StateVector.ts
@@ -1311,6 +1366,17 @@ var _RepTree = class _RepTree {
1311
1366
  this.stateVector = new StateVector();
1312
1367
  }
1313
1368
  }
1369
+ /**
1370
+ * Parses the vertex properties with a provided schema that has a `parse` method (e.g., Zod schema)
1371
+ */
1372
+ parseVertex(vertexId, schema) {
1373
+ const propsArray = this.getVertexProperties(vertexId);
1374
+ const propsObject = {};
1375
+ for (const { key, value } of propsArray) {
1376
+ propsObject[key] = value;
1377
+ }
1378
+ return schema.parse(propsObject);
1379
+ }
1314
1380
  };
1315
1381
  _RepTree.NULL_VERTEX_ID = "0";
1316
1382
  var RepTree = _RepTree;
@@ -1320,6 +1386,7 @@ export {
1320
1386
  TreeState,
1321
1387
  Vertex,
1322
1388
  VertexState,
1389
+ bindVertex,
1323
1390
  isAnyPropertyOp,
1324
1391
  isLWWPropertyOp,
1325
1392
  isModifyPropertyOp,