reptree 0.2.1 → 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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/OpId.ts","../src/operations.ts","../src/VertexState.ts","../src/TreeState.ts","../src/uuid.ts","../src/Vertex.ts","../src/StateVector.ts","../src/RepTree.ts"],"sourcesContent":["// Main class\nexport { RepTree } from './RepTree';\n\n// Core types and classes\nexport { Vertex } from './Vertex';\nexport { VertexState } from './VertexState';\nexport { TreeState } from './TreeState';\nexport { OpId } from './OpId';\nexport { StateVector } from './StateVector';\n\n// Types\nexport * from './treeTypes';\nexport * from './operations';\n\n// Utilities\nexport { default as uuid } from './uuid';","export class OpId {\n constructor(\n readonly counter: number,\n readonly peerId: string\n ) { }\n\n static compare(opIdA: OpId | string, opIdB: OpId | string): number {\n if (!(opIdA instanceof OpId)) {\n const parsedA = OpId.tryParseStr(opIdA);\n if (!parsedA) throw new Error(`Invalid OpId string: ${opIdA}`);\n opIdA = parsedA;\n }\n if (!(opIdB instanceof OpId)) {\n const parsedB = OpId.tryParseStr(opIdB);\n if (!parsedB) throw new Error(`Invalid OpId string: ${opIdB}`);\n opIdB = parsedB;\n }\n\n const counterA = opIdA.counter;\n const counterB = opIdB.counter;\n\n if (counterA > counterB) {\n return 1;\n } else if (counterA < counterB) {\n return -1;\n } else {\n return opIdA.peerId.localeCompare(opIdB.peerId);\n }\n }\n\n static equals(opIdA: OpId | string | null, opIdB: OpId | string | null): boolean {\n if (opIdA === opIdB) {\n return true;\n } else if (!opIdA || !opIdB) {\n return false;\n }\n\n return OpId.compare(opIdA, opIdB) === 0;\n }\n\n static tryParseStr(opIdStr: string): OpId {\n const parts = opIdStr.split('@');\n\n if (parts.length !== 2) {\n throw new Error(`Invalid OpId string: ${opIdStr}`);\n }\n\n return new OpId(parseInt(parts[0], 10), parts[1]);\n }\n \n isGreaterThan(opId: OpId | string): boolean {\n return OpId.compare(this, opId) === 1;\n }\n\n toString(): string {\n return `${this.counter}@${this.peerId}`;\n }\n}\n","import { OpId } from \"./OpId\";\nimport { type VertexPropertyTypeInOperation } from \"./treeTypes\";\n\nexport interface MoveVertex {\n id: OpId;\n targetId: string;\n parentId: string | null;\n}\n\nexport interface SetVertexProperty {\n id: OpId;\n targetId: string;\n key: string;\n value: VertexPropertyTypeInOperation;\n transient: boolean;\n}\n\nexport type VertexOperation = MoveVertex | SetVertexProperty;\n\nexport function isMoveVertexOp(op: VertexOperation): op is MoveVertex {\n return 'parentId' in op;\n}\n\nexport function isAnyPropertyOp(op: VertexOperation): op is SetVertexProperty {\n return 'key' in op;\n}\n\nexport function isLWWPropertyOp(op: VertexOperation): op is SetVertexProperty {\n return 'key' in op && 'value' in op && (!op.value || typeof op.value !== 'object' || !('type' in op.value));\n}\n\nexport function isModifyPropertyOp(op: VertexOperation): op is SetVertexProperty {\n return 'key' in op && 'value' in op && typeof op.value === 'object' && op.value !== null && 'type' in op.value;\n}\n\nexport function newMoveVertexOp(clock: number, peerId: string, targetId: string, parentId: string | null): MoveVertex {\n return { id: new OpId(clock, peerId), targetId, parentId };\n}\n\nexport function newSetVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty {\n return { id: new OpId(clock, peerId), targetId, key, value, transient: false };\n}\n\nexport function newSetTransientVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty {\n return { id: new OpId(clock, peerId), targetId, key, value, transient: true };\n}","import type { TreeVertexId, TreeVertexProperty, VertexPropertyType } from \"./treeTypes\";\n\nexport class VertexState {\n readonly id: string;\n parentId: TreeVertexId | null;\n private properties: TreeVertexProperty[];\n private transientProperties: TreeVertexProperty[];\n children: string[];\n\n constructor(id: string, parentId: TreeVertexId | null) {\n this.id = id;\n this.parentId = parentId;\n this.properties = [];\n this.transientProperties = [];\n this.children = [];\n }\n\n setProperty(key: string, value: any): void {\n const existingPropIndex = this.properties.findIndex(p => p.key === key);\n if (existingPropIndex !== -1) {\n if (value !== undefined) {\n // Update existing property\n this.properties[existingPropIndex] = { key, value };\n } else {\n // Remove existing property\n this.removeProperty(key);\n }\n } else {\n if (value !== undefined) {\n // Add new property\n this.properties.push({ key, value });\n }\n }\n }\n\n setTransientProperty(key: string, value: any): void {\n const existingPropIndex = this.transientProperties.findIndex(p => p.key === key);\n if (existingPropIndex !== -1) {\n if (value !== undefined) {\n // Update existing property\n this.transientProperties[existingPropIndex] = { key, value };\n } else {\n // Remove existing property\n this.removeTransientProperty(key);\n }\n } else {\n if (value !== undefined) {\n // Add new property\n this.transientProperties.push({ key, value });\n }\n }\n }\n\n getProperty(key: string, includingTransient: boolean = true): VertexPropertyType | undefined {\n if (includingTransient) {\n const transientProp = this.transientProperties.find(p => p.key === key);\n if (transientProp) {\n return transientProp.value;\n }\n }\n\n return this.properties.find(p => p.key === key)?.value;\n }\n\n getAllProperties(includingTransient: boolean = true): ReadonlyArray<TreeVertexProperty> {\n if (!includingTransient) {\n return this.properties;\n }\n\n const result: TreeVertexProperty[] = [];\n const seenKeys = new Set<string>();\n\n // Add transient properties first\n for (const prop of this.transientProperties) {\n result.push(prop);\n seenKeys.add(prop.key);\n }\n\n // Add permanent properties that don't have a transient override\n for (const prop of this.properties) {\n if (!seenKeys.has(prop.key)) {\n result.push(prop);\n }\n }\n\n return result;\n }\n\n removeProperty(key: string): void {\n this.properties = this.properties.filter(p => p.key !== key);\n }\n\n removeTransientProperty(key: string): void {\n this.transientProperties = this.transientProperties.filter(p => p.key !== key);\n }\n}\n","import type { TreeVertexId, VertexChangeEvent, VertexPropertyChangeEvent, VertexChildrenChangeEvent, VertexMoveEvent } from \"./treeTypes\";\nimport { VertexState } from \"./VertexState\";\n\nexport class TreeState {\n private vertices: Map<TreeVertexId, VertexState>;\n private changeCallbacks: Map<TreeVertexId, Set<(events: VertexChangeEvent[]) => void>> = new Map();\n private globalChangeCallbacks: Set<(events: VertexChangeEvent[]) => void> = new Set();\n\n private batchTickInterval: NodeJS.Timeout;\n private batchedEvents: Map<TreeVertexId, VertexChangeEvent[]> = new Map();\n\n constructor() {\n this.vertices = new Map();\n\n this.batchTickInterval = setInterval(() => {\n this.processBatchedEvents();\n }, 33.3);\n }\n\n dispose() {\n clearInterval(this.batchTickInterval);\n }\n\n private processBatchedEvents() {\n for (const [vertexId, events] of this.batchedEvents) {\n // Get last property events per key and last move/children events\n let lastMoveEvent: VertexMoveEvent | null = null;\n let lastChildrenEvent: VertexChildrenChangeEvent | null = null;\n const propertyEventsByKey = new Map<string, VertexPropertyChangeEvent>();\n\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i];\n if (!lastMoveEvent && event.type === 'move') lastMoveEvent = event as VertexMoveEvent;\n if (!lastChildrenEvent && event.type === 'children') lastChildrenEvent = event as VertexChildrenChangeEvent;\n if (event.type === 'property') {\n const propertyEvent = event as VertexPropertyChangeEvent;\n if (!propertyEventsByKey.has(propertyEvent.key)) {\n propertyEventsByKey.set(propertyEvent.key, propertyEvent);\n }\n }\n }\n\n // Combine all events with move and children events first\n const filteredEvents = [\n ...(lastMoveEvent ? [lastMoveEvent] : []),\n ...(lastChildrenEvent ? [lastChildrenEvent] : []),\n ...propertyEventsByKey.values()\n ];\n\n this.globalChangeCallbacks.forEach(listener => listener(filteredEvents));\n this.changeCallbacks.get(vertexId)?.forEach(listener => listener(filteredEvents));\n }\n\n this.batchedEvents.clear();\n }\n\n getAllVertices(): ReadonlyArray<VertexState> {\n return Array.from(this.vertices.values());\n }\n\n getVertex(id: string): VertexState | undefined {\n return this.vertices.get(id);\n }\n\n getChildrenIds(vertexId: TreeVertexId): string[] {\n return this.getVertex(vertexId)?.children ?? [];\n }\n\n getChildren(vertexId: TreeVertexId): VertexState[] {\n return this.getChildrenIds(vertexId)\n .map(id => {\n const vertex = this.vertices.get(id);\n return vertex ? vertex : undefined;\n })\n .filter(vertex => vertex !== undefined)\n .sort((a, b) => {\n const aDate = a.getProperty('_c') as string;\n const bDate = b.getProperty('_c') as string;\n if (!aDate) return -1;\n if (!bDate) return 1;\n return new Date(aDate).getTime() - new Date(bDate).getTime();\n }) as VertexState[];\n }\n\n moveVertex(vertexId: TreeVertexId, newParentId: TreeVertexId | null): VertexState {\n let vertex = this.getVertex(vertexId);\n // Undefined if the vertex is new\n const prevParentId = vertex ? vertex.parentId : undefined;\n if (!vertex) {\n vertex = new VertexState(vertexId, newParentId);\n this.vertices.set(vertexId, vertex);\n }\n\n if (prevParentId === newParentId) {\n return vertex;\n }\n\n vertex.parentId = newParentId;\n\n let childrenInNewParent: string[] | null = null;\n let childrenInOldParent: string[] | null = null;\n\n // Update children arrays in vertices\n if (prevParentId) {\n const oldParentVertex = this.getVertex(prevParentId);\n if (oldParentVertex) {\n oldParentVertex.children = oldParentVertex.children.filter(child => child !== vertexId);\n childrenInOldParent = oldParentVertex.children;\n } else {\n console.error(`Old parent vertex not found for ${prevParentId}`);\n }\n }\n\n if (newParentId !== null) {\n const newParentVertex = this.vertices.get(newParentId);\n if (newParentVertex) {\n newParentVertex.children.push(vertexId);\n childrenInNewParent = newParentVertex.children;\n } else {\n console.error(`New parent vertex not found for ${newParentId}`);\n }\n }\n\n // We notify the listeners in the end so that they have the final state of the tree\n\n this.notifyChange({\n type: 'move',\n vertexId: vertexId,\n oldParentId: prevParentId,\n newParentId,\n } as VertexMoveEvent);\n\n if (childrenInNewParent !== null && newParentId !== null) {\n this.notifyChange({\n type: 'children',\n vertexId: newParentId,\n children: childrenInNewParent.map(id => this.vertices.get(id)!),\n } as VertexChildrenChangeEvent);\n }\n\n if (childrenInOldParent !== null && prevParentId) {\n this.notifyChange({\n type: 'children',\n vertexId: prevParentId,\n children: childrenInOldParent.map(id => this.vertices.get(id)!),\n } as VertexChildrenChangeEvent);\n }\n\n return vertex;\n }\n\n setProperty(vertexId: string, key: string, value: any) {\n const vertex = this.getVertex(vertexId);\n if (!vertex) {\n throw new Error(`Vertex ${vertexId} not found`);\n }\n\n vertex.setProperty(key, value);\n\n this.notifyChange({\n type: 'property',\n vertexId: vertexId,\n key,\n value,\n } as VertexPropertyChangeEvent);\n\n if (vertex.parentId !== null) {\n this.notifyChange({\n type: 'children',\n vertexId: vertex.parentId,\n children: [vertex], // @TODO: shoulld I set all children or rename this property?\n } as VertexChildrenChangeEvent);\n }\n }\n\n setTransientProperty(vertexId: string, key: string, value: any) {\n const vertex = this.getVertex(vertexId);\n if (vertex) {\n vertex.setTransientProperty(key, value);\n }\n\n // @TODO: add info that it's a transient property\n this.notifyChange({\n type: 'property',\n vertexId: vertexId,\n key,\n value,\n } as VertexPropertyChangeEvent);\n }\n\n addChangeCallback(vertexId: TreeVertexId, listener: (events: VertexChangeEvent[]) => void) {\n if (!this.changeCallbacks.has(vertexId)) {\n this.changeCallbacks.set(vertexId, new Set());\n }\n this.changeCallbacks.get(vertexId)!.add(listener);\n }\n\n removeChangeCallback(vertexId: TreeVertexId, listener: (events: VertexChangeEvent[]) => void) {\n this.changeCallbacks.get(vertexId)?.delete(listener);\n }\n\n addGlobalChangeCallback(listener: (events: VertexChangeEvent[]) => void) {\n this.globalChangeCallbacks.add(listener);\n }\n\n removeGlobalChangeCallback(listener: (events: VertexChangeEvent[]) => void) {\n this.globalChangeCallbacks.delete(listener);\n }\n\n private notifyChange(event: VertexChangeEvent) {\n let events = this.batchedEvents.get(event.vertexId);\n if (!events) {\n events = [];\n this.batchedEvents.set(event.vertexId, events);\n }\n\n events.push(event);\n\n // @TODO: have immediate events\n //this.globalChangeCallbacks.forEach(listener => listener(event));\n //this.changeCallbacks.get(event.vertexId)?.forEach(listener => listener(event));\n }\n\n printTree(vertexId: TreeVertexId, indent: string = \"\", isLast: boolean = true): string {\n const prefix = indent + (isLast ? \"└── \" : \"├── \");\n let result = prefix + vertexId + \"\\n\";\n\n let vertexName: string | null = null;\n\n if (vertexId !== null) {\n const vertex = this.getVertex(vertexId);\n if (vertex) {\n for (const prop of vertex.getAllProperties()) {\n if (prop.key === \"_n\") {\n vertexName = prop.value as string;\n //continue;\n }\n\n const propPrefix = indent + (isLast ? \" \" : \"│ \") + \"• \";\n result += `${propPrefix}${prop.key}: ${JSON.stringify(prop.value)}\\n`;\n }\n }\n }\n\n // Get children and sort them for deterministic output\n const children = this.getChildrenIds(vertexId);\n const sortedChildren = [...children].sort((a, b) => {\n // Sort by name if available\n const vertexA = this.getVertex(a);\n const vertexB = this.getVertex(b);\n \n const nameA = vertexA?.getProperty('_n') as string | undefined;\n const nameB = vertexB?.getProperty('_n') as string | undefined;\n \n // If both have names, compare them\n if (nameA && nameB) {\n return nameA.localeCompare(nameB);\n }\n \n // If only one has a name, prioritize the one with a name\n if (nameA) return -1;\n if (nameB) return 1;\n \n // Fall back to sorting by ID for consistent output\n return a.localeCompare(b);\n });\n \n for (let i = 0; i < sortedChildren.length; i++) {\n const childId = sortedChildren[i];\n const isLastChild = i === sortedChildren.length - 1;\n result += this.printTree(childId, indent + (isLast ? \" \" : \"│ \"), isLastChild);\n }\n\n return result;\n }\n}","const removeDashes = (guid: string) => guid.replace(/-/g, '');\n\nexport default function uuid(): string {\n return removeDashes(crypto.randomUUID());\n}","import type { VertexState } from \"./VertexState\";\nimport type { RepTree } from \"./RepTree\";\nimport type { TreeVertexProperty, VertexChangeEvent, VertexPropertyType } from \"./treeTypes\";\n\n/**\n * A wrapper class for VertexState that provides a more convenient API\n * for working with vertices in a RepTree.\n */\nexport class Vertex {\n constructor(\n private tree: RepTree,\n private state: VertexState\n ) { }\n\n get id(): string {\n return this.state.id;\n }\n\n get name(): string | undefined {\n return this.getProperty('_n') as string | undefined;\n }\n\n set name(name: string) {\n this.tree.setVertexProperty(this.id, '_n', name);\n }\n\n get createdAt(): Date {\n const createdAt = this.getProperty('_c') as string;\n if (!createdAt) {\n return new Date(0);\n }\n return new Date(createdAt);\n }\n\n get path(): string {\n //return this.tree.getVertexPath(this.id);\n throw new Error('Not implemented');\n }\n\n get parentId(): string | null {\n return this.state.parentId;\n }\n\n get parent(): Vertex | undefined {\n if (!this.parentId) {\n return undefined;\n }\n\n return this.tree.getVertex(this.parentId);\n }\n\n get children(): Vertex[] {\n return this.tree.getChildren(this.id);\n }\n\n get childrenIds(): string[] {\n return this.tree.getChildrenIds(this.id);\n }\n\n getAsTypedObject<T>(): T {\n return this.getProperties() as T;\n }\n\n getChildrenAsTypedArray<T>(): T[] {\n return this.children.map(v => v.getAsTypedObject<T>());\n }\n\n newChild(props?: Record<string, VertexPropertyType> | object | null): Vertex {\n const typedProps = props as Record<string, VertexPropertyType> | null;\n return this.tree.newVertex(this.id, typedProps);\n }\n\n newNamedChild(name: string, props?: Record<string, VertexPropertyType> | object | null): Vertex {\n const typedProps = props as Record<string, VertexPropertyType> | null;\n return this.tree.newNamedVertex(this.id, name, typedProps);\n }\n\n setProperty(key: string, value: VertexPropertyType): void {\n // First check if the property is already set (not including transient properties)\n const existingValue = this.getProperty(key, false);\n if (existingValue === value) {\n return;\n }\n\n this.tree.setVertexProperty(this.id, key, value);\n }\n\n setTransientProperty(key: string, value: VertexPropertyType): void {\n // First check if the property is already set\n const existingValue = this.getProperty(key);\n if (existingValue === value) {\n return;\n }\n\n this.tree.setTransientVertexProperty(this.id, key, value);\n }\n\n setProperties(props: Record<string, VertexPropertyType> | object): void {\n for (const [key, value] of Object.entries(props)) {\n this.setProperty(key, value);\n }\n }\n\n getProperty(key: string, includingTransient: boolean = true): VertexPropertyType | undefined {\n return this.tree.getVertexProperty(this.id, key, includingTransient);\n }\n\n getProperties(): Record<string, VertexPropertyType> {\n const props: Record<string, VertexPropertyType> = {};\n this.tree.getVertexProperties(this.id).forEach(p => {\n props[p.key] = p.value;\n });\n return props;\n }\n\n findAllChildrenWithProperty(key: string, value: VertexPropertyType): Vertex[] {\n return this.children.filter(c => c.getProperty(key) === value);\n }\n\n findFirstChildVertexWithProperty(key: string, value: VertexPropertyType): Vertex | undefined {\n return this.children.find(c => c.getProperty(key) === value);\n }\n\n findFirstTypedChildWithProperty<T>(key: string, value: VertexPropertyType): T | undefined {\n return this.findFirstChildVertexWithProperty(key, value)?.getAsTypedObject<T>();\n }\n\n findAllTypedChildrenWithProperty<T>(key: string, value: VertexPropertyType): T[] {\n return this.findAllChildrenWithProperty(key, value).map(c => c.getAsTypedObject<T>());\n }\n\n observe(listener: (events: VertexChangeEvent[]) => void): () => void {\n const unobserve = this.tree.observe(this.id, listener);\n return () => unobserve();\n }\n\n observeChildren(listener: (children: Vertex[]) => void): () => void {\n const unobserve = this.tree.observe(this.id, (events: VertexChangeEvent[]) => {\n if (events.some(e => e.type === 'children')) {\n listener(this.children);\n }\n });\n return () => unobserve();\n }\n\n observeChildrenAsTypedArray<T>(listener: (children: T[]) => void): () => void {\n return this.observeChildren((children) => {\n listener(children.map(c => c.getProperties() as unknown as T));\n });\n }\n\n delete(): void {\n this.tree.deleteVertex(this.id);\n }\n\n moveTo(parent: Vertex): void {\n this.tree.moveVertex(this.id, parent.id);\n }\n} ","import { OpId } from \"./OpId\";\nimport type { OpIdRange } from \"./treeTypes\";\nimport type { VertexOperation } from \"./operations\";\n\n/**\n * Helper function to subtract one set of ranges from another.\n * Returns the ranges in A that are not in B.\n * Assumes ranges in both A and B are sorted and non-overlapping.\n */\nexport function subtractRanges(rangesA: number[][], rangesB: number[][]): number[][] {\n if (rangesB.length === 0) return rangesA.map(r => [...r]); // Return a copy\n if (rangesA.length === 0) return []; // If A is empty, nothing to subtract\n\n const result: number[][] = [];\n let indexB = 0;\n\n for (const rangeA of rangesA) {\n let currentStart = rangeA[0];\n const endA = rangeA[1];\n\n // Iterate through ranges in B that could potentially overlap with rangeA\n while (indexB < rangesB.length && rangesB[indexB][1] < currentStart) {\n // Skip ranges in B that are entirely before the current start\n indexB++;\n }\n\n while (indexB < rangesB.length && rangesB[indexB][0] <= endA) {\n const startB = rangesB[indexB][0];\n const endB = rangesB[indexB][1];\n\n // If there's a gap before this range in B starts\n if (currentStart < startB) {\n // Add the portion of rangeA before the overlap\n result.push([currentStart, Math.min(endA, startB - 1)]);\n }\n\n // Move current start past this range in B\n currentStart = Math.max(currentStart, endB + 1);\n\n // If we've gone past the end of rangeA, break inner loop\n if (currentStart > endA) break;\n\n // If the current rangeB ends after rangeA, we don't need to check further ranges in B for this rangeA\n if (endB >= endA) break;\n\n // Only advance indexB if the current rangeB is fully processed relative to currentStart\n if (endB < currentStart) {\n indexB++;\n } else if (startB >= currentStart) {\n indexB++;\n }\n }\n\n // If there's a remaining part of rangeA after processing overlaps with B\n if (currentStart <= endA) {\n result.push([currentStart, endA]);\n }\n }\n\n return result;\n}\n\n/**\n * StateVector tracks operations that have been applied using a range-based representation.\n * It's used for synchronization between peers to determine which operations need to be sent.\n */\nexport class StateVector {\n private ranges: Record<string, number[][]> = {};\n\n /**\n * Creates a new StateVector.\n * @param initialState Optional initial state to copy from\n */\n constructor(initialState: Record<string, number[][]> = {}) {\n // Create a deep copy of the initial state\n for (const [peerId, peerRanges] of Object.entries(initialState)) {\n this.ranges[peerId] = peerRanges.map(range => [...range]);\n }\n }\n\n /**\n * Updates the state vector with a newly applied operation.\n * Assumes ranges are sorted and non-overlapping.\n * \n * @param peerId The peer ID of the operation\n * @param counter The counter value of the operation\n */\n update(peerId: string, counter: number): void {\n // Initialize ranges array for this peer if it doesn't exist\n if (!this.ranges[peerId]) {\n this.ranges[peerId] = [];\n }\n\n const ranges = this.ranges[peerId];\n\n // Case 1: No ranges yet\n if (ranges.length === 0) {\n ranges.push([counter, counter]);\n return;\n }\n\n let rangeExtendedOrMerged = false;\n let insertIndex = -1;\n\n for (let i = 0; i < ranges.length; i++) {\n const range = ranges[i];\n\n // If counter is already in a range, do nothing\n if (counter >= range[0] && counter <= range[1]) {\n rangeExtendedOrMerged = true;\n break;\n }\n\n // If counter is one less than range start, extend range start\n if (counter === range[0] - 1) {\n range[0] = counter;\n rangeExtendedOrMerged = true;\n // Check if this range now merges with the previous range\n if (i > 0 && range[0] === ranges[i - 1][1] + 1) {\n ranges[i - 1][1] = range[1]; // Merge into previous\n ranges.splice(i, 1); // Remove current\n }\n break;\n }\n\n // If counter is one more than range end, extend range end\n if (counter === range[1] + 1) {\n range[1] = counter;\n rangeExtendedOrMerged = true;\n // Check if this range now merges with the next range\n if (i < ranges.length - 1 && range[1] + 1 === ranges[i + 1][0]) {\n range[1] = ranges[i + 1][1]; // Merge next into current\n ranges.splice(i + 1, 1); // Remove next\n }\n break;\n }\n\n // Keep track of where to insert if no extension/merge happens\n if (counter < range[0] && insertIndex === -1) {\n insertIndex = i;\n }\n }\n\n // If we couldn't extend or merge any range, add a new one\n if (!rangeExtendedOrMerged) {\n if (insertIndex === -1) {\n // If counter is greater than all existing ranges, add to the end\n insertIndex = ranges.length;\n }\n ranges.splice(insertIndex, 0, [counter, counter]);\n // After inserting, check if the new range merges with neighbors\n // Merge with previous range if possible\n if (insertIndex > 0 && ranges[insertIndex][0] === ranges[insertIndex - 1][1] + 1) {\n ranges[insertIndex - 1][1] = ranges[insertIndex][1];\n ranges.splice(insertIndex, 1);\n insertIndex--; // Adjust index after merging\n }\n // Merge with next range if possible (use adjusted insertIndex)\n if (insertIndex < ranges.length - 1 && ranges[insertIndex][1] + 1 === ranges[insertIndex + 1][0]) {\n ranges[insertIndex][1] = ranges[insertIndex + 1][1];\n ranges.splice(insertIndex + 1, 1);\n }\n }\n }\n\n /**\n * Updates the state vector with a newly applied operation.\n * \n * @param op The operation that was just applied\n */\n updateFromOp(op: VertexOperation): void {\n this.update(op.id.peerId, op.id.counter);\n }\n\n /**\n * Returns the current state vector.\n * Returns a readonly reference to the internal state.\n */\n getState(): Readonly<Record<string, number[][]>> {\n return this.ranges;\n }\n\n /**\n * Calculates which operation ranges we have that the other state vector is missing\n * by comparing state vectors.\n * \n * @param other The other state vector to compare against\n * @returns Array of operation ID ranges that we have but they don't\n */\n diff(other: StateVector): OpIdRange[] {\n const missingRanges: OpIdRange[] = [];\n const theirState = other.getState();\n\n // Check what we have that they don't have\n for (const [peerId, ourRanges] of Object.entries(this.ranges)) {\n const theirRanges = theirState[peerId] || [];\n\n // Calculate ranges we have that they don't\n const missing = subtractRanges(ourRanges, theirRanges);\n\n // Convert to OpIdRange format\n for (const [start, end] of missing) {\n // Ensure the range is valid (start <= end)\n if (start <= end) {\n missingRanges.push({\n peerId,\n start,\n end\n });\n }\n }\n }\n\n return missingRanges;\n }\n\n /**\n * Checks if the state vector contains the given operation ID\n * \n * @param opId The operation ID to check\n * @returns true if the operation is in the state vector, false otherwise\n */\n contains(opId: OpId): boolean {\n const peerId = opId.peerId;\n const counter = opId.counter;\n\n if (!this.ranges[peerId]) {\n return false;\n }\n\n for (const [start, end] of this.ranges[peerId]) {\n if (counter >= start && counter <= end) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Creates a copy of this state vector\n */\n clone(): StateVector {\n return new StateVector(this.ranges);\n }\n\n /**\n * Builds a state vector from an array of operations\n * @param operations The operations to build the state vector from\n * @returns A new StateVector instance\n */\n static fromOperations(operations: ReadonlyArray<VertexOperation>): StateVector {\n const stateVector = new StateVector();\n for (const op of operations) {\n stateVector.updateFromOp(op);\n }\n return stateVector;\n }\n} ","import {\n newMoveVertexOp,\n type MoveVertex,\n type SetVertexProperty,\n isMoveVertexOp,\n isModifyPropertyOp,\n type VertexOperation,\n newSetVertexPropertyOp,\n newSetTransientVertexPropertyOp,\n isAnyPropertyOp\n} from \"./operations\";\nimport type { VertexPropertyType, VertexPropertyTypeInOperation, CRDTType, TreeVertexProperty, VertexChangeEvent, TreeVertexId, VertexMoveEvent } from \"./treeTypes\";\nimport { VertexState } from \"./VertexState\";\nimport { TreeState } from \"./TreeState\";\nimport { OpId } from \"./OpId\";\nimport uuid from \"./uuid\";\nimport { Vertex } from './Vertex';\nimport { StateVector } from './StateVector';\nimport * as Y from 'yjs';\n\ntype PropertyKeyAtVertexId = `${string}@${TreeVertexId}`;\n\n/**\n * RepTree is a tree data structure for storing vertices with properties.\n * It uses 2 conflict-free replicated data types (CRDTs) to manage seamless replication between peers.\n * A move tree CRDT is used for the tree structure (https://martin.kleppmann.com/papers/move-op.pdf).\n * A last writer wins (LWW) CRDT is used for properties.\n */\nexport class RepTree {\n private static NULL_VERTEX_ID = '0';\n\n readonly peerId: string;\n private rootVertexId: string | undefined;\n\n private lamportClock = 0;\n private state: TreeState;\n private moveOps: MoveVertex[] = [];\n private setPropertyOps: SetVertexProperty[] = [];\n private propertiesAndTheirOpIds: Map<PropertyKeyAtVertexId, OpId> = new Map();\n private transientPropertiesAndTheirOpIds: Map<PropertyKeyAtVertexId, OpId> = new Map();\n private yjsObservers: Map<PropertyKeyAtVertexId, (update: Uint8Array, origin: any, doc: Y.Doc, transaction: Y.Transaction) => void> = new Map();\n private localOps: VertexOperation[] = [];\n private pendingMovesWithMissingParent: Map<string, MoveVertex[]> = new Map();\n private pendingPropertiesWithMissingVertex: Map<string, SetVertexProperty[]> = new Map();\n private knownOps: Set<string> = new Set();\n private parentIdBeforeMove: Map<OpId, string | null | undefined> = new Map();\n private opAppliedCallbacks: ((op: VertexOperation) => void)[] = [];\n\n // State vector tracking operations from each peer\n private stateVector: StateVector;\n private _stateVectorEnabled: boolean = true;\n\n /**\n * @param peerId - The peer ID of the current client. Should be unique across all peers.\n * @param ops - The operations to replicate an existing tree, if not provided - an empty tree will be created without a root vertex\n */\n constructor(peerId: string, ops?: ReadonlyArray<VertexOperation>) {\n this.peerId = peerId;\n this.state = new TreeState();\n\n // Initialize state vector (enabled by default)\n this.stateVector = new StateVector();\n\n if (ops && ops.length > 0) {\n this.applyOps(ops);\n\n const root = this.root;\n if (!root) {\n throw new Error('There has to be a root vertex in the operations');\n }\n\n // @TODO: validate the tree structure, throw an exception if it's invalid\n }\n // @TODO: remove it? It creates an extra null vertex op in every new empty tree. Or is it ok?\n else {\n this.ensureNullVertex();\n }\n }\n\n get root(): Vertex | undefined {\n if (!this.rootVertexId) {\n const vertices = this.state.getAllVertices();\n for (const vertex of vertices) {\n if (vertex.parentId === null && vertex.id !== RepTree.NULL_VERTEX_ID) {\n this.rootVertexId = vertex.id;\n return new Vertex(this, vertex);\n }\n }\n\n return undefined;\n }\n\n const rootVertex = this.state.getVertex(this.rootVertexId);\n if (!rootVertex) {\n throw new Error(\"Root vertex not found\");\n }\n\n return new Vertex(this, rootVertex);\n }\n\n replicate(newPeerId: string): RepTree {\n return new RepTree(newPeerId, this.getAllOps());\n }\n\n getMoveOps(): ReadonlyArray<MoveVertex> {\n return this.moveOps;\n }\n\n getAllOps(): ReadonlyArray<VertexOperation> {\n return [...this.moveOps, ...this.setPropertyOps];\n }\n\n getVertex(vertexId: string): Vertex | undefined {\n const vertex = this.state.getVertex(vertexId);\n return vertex ? new Vertex(this, vertex) : undefined;\n }\n\n getAllVertices(): ReadonlyArray<Vertex> {\n return this.state.getAllVertices().map(v => new Vertex(this, v));\n }\n\n getParent(vertexId: string): Vertex | undefined {\n const parentId = this.state.getVertex(vertexId)?.parentId;\n const parent = parentId ? this.state.getVertex(parentId) : undefined;\n return parent ? new Vertex(this, parent) : undefined;\n }\n\n getChildren(vertexId: string): Vertex[] {\n return this.state.getChildren(vertexId).map(v => new Vertex(this, v));\n }\n\n getChildrenIds(vertexId: string): string[] {\n return this.state.getChildrenIds(vertexId);\n }\n\n getAncestors(vertexId: string): Vertex[] {\n const ancestors: Vertex[] = [];\n let currentVertex = this.state.getVertex(vertexId);\n\n while (currentVertex && currentVertex.parentId) {\n const parentVertex = this.state.getVertex(currentVertex.parentId);\n if (parentVertex) {\n ancestors.push(new Vertex(this, parentVertex));\n currentVertex = parentVertex;\n } else {\n break;\n }\n }\n\n return ancestors;\n }\n\n getVertexProperty(vertexId: string, key: string, includingTransient: boolean = true): VertexPropertyType | undefined {\n const vertex = this.state.getVertex(vertexId);\n if (!vertex) {\n return undefined;\n }\n\n return vertex.getProperty(key, includingTransient);\n }\n\n getVertexProperties(vertexId: string): Readonly<TreeVertexProperty[]> {\n const vertex = this.state.getVertex(vertexId);\n if (!vertex) {\n return [];\n }\n\n return vertex.getAllProperties();\n }\n\n /**\n * Returns all local operations and clears the local operations list.\n * Can be used to get all operations that were generated from this peer and need to be sent to other peers.\n */\n popLocalOps(): VertexOperation[] {\n const ops = this.localOps;\n this.localOps = [];\n return ops;\n }\n\n createRoot(): Vertex {\n if (this.rootVertexId) {\n throw new Error('Root vertex already exists');\n }\n\n this.rootVertexId = this.newVertexInternalWithUUID(null);\n\n const rootVertex = this.state.getVertex(this.rootVertexId);\n if (!rootVertex) {\n throw new Error(\"Root vertex not found\");\n }\n\n return new Vertex(this, rootVertex);\n }\n newVertex(parentId: string, props: Record<string, VertexPropertyType> | object | null = null): Vertex {\n const typedProps = props as Record<string, VertexPropertyType> | null;\n const vertexId = this.newVertexInternalWithUUID(parentId);\n if (typedProps) {\n this.setVertexProperties(vertexId, typedProps);\n }\n\n const vertex = this.state.getVertex(vertexId);\n if (!vertex) {\n throw new Error('Failed to create vertex');\n }\n return new Vertex(this, vertex);\n }\n\n newNamedVertex(parentId: string, name: string, props: Record<string, VertexPropertyType> | object | null = null): Vertex {\n const typedProps = props as Record<string, VertexPropertyType> | null;\n const vertexId = this.newVertexInternalWithUUID(parentId);\n if (typedProps) {\n this.setVertexProperties(vertexId, typedProps);\n }\n this.setVertexProperty(vertexId, '_n', name);\n\n const vertex = this.state.getVertex(vertexId);\n if (!vertex) {\n throw new Error('Failed to create named vertex');\n }\n return new Vertex(this, vertex);\n }\n\n moveVertex(vertexId: string, parentId: string) {\n this.lamportClock++;\n const op = newMoveVertexOp(this.lamportClock, this.peerId, vertexId, parentId);\n this.localOps.push(op);\n this.applyMove(op);\n }\n\n deleteVertex(vertexId: string) {\n this.moveVertex(vertexId, RepTree.NULL_VERTEX_ID);\n }\n\n setTransientVertexProperty(vertexId: string, key: string, value: VertexPropertyType) {\n this.lamportClock++;\n\n // Convert Y.Doc to CRDTType for operation\n let opValue: VertexPropertyTypeInOperation;\n if (value instanceof Y.Doc) {\n const state = Y.encodeStateAsUpdate(value);\n opValue = {\n type: \"yjs\",\n value: state\n };\n\n // Set up observer for future changes\n this.setupYjsObserver(value, vertexId, key);\n } else {\n // Regular values pass through unchanged\n opValue = value as VertexPropertyTypeInOperation;\n }\n\n const op = newSetTransientVertexPropertyOp(this.lamportClock, this.peerId, vertexId, key, opValue);\n this.localOps.push(op);\n this.applyProperty(op);\n }\n\n setVertexProperty(vertexId: string, key: string, value: VertexPropertyType) {\n this.lamportClock++;\n\n // Convert Y.Doc to CRDTType for operation\n let opValue: VertexPropertyTypeInOperation;\n if (value instanceof Y.Doc) {\n const state = Y.encodeStateAsUpdate(value);\n opValue = {\n type: \"yjs\",\n value: state\n };\n\n // Set up observer for future changes\n this.setupYjsObserver(value, vertexId, key);\n } else {\n // Regular values pass through unchanged\n opValue = value as VertexPropertyTypeInOperation;\n }\n\n const op = newSetVertexPropertyOp(this.lamportClock, this.peerId, vertexId, key, opValue);\n this.localOps.push(op);\n this.applyProperty(op);\n }\n\n setVertexProperties(vertexId: string, props: Record<string, VertexPropertyType> | object) {\n const typedProps = props as Record<string, VertexPropertyType>;\n for (const [key, value] of Object.entries(typedProps)) {\n this.setVertexProperty(vertexId, key, value);\n }\n }\n\n getVertexByPath(path: string): Vertex | undefined {\n // Let's remove '/' at the start and at the end of the path\n path = path.replace(/^\\/+/, '');\n path = path.replace(/\\/+$/, '');\n\n const pathParts = path.split('/');\n\n if (!this.rootVertexId) {\n return undefined;\n }\n\n const root = this.state.getVertex(this.rootVertexId);\n if (!root) {\n throw new Error('The root vertex is not found');\n }\n\n const vertex = this.getVertexByPathArray(new Vertex(this, root), pathParts);\n return vertex;\n }\n\n private getVertexByPathArray(vertex: Vertex, path: string[]): Vertex | undefined {\n if (path.length === 0) {\n return vertex ?? undefined;\n }\n\n const targetName = path[0];\n // Now, search recursively by name '_n' in children until the path is empty or not found.\n const children = this.getChildren(vertex.id);\n for (const child of children) {\n if (child.getProperty('_n') === targetName) {\n return this.getVertexByPathArray(child, path.slice(1));\n }\n }\n\n return undefined;\n }\n\n printTree() {\n if (!this.rootVertexId) {\n return '';\n }\n\n return this.state.printTree(this.rootVertexId);\n }\n\n merge(ops: ReadonlyArray<VertexOperation>) {\n /*\n if (ops.length > 100) {\n this.applyOpsOptimizedForLotsOfMoves(ops);\n } else {\n this.applyOps(ops);\n }\n */\n\n this.applyOps(ops);\n }\n\n private applyOps(ops: ReadonlyArray<VertexOperation>) {\n for (const op of ops) {\n // We skip the operation if we already know about it.\n // This is to avoid processing the same operation multiple times.\n if (this.knownOps.has(op.id.toString())) {\n continue;\n }\n\n this.applyOperation(op);\n }\n }\n\n /** Applies operations in an optimized way, sorting move ops by OpId to avoid undo-do-redo cycles */\n private applyOpsOptimizedForLotsOfMoves(ops: ReadonlyArray<VertexOperation>) {\n const newMoveOps = ops.filter(op => isMoveVertexOp(op) && !this.knownOps.has(op.id.toString()));\n if (newMoveOps.length > 0) {\n // Get an array of all move ops (without already applied ones)\n const allMoveOps = [...this.moveOps, ...newMoveOps] as MoveVertex[];\n // The main point of this optimization is to apply the moves without undo-do-redo cycles (the conflict resolution algorithm).\n // That is why we sort by OpId.\n allMoveOps.sort((a, b) => OpId.compare(a.id, b.id));\n for (let i = 0, len = allMoveOps.length; i < len; i++) {\n const op = allMoveOps[i];\n this.applyMove(op);\n }\n }\n\n // Get an array of all property ops (without already applied ones)\n const propertyOps = ops.filter(op => isAnyPropertyOp(op) && !this.knownOps.has(op.id.toString()));\n for (let i = 0, len = propertyOps.length; i < len; i++) {\n const op = propertyOps[i];\n this.applyProperty(op as SetVertexProperty);\n }\n }\n\n compareStructure(other: RepTree): boolean {\n if (this.root?.id !== other.root?.id) {\n return false;\n }\n\n if (!this.rootVertexId) {\n return true;\n }\n\n return RepTree.compareVertices(this.rootVertexId, this, other);\n }\n\n compareMoveOps(other: RepTree): boolean {\n const movesA = this.moveOps;\n const movesB = other.getMoveOps();\n\n if (movesA.length !== movesB.length) {\n return false;\n }\n\n for (let i = 0; i < movesA.length; i++) {\n if (!OpId.equals(movesA[i].id, movesB[i].id)) {\n return false;\n }\n }\n\n return true;\n }\n\n /** Checks if the given `ancestorId` is an ancestor of `childId` in the tree */\n isAncestor(childId: string, ancestorId: string | null): boolean {\n let targetId = childId;\n let vertex: VertexState | undefined;\n \n // Set to track visited vertices and detect cycles\n const visitedVertices = new Set<string>();\n\n while (vertex = this.state.getVertex(targetId)) {\n if (vertex.parentId === ancestorId) return true;\n if (!vertex.parentId) return false;\n \n // If we've already visited this vertex, we have a cycle\n if (visitedVertices.has(targetId)) {\n console.error(`isAncestor: cycle detected in the tree structure.`);\n // In the context of tryToMove, we should return false here to prevent the move\n // since the target ancestor isn't actually in the path (we're in a cycle)\n return false;\n }\n \n // Mark this vertex as visited\n visitedVertices.add(targetId);\n \n targetId = vertex.parentId;\n }\n\n return false;\n }\n\n observeVertex(vertexId: string, callback: (updatedVertex: Vertex) => void): () => void {\n const vertex = this.getVertex(vertexId);\n if (vertex) {\n callback(vertex);\n }\n\n const unsubscribe = this.observe(vertexId, (_) => {\n const vertex = this.getVertex(vertexId);\n if (vertex) {\n callback(vertex);\n }\n });\n\n return () => {\n unsubscribe();\n };\n }\n\n observeVertexMove(callback: (movedVertex: Vertex, isNew: boolean) => void): () => void {\n const listener = (events: VertexChangeEvent[]) => {\n const moveEvent = events.find(e => e.type === 'move') as VertexMoveEvent | undefined;\n if (moveEvent) {\n const vertex = this.getVertex(moveEvent.vertexId);\n if (vertex) {\n callback(vertex, moveEvent.oldParentId === undefined);\n }\n }\n };\n\n this.state.addGlobalChangeCallback(listener);\n\n return () => this.state.removeGlobalChangeCallback(listener);\n }\n\n observe(vertexId: string, callback: (events: VertexChangeEvent[]) => void): () => void {\n this.state.addChangeCallback(vertexId, callback);\n return () => this.state.removeChangeCallback(vertexId, callback);\n }\n\n observeOpApplied(callback: (op: VertexOperation) => void): () => void {\n this.opAppliedCallbacks.push(callback);\n return () => this.opAppliedCallbacks = this.opAppliedCallbacks.filter(l => l !== callback);\n }\n\n static compareVertices(vertexId: string, treeA: RepTree, treeB: RepTree): boolean {\n const childrenA = treeA.state.getChildrenIds(vertexId);\n const childrenB = treeB.state.getChildrenIds(vertexId);\n\n if (childrenA.length !== childrenB.length) {\n return false;\n }\n\n // Compare properties of the current vertex\n if (vertexId !== null) {\n const propertiesA = treeA.getVertexProperties(vertexId);\n const propertiesB = treeB.getVertexProperties(vertexId);\n\n if (propertiesA.length !== propertiesB.length) {\n return false;\n }\n\n for (const propA of propertiesA) {\n const propB = propertiesB.find(p => p.key === propA.key);\n if (!propB) {\n return false;\n }\n \n // Special handling for Yjs documents\n if (propA.value instanceof Y.Doc && propB.value instanceof Y.Doc) {\n // Create snapshots of the Yjs documents\n const snapshotA = Y.snapshot(propA.value);\n const snapshotB = Y.snapshot(propB.value);\n \n // Compare the snapshots using Y.equalSnapshots\n // This properly compares the document structure and content\n if (!Y.equalSnapshots(snapshotA, snapshotB)) {\n return false;\n }\n } else if (propA.value !== propB.value) {\n return false;\n } \n }\n }\n\n // Compare children and their properties recursively\n for (const childId of childrenA) {\n if (!childrenB.includes(childId)) {\n return false;\n }\n\n if (!RepTree.compareVertices(childId, treeA, treeB)) {\n return false;\n }\n }\n\n return true;\n }\n\n private newVertexInternal(vertexId: string, parentId: string | null): string {\n this.lamportClock++;\n // To create a vertex - we move a vertex with a fresh id under the parent.\n // No need to have a separate \"create vertex\" operation.\n const op = newMoveVertexOp(this.lamportClock, this.peerId, vertexId, parentId);\n this.localOps.push(op);\n this.applyMove(op);\n\n // Set the creation date\n this.setVertexProperty(vertexId, '_c', new Date().toISOString());\n\n return vertexId;\n }\n\n private newVertexInternalWithUUID(parentId: string | null): string {\n const vertexId = uuid();\n return this.newVertexInternal(vertexId, parentId);\n }\n\n private ensureNullVertex() {\n const vertexId = RepTree.NULL_VERTEX_ID;\n\n // Check if the null vertex already exists\n if (this.state.getVertex(vertexId)) {\n return;\n }\n\n this.newVertexInternal(vertexId, null);\n }\n\n /** Updates the lamport clock with the counter value of the operation */\n private updateLamportClock(operation: VertexOperation): void {\n // This is how Lamport clock updates with a foreign operation that has a greater counter value.\n if (operation.id.counter > this.lamportClock) {\n this.lamportClock = operation.id.counter;\n }\n }\n\n private applyPendingMovesForParent(parentId: string) {\n // If a parent doesn't exist, we can't apply pending moves yet.\n if (!this.state.getVertex(parentId)) {\n return;\n }\n\n const pendingMoves = this.pendingMovesWithMissingParent.get(parentId);\n if (!pendingMoves) {\n return;\n }\n\n this.pendingMovesWithMissingParent.delete(parentId);\n\n for (const pendingOp of pendingMoves) {\n this.applyMove(pendingOp);\n }\n }\n\n private applyMove(op: MoveVertex) {\n // Check if a parent (unless we're dealing with the root vertex) exists for the move operation.\n // If it doesn't exist, stash the move op for later\n if (op.parentId !== null && !this.state.getVertex(op.parentId)) {\n if (!this.pendingMovesWithMissingParent.has(op.parentId)) {\n this.pendingMovesWithMissingParent.set(op.parentId, []);\n }\n this.pendingMovesWithMissingParent.get(op.parentId)!.push(op);\n return;\n }\n\n this.updateLamportClock(op);\n\n const lastOp = this.moveOps.length > 0 ? this.moveOps[this.moveOps.length - 1] : null;\n\n // If it's the most recent move operation - just try to move it. No conflict resolution is needed.\n if (lastOp === null || op.id.isGreaterThan(lastOp.id)) {\n this.moveOps.push(op);\n this.reportOpAsApplied(op);\n this.tryToMove(op);\n }\n\n // Here comes the core of the 'THE REPLICATED TREE ALGORITHM'.\n // From https://martin.kleppmann.com/papers/move-op.pdf\n // We undo all moves that are newer (based on the Lamport clock) than the target move, do the move, and then redo the moves we just undid.\n // The algorithm ensures that all replicas converge to the same tree after applying all operations.\n // The replicas are basically forced to apply the moves in the same order (by undo-do-redo).\n // So if a conflict or a cycle is introduced by some of the peers - the algorithm will resolve it.\n // tryToMove function has the logic to detect cycles and will ignore the move if it creates a cycle. \n else {\n let targetIndex = this.moveOps.length;\n for (let i = this.moveOps.length - 1; i >= 0; i--) {\n const moveOp = this.moveOps[i];\n targetIndex = i;\n if (op.id.isGreaterThan(moveOp.id)) {\n break;\n }\n else {\n this.undoMove(moveOp);\n }\n }\n\n // Insert the op at the correct position\n this.moveOps.splice(targetIndex + 1, 0, op);\n this.reportOpAsApplied(op);\n this.tryToMove(op);\n\n // Redo all of the operations after the operation that we applied\n for (let i = targetIndex + 2; i < this.moveOps.length; i++) {\n this.tryToMove(this.moveOps[i]);\n }\n }\n\n // After applying the move, check if it unblocks any pending moves\n // We use targetId here because this vertex might now be a parent for pending operations\n this.applyPendingMovesForParent(op.targetId);\n }\n\n private setLLWPropertyAndItsOpId(op: SetVertexProperty) {\n this.propertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);\n this.state.setProperty(op.targetId, op.key, op.value);\n this.reportOpAsApplied(op);\n }\n\n private setTransientPropertyAndItsOpId(op: SetVertexProperty) {\n this.transientPropertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);\n this.state.setTransientProperty(op.targetId, op.key, op.value);\n this.reportOpAsApplied(op);\n }\n\n private setupYjsObserver(doc: Y.Doc, vertexId: string, key: string) {\n // Create a unique key for this property\n const propertyKey = `${key}@${vertexId}` as PropertyKeyAtVertexId;\n\n // Remove any existing observer\n if (this.yjsObservers.has(propertyKey)) {\n const existingDoc = this.getVertexProperty(vertexId, key);\n if (existingDoc instanceof Y.Doc) {\n existingDoc.off('update', this.yjsObservers.get(propertyKey)!);\n }\n this.yjsObservers.delete(propertyKey);\n }\n\n // Create and store the new observer\n const ydocObserver = (update: Uint8Array, origin: any, doc: Y.Doc, transaction: Y.Transaction) => { \n if (!transaction.local) {\n return;\n }\n\n // We create ops when the doc changes.\n // Only from the same peer\n\n const crdtValue: CRDTType = {\n type: \"yjs\",\n value: update\n };\n\n this.lamportClock++;\n\n // Create a SetVertexProperty operation with the CRDTType\n const op = newSetVertexPropertyOp(\n this.lamportClock,\n this.peerId,\n vertexId,\n key,\n crdtValue\n );\n\n this.localOps.push(op);\n this.applyProperty(op);\n\n // @TODO: should we remove it and only update form applyProperty\n // Update state vector if enabled\n if (this._stateVectorEnabled) {\n this.stateVector.updateFromOp(op);\n }\n };\n\n // Register the observer\n doc.on('update', ydocObserver);\n this.yjsObservers.set(propertyKey, ydocObserver);\n }\n\n private applyProperty(op: SetVertexProperty) {\n const targetVertex = this.state.getVertex(op.targetId);\n if (!targetVertex) {\n // No need to handle transient properties if the vertex doesn't exist\n if (op.transient) {\n return;\n }\n\n // If the vertex doesn't exist, we will wait for the move operation to appear that will create the vertex\n // so we can apply the property then.\n if (!this.pendingPropertiesWithMissingVertex.has(op.targetId)) {\n this.pendingPropertiesWithMissingVertex.set(op.targetId, []);\n }\n this.pendingPropertiesWithMissingVertex.get(op.targetId)!.push(op);\n return;\n }\n\n this.updateLamportClock(op);\n\n if (isModifyPropertyOp(op)) {\n this.applyModifyProperty(op, targetVertex);\n } else {\n this.applyLLWProperty(op, targetVertex);\n }\n }\n\n private applyLLWProperty(op: SetVertexProperty, targetVertex: VertexState) {\n const prevTransientOpId = this.transientPropertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);\n const prevOpId = this.propertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);\n\n if (!op.transient) {\n this.setPropertyOps.push(op);\n\n // Apply the property if it's not already applied or if the current op is newer\n // This is the last writer wins approach that ensures the same state between replicas.\n if (!prevOpId || op.id.isGreaterThan(prevOpId)) {\n this.setLLWPropertyAndItsOpId(op);\n } else {\n // We add it to set of known ops to avoid adding them to `setPropertyOps` multiple times \n // if we ever receive the same op from another peer.\n this.knownOps.add(op.id.toString());\n }\n\n // Remove the transient property if the current op is greater\n if (prevTransientOpId && op.id.isGreaterThan(prevTransientOpId)) {\n this.transientPropertiesAndTheirOpIds.delete(`${op.key}@${op.targetId}`);\n targetVertex.removeTransientProperty(op.key);\n }\n\n } else {\n // Handle transient properties\n if (!prevTransientOpId || op.id.isGreaterThan(prevTransientOpId)) {\n this.setTransientPropertyAndItsOpId(op);\n }\n }\n }\n\n private applyModifyProperty(op: SetVertexProperty, targetVertex: VertexState) {\n if (op.transient) {\n console.warn(\"Not implemented: transient non LWW property\");\n return;\n }\n\n this.setPropertyOps.push(op);\n const crdtValue = op.value as CRDTType;\n\n if (crdtValue.type !== \"yjs\") {\n throw new Error(\"Unknown CRDT type\");\n }\n\n const ydoc = targetVertex.getProperty(op.key);\n\n if (ydoc instanceof Y.Doc) {\n // Apply update to existing Y.Doc\n Y.applyUpdate(ydoc, crdtValue.value);\n } else {\n // Create new Y.Doc, and apply an update\n const newDoc = new Y.Doc();\n // Setup an observer so we can automatically create ops when the doc changes\n this.setupYjsObserver(newDoc, op.targetId, op.key);\n // Set the new doc as a property on the vertex\n this.state.setProperty(op.targetId, op.key, newDoc);\n // And finally, apply the update to the new doc\n Y.applyUpdate(newDoc, crdtValue.value);\n }\n\n this.propertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);\n this.reportOpAsApplied(op);\n\n // @TODO: should we update state vector here?\n }\n\n private applyOperation(op: VertexOperation) {\n if (isMoveVertexOp(op)) {\n this.applyMove(op);\n } else if (isAnyPropertyOp(op)) {\n this.applyProperty(op);\n }\n }\n\n private reportOpAsApplied(op: VertexOperation) {\n this.knownOps.add(op.id.toString());\n\n if (this._stateVectorEnabled) {\n this.stateVector.updateFromOp(op);\n }\n\n for (const callback of this.opAppliedCallbacks) {\n callback(op);\n }\n }\n\n private tryToMove(op: MoveVertex) {\n let targetVertex = this.state.getVertex(op.targetId);\n\n if (targetVertex) {\n // We cache the parentId before the move operation.\n // We will use it to undo the move according to the move op algorithm.\n this.parentIdBeforeMove.set(op.id, targetVertex.parentId);\n }\n\n // If trying to move the target vertex under itself - do nothing\n if (op.targetId === op.parentId) return;\n\n // If we try to move the vertex (op.targetId) under one of its descendants (op.parentId) - do nothing\n if (op.parentId && this.isAncestor(op.parentId, op.targetId)) return;\n\n this.state.moveVertex(op.targetId, op.parentId);\n\n // If the vertex didn't exist before the move - see if it has pending properties\n // and apply them.\n if (!targetVertex) {\n const pendingProperties = this.pendingPropertiesWithMissingVertex.get(op.targetId) || [];\n this.pendingPropertiesWithMissingVertex.delete(op.targetId);\n for (const prop of pendingProperties) {\n this.applyProperty(prop);\n }\n }\n }\n\n private undoMove(op: MoveVertex) {\n const targetVertex = this.state.getVertex(op.targetId);\n if (!targetVertex) {\n console.error(`An attempt to undo move operation ${op.id.toString()} failed because the target vertex ${op.targetId} not found`);\n return;\n }\n\n const prevParentId = this.parentIdBeforeMove.get(op.id);\n if (prevParentId === undefined) {\n return;\n }\n\n this.state.moveVertex(op.targetId, prevParentId);\n }\n\n // --- Range-Based State Vector Methods --- \n\n /**\n * Returns the current state vector.\n * Returns a readonly reference to the internal state vector.\n */\n getStateVector(): Readonly<Record<string, number[][]>> | null {\n if (!this._stateVectorEnabled) {\n return null;\n }\n return this.stateVector.getState();\n }\n\n /**\n * Determines which operations are needed to synchronize \n * with the provided state vector.\n * \n * @param theirStateVector The state vector from another peer\n * @returns Operations that should be sent to the other peer, sorted by OpId.\n */\n getMissingOps(theirStateVector: Record<string, number[][]>): VertexOperation[] {\n // If state vector is disabled, fallback to sending all ops\n if (!this._stateVectorEnabled) {\n return [...this.moveOps, ...this.setPropertyOps];\n }\n\n // Create a StateVector instance from their state vector\n const otherStateVector = new StateVector(theirStateVector);\n\n // Get the missing ranges\n const missingRanges = this.stateVector.diff(otherStateVector);\n\n // Then, retrieve only the operations that fall within those ranges\n const missingOps: VertexOperation[] = [];\n // Combine moveOps and setPropertyOps for checking\n const allOps = [...this.moveOps, ...this.setPropertyOps];\n\n // Only check operations that might be in the missing ranges\n for (const op of allOps) {\n for (const range of missingRanges) {\n if (op.id.peerId === range.peerId &&\n op.id.counter >= range.start &&\n op.id.counter <= range.end) {\n missingOps.push(op);\n break; // Move to the next op once found in a missing range\n }\n }\n }\n\n // Sort the missing ops by OpId before returning, ensuring causal order\n missingOps.sort((a, b) => OpId.compare(a.id, b.id));\n\n return missingOps;\n }\n\n /**\n * Gets or sets whether state vector tracking is enabled\n */\n get stateVectorEnabled(): boolean {\n return this._stateVectorEnabled;\n }\n\n /**\n * Sets the state vector enabled status\n * When enabled, rebuilds the state vector from existing operations if needed\n */\n set stateVectorEnabled(value: boolean) {\n if (value === this._stateVectorEnabled) return;\n\n if (value) {\n // Enable state vector and rebuild from existing operations\n this._stateVectorEnabled = true;\n this.stateVector = StateVector.fromOperations([...this.moveOps, ...this.setPropertyOps]);\n } else {\n // Disable state vector and clear it to save memory\n this._stateVectorEnabled = false;\n this.stateVector = new StateVector();\n }\n }\n}"],"mappings":"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","names":["vertex","doc"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/OpId.ts","../src/operations.ts","../src/VertexState.ts","../src/TreeState.ts","../src/uuid.ts","../src/reactive.ts","../src/Vertex.ts","../src/StateVector.ts","../src/RepTree.ts"],"sourcesContent":["// Main class\nexport { RepTree } from './RepTree';\n\n// Core types and classes\nexport { Vertex } from './Vertex';\nexport { VertexState } from './VertexState';\nexport { TreeState } from './TreeState';\nexport { OpId } from './OpId';\nexport { StateVector } from './StateVector';\n\n// Types\nexport * from './treeTypes';\nexport * from './operations';\n\n// Utilities\nexport { default as uuid } from './uuid';\n\n// Reactive helpers (opt-in)\nexport { bindVertex } from './reactive';","export interface OpId {\n readonly counter: number;\n readonly peerId: string;\n}\n\nexport function createOpId(counter: number, peerId: string): OpId {\n return { counter, peerId };\n}\n\nexport function compareOpId(opIdA: OpId | string, opIdB: OpId | string): number {\n if (typeof opIdA === 'string') {\n const parsedA = tryParseOpIdStr(opIdA);\n if (!parsedA) throw new Error(`Invalid OpId string: ${opIdA}`);\n opIdA = parsedA;\n }\n if (typeof opIdB === 'string') {\n const parsedB = tryParseOpIdStr(opIdB);\n if (!parsedB) throw new Error(`Invalid OpId string: ${opIdB}`);\n opIdB = parsedB;\n }\n\n const counterA = opIdA.counter;\n const counterB = opIdB.counter;\n\n if (counterA > counterB) {\n return 1;\n } else if (counterA < counterB) {\n return -1;\n } else {\n return opIdA.peerId.localeCompare(opIdB.peerId);\n }\n}\n\nexport function equalsOpId(opIdA: OpId | string | null, opIdB: OpId | string | null): boolean {\n if (opIdA === opIdB) {\n return true;\n } else if (!opIdA || !opIdB) {\n return false;\n }\n\n return compareOpId(opIdA, opIdB) === 0;\n}\n\nexport function tryParseOpIdStr(opIdStr: string): OpId {\n const parts = opIdStr.split('@');\n\n if (parts.length !== 2) {\n throw new Error(`Invalid OpId string: ${opIdStr}`);\n }\n\n return createOpId(parseInt(parts[0], 10), parts[1]);\n}\n\nexport function isOpIdGreaterThan(opIdA: OpId | string, opIdB: OpId | string): boolean {\n return compareOpId(opIdA, opIdB) === 1;\n}\n\nexport function opIdToString(opId: OpId): string {\n return `${opId.counter}@${opId.peerId}`;\n}\n","import { type OpId, createOpId } from \"./OpId\";\nimport { type VertexPropertyTypeInOperation } from \"./treeTypes\";\n\nexport interface MoveVertex {\n id: OpId;\n targetId: string;\n parentId: string | null;\n}\n\nexport interface SetVertexProperty {\n id: OpId;\n targetId: string;\n key: string;\n value: VertexPropertyTypeInOperation;\n transient: boolean;\n}\n\nexport type VertexOperation = MoveVertex | SetVertexProperty;\n\nexport function isMoveVertexOp(op: VertexOperation): op is MoveVertex {\n return 'parentId' in op;\n}\n\nexport function isAnyPropertyOp(op: VertexOperation): op is SetVertexProperty {\n return 'key' in op;\n}\n\nexport function isLWWPropertyOp(op: VertexOperation): op is SetVertexProperty {\n return 'key' in op && 'value' in op && (!op.value || typeof op.value !== 'object' || !('type' in op.value));\n}\n\nexport function isModifyPropertyOp(op: VertexOperation): op is SetVertexProperty {\n return 'key' in op && 'value' in op && typeof op.value === 'object' && op.value !== null && 'type' in op.value;\n}\n\nexport function newMoveVertexOp(clock: number, peerId: string, targetId: string, parentId: string | null): MoveVertex {\n return { id: createOpId(clock, peerId), targetId, parentId };\n}\n\nexport function newSetVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty {\n return { id: createOpId(clock, peerId), targetId, key, value, transient: false };\n}\n\nexport function newSetTransientVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty {\n return { id: createOpId(clock, peerId), targetId, key, value, transient: true };\n}","import type { TreeVertexId, TreeVertexProperty, VertexPropertyType } from \"./treeTypes\";\n\nexport class VertexState {\n readonly id: string;\n parentId: TreeVertexId | null;\n private properties: TreeVertexProperty[];\n private transientProperties: TreeVertexProperty[];\n children: string[];\n\n constructor(id: string, parentId: TreeVertexId | null) {\n this.id = id;\n this.parentId = parentId;\n this.properties = [];\n this.transientProperties = [];\n this.children = [];\n }\n\n setProperty(key: string, value: any): void {\n const existingPropIndex = this.properties.findIndex(p => p.key === key);\n if (existingPropIndex !== -1) {\n if (value !== undefined) {\n // Update existing property\n this.properties[existingPropIndex] = { key, value };\n } else {\n // Remove existing property\n this.removeProperty(key);\n }\n } else {\n if (value !== undefined) {\n // Add new property\n this.properties.push({ key, value });\n }\n }\n }\n\n setTransientProperty(key: string, value: any): void {\n const existingPropIndex = this.transientProperties.findIndex(p => p.key === key);\n if (existingPropIndex !== -1) {\n if (value !== undefined) {\n // Update existing property\n this.transientProperties[existingPropIndex] = { key, value };\n } else {\n // Remove existing property\n this.removeTransientProperty(key);\n }\n } else {\n if (value !== undefined) {\n // Add new property\n this.transientProperties.push({ key, value });\n }\n }\n }\n\n getProperty(key: string, includingTransient: boolean = true): VertexPropertyType | undefined {\n if (includingTransient) {\n const transientProp = this.transientProperties.find(p => p.key === key);\n if (transientProp) {\n return transientProp.value;\n }\n }\n\n return this.properties.find(p => p.key === key)?.value;\n }\n\n getAllProperties(includingTransient: boolean = true): ReadonlyArray<TreeVertexProperty> {\n if (!includingTransient) {\n return this.properties;\n }\n\n const result: TreeVertexProperty[] = [];\n const seenKeys = new Set<string>();\n\n // Add transient properties first\n for (const prop of this.transientProperties) {\n result.push(prop);\n seenKeys.add(prop.key);\n }\n\n // Add permanent properties that don't have a transient override\n for (const prop of this.properties) {\n if (!seenKeys.has(prop.key)) {\n result.push(prop);\n }\n }\n\n return result;\n }\n\n removeProperty(key: string): void {\n this.properties = this.properties.filter(p => p.key !== key);\n }\n\n removeTransientProperty(key: string): void {\n this.transientProperties = this.transientProperties.filter(p => p.key !== key);\n }\n}\n","import type { TreeVertexId, VertexChangeEvent, VertexPropertyChangeEvent, VertexChildrenChangeEvent, VertexMoveEvent } from \"./treeTypes\";\nimport { VertexState } from \"./VertexState\";\n\nexport class TreeState {\n private vertices: Map<TreeVertexId, VertexState>;\n private changeCallbacks: Map<TreeVertexId, Set<(events: VertexChangeEvent[]) => void>> = new Map();\n private globalChangeCallbacks: Set<(events: VertexChangeEvent[]) => void> = new Set();\n\n private batchTickInterval: NodeJS.Timeout;\n private batchedEvents: Map<TreeVertexId, VertexChangeEvent[]> = new Map();\n\n constructor() {\n this.vertices = new Map();\n\n this.batchTickInterval = setInterval(() => {\n this.processBatchedEvents();\n }, 33.3);\n }\n\n dispose() {\n clearInterval(this.batchTickInterval);\n }\n\n private processBatchedEvents() {\n for (const [vertexId, events] of this.batchedEvents) {\n // Get last property events per key and last move/children events\n let lastMoveEvent: VertexMoveEvent | null = null;\n let lastChildrenEvent: VertexChildrenChangeEvent | null = null;\n const propertyEventsByKey = new Map<string, VertexPropertyChangeEvent>();\n\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i];\n if (!lastMoveEvent && event.type === 'move') lastMoveEvent = event as VertexMoveEvent;\n if (!lastChildrenEvent && event.type === 'children') lastChildrenEvent = event as VertexChildrenChangeEvent;\n if (event.type === 'property') {\n const propertyEvent = event as VertexPropertyChangeEvent;\n if (!propertyEventsByKey.has(propertyEvent.key)) {\n propertyEventsByKey.set(propertyEvent.key, propertyEvent);\n }\n }\n }\n\n // Combine all events with move and children events first\n const filteredEvents = [\n ...(lastMoveEvent ? [lastMoveEvent] : []),\n ...(lastChildrenEvent ? [lastChildrenEvent] : []),\n ...propertyEventsByKey.values()\n ];\n\n this.globalChangeCallbacks.forEach(listener => listener(filteredEvents));\n this.changeCallbacks.get(vertexId)?.forEach(listener => listener(filteredEvents));\n }\n\n this.batchedEvents.clear();\n }\n\n getAllVertices(): ReadonlyArray<VertexState> {\n return Array.from(this.vertices.values());\n }\n\n getVertex(id: string): VertexState | undefined {\n return this.vertices.get(id);\n }\n\n getChildrenIds(vertexId: TreeVertexId): string[] {\n return this.getVertex(vertexId)?.children ?? [];\n }\n\n getChildren(vertexId: TreeVertexId): VertexState[] {\n return this.getChildrenIds(vertexId)\n .map(id => {\n const vertex = this.vertices.get(id);\n return vertex ? vertex : undefined;\n })\n .filter(vertex => vertex !== undefined)\n .sort((a, b) => {\n const aDate = a.getProperty('_c') as string;\n const bDate = b.getProperty('_c') as string;\n if (!aDate) return -1;\n if (!bDate) return 1;\n return new Date(aDate).getTime() - new Date(bDate).getTime();\n }) as VertexState[];\n }\n\n moveVertex(vertexId: TreeVertexId, newParentId: TreeVertexId | null): VertexState {\n let vertex = this.getVertex(vertexId);\n // Undefined if the vertex is new\n const prevParentId = vertex ? vertex.parentId : undefined;\n if (!vertex) {\n vertex = new VertexState(vertexId, newParentId);\n this.vertices.set(vertexId, vertex);\n }\n\n if (prevParentId === newParentId) {\n return vertex;\n }\n\n vertex.parentId = newParentId;\n\n let childrenInNewParent: string[] | null = null;\n let childrenInOldParent: string[] | null = null;\n\n // Update children arrays in vertices\n if (prevParentId) {\n const oldParentVertex = this.getVertex(prevParentId);\n if (oldParentVertex) {\n oldParentVertex.children = oldParentVertex.children.filter(child => child !== vertexId);\n childrenInOldParent = oldParentVertex.children;\n } else {\n console.error(`Old parent vertex not found for ${prevParentId}`);\n }\n }\n\n if (newParentId !== null) {\n const newParentVertex = this.vertices.get(newParentId);\n if (newParentVertex) {\n newParentVertex.children.push(vertexId);\n childrenInNewParent = newParentVertex.children;\n } else {\n console.error(`New parent vertex not found for ${newParentId}`);\n }\n }\n\n // We notify the listeners in the end so that they have the final state of the tree\n\n this.notifyChange({\n type: 'move',\n vertexId: vertexId,\n oldParentId: prevParentId,\n newParentId,\n } as VertexMoveEvent);\n\n if (childrenInNewParent !== null && newParentId !== null) {\n this.notifyChange({\n type: 'children',\n vertexId: newParentId,\n children: childrenInNewParent.map(id => this.vertices.get(id)!),\n } as VertexChildrenChangeEvent);\n }\n\n if (childrenInOldParent !== null && prevParentId) {\n this.notifyChange({\n type: 'children',\n vertexId: prevParentId,\n children: childrenInOldParent.map(id => this.vertices.get(id)!),\n } as VertexChildrenChangeEvent);\n }\n\n return vertex;\n }\n\n setProperty(vertexId: string, key: string, value: any) {\n const vertex = this.getVertex(vertexId);\n if (!vertex) {\n throw new Error(`Vertex ${vertexId} not found`);\n }\n\n vertex.setProperty(key, value);\n\n this.notifyChange({\n type: 'property',\n vertexId: vertexId,\n key,\n value,\n } as VertexPropertyChangeEvent);\n\n if (vertex.parentId !== null) {\n this.notifyChange({\n type: 'children',\n vertexId: vertex.parentId,\n children: [vertex], // @TODO: shoulld I set all children or rename this property?\n } as VertexChildrenChangeEvent);\n }\n }\n\n setTransientProperty(vertexId: string, key: string, value: any) {\n const vertex = this.getVertex(vertexId);\n if (vertex) {\n vertex.setTransientProperty(key, value);\n }\n\n // @TODO: add info that it's a transient property\n this.notifyChange({\n type: 'property',\n vertexId: vertexId,\n key,\n value,\n } as VertexPropertyChangeEvent);\n }\n\n addChangeCallback(vertexId: TreeVertexId, listener: (events: VertexChangeEvent[]) => void) {\n if (!this.changeCallbacks.has(vertexId)) {\n this.changeCallbacks.set(vertexId, new Set());\n }\n this.changeCallbacks.get(vertexId)!.add(listener);\n }\n\n removeChangeCallback(vertexId: TreeVertexId, listener: (events: VertexChangeEvent[]) => void) {\n this.changeCallbacks.get(vertexId)?.delete(listener);\n }\n\n addGlobalChangeCallback(listener: (events: VertexChangeEvent[]) => void) {\n this.globalChangeCallbacks.add(listener);\n }\n\n removeGlobalChangeCallback(listener: (events: VertexChangeEvent[]) => void) {\n this.globalChangeCallbacks.delete(listener);\n }\n\n private notifyChange(event: VertexChangeEvent) {\n let events = this.batchedEvents.get(event.vertexId);\n if (!events) {\n events = [];\n this.batchedEvents.set(event.vertexId, events);\n }\n\n events.push(event);\n\n // @TODO: have immediate events\n //this.globalChangeCallbacks.forEach(listener => listener(event));\n //this.changeCallbacks.get(event.vertexId)?.forEach(listener => listener(event));\n }\n\n printTree(vertexId: TreeVertexId, indent: string = \"\", isLast: boolean = true): string {\n const prefix = indent + (isLast ? \"└── \" : \"├── \");\n let result = prefix + vertexId + \"\\n\";\n\n let vertexName: string | null = null;\n\n if (vertexId !== null) {\n const vertex = this.getVertex(vertexId);\n if (vertex) {\n for (const prop of vertex.getAllProperties()) {\n if (prop.key === \"_n\") {\n vertexName = prop.value as string;\n //continue;\n }\n\n const propPrefix = indent + (isLast ? \" \" : \"│ \") + \"• \";\n result += `${propPrefix}${prop.key}: ${JSON.stringify(prop.value)}\\n`;\n }\n }\n }\n\n // Get children and sort them for deterministic output\n const children = this.getChildrenIds(vertexId);\n const sortedChildren = [...children].sort((a, b) => {\n // Sort by name if available\n const vertexA = this.getVertex(a);\n const vertexB = this.getVertex(b);\n \n const nameA = vertexA?.getProperty('_n') as string | undefined;\n const nameB = vertexB?.getProperty('_n') as string | undefined;\n \n // If both have names, compare them\n if (nameA && nameB) {\n return nameA.localeCompare(nameB);\n }\n \n // If only one has a name, prioritize the one with a name\n if (nameA) return -1;\n if (nameB) return 1;\n \n // Fall back to sorting by ID for consistent output\n return a.localeCompare(b);\n });\n \n for (let i = 0; i < sortedChildren.length; i++) {\n const childId = sortedChildren[i];\n const isLastChild = i === sortedChildren.length - 1;\n result += this.printTree(childId, indent + (isLast ? \" \" : \"│ \"), isLastChild);\n }\n\n return result;\n }\n}","const removeDashes = (guid: string) => guid.replace(/-/g, '');\n\nexport default function uuid(): string {\n return removeDashes(crypto.randomUUID());\n}","import type { RepTree } from './RepTree';\n\nexport type FieldSchemaLike = {\n safeParse?: (input: unknown) => { success: true; data: unknown } | { success: false };\n};\n\nexport type SchemaLike<T> = {\n safeParse?: (input: unknown) => { success: true; data: T } | { success: false };\n parse?: (input: unknown) => T;\n shape?: Record<string, FieldSchemaLike>;\n};\n\nfunction toObject(tree: RepTree, id: string): Record<string, unknown> {\n const obj: Record<string, unknown> = {};\n for (const { key, value } of tree.getVertexProperties(id)) obj[key] = value as unknown;\n return obj;\n}\n\n/**\n * Returns a live object that proxies reads/writes to a vertex.\n * - Reads reflect the latest CRDT state.\n * - Writes persist to the CRDT.\n * - If a schema is provided, writes are validated. If a field schema exists in `schema.shape`, field-level validation is applied.\n */\nexport function bindVertex<T extends Record<string, unknown>>(\n tree: RepTree,\n id: string,\n schema?: SchemaLike<T>\n): T {\n return new Proxy({} as T, {\n get(_target, prop: string | symbol) {\n if (typeof prop !== 'string') return undefined;\n return tree.getVertexProperty(id, prop);\n },\n set(_target, prop: string | symbol, value: unknown) {\n if (typeof prop !== 'string') return true;\n\n // Prefer field-level validation when available\n if (schema?.shape && schema.shape[prop]) {\n const field = schema.shape[prop];\n if (field.safeParse) {\n const res = field.safeParse(value);\n if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);\n value = (res as any).data ?? value;\n }\n } else if (schema?.safeParse) {\n // Fallback to whole-object validation when field schema is unavailable\n const next = { ...toObject(tree, id), [prop]: value } as unknown;\n const res = schema.safeParse(next);\n if (!res.success) throw new Error(`Invalid value for ${String(prop)}`);\n // If schema coerces/transforms, apply coerced value\n const parsed = (res as any).data as Record<string, unknown>;\n if (parsed && Object.prototype.hasOwnProperty.call(parsed, prop)) {\n value = parsed[prop];\n }\n }\n\n tree.setVertexProperty(id, prop, value as any);\n return true;\n },\n deleteProperty(_target, prop: string | symbol) {\n if (typeof prop !== 'string') return true;\n tree.setVertexProperty(id, prop, undefined as any);\n return true;\n },\n has(_target, prop: string | symbol) {\n if (typeof prop !== 'string') return false;\n return !!schema?.shape && Object.prototype.hasOwnProperty.call(schema.shape, prop);\n },\n ownKeys() {\n return Object.keys(schema?.shape ?? {});\n },\n getOwnPropertyDescriptor() {\n return { enumerable: true, configurable: true } as PropertyDescriptor;\n },\n });\n}","import type { VertexState } from \"./VertexState\";\nimport type { RepTree } from \"./RepTree\";\nimport { bindVertex, type SchemaLike } from './reactive';\nimport type { VertexChangeEvent, VertexPropertyType } from \"./treeTypes\";\n\n/**\n * A wrapper class for VertexState that provides a more convenient API\n * for working with vertices in a RepTree.\n */\nexport class Vertex {\n constructor(\n private tree: RepTree,\n private state: VertexState\n ) { }\n\n get id(): string {\n return this.state.id;\n }\n\n get name(): string | undefined {\n return this.getProperty('_n') as string | undefined;\n }\n\n set name(name: string) {\n this.tree.setVertexProperty(this.id, '_n', name);\n }\n\n get createdAt(): Date {\n const createdAt = this.getProperty('_c') as string;\n if (!createdAt) {\n return new Date(0);\n }\n return new Date(createdAt);\n }\n\n get path(): string {\n //return this.tree.getVertexPath(this.id);\n throw new Error('Not implemented');\n }\n\n get parentId(): string | null {\n return this.state.parentId;\n }\n\n get parent(): Vertex | undefined {\n if (!this.parentId) {\n return undefined;\n }\n\n return this.tree.getVertex(this.parentId);\n }\n\n get children(): Vertex[] {\n return this.tree.getChildren(this.id);\n }\n\n get childrenIds(): string[] {\n return this.tree.getChildrenIds(this.id);\n }\n\n getAsTypedObject<T>(): T {\n return this.getProperties() as T;\n }\n\n getChildrenAsTypedArray<T>(): T[] {\n return this.children.map(v => v.getAsTypedObject<T>());\n }\n\n newChild(props?: Record<string, VertexPropertyType> | object | null): Vertex {\n const typedProps = props as Record<string, VertexPropertyType> | null;\n return this.tree.newVertex(this.id, typedProps);\n }\n\n newNamedChild(name: string, props?: Record<string, VertexPropertyType> | object | null): Vertex {\n const typedProps = props as Record<string, VertexPropertyType> | null;\n return this.tree.newNamedVertex(this.id, name, typedProps);\n }\n\n setProperty(key: string, value: VertexPropertyType): void {\n // First check if the property is already set (not including transient properties)\n const existingValue = this.getProperty(key, false);\n if (existingValue === value) {\n return;\n }\n\n this.tree.setVertexProperty(this.id, key, value);\n }\n\n setTransientProperty(key: string, value: VertexPropertyType): void {\n // First check if the property is already set\n const existingValue = this.getProperty(key);\n if (existingValue === value) {\n return;\n }\n\n this.tree.setTransientVertexProperty(this.id, key, value);\n }\n\n setProperties(props: Record<string, VertexPropertyType> | object): void {\n for (const [key, value] of Object.entries(props)) {\n this.setProperty(key, value);\n }\n }\n\n getProperty(key: string, includingTransient: boolean = true): VertexPropertyType | undefined {\n return this.tree.getVertexProperty(this.id, key, includingTransient);\n }\n\n getProperties(): Record<string, VertexPropertyType> {\n const props: Record<string, VertexPropertyType> = {};\n this.tree.getVertexProperties(this.id).forEach(p => {\n props[p.key] = p.value;\n });\n return props;\n }\n\n findAllChildrenWithProperty(key: string, value: VertexPropertyType): Vertex[] {\n return this.children.filter(c => c.getProperty(key) === value);\n }\n\n findFirstChildVertexWithProperty(key: string, value: VertexPropertyType): Vertex | undefined {\n return this.children.find(c => c.getProperty(key) === value);\n }\n\n findFirstTypedChildWithProperty<T>(key: string, value: VertexPropertyType): T | undefined {\n return this.findFirstChildVertexWithProperty(key, value)?.getAsTypedObject<T>();\n }\n\n findAllTypedChildrenWithProperty<T>(key: string, value: VertexPropertyType): T[] {\n return this.findAllChildrenWithProperty(key, value).map(c => c.getAsTypedObject<T>());\n }\n\n observe(listener: (events: VertexChangeEvent[]) => void): () => void {\n const unobserve = this.tree.observe(this.id, listener);\n return () => unobserve();\n }\n\n observeChildren(listener: (children: Vertex[]) => void): () => void {\n const unobserve = this.tree.observe(this.id, (events: VertexChangeEvent[]) => {\n if (events.some(e => e.type === 'children')) {\n listener(this.children);\n }\n });\n return () => unobserve();\n }\n\n observeChildrenAsTypedArray<T>(listener: (children: T[]) => void): () => void {\n return this.observeChildren((children) => {\n listener(children.map(c => c.getProperties() as unknown as T));\n });\n }\n\n delete(): void {\n this.tree.deleteVertex(this.id);\n }\n\n moveTo(parent: Vertex): void {\n this.tree.moveVertex(this.id, parent.id);\n }\n\n /** Returns a live reactive object bound to this vertex. Optional schema validates writes. */\n bind<T extends Record<string, unknown>>(schema?: SchemaLike<T>): T {\n return bindVertex<T>(this.tree, this.id, schema);\n }\n} ","import { OpId } from \"./OpId\";\nimport type { OpIdRange } from \"./treeTypes\";\nimport type { VertexOperation } from \"./operations\";\n\n/**\n * Helper function to subtract one set of ranges from another.\n * Returns the ranges in A that are not in B.\n * Assumes ranges in both A and B are sorted and non-overlapping.\n */\nexport function subtractRanges(rangesA: number[][], rangesB: number[][]): number[][] {\n if (rangesB.length === 0) return rangesA.map(r => [...r]); // Return a copy\n if (rangesA.length === 0) return []; // If A is empty, nothing to subtract\n\n const result: number[][] = [];\n let indexB = 0;\n\n for (const rangeA of rangesA) {\n let currentStart = rangeA[0];\n const endA = rangeA[1];\n\n // Iterate through ranges in B that could potentially overlap with rangeA\n while (indexB < rangesB.length && rangesB[indexB][1] < currentStart) {\n // Skip ranges in B that are entirely before the current start\n indexB++;\n }\n\n while (indexB < rangesB.length && rangesB[indexB][0] <= endA) {\n const startB = rangesB[indexB][0];\n const endB = rangesB[indexB][1];\n\n // If there's a gap before this range in B starts\n if (currentStart < startB) {\n // Add the portion of rangeA before the overlap\n result.push([currentStart, Math.min(endA, startB - 1)]);\n }\n\n // Move current start past this range in B\n currentStart = Math.max(currentStart, endB + 1);\n\n // If we've gone past the end of rangeA, break inner loop\n if (currentStart > endA) break;\n\n // If the current rangeB ends after rangeA, we don't need to check further ranges in B for this rangeA\n if (endB >= endA) break;\n\n // Only advance indexB if the current rangeB is fully processed relative to currentStart\n if (endB < currentStart) {\n indexB++;\n } else if (startB >= currentStart) {\n indexB++;\n }\n }\n\n // If there's a remaining part of rangeA after processing overlaps with B\n if (currentStart <= endA) {\n result.push([currentStart, endA]);\n }\n }\n\n return result;\n}\n\n/**\n * StateVector tracks operations that have been applied using a range-based representation.\n * It's used for synchronization between peers to determine which operations need to be sent.\n */\nexport class StateVector {\n private ranges: Record<string, number[][]> = {};\n\n /**\n * Creates a new StateVector.\n * @param initialState Optional initial state to copy from\n */\n constructor(initialState: Record<string, number[][]> = {}) {\n // Create a deep copy of the initial state\n for (const [peerId, peerRanges] of Object.entries(initialState)) {\n this.ranges[peerId] = peerRanges.map(range => [...range]);\n }\n }\n\n /**\n * Updates the state vector with a newly applied operation.\n * Assumes ranges are sorted and non-overlapping.\n * \n * @param peerId The peer ID of the operation\n * @param counter The counter value of the operation\n */\n update(peerId: string, counter: number): void {\n // Initialize ranges array for this peer if it doesn't exist\n if (!this.ranges[peerId]) {\n this.ranges[peerId] = [];\n }\n\n const ranges = this.ranges[peerId];\n\n // Case 1: No ranges yet\n if (ranges.length === 0) {\n ranges.push([counter, counter]);\n return;\n }\n\n let rangeExtendedOrMerged = false;\n let insertIndex = -1;\n\n for (let i = 0; i < ranges.length; i++) {\n const range = ranges[i];\n\n // If counter is already in a range, do nothing\n if (counter >= range[0] && counter <= range[1]) {\n rangeExtendedOrMerged = true;\n break;\n }\n\n // If counter is one less than range start, extend range start\n if (counter === range[0] - 1) {\n range[0] = counter;\n rangeExtendedOrMerged = true;\n // Check if this range now merges with the previous range\n if (i > 0 && range[0] === ranges[i - 1][1] + 1) {\n ranges[i - 1][1] = range[1]; // Merge into previous\n ranges.splice(i, 1); // Remove current\n }\n break;\n }\n\n // If counter is one more than range end, extend range end\n if (counter === range[1] + 1) {\n range[1] = counter;\n rangeExtendedOrMerged = true;\n // Check if this range now merges with the next range\n if (i < ranges.length - 1 && range[1] + 1 === ranges[i + 1][0]) {\n range[1] = ranges[i + 1][1]; // Merge next into current\n ranges.splice(i + 1, 1); // Remove next\n }\n break;\n }\n\n // Keep track of where to insert if no extension/merge happens\n if (counter < range[0] && insertIndex === -1) {\n insertIndex = i;\n }\n }\n\n // If we couldn't extend or merge any range, add a new one\n if (!rangeExtendedOrMerged) {\n if (insertIndex === -1) {\n // If counter is greater than all existing ranges, add to the end\n insertIndex = ranges.length;\n }\n ranges.splice(insertIndex, 0, [counter, counter]);\n // After inserting, check if the new range merges with neighbors\n // Merge with previous range if possible\n if (insertIndex > 0 && ranges[insertIndex][0] === ranges[insertIndex - 1][1] + 1) {\n ranges[insertIndex - 1][1] = ranges[insertIndex][1];\n ranges.splice(insertIndex, 1);\n insertIndex--; // Adjust index after merging\n }\n // Merge with next range if possible (use adjusted insertIndex)\n if (insertIndex < ranges.length - 1 && ranges[insertIndex][1] + 1 === ranges[insertIndex + 1][0]) {\n ranges[insertIndex][1] = ranges[insertIndex + 1][1];\n ranges.splice(insertIndex + 1, 1);\n }\n }\n }\n\n /**\n * Updates the state vector with a newly applied operation.\n * \n * @param op The operation that was just applied\n */\n updateFromOp(op: VertexOperation): void {\n this.update(op.id.peerId, op.id.counter);\n }\n\n /**\n * Returns the current state vector.\n * Returns a readonly reference to the internal state.\n */\n getState(): Readonly<Record<string, number[][]>> {\n return this.ranges;\n }\n\n /**\n * Calculates which operation ranges we have that the other state vector is missing\n * by comparing state vectors.\n * \n * @param other The other state vector to compare against\n * @returns Array of operation ID ranges that we have but they don't\n */\n diff(other: StateVector): OpIdRange[] {\n const missingRanges: OpIdRange[] = [];\n const theirState = other.getState();\n\n // Check what we have that they don't have\n for (const [peerId, ourRanges] of Object.entries(this.ranges)) {\n const theirRanges = theirState[peerId] || [];\n\n // Calculate ranges we have that they don't\n const missing = subtractRanges(ourRanges, theirRanges);\n\n // Convert to OpIdRange format\n for (const [start, end] of missing) {\n // Ensure the range is valid (start <= end)\n if (start <= end) {\n missingRanges.push({\n peerId,\n start,\n end\n });\n }\n }\n }\n\n return missingRanges;\n }\n\n /**\n * Checks if the state vector contains the given operation ID\n * \n * @param opId The operation ID to check\n * @returns true if the operation is in the state vector, false otherwise\n */\n contains(opId: OpId): boolean {\n const peerId = opId.peerId;\n const counter = opId.counter;\n\n if (!this.ranges[peerId]) {\n return false;\n }\n\n for (const [start, end] of this.ranges[peerId]) {\n if (counter >= start && counter <= end) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Creates a copy of this state vector\n */\n clone(): StateVector {\n return new StateVector(this.ranges);\n }\n\n /**\n * Builds a state vector from an array of operations\n * @param operations The operations to build the state vector from\n * @returns A new StateVector instance\n */\n static fromOperations(operations: ReadonlyArray<VertexOperation>): StateVector {\n const stateVector = new StateVector();\n for (const op of operations) {\n stateVector.updateFromOp(op);\n }\n return stateVector;\n }\n} ","import {\n newMoveVertexOp,\n type MoveVertex,\n type SetVertexProperty,\n isMoveVertexOp,\n isModifyPropertyOp,\n type VertexOperation,\n newSetVertexPropertyOp,\n newSetTransientVertexPropertyOp,\n isAnyPropertyOp\n} from \"./operations\";\nimport type { VertexPropertyType, VertexPropertyTypeInOperation, CRDTType, TreeVertexProperty, VertexChangeEvent, TreeVertexId, VertexMoveEvent } from \"./treeTypes\";\nimport { VertexState } from \"./VertexState\";\nimport { TreeState } from \"./TreeState\";\nimport { type OpId, compareOpId, equalsOpId, isOpIdGreaterThan, opIdToString } from \"./OpId\";\nimport uuid from \"./uuid\";\nimport { Vertex } from './Vertex';\nimport { StateVector } from './StateVector';\nimport * as Y from 'yjs';\n\ntype PropertyKeyAtVertexId = `${string}@${TreeVertexId}`;\n\n/**\n * RepTree is a tree data structure for storing vertices with properties.\n * It uses 2 conflict-free replicated data types (CRDTs) to manage seamless replication between peers.\n * A move tree CRDT is used for the tree structure (https://martin.kleppmann.com/papers/move-op.pdf).\n * A last writer wins (LWW) CRDT is used for properties.\n */\nexport class RepTree {\n private static NULL_VERTEX_ID = '0';\n\n readonly peerId: string;\n private rootVertexId: string | undefined;\n\n private lamportClock = 0;\n private state: TreeState;\n private moveOps: MoveVertex[] = [];\n private setPropertyOps: SetVertexProperty[] = [];\n private propertiesAndTheirOpIds: Map<PropertyKeyAtVertexId, OpId> = new Map();\n private transientPropertiesAndTheirOpIds: Map<PropertyKeyAtVertexId, OpId> = new Map();\n private yjsObservers: Map<PropertyKeyAtVertexId, (update: Uint8Array, origin: any, doc: Y.Doc, transaction: Y.Transaction) => void> = new Map();\n private localOps: VertexOperation[] = [];\n private pendingMovesWithMissingParent: Map<string, MoveVertex[]> = new Map();\n private pendingPropertiesWithMissingVertex: Map<string, SetVertexProperty[]> = new Map();\n private knownOps: Set<string> = new Set();\n private parentIdBeforeMove: Map<OpId, string | null | undefined> = new Map();\n private opAppliedCallbacks: ((op: VertexOperation) => void)[] = [];\n\n // State vector tracking operations from each peer\n private stateVector: StateVector;\n private _stateVectorEnabled: boolean = true;\n\n /**\n * @param peerId - The peer ID of the current client. Should be unique across all peers.\n * @param ops - The operations to replicate an existing tree, if not provided - an empty tree will be created without a root vertex\n */\n constructor(peerId: string, ops?: ReadonlyArray<VertexOperation>) {\n this.peerId = peerId;\n this.state = new TreeState();\n\n // Initialize state vector (enabled by default)\n this.stateVector = new StateVector();\n\n if (ops && ops.length > 0) {\n this.applyOps(ops);\n\n const root = this.root;\n if (!root) {\n throw new Error('There has to be a root vertex in the operations');\n }\n\n // @TODO: validate the tree structure, throw an exception if it's invalid\n }\n // @TODO: remove it? It creates an extra null vertex op in every new empty tree. Or is it ok?\n else {\n this.ensureNullVertex();\n }\n }\n\n get root(): Vertex | undefined {\n if (!this.rootVertexId) {\n const vertices = this.state.getAllVertices();\n for (const vertex of vertices) {\n if (vertex.parentId === null && vertex.id !== RepTree.NULL_VERTEX_ID) {\n this.rootVertexId = vertex.id;\n return new Vertex(this, vertex);\n }\n }\n\n return undefined;\n }\n\n const rootVertex = this.state.getVertex(this.rootVertexId);\n if (!rootVertex) {\n throw new Error(\"Root vertex not found\");\n }\n\n return new Vertex(this, rootVertex);\n }\n\n replicate(newPeerId: string): RepTree {\n return new RepTree(newPeerId, this.getAllOps());\n }\n\n getMoveOps(): ReadonlyArray<MoveVertex> {\n return this.moveOps;\n }\n\n getAllOps(): ReadonlyArray<VertexOperation> {\n return [...this.moveOps, ...this.setPropertyOps];\n }\n\n getVertex(vertexId: string): Vertex | undefined {\n const vertex = this.state.getVertex(vertexId);\n return vertex ? new Vertex(this, vertex) : undefined;\n }\n\n getAllVertices(): ReadonlyArray<Vertex> {\n return this.state.getAllVertices().map(v => new Vertex(this, v));\n }\n\n getParent(vertexId: string): Vertex | undefined {\n const parentId = this.state.getVertex(vertexId)?.parentId;\n const parent = parentId ? this.state.getVertex(parentId) : undefined;\n return parent ? new Vertex(this, parent) : undefined;\n }\n\n getChildren(vertexId: string): Vertex[] {\n return this.state.getChildren(vertexId).map(v => new Vertex(this, v));\n }\n\n getChildrenIds(vertexId: string): string[] {\n return this.state.getChildrenIds(vertexId);\n }\n\n getAncestors(vertexId: string): Vertex[] {\n const ancestors: Vertex[] = [];\n let currentVertex = this.state.getVertex(vertexId);\n\n while (currentVertex && currentVertex.parentId) {\n const parentVertex = this.state.getVertex(currentVertex.parentId);\n if (parentVertex) {\n ancestors.push(new Vertex(this, parentVertex));\n currentVertex = parentVertex;\n } else {\n break;\n }\n }\n\n return ancestors;\n }\n\n getVertexProperty(vertexId: string, key: string, includingTransient: boolean = true): VertexPropertyType | undefined {\n const vertex = this.state.getVertex(vertexId);\n if (!vertex) {\n return undefined;\n }\n\n return vertex.getProperty(key, includingTransient);\n }\n\n getVertexProperties(vertexId: string): Readonly<TreeVertexProperty[]> {\n const vertex = this.state.getVertex(vertexId);\n if (!vertex) {\n return [];\n }\n\n return vertex.getAllProperties();\n }\n\n /**\n * Returns all local operations and clears the local operations list.\n * Can be used to get all operations that were generated from this peer and need to be sent to other peers.\n */\n popLocalOps(): VertexOperation[] {\n const ops = this.localOps;\n this.localOps = [];\n return ops;\n }\n\n createRoot(): Vertex {\n if (this.rootVertexId) {\n throw new Error('Root vertex already exists');\n }\n\n this.rootVertexId = this.newVertexInternalWithUUID(null);\n\n const rootVertex = this.state.getVertex(this.rootVertexId);\n if (!rootVertex) {\n throw new Error(\"Root vertex not found\");\n }\n\n return new Vertex(this, rootVertex);\n }\n newVertex(parentId: string, props: Record<string, VertexPropertyType> | object | null = null): Vertex {\n const typedProps = props as Record<string, VertexPropertyType> | null;\n const vertexId = this.newVertexInternalWithUUID(parentId);\n if (typedProps) {\n this.setVertexProperties(vertexId, typedProps);\n }\n\n const vertex = this.state.getVertex(vertexId);\n if (!vertex) {\n throw new Error('Failed to create vertex');\n }\n return new Vertex(this, vertex);\n }\n\n newNamedVertex(parentId: string, name: string, props: Record<string, VertexPropertyType> | object | null = null): Vertex {\n const typedProps = props as Record<string, VertexPropertyType> | null;\n const vertexId = this.newVertexInternalWithUUID(parentId);\n if (typedProps) {\n this.setVertexProperties(vertexId, typedProps);\n }\n this.setVertexProperty(vertexId, '_n', name);\n\n const vertex = this.state.getVertex(vertexId);\n if (!vertex) {\n throw new Error('Failed to create named vertex');\n }\n return new Vertex(this, vertex);\n }\n\n moveVertex(vertexId: string, parentId: string) {\n this.lamportClock++;\n const op = newMoveVertexOp(this.lamportClock, this.peerId, vertexId, parentId);\n this.localOps.push(op);\n this.applyMove(op);\n }\n\n deleteVertex(vertexId: string) {\n this.moveVertex(vertexId, RepTree.NULL_VERTEX_ID);\n }\n\n setTransientVertexProperty(vertexId: string, key: string, value: VertexPropertyType) {\n this.lamportClock++;\n\n // Convert Y.Doc to CRDTType for operation\n let opValue: VertexPropertyTypeInOperation;\n if (value instanceof Y.Doc) {\n const state = Y.encodeStateAsUpdate(value);\n opValue = {\n type: \"yjs\",\n value: state\n };\n\n // Set up observer for future changes\n this.setupYjsObserver(value, vertexId, key);\n } else {\n // Regular values pass through unchanged\n opValue = value as VertexPropertyTypeInOperation;\n }\n\n const op = newSetTransientVertexPropertyOp(this.lamportClock, this.peerId, vertexId, key, opValue);\n this.localOps.push(op);\n this.applyProperty(op);\n }\n\n setVertexProperty(vertexId: string, key: string, value: VertexPropertyType) {\n this.lamportClock++;\n\n // Convert Y.Doc to CRDTType for operation\n let opValue: VertexPropertyTypeInOperation;\n if (value instanceof Y.Doc) {\n const state = Y.encodeStateAsUpdate(value);\n opValue = {\n type: \"yjs\",\n value: state\n };\n\n // Set up observer for future changes\n this.setupYjsObserver(value, vertexId, key);\n } else {\n // Regular values pass through unchanged\n opValue = value as VertexPropertyTypeInOperation;\n }\n\n const op = newSetVertexPropertyOp(this.lamportClock, this.peerId, vertexId, key, opValue);\n this.localOps.push(op);\n this.applyProperty(op);\n }\n\n setVertexProperties(vertexId: string, props: Record<string, VertexPropertyType> | object) {\n const typedProps = props as Record<string, VertexPropertyType>;\n for (const [key, value] of Object.entries(typedProps)) {\n this.setVertexProperty(vertexId, key, value);\n }\n }\n\n getVertexByPath(path: string): Vertex | undefined {\n // Let's remove '/' at the start and at the end of the path\n path = path.replace(/^\\/+/, '');\n path = path.replace(/\\/+$/, '');\n\n const pathParts = path.split('/');\n\n if (!this.rootVertexId) {\n return undefined;\n }\n\n const root = this.state.getVertex(this.rootVertexId);\n if (!root) {\n throw new Error('The root vertex is not found');\n }\n\n const vertex = this.getVertexByPathArray(new Vertex(this, root), pathParts);\n return vertex;\n }\n\n private getVertexByPathArray(vertex: Vertex, path: string[]): Vertex | undefined {\n if (path.length === 0) {\n return vertex ?? undefined;\n }\n\n const targetName = path[0];\n // Now, search recursively by name '_n' in children until the path is empty or not found.\n const children = this.getChildren(vertex.id);\n for (const child of children) {\n if (child.getProperty('_n') === targetName) {\n return this.getVertexByPathArray(child, path.slice(1));\n }\n }\n\n return undefined;\n }\n\n printTree() {\n if (!this.rootVertexId) {\n return '';\n }\n\n return this.state.printTree(this.rootVertexId);\n }\n\n merge(ops: ReadonlyArray<VertexOperation>) {\n /*\n if (ops.length > 100) {\n this.applyOpsOptimizedForLotsOfMoves(ops);\n } else {\n this.applyOps(ops);\n }\n */\n\n this.applyOps(ops);\n }\n\n private applyOps(ops: ReadonlyArray<VertexOperation>) {\n for (const op of ops) {\n // We skip the operation if we already know about it.\n // This is to avoid processing the same operation multiple times.\n if (this.knownOps.has(opIdToString(op.id))) {\n continue;\n }\n\n this.applyOperation(op);\n }\n }\n\n /** Applies operations in an optimized way, sorting move ops by OpId to avoid undo-do-redo cycles */\n private applyOpsOptimizedForLotsOfMoves(ops: ReadonlyArray<VertexOperation>) {\n const newMoveOps = ops.filter(op => isMoveVertexOp(op) && !this.knownOps.has(opIdToString(op.id)));\n if (newMoveOps.length > 0) {\n // Get an array of all move ops (without already applied ones)\n const allMoveOps = [...this.moveOps, ...newMoveOps] as MoveVertex[];\n // The main point of this optimization is to apply the moves without undo-do-redo cycles (the conflict resolution algorithm).\n // That is why we sort by OpId.\n allMoveOps.sort((a, b) => compareOpId(a.id, b.id));\n for (let i = 0, len = allMoveOps.length; i < len; i++) {\n const op = allMoveOps[i];\n this.applyMove(op);\n }\n }\n\n // Get an array of all property ops (without already applied ones)\n const propertyOps = ops.filter(op => isAnyPropertyOp(op) && !this.knownOps.has(opIdToString(op.id)));\n for (let i = 0, len = propertyOps.length; i < len; i++) {\n const op = propertyOps[i];\n this.applyProperty(op as SetVertexProperty);\n }\n }\n\n compareStructure(other: RepTree): boolean {\n if (this.root?.id !== other.root?.id) {\n return false;\n }\n\n if (!this.rootVertexId) {\n return true;\n }\n\n return RepTree.compareVertices(this.rootVertexId, this, other);\n }\n\n compareMoveOps(other: RepTree): boolean {\n const movesA = this.moveOps;\n const movesB = other.getMoveOps();\n\n if (movesA.length !== movesB.length) {\n return false;\n }\n\n for (let i = 0; i < movesA.length; i++) {\n if (!equalsOpId(movesA[i].id, movesB[i].id)) {\n return false;\n }\n }\n\n return true;\n }\n\n /** Checks if the given `ancestorId` is an ancestor of `childId` in the tree */\n isAncestor(childId: string, ancestorId: string | null): boolean {\n let targetId = childId;\n let vertex: VertexState | undefined;\n \n // Set to track visited vertices and detect cycles\n const visitedVertices = new Set<string>();\n\n while (vertex = this.state.getVertex(targetId)) {\n if (vertex.parentId === ancestorId) return true;\n if (!vertex.parentId) return false;\n \n // If we've already visited this vertex, we have a cycle\n if (visitedVertices.has(targetId)) {\n console.error(`isAncestor: cycle detected in the tree structure.`);\n // In the context of tryToMove, we should return false here to prevent the move\n // since the target ancestor isn't actually in the path (we're in a cycle)\n return false;\n }\n \n // Mark this vertex as visited\n visitedVertices.add(targetId);\n \n targetId = vertex.parentId;\n }\n\n return false;\n }\n\n observeVertex(vertexId: string, callback: (updatedVertex: Vertex) => void): () => void {\n const vertex = this.getVertex(vertexId);\n if (vertex) {\n callback(vertex);\n }\n\n const unsubscribe = this.observe(vertexId, (_) => {\n const vertex = this.getVertex(vertexId);\n if (vertex) {\n callback(vertex);\n }\n });\n\n return () => {\n unsubscribe();\n };\n }\n\n observeVertexMove(callback: (movedVertex: Vertex, isNew: boolean) => void): () => void {\n const listener = (events: VertexChangeEvent[]) => {\n const moveEvent = events.find(e => e.type === 'move') as VertexMoveEvent | undefined;\n if (moveEvent) {\n const vertex = this.getVertex(moveEvent.vertexId);\n if (vertex) {\n callback(vertex, moveEvent.oldParentId === undefined);\n }\n }\n };\n\n this.state.addGlobalChangeCallback(listener);\n\n return () => this.state.removeGlobalChangeCallback(listener);\n }\n\n observe(vertexId: string, callback: (events: VertexChangeEvent[]) => void): () => void {\n this.state.addChangeCallback(vertexId, callback);\n return () => this.state.removeChangeCallback(vertexId, callback);\n }\n\n observeOpApplied(callback: (op: VertexOperation) => void): () => void {\n this.opAppliedCallbacks.push(callback);\n return () => this.opAppliedCallbacks = this.opAppliedCallbacks.filter(l => l !== callback);\n }\n\n static compareVertices(vertexId: string, treeA: RepTree, treeB: RepTree): boolean {\n const childrenA = treeA.state.getChildrenIds(vertexId);\n const childrenB = treeB.state.getChildrenIds(vertexId);\n\n if (childrenA.length !== childrenB.length) {\n return false;\n }\n\n // Compare properties of the current vertex\n if (vertexId !== null) {\n const propertiesA = treeA.getVertexProperties(vertexId);\n const propertiesB = treeB.getVertexProperties(vertexId);\n\n if (propertiesA.length !== propertiesB.length) {\n return false;\n }\n\n for (const propA of propertiesA) {\n const propB = propertiesB.find(p => p.key === propA.key);\n if (!propB) {\n return false;\n }\n \n // Special handling for Yjs documents\n if (propA.value instanceof Y.Doc && propB.value instanceof Y.Doc) {\n // Create snapshots of the Yjs documents\n const snapshotA = Y.snapshot(propA.value);\n const snapshotB = Y.snapshot(propB.value);\n \n // Compare the snapshots using Y.equalSnapshots\n // This properly compares the document structure and content\n if (!Y.equalSnapshots(snapshotA, snapshotB)) {\n return false;\n }\n } else if (propA.value !== propB.value) {\n return false;\n } \n }\n }\n\n // Compare children and their properties recursively\n for (const childId of childrenA) {\n if (!childrenB.includes(childId)) {\n return false;\n }\n\n if (!RepTree.compareVertices(childId, treeA, treeB)) {\n return false;\n }\n }\n\n return true;\n }\n\n private newVertexInternal(vertexId: string, parentId: string | null): string {\n this.lamportClock++;\n // To create a vertex - we move a vertex with a fresh id under the parent.\n // No need to have a separate \"create vertex\" operation.\n const op = newMoveVertexOp(this.lamportClock, this.peerId, vertexId, parentId);\n this.localOps.push(op);\n this.applyMove(op);\n\n // Set the creation date\n this.setVertexProperty(vertexId, '_c', new Date().toISOString());\n\n return vertexId;\n }\n\n private newVertexInternalWithUUID(parentId: string | null): string {\n const vertexId = uuid();\n return this.newVertexInternal(vertexId, parentId);\n }\n\n private ensureNullVertex() {\n const vertexId = RepTree.NULL_VERTEX_ID;\n\n // Check if the null vertex already exists\n if (this.state.getVertex(vertexId)) {\n return;\n }\n\n this.newVertexInternal(vertexId, null);\n }\n\n /** Updates the lamport clock with the counter value of the operation */\n private updateLamportClock(operation: VertexOperation): void {\n // This is how Lamport clock updates with a foreign operation that has a greater counter value.\n if (operation.id.counter > this.lamportClock) {\n this.lamportClock = operation.id.counter;\n }\n }\n\n private applyPendingMovesForParent(parentId: string) {\n // If a parent doesn't exist, we can't apply pending moves yet.\n if (!this.state.getVertex(parentId)) {\n return;\n }\n\n const pendingMoves = this.pendingMovesWithMissingParent.get(parentId);\n if (!pendingMoves) {\n return;\n }\n\n this.pendingMovesWithMissingParent.delete(parentId);\n\n for (const pendingOp of pendingMoves) {\n this.applyMove(pendingOp);\n }\n }\n\n private applyMove(op: MoveVertex) {\n // Check if a parent (unless we're dealing with the root vertex) exists for the move operation.\n // If it doesn't exist, stash the move op for later\n if (op.parentId !== null && !this.state.getVertex(op.parentId)) {\n if (!this.pendingMovesWithMissingParent.has(op.parentId)) {\n this.pendingMovesWithMissingParent.set(op.parentId, []);\n }\n this.pendingMovesWithMissingParent.get(op.parentId)!.push(op);\n return;\n }\n\n this.updateLamportClock(op);\n\n const lastOp = this.moveOps.length > 0 ? this.moveOps[this.moveOps.length - 1] : null;\n\n // If it's the most recent move operation - just try to move it. No conflict resolution is needed.\n if (lastOp === null || isOpIdGreaterThan(op.id, lastOp.id)) {\n this.moveOps.push(op);\n this.reportOpAsApplied(op);\n this.tryToMove(op);\n }\n\n // Here comes the core of the 'THE REPLICATED TREE ALGORITHM'.\n // From https://martin.kleppmann.com/papers/move-op.pdf\n // We undo all moves that are newer (based on the Lamport clock) than the target move, do the move, and then redo the moves we just undid.\n // The algorithm ensures that all replicas converge to the same tree after applying all operations.\n // The replicas are basically forced to apply the moves in the same order (by undo-do-redo).\n // So if a conflict or a cycle is introduced by some of the peers - the algorithm will resolve it.\n // tryToMove function has the logic to detect cycles and will ignore the move if it creates a cycle. \n else {\n let targetIndex = this.moveOps.length;\n for (let i = this.moveOps.length - 1; i >= 0; i--) {\n const moveOp = this.moveOps[i];\n targetIndex = i;\n if (isOpIdGreaterThan(op.id, moveOp.id)) {\n break;\n }\n else {\n this.undoMove(moveOp);\n }\n }\n\n // Insert the op at the correct position\n this.moveOps.splice(targetIndex + 1, 0, op);\n this.reportOpAsApplied(op);\n this.tryToMove(op);\n\n // Redo all of the operations after the operation that we applied\n for (let i = targetIndex + 2; i < this.moveOps.length; i++) {\n this.tryToMove(this.moveOps[i]);\n }\n }\n\n // After applying the move, check if it unblocks any pending moves\n // We use targetId here because this vertex might now be a parent for pending operations\n this.applyPendingMovesForParent(op.targetId);\n }\n\n private setLLWPropertyAndItsOpId(op: SetVertexProperty) {\n this.propertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);\n this.state.setProperty(op.targetId, op.key, op.value);\n this.reportOpAsApplied(op);\n }\n\n private setTransientPropertyAndItsOpId(op: SetVertexProperty) {\n this.transientPropertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);\n this.state.setTransientProperty(op.targetId, op.key, op.value);\n this.reportOpAsApplied(op);\n }\n\n private setupYjsObserver(doc: Y.Doc, vertexId: string, key: string) {\n // Create a unique key for this property\n const propertyKey = `${key}@${vertexId}` as PropertyKeyAtVertexId;\n\n // Remove any existing observer\n if (this.yjsObservers.has(propertyKey)) {\n const existingDoc = this.getVertexProperty(vertexId, key);\n if (existingDoc instanceof Y.Doc) {\n existingDoc.off('update', this.yjsObservers.get(propertyKey)!);\n }\n this.yjsObservers.delete(propertyKey);\n }\n\n // Create and store the new observer\n const ydocObserver = (update: Uint8Array, origin: any, doc: Y.Doc, transaction: Y.Transaction) => { \n if (!transaction.local) {\n return;\n }\n\n // We create ops when the doc changes.\n // Only from the same peer\n\n const crdtValue: CRDTType = {\n type: \"yjs\",\n value: update\n };\n\n this.lamportClock++;\n\n // Create a SetVertexProperty operation with the CRDTType\n const op = newSetVertexPropertyOp(\n this.lamportClock,\n this.peerId,\n vertexId,\n key,\n crdtValue\n );\n\n this.localOps.push(op);\n this.applyProperty(op);\n\n // @TODO: should we remove it and only update form applyProperty\n // Update state vector if enabled\n if (this._stateVectorEnabled) {\n this.stateVector.updateFromOp(op);\n }\n };\n\n // Register the observer\n doc.on('update', ydocObserver);\n this.yjsObservers.set(propertyKey, ydocObserver);\n }\n\n private applyProperty(op: SetVertexProperty) {\n const targetVertex = this.state.getVertex(op.targetId);\n if (!targetVertex) {\n // No need to handle transient properties if the vertex doesn't exist\n if (op.transient) {\n return;\n }\n\n // If the vertex doesn't exist, we will wait for the move operation to appear that will create the vertex\n // so we can apply the property then.\n if (!this.pendingPropertiesWithMissingVertex.has(op.targetId)) {\n this.pendingPropertiesWithMissingVertex.set(op.targetId, []);\n }\n this.pendingPropertiesWithMissingVertex.get(op.targetId)!.push(op);\n return;\n }\n\n this.updateLamportClock(op);\n\n if (isModifyPropertyOp(op)) {\n this.applyModifyProperty(op, targetVertex);\n } else {\n this.applyLLWProperty(op, targetVertex);\n }\n }\n\n private applyLLWProperty(op: SetVertexProperty, targetVertex: VertexState) {\n const prevTransientOpId = this.transientPropertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);\n const prevOpId = this.propertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);\n\n if (!op.transient) {\n this.setPropertyOps.push(op);\n\n // Apply the property if it's not already applied or if the current op is newer\n // This is the last writer wins approach that ensures the same state between replicas.\n if (!prevOpId || isOpIdGreaterThan(op.id, prevOpId)) {\n this.setLLWPropertyAndItsOpId(op);\n } else {\n // We add it to set of known ops to avoid adding them to `setPropertyOps` multiple times \n // if we ever receive the same op from another peer.\n this.knownOps.add(opIdToString(op.id));\n }\n\n // Remove the transient property if the current op is greater\n if (prevTransientOpId && isOpIdGreaterThan(op.id, prevTransientOpId)) {\n this.transientPropertiesAndTheirOpIds.delete(`${op.key}@${op.targetId}`);\n targetVertex.removeTransientProperty(op.key);\n }\n\n } else {\n // Handle transient properties\n if (!prevTransientOpId || isOpIdGreaterThan(op.id, prevTransientOpId)) {\n this.setTransientPropertyAndItsOpId(op);\n }\n }\n }\n\n private applyModifyProperty(op: SetVertexProperty, targetVertex: VertexState) {\n if (op.transient) {\n console.warn(\"Not implemented: transient non LWW property\");\n return;\n }\n\n this.setPropertyOps.push(op);\n const crdtValue = op.value as CRDTType;\n\n if (crdtValue.type !== \"yjs\") {\n throw new Error(\"Unknown CRDT type\");\n }\n\n const ydoc = targetVertex.getProperty(op.key);\n\n if (ydoc instanceof Y.Doc) {\n // Apply update to existing Y.Doc\n Y.applyUpdate(ydoc, crdtValue.value);\n } else {\n // Create new Y.Doc, and apply an update\n const newDoc = new Y.Doc();\n // Setup an observer so we can automatically create ops when the doc changes\n this.setupYjsObserver(newDoc, op.targetId, op.key);\n // Set the new doc as a property on the vertex\n this.state.setProperty(op.targetId, op.key, newDoc);\n // And finally, apply the update to the new doc\n Y.applyUpdate(newDoc, crdtValue.value);\n }\n\n this.propertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);\n this.reportOpAsApplied(op);\n\n // @TODO: should we update state vector here?\n }\n\n private applyOperation(op: VertexOperation) {\n if (isMoveVertexOp(op)) {\n this.applyMove(op);\n } else if (isAnyPropertyOp(op)) {\n this.applyProperty(op);\n }\n }\n\n private reportOpAsApplied(op: VertexOperation) {\n this.knownOps.add(opIdToString(op.id));\n\n if (this._stateVectorEnabled) {\n this.stateVector.updateFromOp(op);\n }\n\n for (const callback of this.opAppliedCallbacks) {\n callback(op);\n }\n }\n\n private tryToMove(op: MoveVertex) {\n let targetVertex = this.state.getVertex(op.targetId);\n\n if (targetVertex) {\n // We cache the parentId before the move operation.\n // We will use it to undo the move according to the move op algorithm.\n this.parentIdBeforeMove.set(op.id, targetVertex.parentId);\n }\n\n // If trying to move the target vertex under itself - do nothing\n if (op.targetId === op.parentId) return;\n\n // If we try to move the vertex (op.targetId) under one of its descendants (op.parentId) - do nothing\n if (op.parentId && this.isAncestor(op.parentId, op.targetId)) return;\n\n this.state.moveVertex(op.targetId, op.parentId);\n\n // If the vertex didn't exist before the move - see if it has pending properties\n // and apply them.\n if (!targetVertex) {\n const pendingProperties = this.pendingPropertiesWithMissingVertex.get(op.targetId) || [];\n this.pendingPropertiesWithMissingVertex.delete(op.targetId);\n for (const prop of pendingProperties) {\n this.applyProperty(prop);\n }\n }\n }\n\n private undoMove(op: MoveVertex) {\n const targetVertex = this.state.getVertex(op.targetId);\n if (!targetVertex) {\n console.error(`An attempt to undo move operation ${opIdToString(op.id)} failed because the target vertex ${op.targetId} not found`);\n return;\n }\n\n const prevParentId = this.parentIdBeforeMove.get(op.id);\n if (prevParentId === undefined) {\n return;\n }\n\n this.state.moveVertex(op.targetId, prevParentId);\n }\n\n // --- Range-Based State Vector Methods --- \n\n /**\n * Returns the current state vector.\n * Returns a readonly reference to the internal state vector.\n */\n getStateVector(): Readonly<Record<string, number[][]>> | null {\n if (!this._stateVectorEnabled) {\n return null;\n }\n return this.stateVector.getState();\n }\n\n /**\n * Determines which operations are needed to synchronize \n * with the provided state vector.\n * \n * @param theirStateVector The state vector from another peer\n * @returns Operations that should be sent to the other peer, sorted by OpId.\n */\n getMissingOps(theirStateVector: Record<string, number[][]>): VertexOperation[] {\n // If state vector is disabled, fallback to sending all ops\n if (!this._stateVectorEnabled) {\n return [...this.moveOps, ...this.setPropertyOps];\n }\n\n // Create a StateVector instance from their state vector\n const otherStateVector = new StateVector(theirStateVector);\n\n // Get the missing ranges\n const missingRanges = this.stateVector.diff(otherStateVector);\n\n // Then, retrieve only the operations that fall within those ranges\n const missingOps: VertexOperation[] = [];\n // Combine moveOps and setPropertyOps for checking\n const allOps = [...this.moveOps, ...this.setPropertyOps];\n\n // Only check operations that might be in the missing ranges\n for (const op of allOps) {\n for (const range of missingRanges) {\n if (op.id.peerId === range.peerId &&\n op.id.counter >= range.start &&\n op.id.counter <= range.end) {\n missingOps.push(op);\n break; // Move to the next op once found in a missing range\n }\n }\n }\n\n // Sort the missing ops by OpId before returning, ensuring causal order\n missingOps.sort((a, b) => compareOpId(a.id, b.id));\n\n return missingOps;\n }\n\n /**\n * Gets or sets whether state vector tracking is enabled\n */\n get stateVectorEnabled(): boolean {\n return this._stateVectorEnabled;\n }\n\n /**\n * Sets the state vector enabled status\n * When enabled, rebuilds the state vector from existing operations if needed\n */\n set stateVectorEnabled(value: boolean) {\n if (value === this._stateVectorEnabled) return;\n\n if (value) {\n // Enable state vector and rebuild from existing operations\n this._stateVectorEnabled = true;\n this.stateVector = StateVector.fromOperations([...this.moveOps, ...this.setPropertyOps]);\n } else {\n // Disable state vector and clear it to save memory\n this._stateVectorEnabled = false;\n this.stateVector = new StateVector();\n }\n }\n\n /**\n * Parses the vertex properties with a provided schema that has a `parse` method (e.g., Zod schema)\n */\n parseVertex<T>(vertexId: string, schema: { parse: (data: unknown) => T }): T {\n const propsArray = this.getVertexProperties(vertexId);\n const propsObject: Record<string, unknown> = {};\n for (const { key, value } of propsArray) {\n propsObject[key] = value as unknown;\n }\n return schema.parse(propsObject);\n }\n}"],"mappings":"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","names":["vertex","doc"]}
package/dist/index.d.cts CHANGED
@@ -1,14 +1,8 @@
1
1
  import * as Y from 'yjs';
2
2
 
3
- declare class OpId {
3
+ interface OpId {
4
4
  readonly counter: number;
5
5
  readonly peerId: string;
6
- constructor(counter: number, peerId: string);
7
- static compare(opIdA: OpId | string, opIdB: OpId | string): number;
8
- static equals(opIdA: OpId | string | null, opIdB: OpId | string | null): boolean;
9
- static tryParseStr(opIdStr: string): OpId;
10
- isGreaterThan(opId: OpId | string): boolean;
11
- toString(): string;
12
6
  }
13
7
 
14
8
  declare class VertexState {
@@ -95,6 +89,32 @@ declare function newMoveVertexOp(clock: number, peerId: string, targetId: string
95
89
  declare function newSetVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty;
96
90
  declare function newSetTransientVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty;
97
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
+
98
118
  /**
99
119
  * A wrapper class for VertexState that provides a more convenient API
100
120
  * for working with vertices in a RepTree.
@@ -130,6 +150,8 @@ declare class Vertex {
130
150
  observeChildrenAsTypedArray<T>(listener: (children: T[]) => void): () => void;
131
151
  delete(): void;
132
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;
133
155
  }
134
156
 
135
157
  /**
@@ -242,6 +264,12 @@ declare class RepTree {
242
264
  * When enabled, rebuilds the state vector from existing operations if needed
243
265
  */
244
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;
245
273
  }
246
274
 
247
275
  declare class TreeState {
@@ -327,4 +355,4 @@ declare class StateVector {
327
355
 
328
356
  declare function uuid(): string;
329
357
 
330
- export { type CRDTType, type MoveVertex, 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
@@ -1,14 +1,8 @@
1
1
  import * as Y from 'yjs';
2
2
 
3
- declare class OpId {
3
+ interface OpId {
4
4
  readonly counter: number;
5
5
  readonly peerId: string;
6
- constructor(counter: number, peerId: string);
7
- static compare(opIdA: OpId | string, opIdB: OpId | string): number;
8
- static equals(opIdA: OpId | string | null, opIdB: OpId | string | null): boolean;
9
- static tryParseStr(opIdStr: string): OpId;
10
- isGreaterThan(opId: OpId | string): boolean;
11
- toString(): string;
12
6
  }
13
7
 
14
8
  declare class VertexState {
@@ -95,6 +89,32 @@ declare function newMoveVertexOp(clock: number, peerId: string, targetId: string
95
89
  declare function newSetVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty;
96
90
  declare function newSetTransientVertexPropertyOp(clock: number, peerId: string, targetId: string, key: string, value: VertexPropertyTypeInOperation): SetVertexProperty;
97
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
+
98
118
  /**
99
119
  * A wrapper class for VertexState that provides a more convenient API
100
120
  * for working with vertices in a RepTree.
@@ -130,6 +150,8 @@ declare class Vertex {
130
150
  observeChildrenAsTypedArray<T>(listener: (children: T[]) => void): () => void;
131
151
  delete(): void;
132
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;
133
155
  }
134
156
 
135
157
  /**
@@ -242,6 +264,12 @@ declare class RepTree {
242
264
  * When enabled, rebuilds the state vector from existing operations if needed
243
265
  */
244
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;
245
273
  }
246
274
 
247
275
  declare class TreeState {
@@ -327,4 +355,4 @@ declare class StateVector {
327
355
 
328
356
  declare function uuid(): string;
329
357
 
330
- export { type CRDTType, type MoveVertex, 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 };