@voidhash/mimic 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +202 -198
- package/dist/Document.cjs +1 -2
- package/dist/Document.d.cts +9 -3
- package/dist/Document.d.cts.map +1 -1
- package/dist/Document.d.mts +9 -3
- package/dist/Document.d.mts.map +1 -1
- package/dist/Document.mjs +1 -2
- package/dist/Document.mjs.map +1 -1
- package/dist/Primitive.d.cts +2 -2
- package/dist/Primitive.d.mts +2 -2
- package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectWithoutProperties.cjs +15 -0
- package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectWithoutProperties.mjs +15 -0
- package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectWithoutPropertiesLoose.cjs +14 -0
- package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectWithoutPropertiesLoose.mjs +13 -0
- package/dist/client/ClientDocument.cjs +17 -12
- package/dist/client/ClientDocument.d.mts.map +1 -1
- package/dist/client/ClientDocument.mjs +17 -12
- package/dist/client/ClientDocument.mjs.map +1 -1
- package/dist/client/WebSocketTransport.cjs +6 -6
- package/dist/client/WebSocketTransport.mjs +6 -6
- package/dist/client/WebSocketTransport.mjs.map +1 -1
- package/dist/primitives/Tree.cjs +55 -7
- package/dist/primitives/Tree.d.cts +97 -10
- package/dist/primitives/Tree.d.cts.map +1 -1
- package/dist/primitives/Tree.d.mts +97 -10
- package/dist/primitives/Tree.d.mts.map +1 -1
- package/dist/primitives/Tree.mjs +55 -7
- package/dist/primitives/Tree.mjs.map +1 -1
- package/dist/primitives/shared.d.cts +9 -0
- package/dist/primitives/shared.d.cts.map +1 -1
- package/dist/primitives/shared.d.mts +9 -0
- package/dist/primitives/shared.d.mts.map +1 -1
- package/dist/primitives/shared.mjs.map +1 -1
- package/dist/server/ServerDocument.cjs +1 -1
- package/dist/server/ServerDocument.d.cts +3 -3
- package/dist/server/ServerDocument.d.cts.map +1 -1
- package/dist/server/ServerDocument.d.mts +3 -3
- package/dist/server/ServerDocument.d.mts.map +1 -1
- package/dist/server/ServerDocument.mjs +1 -1
- package/dist/server/ServerDocument.mjs.map +1 -1
- package/package.json +2 -2
- package/src/Document.ts +18 -5
- package/src/client/ClientDocument.ts +20 -21
- package/src/client/WebSocketTransport.ts +9 -9
- package/src/primitives/Tree.ts +209 -19
- package/src/primitives/shared.ts +10 -1
- package/src/server/ServerDocument.ts +4 -3
- package/tests/client/ClientDocument.test.ts +309 -2
- package/tests/client/WebSocketTransport.test.ts +228 -3
- package/tests/primitives/Tree.test.ts +291 -17
- package/tests/server/ServerDocument.test.ts +1 -1
- package/tsconfig.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tree.mjs","names":["descendantIds: string[]","FractionalIndex.base62CharSet","FractionalIndex.generateKeyBetween","OperationDefinition.make","children: TreeNodeSnapshot<any>[]","Operation.fromDefinition","newState: TreeState<TRoot>","node","OperationPath.pathsOverlap","clientTokens","serverTokens","OperationPath.pathsEqual","OperationPath.isPrefix"],"sources":["../../src/primitives/Tree.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\nimport * as OperationDefinition from \"../OperationDefinition\";\nimport * as Operation from \"../Operation\";\nimport * as OperationPath from \"../OperationPath\";\nimport * as ProxyEnvironment from \"../ProxyEnvironment\";\nimport * as Transform from \"../Transform\";\nimport * as FractionalIndex from \"../FractionalIndex\";\nimport type { Primitive, PrimitiveInternal, Validator, InferProxy, AnyPrimitive, InferSetInput, InferUpdateInput } from \"./shared\";\nimport { ValidationError, applyDefaults } from \"./shared\";\nimport { runValidators } from \"./shared\";\nimport type { AnyTreeNodePrimitive, InferTreeNodeType, InferTreeNodeDataState, InferTreeNodeChildren } from \"./TreeNode\";\nimport { InferStructState, StructSetInput, StructUpdateValue } from \"./Struct\";\nimport { StructPrimitive } from \"./Struct\";\n\n\n/**\n * A node in the tree state (flat storage format)\n */\nexport interface TreeNodeState {\n readonly id: string; // Unique node identifier (UUID)\n readonly type: string; // Node type discriminator\n readonly parentId: string | null; // Parent node ID (null for root)\n readonly pos: string; // Fractional index for sibling ordering\n readonly data: unknown; // Node-specific data\n}\n\n/**\n * Typed node state for a specific node type\n */\nexport interface TypedTreeNodeState<TNode extends AnyTreeNodePrimitive> {\n readonly id: string;\n readonly type: InferTreeNodeType<TNode>;\n readonly parentId: string | null;\n readonly pos: string;\n readonly data: InferTreeNodeDataState<TNode>;\n}\n\n/**\n * The state type for trees - a flat array of nodes\n */\nexport type TreeState<_TRoot extends AnyTreeNodePrimitive> = readonly TreeNodeState[];\n\n/**\n * Helper to get children sorted by position\n */\nconst getOrderedChildren = (\n nodes: readonly TreeNodeState[],\n parentId: string | null\n): TreeNodeState[] => {\n return [...nodes]\n .filter(n => n.parentId === parentId)\n .sort((a, b) => a.pos < b.pos ? -1 : a.pos > b.pos ? 1 : 0);\n};\n\n/**\n * Get all descendant IDs of a node (recursive)\n */\nconst getDescendantIds = (\n nodes: readonly TreeNodeState[],\n nodeId: string\n): string[] => {\n const children = nodes.filter(n => n.parentId === nodeId);\n const descendantIds: string[] = [];\n for (const child of children) {\n descendantIds.push(child.id);\n descendantIds.push(...getDescendantIds(nodes, child.id));\n }\n return descendantIds;\n};\n\n/**\n * Check if moving a node to a new parent would create a cycle\n */\nconst wouldCreateCycle = (\n nodes: readonly TreeNodeState[],\n nodeId: string,\n newParentId: string | null\n): boolean => {\n if (newParentId === null) return false;\n if (newParentId === nodeId) return true;\n \n const descendants = getDescendantIds(nodes, nodeId);\n return descendants.includes(newParentId);\n};\n\n/**\n * Generate a fractional position between two positions\n */\nconst generateTreePosBetween = (left: string | null, right: string | null): string => {\n const charSet = FractionalIndex.base62CharSet();\n return Effect.runSync(FractionalIndex.generateKeyBetween(left, right, charSet));\n};\n\n/**\n * Snapshot of a single node for UI rendering (data properties spread at node level)\n */\nexport type TreeNodeSnapshot<TNode extends AnyTreeNodePrimitive> = {\n readonly id: string;\n readonly type: InferTreeNodeType<TNode>;\n readonly children: TreeNodeSnapshot<InferTreeNodeChildren<TNode>>[];\n} & InferTreeNodeDataState<TNode>;\n\n/**\n * Infer the snapshot type for a tree (recursive tree structure for UI)\n */\nexport type InferTreeSnapshot<T extends TreePrimitive<any>> =\n T extends TreePrimitive<infer TRoot> ? TreeNodeSnapshot<TRoot> : never;\n\n/**\n * Helper type to infer the update value type from a TreeNode's data.\n * Uses StructUpdateValue directly to get field-level partial update semantics.\n * All fields are optional in update operations.\n */\nexport type TreeNodeUpdateValue<TNode extends AnyTreeNodePrimitive> = \n TNode[\"data\"] extends StructPrimitive<infer TFields, any, any>\n ? StructUpdateValue<TFields>\n : InferUpdateInput<TNode[\"data\"]>;\n\n/**\n * Helper type to infer the input type for node data (respects field defaults).\n * Uses StructSetInput directly so that:\n * - Fields that are required AND have no default must be provided\n * - Fields that are optional OR have defaults can be omitted\n * \n * This bypasses the struct-level NeedsValue wrapper since tree inserts\n * always require a data object (even if empty for all-optional fields).\n */\nexport type TreeNodeDataSetInput<TNode extends AnyTreeNodePrimitive> = \n TNode[\"data\"] extends StructPrimitive<infer TFields, any, any>\n ? StructSetInput<TFields>\n : InferSetInput<TNode[\"data\"]>;\n\n/**\n * Typed proxy for a specific node type - provides type-safe data access\n */\nexport interface TypedNodeProxy<TNode extends AnyTreeNodePrimitive> {\n /** The node ID */\n readonly id: string;\n /** The node type */\n readonly type: InferTreeNodeType<TNode>;\n /** Access the node's data proxy */\n readonly data: InferProxy<TNode[\"data\"]>;\n /** Get the raw node state */\n get(): TypedTreeNodeState<TNode>;\n /** Updates only the specified data fields (partial update, handles nested structs recursively) */\n update(value: TreeNodeUpdateValue<TNode>): void;\n}\n\n/**\n * Node proxy with type narrowing capabilities\n */\nexport interface TreeNodeProxyBase<_TRoot extends AnyTreeNodePrimitive> {\n /** The node ID */\n readonly id: string;\n /** The node type (string) */\n readonly type: string;\n /** Type guard - narrows the proxy to a specific node type */\n is<TNode extends AnyTreeNodePrimitive>(\n nodeType: TNode\n ): this is TypedNodeProxy<TNode>;\n /** Type assertion - returns typed proxy (throws if wrong type) */\n as<TNode extends AnyTreeNodePrimitive>(\n nodeType: TNode\n ): TypedNodeProxy<TNode>;\n /** Get the raw node state */\n get(): TreeNodeState;\n}\n\n/**\n * Proxy for accessing and modifying tree nodes\n */\nexport interface TreeProxy<TRoot extends AnyTreeNodePrimitive> {\n /** Gets the entire tree state (flat array of nodes) */\n get(): TreeState<TRoot>;\n \n /** Replaces the entire tree */\n set(nodes: TreeState<TRoot>): void;\n \n /** Gets the root node state */\n root(): TypedTreeNodeState<TRoot> | undefined;\n \n /** Gets ordered children states of a parent (null for root's children) */\n children(parentId: string | null): TreeNodeState[];\n \n /** Gets a node proxy by ID with type narrowing capabilities */\n node(id: string): TreeNodeProxyBase<TRoot> | undefined;\n \n /** Insert a new node as the first child (applies defaults for node data) */\n insertFirst<TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Insert a new node as the last child (applies defaults for node data) */\n insertLast<TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Insert a new node at a specific index among siblings (applies defaults for node data) */\n insertAt<TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n index: number,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Insert a new node after a sibling (applies defaults for node data) */\n insertAfter<TNode extends AnyTreeNodePrimitive>(\n siblingId: string,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Insert a new node before a sibling (applies defaults for node data) */\n insertBefore<TNode extends AnyTreeNodePrimitive>(\n siblingId: string,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Remove a node and all its descendants */\n remove(id: string): void;\n \n /** Move a node to a new parent at a specific index */\n move(nodeId: string, newParentId: string | null, toIndex: number): void;\n \n /** Move a node after a sibling */\n moveAfter(nodeId: string, siblingId: string): void;\n \n /** Move a node before a sibling */\n moveBefore(nodeId: string, siblingId: string): void;\n \n /** Move a node to be the first child of a parent */\n moveToFirst(nodeId: string, newParentId: string | null): void;\n \n /** Move a node to be the last child of a parent */\n moveToLast(nodeId: string, newParentId: string | null): void;\n \n /** Returns a typed proxy for a specific node's data */\n at<TNode extends AnyTreeNodePrimitive>(\n id: string,\n nodeType: TNode\n ): InferProxy<TNode[\"data\"]>;\n \n /** Updates only the specified data fields of a node (partial update) */\n updateAt<TNode extends AnyTreeNodePrimitive>(\n id: string,\n nodeType: TNode,\n value: TreeNodeUpdateValue<TNode>\n ): void;\n \n /** Convert tree to a nested snapshot for UI rendering */\n toSnapshot(): TreeNodeSnapshot<TRoot> | undefined;\n}\n\ninterface TreePrimitiveSchema<TRoot extends AnyTreeNodePrimitive> {\n readonly required: boolean;\n readonly defaultValue: TreeState<TRoot> | undefined;\n readonly root: TRoot;\n readonly validators: readonly Validator<TreeState<TRoot>>[];\n}\n\n/** Input type for tree set() - tree state */\nexport type TreeSetInput<TRoot extends AnyTreeNodePrimitive> = TreeState<TRoot>;\n\n/** Input type for tree update() - same as set() for trees */\nexport type TreeUpdateInput<TRoot extends AnyTreeNodePrimitive> = TreeState<TRoot>;\n\nexport class TreePrimitive<TRoot extends AnyTreeNodePrimitive, TRequired extends boolean = false, THasDefault extends boolean = false>\n implements Primitive<TreeState<TRoot>, TreeProxy<TRoot>, TRequired, THasDefault, TreeSetInput<TRoot>, TreeUpdateInput<TRoot>>\n{\n readonly _tag = \"TreePrimitive\" as const;\n readonly _State!: TreeState<TRoot>;\n readonly _Proxy!: TreeProxy<TRoot>;\n readonly _TRequired!: TRequired;\n readonly _THasDefault!: THasDefault;\n readonly TSetInput!: TreeSetInput<TRoot>;\n readonly TUpdateInput!: TreeUpdateInput<TRoot>;\n\n private readonly _schema: TreePrimitiveSchema<TRoot>;\n private _nodeTypeRegistry: Map<string, AnyTreeNodePrimitive> | undefined;\n\n private readonly _opDefinitions = {\n set: OperationDefinition.make({\n kind: \"tree.set\" as const,\n payload: Schema.Unknown,\n target: Schema.Unknown,\n apply: (payload) => payload,\n }),\n insert: OperationDefinition.make({\n kind: \"tree.insert\" as const,\n payload: Schema.Unknown,\n target: Schema.Unknown,\n apply: (payload) => payload,\n }),\n remove: OperationDefinition.make({\n kind: \"tree.remove\" as const,\n payload: Schema.Unknown,\n target: Schema.Unknown,\n apply: (payload) => payload,\n }),\n move: OperationDefinition.make({\n kind: \"tree.move\" as const,\n payload: Schema.Unknown,\n target: Schema.Unknown,\n apply: (payload) => payload,\n }),\n };\n\n constructor(schema: TreePrimitiveSchema<TRoot>) {\n this._schema = schema;\n }\n\n /** Mark this tree as required */\n required(): TreePrimitive<TRoot, true, THasDefault> {\n return new TreePrimitive({\n ...this._schema,\n required: true,\n });\n }\n\n /** Set a default value for this tree */\n default(defaultValue: TreeState<TRoot>): TreePrimitive<TRoot, TRequired, true> {\n return new TreePrimitive({\n ...this._schema,\n defaultValue,\n });\n }\n\n /** Get the root node type */\n get root(): TRoot {\n return this._schema.root;\n }\n\n /** Add a custom validation rule */\n refine(fn: (value: TreeState<TRoot>) => boolean, message: string): TreePrimitive<TRoot, TRequired, THasDefault> {\n return new TreePrimitive({\n ...this._schema,\n validators: [...this._schema.validators, { validate: fn, message }],\n });\n }\n\n /**\n * Build a registry of all node types reachable from root\n */\n private _buildNodeTypeRegistry(): Map<string, AnyTreeNodePrimitive> {\n if (this._nodeTypeRegistry !== undefined) {\n return this._nodeTypeRegistry;\n }\n\n const registry = new Map<string, AnyTreeNodePrimitive>();\n const visited = new Set<string>();\n\n const visit = (node: AnyTreeNodePrimitive) => {\n if (visited.has(node.type)) return;\n visited.add(node.type);\n registry.set(node.type, node);\n\n for (const child of node.children) {\n visit(child);\n }\n };\n\n visit(this._schema.root);\n this._nodeTypeRegistry = registry;\n return registry;\n }\n\n /**\n * Get a node type primitive by its type string\n */\n private _getNodeTypePrimitive(type: string): AnyTreeNodePrimitive {\n const registry = this._buildNodeTypeRegistry();\n const nodeType = registry.get(type);\n if (!nodeType) {\n throw new ValidationError(`Unknown node type: ${type}`);\n }\n return nodeType;\n }\n\n /**\n * Validate that a node type can be a child of a parent node type\n */\n private _validateChildType(\n parentType: string | null,\n childType: string\n ): void {\n if (parentType === null) {\n // Root level - child must be the root type\n if (childType !== this._schema.root.type) {\n throw new ValidationError(\n `Root node must be of type \"${this._schema.root.type}\", got \"${childType}\"`\n );\n }\n return;\n }\n\n const parentNodePrimitive = this._getNodeTypePrimitive(parentType);\n if (!parentNodePrimitive.isChildAllowed(childType)) {\n const allowedTypes = parentNodePrimitive.children.map(c => c.type).join(\", \");\n throw new ValidationError(\n `Node type \"${childType}\" is not allowed as a child of \"${parentType}\". ` +\n `Allowed types: ${allowedTypes || \"none\"}`\n );\n }\n }\n\n readonly _internal: PrimitiveInternal<TreeState<TRoot>, TreeProxy<TRoot>> = {\n createProxy: (\n env: ProxyEnvironment.ProxyEnvironment,\n operationPath: OperationPath.OperationPath\n ): TreeProxy<TRoot> => {\n // Helper to get current state\n const getCurrentState = (): TreeState<TRoot> => {\n const state = env.getState(operationPath) as TreeState<TRoot> | undefined;\n return state ?? [];\n };\n\n // Helper to get parent type from state\n const getParentType = (parentId: string | null): string | null => {\n if (parentId === null) return null;\n const state = getCurrentState();\n const parent = state.find(n => n.id === parentId);\n return parent?.type ?? null;\n };\n\n // Helper to create a node proxy with type narrowing\n const createNodeProxy = (nodeState: TreeNodeState): TreeNodeProxyBase<TRoot> => {\n return {\n id: nodeState.id,\n type: nodeState.type,\n \n is: <TNode extends AnyTreeNodePrimitive>(\n nodeType: TNode\n ): boolean => {\n return nodeState.type === nodeType.type;\n },\n \n as: <TNode extends AnyTreeNodePrimitive>(\n nodeType: TNode\n ): TypedNodeProxy<TNode> => {\n if (nodeState.type !== nodeType.type) {\n throw new ValidationError(\n `Node is of type \"${nodeState.type}\", not \"${nodeType.type}\"`\n );\n }\n const nodePath = operationPath.append(nodeState.id);\n const dataProxy = nodeType.data._internal.createProxy(env, nodePath) as InferProxy<TNode[\"data\"]>;\n return {\n id: nodeState.id,\n type: nodeType.type as InferTreeNodeType<TNode>,\n data: dataProxy,\n get: () => nodeState as TypedTreeNodeState<TNode>,\n update: (value: TreeNodeUpdateValue<TNode>) => {\n // Delegate to the data proxy's update method\n (dataProxy as { update: (v: unknown) => void }).update(value);\n },\n };\n },\n \n get: () => nodeState,\n } as TreeNodeProxyBase<TRoot>;\n };\n\n // Helper to build recursive snapshot\n const buildSnapshot = (\n nodeId: string,\n nodes: readonly TreeNodeState[]\n ): TreeNodeSnapshot<TRoot> | undefined => {\n const node = nodes.find(n => n.id === nodeId);\n if (!node) return undefined;\n\n const childNodes = getOrderedChildren(nodes, nodeId);\n const children: TreeNodeSnapshot<any>[] = [];\n for (const child of childNodes) {\n const childSnapshot = buildSnapshot(child.id, nodes);\n if (childSnapshot) {\n children.push(childSnapshot);\n }\n }\n\n // Spread data properties at node level\n return {\n id: node.id,\n type: node.type,\n ...(node.data as object),\n children,\n } as unknown as TreeNodeSnapshot<TRoot>;\n };\n\n return {\n get: (): TreeState<TRoot> => {\n return getCurrentState();\n },\n\n set: (nodes: TreeState<TRoot>) => {\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.set, nodes)\n );\n },\n\n root: (): TypedTreeNodeState<TRoot> | undefined => {\n const state = getCurrentState();\n const rootNode = state.find(n => n.parentId === null);\n return rootNode as TypedTreeNodeState<TRoot> | undefined;\n },\n\n children: (parentId: string | null): TreeNodeState[] => {\n const state = getCurrentState();\n return getOrderedChildren(state, parentId);\n },\n\n node: (id: string): TreeNodeProxyBase<TRoot> | undefined => {\n const state = getCurrentState();\n const nodeState = state.find(n => n.id === id);\n if (!nodeState) return undefined;\n return createNodeProxy(nodeState);\n },\n\n insertFirst: <TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const siblings = getOrderedChildren(state, parentId);\n const firstPos = siblings.length > 0 ? siblings[0]!.pos : null;\n const pos = generateTreePosBetween(null, firstPos);\n const id = env.generateId();\n\n // Validate parent exists (if not root)\n if (parentId !== null && !state.find(n => n.id === parentId)) {\n throw new ValidationError(`Parent node not found: ${parentId}`);\n }\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Validate single root\n if (parentId === null && state.some(n => n.parentId === null)) {\n throw new ValidationError(\"Tree already has a root node\");\n }\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n insertLast: <TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const siblings = getOrderedChildren(state, parentId);\n const lastPos = siblings.length > 0 ? siblings[siblings.length - 1]!.pos : null;\n const pos = generateTreePosBetween(lastPos, null);\n const id = env.generateId();\n\n // Validate parent exists (if not root)\n if (parentId !== null && !state.find(n => n.id === parentId)) {\n throw new ValidationError(`Parent node not found: ${parentId}`);\n }\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Validate single root\n if (parentId === null && state.some(n => n.parentId === null)) {\n throw new ValidationError(\"Tree already has a root node\");\n }\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n insertAt: <TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n index: number,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const siblings = getOrderedChildren(state, parentId);\n const clampedIndex = Math.max(0, Math.min(index, siblings.length));\n const leftPos = clampedIndex > 0 && siblings[clampedIndex - 1] ? siblings[clampedIndex - 1]!.pos : null;\n const rightPos = clampedIndex < siblings.length && siblings[clampedIndex] ? siblings[clampedIndex]!.pos : null;\n const pos = generateTreePosBetween(leftPos, rightPos);\n const id = env.generateId();\n\n // Validate parent exists (if not root)\n if (parentId !== null && !state.find(n => n.id === parentId)) {\n throw new ValidationError(`Parent node not found: ${parentId}`);\n }\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Validate single root\n if (parentId === null && state.some(n => n.parentId === null)) {\n throw new ValidationError(\"Tree already has a root node\");\n }\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n insertAfter: <TNode extends AnyTreeNodePrimitive>(\n siblingId: string,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const sibling = state.find(n => n.id === siblingId);\n if (!sibling) {\n throw new ValidationError(`Sibling node not found: ${siblingId}`);\n }\n\n const parentId = sibling.parentId;\n const siblings = getOrderedChildren(state, parentId);\n const siblingIndex = siblings.findIndex(n => n.id === siblingId);\n const nextSibling = siblings[siblingIndex + 1];\n const pos = generateTreePosBetween(sibling.pos, nextSibling?.pos ?? null);\n const id = env.generateId();\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n insertBefore: <TNode extends AnyTreeNodePrimitive>(\n siblingId: string,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const sibling = state.find(n => n.id === siblingId);\n if (!sibling) {\n throw new ValidationError(`Sibling node not found: ${siblingId}`);\n }\n\n const parentId = sibling.parentId;\n const siblings = getOrderedChildren(state, parentId);\n const siblingIndex = siblings.findIndex(n => n.id === siblingId);\n const prevSibling = siblings[siblingIndex - 1];\n const pos = generateTreePosBetween(prevSibling?.pos ?? null, sibling.pos);\n const id = env.generateId();\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n remove: (id: string) => {\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.remove, { id })\n );\n },\n\n move: (nodeId: string, newParentId: string | null, toIndex: number) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n\n // Validate parent exists (if not moving to root)\n if (newParentId !== null && !state.find(n => n.id === newParentId)) {\n throw new ValidationError(`Parent node not found: ${newParentId}`);\n }\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n // Calculate new position among new siblings (excluding self)\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const clampedIndex = Math.max(0, Math.min(toIndex, siblings.length));\n const leftPos = clampedIndex > 0 && siblings[clampedIndex - 1] ? siblings[clampedIndex - 1]!.pos : null;\n const rightPos = clampedIndex < siblings.length && siblings[clampedIndex] ? siblings[clampedIndex]!.pos : null;\n const pos = generateTreePosBetween(leftPos, rightPos);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n moveAfter: (nodeId: string, siblingId: string) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n const sibling = state.find(n => n.id === siblingId);\n \n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n if (!sibling) {\n throw new ValidationError(`Sibling node not found: ${siblingId}`);\n }\n\n const newParentId = sibling.parentId;\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const siblingIndex = siblings.findIndex(n => n.id === siblingId);\n const nextSibling = siblings[siblingIndex + 1];\n const pos = generateTreePosBetween(sibling.pos, nextSibling?.pos ?? null);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n moveBefore: (nodeId: string, siblingId: string) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n const sibling = state.find(n => n.id === siblingId);\n \n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n if (!sibling) {\n throw new ValidationError(`Sibling node not found: ${siblingId}`);\n }\n\n const newParentId = sibling.parentId;\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const siblingIndex = siblings.findIndex(n => n.id === siblingId);\n const prevSibling = siblings[siblingIndex - 1];\n const pos = generateTreePosBetween(prevSibling?.pos ?? null, sibling.pos);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n moveToFirst: (nodeId: string, newParentId: string | null) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n \n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n\n // Validate parent exists (if not moving to root)\n if (newParentId !== null && !state.find(n => n.id === newParentId)) {\n throw new ValidationError(`Parent node not found: ${newParentId}`);\n }\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const firstPos = siblings.length > 0 ? siblings[0]!.pos : null;\n const pos = generateTreePosBetween(null, firstPos);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n moveToLast: (nodeId: string, newParentId: string | null) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n \n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n\n // Validate parent exists (if not moving to root)\n if (newParentId !== null && !state.find(n => n.id === newParentId)) {\n throw new ValidationError(`Parent node not found: ${newParentId}`);\n }\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const lastPos = siblings.length > 0 ? siblings[siblings.length - 1]!.pos : null;\n const pos = generateTreePosBetween(lastPos, null);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n at: <TNode extends AnyTreeNodePrimitive>(\n id: string,\n nodeType: TNode\n ): InferProxy<TNode[\"data\"]> => {\n // Get the node to verify its type\n const state = getCurrentState();\n const node = state.find(n => n.id === id);\n if (!node) {\n throw new ValidationError(`Node not found: ${id}`);\n }\n if (node.type !== nodeType.type) {\n throw new ValidationError(\n `Node is of type \"${node.type}\", not \"${nodeType.type}\"`\n );\n }\n\n const nodePath = operationPath.append(id);\n return nodeType.data._internal.createProxy(env, nodePath) as InferProxy<TNode[\"data\"]>;\n },\n\n updateAt: <TNode extends AnyTreeNodePrimitive>(\n id: string,\n nodeType: TNode,\n value: TreeNodeUpdateValue<TNode>\n ): void => {\n // Get the node to verify its type\n const state = getCurrentState();\n const node = state.find(n => n.id === id);\n if (!node) {\n throw new ValidationError(`Node not found: ${id}`);\n }\n if (node.type !== nodeType.type) {\n throw new ValidationError(\n `Node is of type \"${node.type}\", not \"${nodeType.type}\"`\n );\n }\n\n const nodePath = operationPath.append(id);\n const dataProxy = nodeType.data._internal.createProxy(env, nodePath);\n // Delegate to the data proxy's update method\n (dataProxy as { update: (v: unknown) => void }).update(value);\n },\n\n toSnapshot: (): TreeNodeSnapshot<TRoot> | undefined => {\n const state = getCurrentState();\n const rootNode = state.find(n => n.parentId === null);\n if (!rootNode) return undefined;\n return buildSnapshot(rootNode.id, state);\n },\n };\n },\n\n applyOperation: (\n state: TreeState<TRoot> | undefined,\n operation: Operation.Operation<any, any, any>\n ): TreeState<TRoot> => {\n const path = operation.path;\n const tokens = path.toTokens().filter((t: string) => t !== \"\");\n const currentState = state ?? [];\n\n let newState: TreeState<TRoot>;\n\n // If path is empty, this is a tree-level operation\n if (tokens.length === 0) {\n switch (operation.kind) {\n case \"tree.set\": {\n const payload = operation.payload;\n if (!globalThis.Array.isArray(payload)) {\n throw new ValidationError(`TreePrimitive.set requires an array payload`);\n }\n newState = payload as TreeState<TRoot>;\n break;\n }\n case \"tree.insert\": {\n const { id, type, parentId, pos, data } = operation.payload as {\n id: string;\n type: string;\n parentId: string | null;\n pos: string;\n data: unknown;\n };\n newState = [...currentState, { id, type, parentId, pos, data }] as TreeState<TRoot>;\n break;\n }\n case \"tree.remove\": {\n const { id } = operation.payload as { id: string };\n // Get all descendants to remove\n const descendantIds = getDescendantIds(currentState, id);\n const idsToRemove = new Set([id, ...descendantIds]);\n newState = currentState.filter(node => !idsToRemove.has(node.id));\n break;\n }\n case \"tree.move\": {\n const { id, parentId, pos } = operation.payload as {\n id: string;\n parentId: string | null;\n pos: string;\n };\n newState = currentState.map(node =>\n node.id === id ? { ...node, parentId, pos } : node\n ) as TreeState<TRoot>;\n break;\n }\n default:\n throw new ValidationError(`TreePrimitive cannot apply operation of kind: ${operation.kind}`);\n }\n } else {\n // Otherwise, delegate to the node's data primitive\n const nodeId = tokens[0]!;\n const nodeIndex = currentState.findIndex(node => node.id === nodeId);\n \n if (nodeIndex === -1) {\n throw new ValidationError(`Tree node not found with ID: ${nodeId}`);\n }\n\n const node = currentState[nodeIndex]!;\n const nodeTypePrimitive = this._getNodeTypePrimitive(node.type);\n const remainingPath = path.shift();\n const nodeOperation = {\n ...operation,\n path: remainingPath,\n };\n\n const newData = nodeTypePrimitive.data._internal.applyOperation(\n node.data as InferStructState<any> | undefined,\n nodeOperation\n );\n\n const mutableState = [...currentState];\n mutableState[nodeIndex] = { ...node, data: newData };\n newState = mutableState as TreeState<TRoot>;\n }\n\n // Run validators on the new state\n runValidators(newState, this._schema.validators);\n\n return newState;\n },\n\n getInitialState: (): TreeState<TRoot> | undefined => {\n if (this._schema.defaultValue !== undefined) {\n return this._schema.defaultValue;\n }\n\n // Automatically create a root node with default data\n const rootNodeType = this._schema.root;\n const rootData = rootNodeType.data._internal.getInitialState() ?? {};\n const rootId = crypto.randomUUID();\n const rootPos = generateTreePosBetween(null, null);\n\n return [{\n id: rootId,\n type: rootNodeType.type,\n parentId: null,\n pos: rootPos,\n data: rootData,\n }] as TreeState<TRoot>;\n },\n\n transformOperation: (\n clientOp: Operation.Operation<any, any, any>,\n serverOp: Operation.Operation<any, any, any>\n ): Transform.TransformResult => {\n const clientPath = clientOp.path;\n const serverPath = serverOp.path;\n\n // If paths don't overlap at all, no transformation needed\n if (!OperationPath.pathsOverlap(clientPath, serverPath)) {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Handle tree.remove from server - check if client is operating on removed node or descendants\n if (serverOp.kind === \"tree.remove\") {\n const removedId = (serverOp.payload as { id: string }).id;\n const clientTokens = clientPath.toTokens().filter((t: string) => t !== \"\");\n const serverTokens = serverPath.toTokens().filter((t: string) => t !== \"\");\n\n // Check if client operation targets the removed node or uses it\n if (clientOp.kind === \"tree.move\") {\n const movePayload = clientOp.payload as { id: string; parentId: string | null };\n // If moving the removed node or moving to a removed parent\n if (movePayload.id === removedId || movePayload.parentId === removedId) {\n return { type: \"noop\" };\n }\n }\n\n if (clientOp.kind === \"tree.insert\") {\n const insertPayload = clientOp.payload as { parentId: string | null };\n // If inserting into a removed parent\n if (insertPayload.parentId === removedId) {\n return { type: \"noop\" };\n }\n }\n\n // Check if client is operating on a node that was removed\n if (clientTokens.length > serverTokens.length) {\n const nodeId = clientTokens[serverTokens.length];\n if (nodeId === removedId) {\n return { type: \"noop\" };\n }\n }\n }\n\n // Both inserting - no conflict (fractional indexing handles order)\n if (serverOp.kind === \"tree.insert\" && clientOp.kind === \"tree.insert\") {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Both moving same node - client wins\n if (serverOp.kind === \"tree.move\" && clientOp.kind === \"tree.move\") {\n const serverMoveId = (serverOp.payload as { id: string }).id;\n const clientMoveId = (clientOp.payload as { id: string }).id;\n\n if (serverMoveId === clientMoveId) {\n return { type: \"transformed\", operation: clientOp };\n }\n // Different nodes - no conflict\n return { type: \"transformed\", operation: clientOp };\n }\n\n // For same exact path: client wins (last-write-wins)\n if (OperationPath.pathsEqual(clientPath, serverPath)) {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // If server set entire tree and client is operating on a node\n if (serverOp.kind === \"tree.set\" && OperationPath.isPrefix(serverPath, clientPath)) {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Delegate to node data primitive for nested operations\n const clientTokens = clientPath.toTokens().filter((t: string) => t !== \"\");\n const serverTokens = serverPath.toTokens().filter((t: string) => t !== \"\");\n\n // Both operations target children of this tree\n if (clientTokens.length > 0 && serverTokens.length > 0) {\n const clientNodeId = clientTokens[0];\n const serverNodeId = serverTokens[0];\n\n // If operating on different nodes, no conflict\n if (clientNodeId !== serverNodeId) {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Same node - would need to delegate to node's data primitive\n // For simplicity, let client win\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Default: no transformation needed\n return { type: \"transformed\", operation: clientOp };\n },\n };\n}\n\n/** Options for creating a Tree primitive */\nexport interface TreeOptions<TRoot extends AnyTreeNodePrimitive> {\n /** The root node type */\n readonly root: TRoot;\n}\n\n/** Creates a new TreePrimitive with the given root node type */\nexport const Tree = <TRoot extends AnyTreeNodePrimitive>(\n options: TreeOptions<TRoot>\n): TreePrimitive<TRoot, false, false> =>\n new TreePrimitive({\n required: false,\n defaultValue: undefined,\n root: options.root,\n validators: [],\n });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tree.mjs","names":["descendantIds: string[]","FractionalIndex.base62CharSet","FractionalIndex.generateKeyBetween","OperationDefinition.make","children: TreeNodeSnapshot<any>[]","Operation.fromDefinition","newState: TreeState<TRoot>","node","OperationPath.pathsOverlap","clientTokens","serverTokens","OperationPath.pathsEqual","OperationPath.isPrefix","result: TreeNodeState[]","prevChildPos: string | null"],"sources":["../../src/primitives/Tree.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\nimport * as OperationDefinition from \"../OperationDefinition\";\nimport * as Operation from \"../Operation\";\nimport * as OperationPath from \"../OperationPath\";\nimport * as ProxyEnvironment from \"../ProxyEnvironment\";\nimport * as Transform from \"../Transform\";\nimport * as FractionalIndex from \"../FractionalIndex\";\nimport type { Primitive, PrimitiveInternal, Validator, InferProxy, AnyPrimitive, InferSetInput, InferUpdateInput } from \"./shared\";\nimport { ValidationError, applyDefaults } from \"./shared\";\nimport { runValidators } from \"./shared\";\nimport type { AnyTreeNodePrimitive, InferTreeNodeType, InferTreeNodeDataState, InferTreeNodeChildren } from \"./TreeNode\";\nimport { InferStructState, StructSetInput, StructUpdateValue } from \"./Struct\";\nimport { StructPrimitive } from \"./Struct\";\n\n\n/**\n * A node in the tree state (flat storage format)\n */\nexport interface TreeNodeState {\n readonly id: string; // Unique node identifier (UUID)\n readonly type: string; // Node type discriminator\n readonly parentId: string | null; // Parent node ID (null for root)\n readonly pos: string; // Fractional index for sibling ordering\n readonly data: unknown; // Node-specific data\n}\n\n/**\n * Typed node state for a specific node type\n */\nexport interface TypedTreeNodeState<TNode extends AnyTreeNodePrimitive> {\n readonly id: string;\n readonly type: InferTreeNodeType<TNode>;\n readonly parentId: string | null;\n readonly pos: string;\n readonly data: InferTreeNodeDataState<TNode>;\n}\n\n/**\n * The state type for trees - a flat array of nodes\n */\nexport type TreeState<_TRoot extends AnyTreeNodePrimitive> = readonly TreeNodeState[];\n\n/**\n * Helper to get children sorted by position\n */\nconst getOrderedChildren = (\n nodes: readonly TreeNodeState[],\n parentId: string | null\n): TreeNodeState[] => {\n return [...nodes]\n .filter(n => n.parentId === parentId)\n .sort((a, b) => a.pos < b.pos ? -1 : a.pos > b.pos ? 1 : 0);\n};\n\n/**\n * Get all descendant IDs of a node (recursive)\n */\nconst getDescendantIds = (\n nodes: readonly TreeNodeState[],\n nodeId: string\n): string[] => {\n const children = nodes.filter(n => n.parentId === nodeId);\n const descendantIds: string[] = [];\n for (const child of children) {\n descendantIds.push(child.id);\n descendantIds.push(...getDescendantIds(nodes, child.id));\n }\n return descendantIds;\n};\n\n/**\n * Check if moving a node to a new parent would create a cycle\n */\nconst wouldCreateCycle = (\n nodes: readonly TreeNodeState[],\n nodeId: string,\n newParentId: string | null\n): boolean => {\n if (newParentId === null) return false;\n if (newParentId === nodeId) return true;\n \n const descendants = getDescendantIds(nodes, nodeId);\n return descendants.includes(newParentId);\n};\n\n/**\n * Generate a fractional position between two positions\n */\nconst generateTreePosBetween = (left: string | null, right: string | null): string => {\n const charSet = FractionalIndex.base62CharSet();\n return Effect.runSync(FractionalIndex.generateKeyBetween(left, right, charSet));\n};\n\n/**\n * Snapshot of a single node for UI rendering (data properties spread at node level)\n */\nexport type TreeNodeSnapshot<TNode extends AnyTreeNodePrimitive> = {\n readonly id: string;\n readonly type: InferTreeNodeType<TNode>;\n readonly children: TreeNodeSnapshot<InferTreeNodeChildren<TNode>>[];\n} & InferTreeNodeDataState<TNode>;\n\n/**\n * Infer the snapshot type for a tree (recursive tree structure for UI)\n */\nexport type InferTreeSnapshot<T extends TreePrimitive<any>> =\n T extends TreePrimitive<infer TRoot> ? TreeNodeSnapshot<TRoot> : never;\n\n/**\n * Helper type to infer the update value type from a TreeNode's data.\n * Uses StructUpdateValue directly to get field-level partial update semantics.\n * All fields are optional in update operations.\n */\nexport type TreeNodeUpdateValue<TNode extends AnyTreeNodePrimitive> = \n TNode[\"data\"] extends StructPrimitive<infer TFields, any, any>\n ? StructUpdateValue<TFields>\n : InferUpdateInput<TNode[\"data\"]>;\n\n/**\n * Helper type to infer the input type for node data (respects field defaults).\n * Uses StructSetInput directly so that:\n * - Fields that are required AND have no default must be provided\n * - Fields that are optional OR have defaults can be omitted\n *\n * This bypasses the struct-level NeedsValue wrapper since tree inserts\n * always require a data object (even if empty for all-optional fields).\n */\nexport type TreeNodeDataSetInput<TNode extends AnyTreeNodePrimitive> =\n TNode[\"data\"] extends StructPrimitive<infer TFields, any, any>\n ? StructSetInput<TFields>\n : InferSetInput<TNode[\"data\"]>;\n\n// =============================================================================\n// Nested Input Types for set() and default()\n// =============================================================================\n\n/**\n * Type guard to check if a type is `any` or unknown (structural check).\n * Returns true if T is `any`, false otherwise.\n */\ntype IsAny<T> = 0 extends (1 & T) ? true : false;\n\n/**\n * Get children types, with special handling for self-referential nodes.\n * When InferTreeNodeChildren returns `any` (from TreeNodePrimitive<..., any>),\n * we fall back to using TNode itself as its own child type.\n * This handles the common case of self-referential nodes like:\n * FolderNode = TreeNode(\"folder\", { children: [TreeNodeSelf, FileNode] })\n * Where FolderNode's TChildren is resolved to FolderNode | FileNode,\n * but the self-referenced FolderNode has TChildren = any.\n */\ntype ResolveChildrenForInput<TNode extends AnyTreeNodePrimitive, TOriginalNode extends AnyTreeNodePrimitive> =\n IsAny<InferTreeNodeChildren<TNode>> extends true\n ? TOriginalNode // Self-reference: use the original node's type\n : InferTreeNodeChildren<TNode>;\n\n/**\n * Helper type that creates a properly typed node input for a specific node type.\n * This is the \"strict\" version that enforces exact property matching.\n *\n * The TOriginalNode parameter is used to track the original root node type\n * for proper self-reference resolution in deeply nested structures.\n */\ntype TreeNodeSetInputStrictWithRoot<TNode extends AnyTreeNodePrimitive, TOriginalNode extends AnyTreeNodePrimitive> = {\n readonly type: InferTreeNodeType<TNode>;\n readonly id?: string;\n readonly children: TreeNodeSetInputUnionWithRoot<ResolveChildrenForInput<TNode, TOriginalNode>, TOriginalNode>[];\n} & TreeNodeDataSetInput<TNode>;\n\n/**\n * Distributive conditional type that creates a union of TreeNodeSetInputStrict\n * for each node type in the union. This ensures proper type discrimination.\n *\n * When TNode is a union (e.g., FolderNode | FileNode), this distributes to:\n * TreeNodeSetInputStrict<FolderNode> | TreeNodeSetInputStrict<FileNode>\n *\n * This creates a proper discriminated union where excess property checking works.\n */\ntype TreeNodeSetInputUnionWithRoot<TNode extends AnyTreeNodePrimitive, TOriginalNode extends AnyTreeNodePrimitive> =\n TNode extends AnyTreeNodePrimitive ? TreeNodeSetInputStrictWithRoot<TNode, TOriginalNode> : never;\n\n/**\n * Helper type for single-parameter usage - uses TNode as its own original.\n */\ntype TreeNodeSetInputStrict<TNode extends AnyTreeNodePrimitive> =\n TreeNodeSetInputStrictWithRoot<TNode, TNode>;\n\n/**\n * Distributive conditional for single-parameter usage.\n */\nexport type TreeNodeSetInputUnion<TNode extends AnyTreeNodePrimitive> =\n TNode extends AnyTreeNodePrimitive ? TreeNodeSetInputStrict<TNode> : never;\n\n/**\n * Input type for a single node in a nested tree set/default operation.\n *\n * - `type` is REQUIRED - explicit type discriminator for the node\n * - `id` is optional - auto-generated if not provided\n * - `children` is a typed array of allowed child node inputs\n * - Data fields are spread at the node level (like TreeNodeSnapshot)\n *\n * When TNode is a union type (e.g., from InferTreeNodeChildren), this properly\n * distributes to create a discriminated union where:\n * - Each variant has its specific `type` literal\n * - Each variant has its specific data fields\n * - Excess property checking works correctly\n *\n * @example\n * ```typescript\n * const input: TreeNodeSetInput<BoardNode> = {\n * type: \"board\",\n * name: \"My Board\",\n * children: [\n * { type: \"column\", name: \"Todo\", children: [] }\n * ]\n * };\n * ```\n */\nexport type TreeNodeSetInput<TNode extends AnyTreeNodePrimitive> = TreeNodeSetInputUnion<TNode>;\n\n/**\n * Input type for tree set() and default() operations.\n * Accepts a nested tree structure that will be converted to flat TreeState internally.\n */\nexport type TreeSetInput<TRoot extends AnyTreeNodePrimitive> = TreeNodeSetInput<TRoot>;\n\n/**\n * Infer the set input type for a tree primitive.\n */\nexport type InferTreeSetInput<T extends TreePrimitive<any>> =\n T extends TreePrimitive<infer TRoot> ? TreeSetInput<TRoot> : never;\n\n/**\n * Internal type for processing any node input during conversion.\n * This is only used internally in _convertNestedToFlat and is not exported.\n * Allows us to keep the public TreeNodeSetInput<TNode> fully type-safe while\n * having a runtime-compatible type for internal processing.\n */\ntype InternalNodeInput = {\n readonly type: string;\n readonly id?: string;\n readonly children: InternalNodeInput[];\n readonly [key: string]: unknown;\n};\n\n/**\n * Typed proxy for a specific node type - provides type-safe data access\n */\nexport interface TypedNodeProxy<TNode extends AnyTreeNodePrimitive> {\n /** The node ID */\n readonly id: string;\n /** The node type */\n readonly type: InferTreeNodeType<TNode>;\n /** Access the node's data proxy */\n readonly data: InferProxy<TNode[\"data\"]>;\n /** Get the raw node state */\n get(): TypedTreeNodeState<TNode>;\n /** Updates only the specified data fields (partial update, handles nested structs recursively) */\n update(value: TreeNodeUpdateValue<TNode>): void;\n}\n\n/**\n * Node proxy with type narrowing capabilities\n */\nexport interface TreeNodeProxyBase<_TRoot extends AnyTreeNodePrimitive> {\n /** The node ID */\n readonly id: string;\n /** The node type (string) */\n readonly type: string;\n /** Type guard - narrows the proxy to a specific node type */\n is<TNode extends AnyTreeNodePrimitive>(\n nodeType: TNode\n ): this is TypedNodeProxy<TNode>;\n /** Type assertion - returns typed proxy (throws if wrong type) */\n as<TNode extends AnyTreeNodePrimitive>(\n nodeType: TNode\n ): TypedNodeProxy<TNode>;\n /** Get the raw node state */\n get(): TreeNodeState;\n}\n\n/**\n * Proxy for accessing and modifying tree nodes\n */\nexport interface TreeProxy<TRoot extends AnyTreeNodePrimitive> {\n /** Gets the entire tree state (flat array of nodes) */\n get(): TreeState<TRoot>;\n\n /** Replaces the entire tree with a nested input structure */\n set(input: TreeSetInput<TRoot>): void;\n \n /** Gets the root node state */\n root(): TypedTreeNodeState<TRoot> | undefined;\n \n /** Gets ordered children states of a parent (null for root's children) */\n children(parentId: string | null): TreeNodeState[];\n \n /** Gets a node proxy by ID with type narrowing capabilities */\n node(id: string): TreeNodeProxyBase<TRoot> | undefined;\n \n /** Insert a new node as the first child (applies defaults for node data) */\n insertFirst<TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Insert a new node as the last child (applies defaults for node data) */\n insertLast<TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Insert a new node at a specific index among siblings (applies defaults for node data) */\n insertAt<TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n index: number,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Insert a new node after a sibling (applies defaults for node data) */\n insertAfter<TNode extends AnyTreeNodePrimitive>(\n siblingId: string,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Insert a new node before a sibling (applies defaults for node data) */\n insertBefore<TNode extends AnyTreeNodePrimitive>(\n siblingId: string,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string;\n \n /** Remove a node and all its descendants */\n remove(id: string): void;\n \n /** Move a node to a new parent at a specific index */\n move(nodeId: string, newParentId: string | null, toIndex: number): void;\n \n /** Move a node after a sibling */\n moveAfter(nodeId: string, siblingId: string): void;\n \n /** Move a node before a sibling */\n moveBefore(nodeId: string, siblingId: string): void;\n \n /** Move a node to be the first child of a parent */\n moveToFirst(nodeId: string, newParentId: string | null): void;\n \n /** Move a node to be the last child of a parent */\n moveToLast(nodeId: string, newParentId: string | null): void;\n \n /** Returns a typed proxy for a specific node's data */\n at<TNode extends AnyTreeNodePrimitive>(\n id: string,\n nodeType: TNode\n ): InferProxy<TNode[\"data\"]>;\n \n /** Updates only the specified data fields of a node (partial update) */\n updateAt<TNode extends AnyTreeNodePrimitive>(\n id: string,\n nodeType: TNode,\n value: TreeNodeUpdateValue<TNode>\n ): void;\n \n /** Convert tree to a nested snapshot for UI rendering */\n toSnapshot(): TreeNodeSnapshot<TRoot> | undefined;\n}\n\ninterface TreePrimitiveSchema<TRoot extends AnyTreeNodePrimitive> {\n readonly required: boolean;\n readonly defaultInput: TreeNodeSetInput<TRoot> | undefined;\n readonly root: TRoot;\n readonly validators: readonly Validator<TreeState<TRoot>>[];\n}\n\n/** Input type for tree update() - same as set() for trees (nested format) */\nexport type TreeUpdateInput<TRoot extends AnyTreeNodePrimitive> = TreeNodeSetInput<TRoot>;\n\nexport class TreePrimitive<TRoot extends AnyTreeNodePrimitive, TRequired extends boolean = false, THasDefault extends boolean = false>\n implements Primitive<TreeState<TRoot>, TreeProxy<TRoot>, TRequired, THasDefault, TreeSetInput<TRoot>, TreeUpdateInput<TRoot>>\n{\n readonly _tag = \"TreePrimitive\" as const;\n readonly _State!: TreeState<TRoot>;\n readonly _Proxy!: TreeProxy<TRoot>;\n readonly _TRequired!: TRequired;\n readonly _THasDefault!: THasDefault;\n readonly TSetInput!: TreeSetInput<TRoot>;\n readonly TUpdateInput!: TreeUpdateInput<TRoot>;\n\n private readonly _schema: TreePrimitiveSchema<TRoot>;\n private _nodeTypeRegistry: Map<string, AnyTreeNodePrimitive> | undefined;\n\n private readonly _opDefinitions = {\n set: OperationDefinition.make({\n kind: \"tree.set\" as const,\n payload: Schema.Unknown,\n target: Schema.Unknown,\n apply: (payload) => payload,\n }),\n insert: OperationDefinition.make({\n kind: \"tree.insert\" as const,\n payload: Schema.Unknown,\n target: Schema.Unknown,\n apply: (payload) => payload,\n }),\n remove: OperationDefinition.make({\n kind: \"tree.remove\" as const,\n payload: Schema.Unknown,\n target: Schema.Unknown,\n apply: (payload) => payload,\n }),\n move: OperationDefinition.make({\n kind: \"tree.move\" as const,\n payload: Schema.Unknown,\n target: Schema.Unknown,\n apply: (payload) => payload,\n }),\n };\n\n constructor(schema: TreePrimitiveSchema<TRoot>) {\n this._schema = schema;\n }\n\n /** Mark this tree as required */\n required(): TreePrimitive<TRoot, true, THasDefault> {\n return new TreePrimitive({\n ...this._schema,\n required: true,\n });\n }\n\n /** Set a default value for this tree (nested format) */\n default(defaultInput: TreeNodeSetInput<TRoot>): TreePrimitive<TRoot, TRequired, true> {\n return new TreePrimitive({\n ...this._schema,\n defaultInput,\n });\n }\n\n /** Get the root node type */\n get root(): TRoot {\n return this._schema.root;\n }\n\n /** Add a custom validation rule */\n refine(fn: (value: TreeState<TRoot>) => boolean, message: string): TreePrimitive<TRoot, TRequired, THasDefault> {\n return new TreePrimitive({\n ...this._schema,\n validators: [...this._schema.validators, { validate: fn, message }],\n });\n }\n\n /**\n * Build a registry of all node types reachable from root\n */\n private _buildNodeTypeRegistry(): Map<string, AnyTreeNodePrimitive> {\n if (this._nodeTypeRegistry !== undefined) {\n return this._nodeTypeRegistry;\n }\n\n const registry = new Map<string, AnyTreeNodePrimitive>();\n const visited = new Set<string>();\n\n const visit = (node: AnyTreeNodePrimitive) => {\n if (visited.has(node.type)) return;\n visited.add(node.type);\n registry.set(node.type, node);\n\n for (const child of node.children) {\n visit(child);\n }\n };\n\n visit(this._schema.root);\n this._nodeTypeRegistry = registry;\n return registry;\n }\n\n /**\n * Get a node type primitive by its type string\n */\n private _getNodeTypePrimitive(type: string): AnyTreeNodePrimitive {\n const registry = this._buildNodeTypeRegistry();\n const nodeType = registry.get(type);\n if (!nodeType) {\n throw new ValidationError(`Unknown node type: ${type}`);\n }\n return nodeType;\n }\n\n /**\n * Validate that a node type can be a child of a parent node type\n */\n private _validateChildType(\n parentType: string | null,\n childType: string\n ): void {\n if (parentType === null) {\n // Root level - child must be the root type\n if (childType !== this._schema.root.type) {\n throw new ValidationError(\n `Root node must be of type \"${this._schema.root.type}\", got \"${childType}\"`\n );\n }\n return;\n }\n\n const parentNodePrimitive = this._getNodeTypePrimitive(parentType);\n if (!parentNodePrimitive.isChildAllowed(childType)) {\n const allowedTypes = parentNodePrimitive.children.map(c => c.type).join(\", \");\n throw new ValidationError(\n `Node type \"${childType}\" is not allowed as a child of \"${parentType}\". ` +\n `Allowed types: ${allowedTypes || \"none\"}`\n );\n }\n }\n\n /**\n * Convert a nested TreeNodeSetInput to flat TreeState format.\n * Recursively processes nodes, generating IDs and positions as needed.\n *\n * @param input - The root nested input to convert\n * @param generateId - Optional ID generator (defaults to crypto.randomUUID)\n * @returns Flat TreeState array\n */\n private _convertNestedToFlat(\n input: TreeNodeSetInput<TRoot>,\n generateId: () => string = () => crypto.randomUUID()\n ): TreeState<TRoot> {\n const result: TreeNodeState[] = [];\n const seenIds = new Set<string>();\n\n const processNode = (\n nodeInput: InternalNodeInput,\n parentId: string | null,\n parentType: string | null,\n leftPos: string | null,\n rightPos: string | null\n ): void => {\n // Validate node type\n this._validateChildType(parentType, nodeInput.type);\n\n // Get the node primitive for this type\n const nodePrimitive = this._getNodeTypePrimitive(nodeInput.type);\n\n // Generate or use provided ID\n const id = nodeInput.id ?? generateId();\n\n // Check for duplicate IDs\n if (seenIds.has(id)) {\n throw new ValidationError(`Duplicate node ID: ${id}`);\n }\n seenIds.add(id);\n\n // Generate position\n const pos = generateTreePosBetween(leftPos, rightPos);\n\n // Extract data fields (everything except type, id, and children)\n const { type: _type, id: _id, children, ...dataFields } = nodeInput;\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodePrimitive.data as AnyPrimitive, dataFields);\n\n // Add this node to result\n result.push({\n id,\n type: nodeInput.type,\n parentId,\n pos,\n data: mergedData,\n });\n\n // Process children recursively\n let prevChildPos: string | null = null;\n for (let i = 0; i < children.length; i++) {\n const childInput = children[i]!;\n // Each child gets a position after the previous child\n processNode(childInput, id, nodeInput.type, prevChildPos, null);\n // Update prevChildPos to the pos that was just assigned (it's the last item in result)\n prevChildPos = result[result.length - 1]!.pos;\n }\n };\n\n // Process root node (cast to InternalNodeInput for internal processing)\n processNode(input as unknown as InternalNodeInput, null, null, null, null);\n\n return result as TreeState<TRoot>;\n }\n\n readonly _internal: PrimitiveInternal<TreeState<TRoot>, TreeProxy<TRoot>> = {\n createProxy: (\n env: ProxyEnvironment.ProxyEnvironment,\n operationPath: OperationPath.OperationPath\n ): TreeProxy<TRoot> => {\n // Helper to get current state\n const getCurrentState = (): TreeState<TRoot> => {\n const state = env.getState(operationPath) as TreeState<TRoot> | undefined;\n return state ?? [];\n };\n\n // Helper to get parent type from state\n const getParentType = (parentId: string | null): string | null => {\n if (parentId === null) return null;\n const state = getCurrentState();\n const parent = state.find(n => n.id === parentId);\n return parent?.type ?? null;\n };\n\n // Helper to create a node proxy with type narrowing\n const createNodeProxy = (nodeState: TreeNodeState): TreeNodeProxyBase<TRoot> => {\n return {\n id: nodeState.id,\n type: nodeState.type,\n \n is: <TNode extends AnyTreeNodePrimitive>(\n nodeType: TNode\n ): boolean => {\n return nodeState.type === nodeType.type;\n },\n \n as: <TNode extends AnyTreeNodePrimitive>(\n nodeType: TNode\n ): TypedNodeProxy<TNode> => {\n if (nodeState.type !== nodeType.type) {\n throw new ValidationError(\n `Node is of type \"${nodeState.type}\", not \"${nodeType.type}\"`\n );\n }\n const nodePath = operationPath.append(nodeState.id);\n const dataProxy = nodeType.data._internal.createProxy(env, nodePath) as InferProxy<TNode[\"data\"]>;\n return {\n id: nodeState.id,\n type: nodeType.type as InferTreeNodeType<TNode>,\n data: dataProxy,\n get: () => nodeState as TypedTreeNodeState<TNode>,\n update: (value: TreeNodeUpdateValue<TNode>) => {\n // Delegate to the data proxy's update method\n (dataProxy as { update: (v: unknown) => void }).update(value);\n },\n };\n },\n \n get: () => nodeState,\n } as TreeNodeProxyBase<TRoot>;\n };\n\n // Helper to build recursive snapshot\n const buildSnapshot = (\n nodeId: string,\n nodes: readonly TreeNodeState[]\n ): TreeNodeSnapshot<TRoot> | undefined => {\n const node = nodes.find(n => n.id === nodeId);\n if (!node) return undefined;\n\n const childNodes = getOrderedChildren(nodes, nodeId);\n const children: TreeNodeSnapshot<any>[] = [];\n for (const child of childNodes) {\n const childSnapshot = buildSnapshot(child.id, nodes);\n if (childSnapshot) {\n children.push(childSnapshot);\n }\n }\n\n // Spread data properties at node level\n return {\n id: node.id,\n type: node.type,\n ...(node.data as object),\n children,\n } as unknown as TreeNodeSnapshot<TRoot>;\n };\n\n return {\n get: (): TreeState<TRoot> => {\n return getCurrentState();\n },\n\n set: (input: TreeSetInput<TRoot>) => {\n // Convert nested input to flat TreeState using env.generateId for IDs\n const flatState = this._convertNestedToFlat(input, env.generateId);\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.set, flatState)\n );\n },\n\n root: (): TypedTreeNodeState<TRoot> | undefined => {\n const state = getCurrentState();\n const rootNode = state.find(n => n.parentId === null);\n return rootNode as TypedTreeNodeState<TRoot> | undefined;\n },\n\n children: (parentId: string | null): TreeNodeState[] => {\n const state = getCurrentState();\n return getOrderedChildren(state, parentId);\n },\n\n node: (id: string): TreeNodeProxyBase<TRoot> | undefined => {\n const state = getCurrentState();\n const nodeState = state.find(n => n.id === id);\n if (!nodeState) return undefined;\n return createNodeProxy(nodeState);\n },\n\n insertFirst: <TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const siblings = getOrderedChildren(state, parentId);\n const firstPos = siblings.length > 0 ? siblings[0]!.pos : null;\n const pos = generateTreePosBetween(null, firstPos);\n const id = env.generateId();\n\n // Validate parent exists (if not root)\n if (parentId !== null && !state.find(n => n.id === parentId)) {\n throw new ValidationError(`Parent node not found: ${parentId}`);\n }\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Validate single root\n if (parentId === null && state.some(n => n.parentId === null)) {\n throw new ValidationError(\"Tree already has a root node\");\n }\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n insertLast: <TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const siblings = getOrderedChildren(state, parentId);\n const lastPos = siblings.length > 0 ? siblings[siblings.length - 1]!.pos : null;\n const pos = generateTreePosBetween(lastPos, null);\n const id = env.generateId();\n\n // Validate parent exists (if not root)\n if (parentId !== null && !state.find(n => n.id === parentId)) {\n throw new ValidationError(`Parent node not found: ${parentId}`);\n }\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Validate single root\n if (parentId === null && state.some(n => n.parentId === null)) {\n throw new ValidationError(\"Tree already has a root node\");\n }\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n insertAt: <TNode extends AnyTreeNodePrimitive>(\n parentId: string | null,\n index: number,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const siblings = getOrderedChildren(state, parentId);\n const clampedIndex = Math.max(0, Math.min(index, siblings.length));\n const leftPos = clampedIndex > 0 && siblings[clampedIndex - 1] ? siblings[clampedIndex - 1]!.pos : null;\n const rightPos = clampedIndex < siblings.length && siblings[clampedIndex] ? siblings[clampedIndex]!.pos : null;\n const pos = generateTreePosBetween(leftPos, rightPos);\n const id = env.generateId();\n\n // Validate parent exists (if not root)\n if (parentId !== null && !state.find(n => n.id === parentId)) {\n throw new ValidationError(`Parent node not found: ${parentId}`);\n }\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Validate single root\n if (parentId === null && state.some(n => n.parentId === null)) {\n throw new ValidationError(\"Tree already has a root node\");\n }\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n insertAfter: <TNode extends AnyTreeNodePrimitive>(\n siblingId: string,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const sibling = state.find(n => n.id === siblingId);\n if (!sibling) {\n throw new ValidationError(`Sibling node not found: ${siblingId}`);\n }\n\n const parentId = sibling.parentId;\n const siblings = getOrderedChildren(state, parentId);\n const siblingIndex = siblings.findIndex(n => n.id === siblingId);\n const nextSibling = siblings[siblingIndex + 1];\n const pos = generateTreePosBetween(sibling.pos, nextSibling?.pos ?? null);\n const id = env.generateId();\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n insertBefore: <TNode extends AnyTreeNodePrimitive>(\n siblingId: string,\n nodeType: TNode,\n data: TreeNodeDataSetInput<TNode>\n ): string => {\n const state = getCurrentState();\n const sibling = state.find(n => n.id === siblingId);\n if (!sibling) {\n throw new ValidationError(`Sibling node not found: ${siblingId}`);\n }\n\n const parentId = sibling.parentId;\n const siblings = getOrderedChildren(state, parentId);\n const siblingIndex = siblings.findIndex(n => n.id === siblingId);\n const prevSibling = siblings[siblingIndex - 1];\n const pos = generateTreePosBetween(prevSibling?.pos ?? null, sibling.pos);\n const id = env.generateId();\n\n // Validate child type is allowed\n const parentType = getParentType(parentId);\n this._validateChildType(parentType, nodeType.type);\n\n // Apply defaults to node data\n const mergedData = applyDefaults(nodeType.data as AnyPrimitive, data as Partial<InferTreeNodeDataState<TNode>>) as InferTreeNodeDataState<TNode>;\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.insert, {\n id,\n type: nodeType.type,\n parentId,\n pos,\n data: mergedData,\n })\n );\n\n return id;\n },\n\n remove: (id: string) => {\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.remove, { id })\n );\n },\n\n move: (nodeId: string, newParentId: string | null, toIndex: number) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n\n // Validate parent exists (if not moving to root)\n if (newParentId !== null && !state.find(n => n.id === newParentId)) {\n throw new ValidationError(`Parent node not found: ${newParentId}`);\n }\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n // Calculate new position among new siblings (excluding self)\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const clampedIndex = Math.max(0, Math.min(toIndex, siblings.length));\n const leftPos = clampedIndex > 0 && siblings[clampedIndex - 1] ? siblings[clampedIndex - 1]!.pos : null;\n const rightPos = clampedIndex < siblings.length && siblings[clampedIndex] ? siblings[clampedIndex]!.pos : null;\n const pos = generateTreePosBetween(leftPos, rightPos);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n moveAfter: (nodeId: string, siblingId: string) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n const sibling = state.find(n => n.id === siblingId);\n \n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n if (!sibling) {\n throw new ValidationError(`Sibling node not found: ${siblingId}`);\n }\n\n const newParentId = sibling.parentId;\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const siblingIndex = siblings.findIndex(n => n.id === siblingId);\n const nextSibling = siblings[siblingIndex + 1];\n const pos = generateTreePosBetween(sibling.pos, nextSibling?.pos ?? null);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n moveBefore: (nodeId: string, siblingId: string) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n const sibling = state.find(n => n.id === siblingId);\n \n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n if (!sibling) {\n throw new ValidationError(`Sibling node not found: ${siblingId}`);\n }\n\n const newParentId = sibling.parentId;\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const siblingIndex = siblings.findIndex(n => n.id === siblingId);\n const prevSibling = siblings[siblingIndex - 1];\n const pos = generateTreePosBetween(prevSibling?.pos ?? null, sibling.pos);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n moveToFirst: (nodeId: string, newParentId: string | null) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n \n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n\n // Validate parent exists (if not moving to root)\n if (newParentId !== null && !state.find(n => n.id === newParentId)) {\n throw new ValidationError(`Parent node not found: ${newParentId}`);\n }\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const firstPos = siblings.length > 0 ? siblings[0]!.pos : null;\n const pos = generateTreePosBetween(null, firstPos);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n moveToLast: (nodeId: string, newParentId: string | null) => {\n const state = getCurrentState();\n const node = state.find(n => n.id === nodeId);\n \n if (!node) {\n throw new ValidationError(`Node not found: ${nodeId}`);\n }\n\n // Validate parent exists (if not moving to root)\n if (newParentId !== null && !state.find(n => n.id === newParentId)) {\n throw new ValidationError(`Parent node not found: ${newParentId}`);\n }\n\n // Validate no cycle\n if (wouldCreateCycle(state, nodeId, newParentId)) {\n throw new ValidationError(\"Move would create a cycle in the tree\");\n }\n\n // Validate child type is allowed in new parent\n const newParentType = newParentId === null ? null : state.find(n => n.id === newParentId)?.type ?? null;\n this._validateChildType(newParentType, node.type);\n\n // Validate not moving root to a parent\n if (node.parentId === null && newParentId !== null) {\n throw new ValidationError(\"Cannot move root node to have a parent\");\n }\n\n const siblings = getOrderedChildren(state, newParentId).filter(n => n.id !== nodeId);\n const lastPos = siblings.length > 0 ? siblings[siblings.length - 1]!.pos : null;\n const pos = generateTreePosBetween(lastPos, null);\n\n env.addOperation(\n Operation.fromDefinition(operationPath, this._opDefinitions.move, {\n id: nodeId,\n parentId: newParentId,\n pos,\n })\n );\n },\n\n at: <TNode extends AnyTreeNodePrimitive>(\n id: string,\n nodeType: TNode\n ): InferProxy<TNode[\"data\"]> => {\n // Get the node to verify its type\n const state = getCurrentState();\n const node = state.find(n => n.id === id);\n if (!node) {\n throw new ValidationError(`Node not found: ${id}`);\n }\n if (node.type !== nodeType.type) {\n throw new ValidationError(\n `Node is of type \"${node.type}\", not \"${nodeType.type}\"`\n );\n }\n\n const nodePath = operationPath.append(id);\n return nodeType.data._internal.createProxy(env, nodePath) as InferProxy<TNode[\"data\"]>;\n },\n\n updateAt: <TNode extends AnyTreeNodePrimitive>(\n id: string,\n nodeType: TNode,\n value: TreeNodeUpdateValue<TNode>\n ): void => {\n // Get the node to verify its type\n const state = getCurrentState();\n const node = state.find(n => n.id === id);\n if (!node) {\n throw new ValidationError(`Node not found: ${id}`);\n }\n if (node.type !== nodeType.type) {\n throw new ValidationError(\n `Node is of type \"${node.type}\", not \"${nodeType.type}\"`\n );\n }\n\n const nodePath = operationPath.append(id);\n const dataProxy = nodeType.data._internal.createProxy(env, nodePath);\n // Delegate to the data proxy's update method\n (dataProxy as { update: (v: unknown) => void }).update(value);\n },\n\n toSnapshot: (): TreeNodeSnapshot<TRoot> | undefined => {\n const state = getCurrentState();\n const rootNode = state.find(n => n.parentId === null);\n if (!rootNode) return undefined;\n return buildSnapshot(rootNode.id, state);\n },\n };\n },\n\n applyOperation: (\n state: TreeState<TRoot> | undefined,\n operation: Operation.Operation<any, any, any>\n ): TreeState<TRoot> => {\n const path = operation.path;\n const tokens = path.toTokens().filter((t: string) => t !== \"\");\n const currentState = state ?? [];\n\n let newState: TreeState<TRoot>;\n\n // If path is empty, this is a tree-level operation\n if (tokens.length === 0) {\n switch (operation.kind) {\n case \"tree.set\": {\n const payload = operation.payload;\n if (!globalThis.Array.isArray(payload)) {\n throw new ValidationError(`TreePrimitive.set requires an array payload`);\n }\n newState = payload as TreeState<TRoot>;\n break;\n }\n case \"tree.insert\": {\n const { id, type, parentId, pos, data } = operation.payload as {\n id: string;\n type: string;\n parentId: string | null;\n pos: string;\n data: unknown;\n };\n newState = [...currentState, { id, type, parentId, pos, data }] as TreeState<TRoot>;\n break;\n }\n case \"tree.remove\": {\n const { id } = operation.payload as { id: string };\n // Get all descendants to remove\n const descendantIds = getDescendantIds(currentState, id);\n const idsToRemove = new Set([id, ...descendantIds]);\n newState = currentState.filter(node => !idsToRemove.has(node.id));\n break;\n }\n case \"tree.move\": {\n const { id, parentId, pos } = operation.payload as {\n id: string;\n parentId: string | null;\n pos: string;\n };\n newState = currentState.map(node =>\n node.id === id ? { ...node, parentId, pos } : node\n ) as TreeState<TRoot>;\n break;\n }\n default:\n throw new ValidationError(`TreePrimitive cannot apply operation of kind: ${operation.kind}`);\n }\n } else {\n // Otherwise, delegate to the node's data primitive\n const nodeId = tokens[0]!;\n const nodeIndex = currentState.findIndex(node => node.id === nodeId);\n \n if (nodeIndex === -1) {\n throw new ValidationError(`Tree node not found with ID: ${nodeId}`);\n }\n\n const node = currentState[nodeIndex]!;\n const nodeTypePrimitive = this._getNodeTypePrimitive(node.type);\n const remainingPath = path.shift();\n const nodeOperation = {\n ...operation,\n path: remainingPath,\n };\n\n const newData = nodeTypePrimitive.data._internal.applyOperation(\n node.data as InferStructState<any> | undefined,\n nodeOperation\n );\n\n const mutableState = [...currentState];\n mutableState[nodeIndex] = { ...node, data: newData };\n newState = mutableState as TreeState<TRoot>;\n }\n\n // Run validators on the new state\n runValidators(newState, this._schema.validators);\n\n return newState;\n },\n\n getInitialState: (): TreeState<TRoot> | undefined => {\n if (this._schema.defaultInput !== undefined) {\n // Convert nested input to flat TreeState\n return this._convertNestedToFlat(this._schema.defaultInput);\n }\n\n // Automatically create a root node with default data\n const rootNodeType = this._schema.root;\n const rootData = rootNodeType.data._internal.getInitialState() ?? {};\n const rootId = crypto.randomUUID();\n const rootPos = generateTreePosBetween(null, null);\n\n return [{\n id: rootId,\n type: rootNodeType.type,\n parentId: null,\n pos: rootPos,\n data: rootData,\n }] as TreeState<TRoot>;\n },\n\n convertSetInputToState: (input: unknown): TreeState<TRoot> => {\n // Convert nested input format to flat TreeState\n return this._convertNestedToFlat(input as TreeNodeSetInput<TRoot>);\n },\n\n transformOperation: (\n clientOp: Operation.Operation<any, any, any>,\n serverOp: Operation.Operation<any, any, any>\n ): Transform.TransformResult => {\n const clientPath = clientOp.path;\n const serverPath = serverOp.path;\n\n // If paths don't overlap at all, no transformation needed\n if (!OperationPath.pathsOverlap(clientPath, serverPath)) {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Handle tree.remove from server - check if client is operating on removed node or descendants\n if (serverOp.kind === \"tree.remove\") {\n const removedId = (serverOp.payload as { id: string }).id;\n const clientTokens = clientPath.toTokens().filter((t: string) => t !== \"\");\n const serverTokens = serverPath.toTokens().filter((t: string) => t !== \"\");\n\n // Check if client operation targets the removed node or uses it\n if (clientOp.kind === \"tree.move\") {\n const movePayload = clientOp.payload as { id: string; parentId: string | null };\n // If moving the removed node or moving to a removed parent\n if (movePayload.id === removedId || movePayload.parentId === removedId) {\n return { type: \"noop\" };\n }\n }\n\n if (clientOp.kind === \"tree.insert\") {\n const insertPayload = clientOp.payload as { parentId: string | null };\n // If inserting into a removed parent\n if (insertPayload.parentId === removedId) {\n return { type: \"noop\" };\n }\n }\n\n // Check if client is operating on a node that was removed\n if (clientTokens.length > serverTokens.length) {\n const nodeId = clientTokens[serverTokens.length];\n if (nodeId === removedId) {\n return { type: \"noop\" };\n }\n }\n }\n\n // Both inserting - no conflict (fractional indexing handles order)\n if (serverOp.kind === \"tree.insert\" && clientOp.kind === \"tree.insert\") {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Both moving same node - client wins\n if (serverOp.kind === \"tree.move\" && clientOp.kind === \"tree.move\") {\n const serverMoveId = (serverOp.payload as { id: string }).id;\n const clientMoveId = (clientOp.payload as { id: string }).id;\n\n if (serverMoveId === clientMoveId) {\n return { type: \"transformed\", operation: clientOp };\n }\n // Different nodes - no conflict\n return { type: \"transformed\", operation: clientOp };\n }\n\n // For same exact path: client wins (last-write-wins)\n if (OperationPath.pathsEqual(clientPath, serverPath)) {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // If server set entire tree and client is operating on a node\n if (serverOp.kind === \"tree.set\" && OperationPath.isPrefix(serverPath, clientPath)) {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Delegate to node data primitive for nested operations\n const clientTokens = clientPath.toTokens().filter((t: string) => t !== \"\");\n const serverTokens = serverPath.toTokens().filter((t: string) => t !== \"\");\n\n // Both operations target children of this tree\n if (clientTokens.length > 0 && serverTokens.length > 0) {\n const clientNodeId = clientTokens[0];\n const serverNodeId = serverTokens[0];\n\n // If operating on different nodes, no conflict\n if (clientNodeId !== serverNodeId) {\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Same node - would need to delegate to node's data primitive\n // For simplicity, let client win\n return { type: \"transformed\", operation: clientOp };\n }\n\n // Default: no transformation needed\n return { type: \"transformed\", operation: clientOp };\n },\n };\n}\n\n/** Options for creating a Tree primitive */\nexport interface TreeOptions<TRoot extends AnyTreeNodePrimitive> {\n /** The root node type */\n readonly root: TRoot;\n}\n\n/** Creates a new TreePrimitive with the given root node type */\nexport const Tree = <TRoot extends AnyTreeNodePrimitive>(\n options: TreeOptions<TRoot>\n): TreePrimitive<TRoot, false, false> =>\n new TreePrimitive({\n required: false,\n defaultInput: undefined,\n root: options.root,\n validators: [],\n });\n"],"mappings":"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"}
|
|
@@ -35,6 +35,15 @@ interface PrimitiveInternal<TState, TProxy> {
|
|
|
35
35
|
readonly applyOperation: (state: TState | undefined, operation: Operation<any, any, any>) => TState;
|
|
36
36
|
/** Returns the initial/default state for this primitive */
|
|
37
37
|
readonly getInitialState: () => TState | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Converts a set input value to state format.
|
|
40
|
+
* For most primitives, this is a simple pass-through with defaults applied.
|
|
41
|
+
* For Tree primitives, this converts nested input to flat TreeState.
|
|
42
|
+
*
|
|
43
|
+
* @param input - The set input value
|
|
44
|
+
* @returns The corresponding state value
|
|
45
|
+
*/
|
|
46
|
+
readonly convertSetInputToState?: (input: unknown) => TState;
|
|
38
47
|
/**
|
|
39
48
|
* Transforms a client operation against a server operation.
|
|
40
49
|
* Used for operational transformation (OT) conflict resolution.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.cts","names":[],"sources":["../../src/primitives/shared.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAmBA;;;;;;;AAMwB,UANP,SAMO,CAAA,MAAA,EAAA,MAAA,EAAA,kBAAA,OAAA,GAAA,KAAA,EAAA,oBAAA,OAAA,GAAA,KAAA,EAAA,YAAA,OAAA,EAAA,eAAA,OAAA,CAAA,CAAA;EACA,SAAA,IAAA,EAAA,MAAA;EACG,SAAA,MAAA,EANN,MAMM;EAAY,SAAA,MAAA,EALlB,MAKkB;EAMpB,SAAA,UAAA,EAVM,SAUW;EAEJ,SAAA,YAAA,EAXL,WAWK;EAAyC,SAAA,SAAA,EAVjD,iBAUiD,CAV/B,MAU+B,EAVvB,MAUuB,CAAA;EAAgC,SAAA,SAAA,EATjF,SASiF;EAEpE,SAAA,YAAA,EAVV,YAUU;;;;;
|
|
1
|
+
{"version":3,"file":"shared.d.cts","names":[],"sources":["../../src/primitives/shared.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -35,6 +35,15 @@ interface PrimitiveInternal<TState, TProxy> {
|
|
|
35
35
|
readonly applyOperation: (state: TState | undefined, operation: Operation<any, any, any>) => TState;
|
|
36
36
|
/** Returns the initial/default state for this primitive */
|
|
37
37
|
readonly getInitialState: () => TState | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Converts a set input value to state format.
|
|
40
|
+
* For most primitives, this is a simple pass-through with defaults applied.
|
|
41
|
+
* For Tree primitives, this converts nested input to flat TreeState.
|
|
42
|
+
*
|
|
43
|
+
* @param input - The set input value
|
|
44
|
+
* @returns The corresponding state value
|
|
45
|
+
*/
|
|
46
|
+
readonly convertSetInputToState?: (input: unknown) => TState;
|
|
38
47
|
/**
|
|
39
48
|
* Transforms a client operation against a server operation.
|
|
40
49
|
* Used for operational transformation (OT) conflict resolution.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.mts","names":[],"sources":["../../src/primitives/shared.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAmBA;;;;;;;AAMwB,UANP,SAMO,CAAA,MAAA,EAAA,MAAA,EAAA,kBAAA,OAAA,GAAA,KAAA,EAAA,oBAAA,OAAA,GAAA,KAAA,EAAA,YAAA,OAAA,EAAA,eAAA,OAAA,CAAA,CAAA;EACA,SAAA,IAAA,EAAA,MAAA;EACG,SAAA,MAAA,EANN,MAMM;EAAY,SAAA,MAAA,EALlB,MAKkB;EAMpB,SAAA,UAAA,EAVM,SAUW;EAEJ,SAAA,YAAA,EAXL,WAWK;EAAyC,SAAA,SAAA,EAVjD,iBAUiD,CAV/B,MAU+B,EAVvB,MAUuB,CAAA;EAAgC,SAAA,SAAA,EATjF,SASiF;EAEpE,SAAA,YAAA,EAVV,YAUU;;;;;
|
|
1
|
+
{"version":3,"file":"shared.d.mts","names":[],"sources":["../../src/primitives/shared.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.mjs","names":["result: Record<string, unknown>"],"sources":["../../src/primitives/shared.ts"],"sourcesContent":["import * as Operation from \"../Operation\";\nimport * as OperationDefinition from \"../OperationDefinition\";\nimport * as ProxyEnvironment from \"../ProxyEnvironment\";\nimport * as OperationPath from \"../OperationPath\";\nimport * as Transform from \"../Transform\";\n\n// =============================================================================\n// Primitive Interface & Type Utilities\n// =============================================================================\n\n/**\n * Base interface that all primitives must implement.\n * Provides type inference helpers and internal operations.\n * \n * @typeParam TState - The state type this primitive holds\n * @typeParam TProxy - The proxy type for interacting with this primitive\n * @typeParam TDefined - Whether the value is guaranteed to be defined (via required() or default())\n * @typeParam THasDefault - Whether this primitive has a default value\n */\nexport interface Primitive<TState, TProxy, TRequired extends boolean = false, THasDefault extends boolean = false, TSetInput = unknown, TUpdateInput = unknown> {\n readonly _tag: string;\n readonly _State: TState;\n readonly _Proxy: TProxy;\n readonly _TRequired: TRequired;\n readonly _THasDefault: THasDefault;\n readonly _internal: PrimitiveInternal<TState, TProxy>;\n readonly TSetInput: TSetInput;\n readonly TUpdateInput: TUpdateInput;\n }\n \n /**\n * Internal operations that each primitive must provide.\n */\n export interface PrimitiveInternal<TState, TProxy> {\n /** Creates a proxy for generating operations */\n readonly createProxy: (env: ProxyEnvironment.ProxyEnvironment, path: OperationPath.OperationPath) => TProxy;\n /** Applies an operation to the current state, returning the new state */\n readonly applyOperation: (state: TState | undefined, operation: Operation.Operation<any, any, any>) => TState;\n /** Returns the initial/default state for this primitive */\n readonly getInitialState: () => TState | undefined;\n /**\n * Transforms a client operation against a server operation.\n * Used for operational transformation (OT) conflict resolution.\n * \n * @param clientOp - The client's operation to transform\n * @param serverOp - The server's operation that has already been applied\n * @returns TransformResult indicating how the client operation should be handled\n */\n readonly transformOperation: (\n clientOp: Operation.Operation<any, any, any>,\n serverOp: Operation.Operation<any, any, any>\n ) => Transform.TransformResult;\n }\n \n /**\n * Any primitive type - used for generic constraints.\n */\n export type AnyPrimitive = Primitive<any, any, any, any>;\n \n /**\n * Infer the state type from a primitive.\n */\n export type InferState<T> = T extends Primitive<infer S, any, any, any> ? S : never;\n \n /**\n * Infer the proxy type from a primitive.\n */\n export type InferProxy<T> = T extends Primitive<any, infer P, any, any> ? P : never;\n\n /**\n * Infer the SetInput type from a primitive.\n * Works with both Primitive interface types and types with a TSetInput property (like TreeNodePrimitive).\n */\n export type InferSetInput<T> = \n T extends Primitive<any, any, any, any, infer S, any> ? S : \n T extends { TSetInput: infer S } ? S : \n never;\n\n /**\n * Infer the UpdateInput type from a primitive.\n * Works with both Primitive interface types and types with a TUpdateInput property (like TreeNodePrimitive).\n */\n export type InferUpdateInput<T> = \n T extends Primitive<any, any, any, any, any, infer U> ? U : \n T extends { TUpdateInput: infer U } ? U : \n never;\n \n /**\n * Helper type to conditionally add undefined based on TRequired and THasDefault.\n * When TRequired is false and THasDefault is false, the value may be undefined.\n * Otherwise, the value is guaranteed to be defined.\n */\n export type MaybeUndefined<T, TRequired extends boolean, THasDefault extends boolean> = TRequired extends false ? THasDefault extends false ? Optional<T> : T : T;\n\n export type Optional<T> = T | undefined;\n\n /**\n * Helper type to conditionally add undefined based on TRequired and THasDefault.\n * When TRequired is true and THasDefault is false, the value must be provided.\n * Otherwise, the value may be undefined.\n */\n export type NeedsValue<T, TRequired extends boolean, THasDefault extends boolean> = TRequired extends true ? THasDefault extends false ? T : Optional<T> : Optional<T>;\n \n /**\n * Infer the snapshot type from a primitive.\n * The snapshot is a readonly, type-safe structure suitable for rendering.\n */\n export type InferSnapshot<T> = T extends Primitive<any, infer P, any, any>\n ? P extends { toSnapshot(): infer S } ? S : never\n : never;\n\n /**\n * Extract THasDefault from a primitive.\n */\n export type HasDefault<T> = T extends Primitive<any, any, any, infer H> ? H : false;\n\n /**\n * Extract TDefined from a primitive.\n */\n export type IsDefined<T> = T extends Primitive<any, any, infer D, any> ? D : false;\n\n /**\n * Infer whether a primitive is required.\n * Alias for IsDefined for clarity.\n */\n export type IsRequired<T> = IsDefined<T>;\n\n\n // =============================================================================\n // Validation Errors\n // =============================================================================\n \n export class ValidationError extends Error {\n readonly _tag = \"ValidationError\";\n constructor(message: string) {\n super(message);\n this.name = \"ValidationError\";\n }\n }\n \n // =============================================================================\n // Validation Infrastructure\n // =============================================================================\n \n /**\n * A validator that checks a value and returns whether it's valid.\n */\n export interface Validator<T> {\n readonly validate: (value: T) => boolean;\n readonly message: string;\n }\n \n\n/**\n * Runs all validators against a value, throwing ValidationError if any fail.\n */\nexport function runValidators<T>(value: T, validators: readonly { validate: (value: T) => boolean; message: string }[]): void {\n for (const validator of validators) {\n if (!validator.validate(value)) {\n throw new ValidationError(validator.message);\n }\n }\n}\n\n/**\n * Checks if an operation is compatible with the given operation definitions.\n * @param operation - The operation to check.\n * @param operationDefinitions - The operation definitions to check against.\n * @returns True if the operation is compatible, false otherwise.\n */\nexport function isCompatibleOperation(operation: Operation.Operation<any, any, any>, operationDefinitions: Record<string, OperationDefinition.OperationDefinition<any, any, any>>) {\n const values = Object.values(operationDefinitions);\n return values.some(value => value.kind === operation.kind);\n}\n\n// =============================================================================\n// Default Value Utilities\n// =============================================================================\n\n/**\n * Applies default values to a partial input, recursively handling nested structs.\n * \n * Uses a two-layer approach:\n * 1. First, get the struct's initial state (which includes struct-level defaults)\n * 2. Then, layer the provided values on top\n * 3. Finally, ensure nested structs are recursively processed\n * \n * @param primitive - The primitive definition containing field information\n * @param value - The partial value provided by the user\n * @returns The value with defaults applied for missing fields\n */\nexport function applyDefaults<T extends AnyPrimitive>(\n primitive: T,\n value: Partial<InferState<T>>\n): InferState<T> {\n // Only structs need default merging\n if (primitive._tag === \"StructPrimitive\") {\n const structPrimitive = primitive as unknown as { \n fields: Record<string, AnyPrimitive>;\n _internal: { getInitialState: () => Record<string, unknown> | undefined };\n };\n \n // Start with the struct's initial state (struct-level default or field defaults)\n const structInitialState = structPrimitive._internal.getInitialState() ?? {};\n \n // Layer the provided values on top of initial state\n const result: Record<string, unknown> = { ...structInitialState, ...value };\n \n for (const key in structPrimitive.fields) {\n const fieldPrimitive = structPrimitive.fields[key]!;\n \n if (result[key] === undefined) {\n // Field still not provided after merging - try individual field default\n const fieldDefault = fieldPrimitive._internal.getInitialState();\n if (fieldDefault !== undefined) {\n result[key] = fieldDefault;\n }\n } else if (fieldPrimitive._tag === \"StructPrimitive\" && typeof result[key] === \"object\" && result[key] !== null) {\n // Recursively apply defaults to nested structs\n result[key] = applyDefaults(fieldPrimitive, result[key] as Partial<InferState<typeof fieldPrimitive>>);\n }\n }\n \n return result as InferState<T>;\n }\n \n // For non-struct primitives, return the value as-is\n return value as InferState<T>;\n}\n\n"],"mappings":";;;;AAoIE,IAAa,kBAAb,cAAqC,MAAM;CAEzC,YAAY,SAAiB;AAC3B,QAAM,QAAQ;wBAFP,QAAO;AAGd,OAAK,OAAO;;;;;;AAoBlB,SAAgB,cAAiB,OAAU,YAAmF;AAC5H,MAAK,MAAM,aAAa,WACtB,KAAI,CAAC,UAAU,SAAS,MAAM,CAC5B,OAAM,IAAI,gBAAgB,UAAU,QAAQ;;;;;;;;AAWlD,SAAgB,sBAAsB,WAA+C,sBAA8F;AAEjL,QADe,OAAO,OAAO,qBAAqB,CACpC,MAAK,UAAS,MAAM,SAAS,UAAU,KAAK;;;;;;;;;;;;;;AAmB5D,SAAgB,cACd,WACA,OACe;AAEf,KAAI,UAAU,SAAS,mBAAmB;;EACxC,MAAM,kBAAkB;EASxB,MAAMA,oEAHqB,gBAAgB,UAAU,iBAAiB,yEAAI,EAAE,GAGR;AAEpE,OAAK,MAAM,OAAO,gBAAgB,QAAQ;GACxC,MAAM,iBAAiB,gBAAgB,OAAO;AAE9C,OAAI,OAAO,SAAS,QAAW;IAE7B,MAAM,eAAe,eAAe,UAAU,iBAAiB;AAC/D,QAAI,iBAAiB,OACnB,QAAO,OAAO;cAEP,eAAe,SAAS,qBAAqB,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,KAEzG,QAAO,OAAO,cAAc,gBAAgB,OAAO,KAAmD;;AAI1G,SAAO;;AAIT,QAAO"}
|
|
1
|
+
{"version":3,"file":"shared.mjs","names":["result: Record<string, unknown>"],"sources":["../../src/primitives/shared.ts"],"sourcesContent":["import * as Operation from \"../Operation\";\nimport * as OperationDefinition from \"../OperationDefinition\";\nimport * as ProxyEnvironment from \"../ProxyEnvironment\";\nimport * as OperationPath from \"../OperationPath\";\nimport * as Transform from \"../Transform\";\n\n// =============================================================================\n// Primitive Interface & Type Utilities\n// =============================================================================\n\n/**\n * Base interface that all primitives must implement.\n * Provides type inference helpers and internal operations.\n * \n * @typeParam TState - The state type this primitive holds\n * @typeParam TProxy - The proxy type for interacting with this primitive\n * @typeParam TDefined - Whether the value is guaranteed to be defined (via required() or default())\n * @typeParam THasDefault - Whether this primitive has a default value\n */\nexport interface Primitive<TState, TProxy, TRequired extends boolean = false, THasDefault extends boolean = false, TSetInput = unknown, TUpdateInput = unknown> {\n readonly _tag: string;\n readonly _State: TState;\n readonly _Proxy: TProxy;\n readonly _TRequired: TRequired;\n readonly _THasDefault: THasDefault;\n readonly _internal: PrimitiveInternal<TState, TProxy>;\n readonly TSetInput: TSetInput;\n readonly TUpdateInput: TUpdateInput;\n }\n \n /**\n * Internal operations that each primitive must provide.\n */\n export interface PrimitiveInternal<TState, TProxy> {\n /** Creates a proxy for generating operations */\n readonly createProxy: (env: ProxyEnvironment.ProxyEnvironment, path: OperationPath.OperationPath) => TProxy;\n /** Applies an operation to the current state, returning the new state */\n readonly applyOperation: (state: TState | undefined, operation: Operation.Operation<any, any, any>) => TState;\n /** Returns the initial/default state for this primitive */\n readonly getInitialState: () => TState | undefined;\n /**\n * Converts a set input value to state format.\n * For most primitives, this is a simple pass-through with defaults applied.\n * For Tree primitives, this converts nested input to flat TreeState.\n *\n * @param input - The set input value\n * @returns The corresponding state value\n */\n readonly convertSetInputToState?: (input: unknown) => TState;\n /**\n * Transforms a client operation against a server operation.\n * Used for operational transformation (OT) conflict resolution.\n *\n * @param clientOp - The client's operation to transform\n * @param serverOp - The server's operation that has already been applied\n * @returns TransformResult indicating how the client operation should be handled\n */\n readonly transformOperation: (\n clientOp: Operation.Operation<any, any, any>,\n serverOp: Operation.Operation<any, any, any>\n ) => Transform.TransformResult;\n }\n \n /**\n * Any primitive type - used for generic constraints.\n */\n export type AnyPrimitive = Primitive<any, any, any, any>;\n \n /**\n * Infer the state type from a primitive.\n */\n export type InferState<T> = T extends Primitive<infer S, any, any, any> ? S : never;\n \n /**\n * Infer the proxy type from a primitive.\n */\n export type InferProxy<T> = T extends Primitive<any, infer P, any, any> ? P : never;\n\n /**\n * Infer the SetInput type from a primitive.\n * Works with both Primitive interface types and types with a TSetInput property (like TreeNodePrimitive).\n */\n export type InferSetInput<T> = \n T extends Primitive<any, any, any, any, infer S, any> ? S : \n T extends { TSetInput: infer S } ? S : \n never;\n\n /**\n * Infer the UpdateInput type from a primitive.\n * Works with both Primitive interface types and types with a TUpdateInput property (like TreeNodePrimitive).\n */\n export type InferUpdateInput<T> = \n T extends Primitive<any, any, any, any, any, infer U> ? U : \n T extends { TUpdateInput: infer U } ? U : \n never;\n \n /**\n * Helper type to conditionally add undefined based on TRequired and THasDefault.\n * When TRequired is false and THasDefault is false, the value may be undefined.\n * Otherwise, the value is guaranteed to be defined.\n */\n export type MaybeUndefined<T, TRequired extends boolean, THasDefault extends boolean> = TRequired extends false ? THasDefault extends false ? Optional<T> : T : T;\n\n export type Optional<T> = T | undefined;\n\n /**\n * Helper type to conditionally add undefined based on TRequired and THasDefault.\n * When TRequired is true and THasDefault is false, the value must be provided.\n * Otherwise, the value may be undefined.\n */\n export type NeedsValue<T, TRequired extends boolean, THasDefault extends boolean> = TRequired extends true ? THasDefault extends false ? T : Optional<T> : Optional<T>;\n \n /**\n * Infer the snapshot type from a primitive.\n * The snapshot is a readonly, type-safe structure suitable for rendering.\n */\n export type InferSnapshot<T> = T extends Primitive<any, infer P, any, any>\n ? P extends { toSnapshot(): infer S } ? S : never\n : never;\n\n /**\n * Extract THasDefault from a primitive.\n */\n export type HasDefault<T> = T extends Primitive<any, any, any, infer H> ? H : false;\n\n /**\n * Extract TDefined from a primitive.\n */\n export type IsDefined<T> = T extends Primitive<any, any, infer D, any> ? D : false;\n\n /**\n * Infer whether a primitive is required.\n * Alias for IsDefined for clarity.\n */\n export type IsRequired<T> = IsDefined<T>;\n\n\n // =============================================================================\n // Validation Errors\n // =============================================================================\n \n export class ValidationError extends Error {\n readonly _tag = \"ValidationError\";\n constructor(message: string) {\n super(message);\n this.name = \"ValidationError\";\n }\n }\n \n // =============================================================================\n // Validation Infrastructure\n // =============================================================================\n \n /**\n * A validator that checks a value and returns whether it's valid.\n */\n export interface Validator<T> {\n readonly validate: (value: T) => boolean;\n readonly message: string;\n }\n \n\n/**\n * Runs all validators against a value, throwing ValidationError if any fail.\n */\nexport function runValidators<T>(value: T, validators: readonly { validate: (value: T) => boolean; message: string }[]): void {\n for (const validator of validators) {\n if (!validator.validate(value)) {\n throw new ValidationError(validator.message);\n }\n }\n}\n\n/**\n * Checks if an operation is compatible with the given operation definitions.\n * @param operation - The operation to check.\n * @param operationDefinitions - The operation definitions to check against.\n * @returns True if the operation is compatible, false otherwise.\n */\nexport function isCompatibleOperation(operation: Operation.Operation<any, any, any>, operationDefinitions: Record<string, OperationDefinition.OperationDefinition<any, any, any>>) {\n const values = Object.values(operationDefinitions);\n return values.some(value => value.kind === operation.kind);\n}\n\n// =============================================================================\n// Default Value Utilities\n// =============================================================================\n\n/**\n * Applies default values to a partial input, recursively handling nested structs.\n * \n * Uses a two-layer approach:\n * 1. First, get the struct's initial state (which includes struct-level defaults)\n * 2. Then, layer the provided values on top\n * 3. Finally, ensure nested structs are recursively processed\n * \n * @param primitive - The primitive definition containing field information\n * @param value - The partial value provided by the user\n * @returns The value with defaults applied for missing fields\n */\nexport function applyDefaults<T extends AnyPrimitive>(\n primitive: T,\n value: Partial<InferState<T>>\n): InferState<T> {\n // Only structs need default merging\n if (primitive._tag === \"StructPrimitive\") {\n const structPrimitive = primitive as unknown as { \n fields: Record<string, AnyPrimitive>;\n _internal: { getInitialState: () => Record<string, unknown> | undefined };\n };\n \n // Start with the struct's initial state (struct-level default or field defaults)\n const structInitialState = structPrimitive._internal.getInitialState() ?? {};\n \n // Layer the provided values on top of initial state\n const result: Record<string, unknown> = { ...structInitialState, ...value };\n \n for (const key in structPrimitive.fields) {\n const fieldPrimitive = structPrimitive.fields[key]!;\n \n if (result[key] === undefined) {\n // Field still not provided after merging - try individual field default\n const fieldDefault = fieldPrimitive._internal.getInitialState();\n if (fieldDefault !== undefined) {\n result[key] = fieldDefault;\n }\n } else if (fieldPrimitive._tag === \"StructPrimitive\" && typeof result[key] === \"object\" && result[key] !== null) {\n // Recursively apply defaults to nested structs\n result[key] = applyDefaults(fieldPrimitive, result[key] as Partial<InferState<typeof fieldPrimitive>>);\n }\n }\n \n return result as InferState<T>;\n }\n \n // For non-struct primitives, return the value as-is\n return value as InferState<T>;\n}\n\n"],"mappings":";;;;AA6IE,IAAa,kBAAb,cAAqC,MAAM;CAEzC,YAAY,SAAiB;AAC3B,QAAM,QAAQ;wBAFP,QAAO;AAGd,OAAK,OAAO;;;;;;AAoBlB,SAAgB,cAAiB,OAAU,YAAmF;AAC5H,MAAK,MAAM,aAAa,WACtB,KAAI,CAAC,UAAU,SAAS,MAAM,CAC5B,OAAM,IAAI,gBAAgB,UAAU,QAAQ;;;;;;;;AAWlD,SAAgB,sBAAsB,WAA+C,sBAA8F;AAEjL,QADe,OAAO,OAAO,qBAAqB,CACpC,MAAK,UAAS,MAAM,SAAS,UAAU,KAAK;;;;;;;;;;;;;;AAmB5D,SAAgB,cACd,WACA,OACe;AAEf,KAAI,UAAU,SAAS,mBAAmB;;EACxC,MAAM,kBAAkB;EASxB,MAAMA,oEAHqB,gBAAgB,UAAU,iBAAiB,yEAAI,EAAE,GAGR;AAEpE,OAAK,MAAM,OAAO,gBAAgB,QAAQ;GACxC,MAAM,iBAAiB,gBAAgB,OAAO;AAE9C,OAAI,OAAO,SAAS,QAAW;IAE7B,MAAM,eAAe,eAAe,UAAU,iBAAiB;AAC/D,QAAI,iBAAiB,OACnB,QAAO,OAAO;cAEP,eAAe,SAAS,qBAAqB,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,KAEzG,QAAO,OAAO,cAAc,gBAAgB,OAAO,KAAmD;;AAI1G,SAAO;;AAIT,QAAO"}
|
|
@@ -38,7 +38,7 @@ const make = (options) => {
|
|
|
38
38
|
reason: "Transaction has already been processed"
|
|
39
39
|
};
|
|
40
40
|
const currentState = _document.get();
|
|
41
|
-
const tempDoc = require_Document.make(schema, {
|
|
41
|
+
const tempDoc = require_Document.make(schema, { initialState: currentState });
|
|
42
42
|
try {
|
|
43
43
|
tempDoc.apply(transaction.ops);
|
|
44
44
|
return { valid: true };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Transaction } from "../Transaction.cjs";
|
|
2
|
-
import { AnyPrimitive, InferState } from "../primitives/shared.cjs";
|
|
2
|
+
import { AnyPrimitive, InferSetInput, InferState } from "../primitives/shared.cjs";
|
|
3
3
|
|
|
4
4
|
//#region src/server/ServerDocument.d.ts
|
|
5
5
|
declare namespace ServerDocument_d_exports {
|
|
@@ -50,8 +50,8 @@ type SubmitResult = {
|
|
|
50
50
|
interface ServerDocumentOptions<TSchema extends AnyPrimitive> {
|
|
51
51
|
/** The schema defining the document structure */
|
|
52
52
|
readonly schema: TSchema;
|
|
53
|
-
/** Initial
|
|
54
|
-
readonly initialState?:
|
|
53
|
+
/** Initial value (optional, will use schema defaults if not provided) - uses set input format */
|
|
54
|
+
readonly initialState?: InferSetInput<TSchema>;
|
|
55
55
|
/** Initial version number (optional, defaults to 0) */
|
|
56
56
|
readonly initialVersion?: number;
|
|
57
57
|
/** Called when a transaction is successfully applied and should be broadcast */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerDocument.d.cts","names":[],"sources":["../../src/server/ServerDocument.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UAWiB,kBAAA;;wBAEO;;;;;;;UAQP,YAAA;EAVA,SAAA,IAAA,EAAA,OAAkB;EAUlB,SAAA,aAAY,EAAA,MAAA;EASZ,SAAA,MAAA,EAAA,MAAe;AAShC;;;;AAA+E,UAT9D,eAAA,CAS8D;EASnE,SAAA,IAAA,EAAY,UAAA;EAWP,SAAA,KAAA,EAAA,OAAA;EAAsC,SAAA,OAAA,EAAA,MAAA;;;;;AAQH,KA5BxC,aAAA,GAAgB,kBA4BwB,GA5BH,YA4BG,GA5BY,eA4BZ;AAUpD;;;AAK8B,KAlClB,YAAA,GAkCkB;EAArB,SAAA,OAAA,EAAA,IAAA;EAWa,SAAA,OAAA,EAAA,MAAA;CAA0B,GAAA;EAM/B,SAAA,OAAA,EAAA,KAAA;EAAe,SAAA,MAAA,EAAA,MAAA;AAgBhC,CAAA;;;;AAEkB,UA1DD,qBA0DC,CAAA,gBA1DqC,YA0DrC,CAAA,CAAA;EAAf;EAAc,SAAA,MAAA,EAxDE,OAwDF;;0BAtDS,
|
|
1
|
+
{"version":3,"file":"ServerDocument.d.cts","names":[],"sources":["../../src/server/ServerDocument.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UAWiB,kBAAA;;wBAEO;;;;;;;UAQP,YAAA;EAVA,SAAA,IAAA,EAAA,OAAkB;EAUlB,SAAA,aAAY,EAAA,MAAA;EASZ,SAAA,MAAA,EAAA,MAAe;AAShC;;;;AAA+E,UAT9D,eAAA,CAS8D;EASnE,SAAA,IAAA,EAAY,UAAA;EAWP,SAAA,KAAA,EAAA,OAAA;EAAsC,SAAA,OAAA,EAAA,MAAA;;;;;AAQH,KA5BxC,aAAA,GAAgB,kBA4BwB,GA5BH,YA4BG,GA5BY,eA4BZ;AAUpD;;;AAK8B,KAlClB,YAAA,GAkCkB;EAArB,SAAA,OAAA,EAAA,IAAA;EAWa,SAAA,OAAA,EAAA,MAAA;CAA0B,GAAA;EAM/B,SAAA,OAAA,EAAA,KAAA;EAAe,SAAA,MAAA,EAAA,MAAA;AAgBhC,CAAA;;;;AAEkB,UA1DD,qBA0DC,CAAA,gBA1DqC,YA0DrC,CAAA,CAAA;EAAf;EAAc,SAAA,MAAA,EAxDE,OAwDF;;0BAtDS,cAAwB;;;;kCAIhB;;;;;;;;;UAUjB,+BAA+B;;mBAE7B;;SAGV,WAAqB;;;;;;;;;sBAWR,cAA0B;;;;;iBAM/B;;;;;;;;;;cAgBJ,uBAAwB,uBAC1B,sBAAsB,aAC9B,eAAe"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Transaction } from "../Transaction.mjs";
|
|
2
|
-
import { AnyPrimitive, InferState } from "../primitives/shared.mjs";
|
|
2
|
+
import { AnyPrimitive, InferSetInput, InferState } from "../primitives/shared.mjs";
|
|
3
3
|
import "../Primitive.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/server/ServerDocument.d.ts
|
|
@@ -51,8 +51,8 @@ type SubmitResult = {
|
|
|
51
51
|
interface ServerDocumentOptions<TSchema extends AnyPrimitive> {
|
|
52
52
|
/** The schema defining the document structure */
|
|
53
53
|
readonly schema: TSchema;
|
|
54
|
-
/** Initial
|
|
55
|
-
readonly initialState?:
|
|
54
|
+
/** Initial value (optional, will use schema defaults if not provided) - uses set input format */
|
|
55
|
+
readonly initialState?: InferSetInput<TSchema>;
|
|
56
56
|
/** Initial version number (optional, defaults to 0) */
|
|
57
57
|
readonly initialVersion?: number;
|
|
58
58
|
/** Called when a transaction is successfully applied and should be broadcast */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerDocument.d.mts","names":[],"sources":["../../src/server/ServerDocument.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;UAWiB,kBAAA;;wBAEO;;;;;;;UAQP,YAAA;;EAVA,SAAA,aAAkB,EAAA,MAAA;EAUlB,SAAA,MAAY,EAAA,MAAA;AAS7B;AASA;;;AAAgE,UAT/C,eAAA,CAS+C;EAAe,SAAA,IAAA,EAAA,UAAA;EASnE,SAAA,KAAA,EAAY,OAAA;EAWP,SAAA,OAAA,EAAA,MAAqB;;;;;AAQJ,KA5BtB,aAAA,GAAgB,kBA4BM,GA5Be,YA4Bf,GA5B8B,eA4B9B;;AAUlC;;AAEmB,KA/BP,YAAA,GA+BO;EAGW,SAAA,OAAA,EAAA,IAAA;EAArB,SAAA,OAAA,EAAA,MAAA;CAWa,GAAA;EAA0B,SAAA,OAAA,EAAA,KAAA;EAM/B,SAAA,MAAA,EAAA,MAAA;CAAe;AAgBhC;;;AACW,UAzDM,qBAyDN,CAAA,gBAzD4C,YAyD5C,CAAA,CAAA;EACO;EAAf,SAAA,MAAA,EAxDgB,OAwDhB;EAAc;0BAtDS,
|
|
1
|
+
{"version":3,"file":"ServerDocument.d.mts","names":[],"sources":["../../src/server/ServerDocument.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;UAWiB,kBAAA;;wBAEO;;;;;;;UAQP,YAAA;;EAVA,SAAA,aAAkB,EAAA,MAAA;EAUlB,SAAA,MAAY,EAAA,MAAA;AAS7B;AASA;;;AAAgE,UAT/C,eAAA,CAS+C;EAAe,SAAA,IAAA,EAAA,UAAA;EASnE,SAAA,KAAA,EAAY,OAAA;EAWP,SAAA,OAAA,EAAA,MAAqB;;;;;AAQJ,KA5BtB,aAAA,GAAgB,kBA4BM,GA5Be,YA4Bf,GA5B8B,eA4B9B;;AAUlC;;AAEmB,KA/BP,YAAA,GA+BO;EAGW,SAAA,OAAA,EAAA,IAAA;EAArB,SAAA,OAAA,EAAA,MAAA;CAWa,GAAA;EAA0B,SAAA,OAAA,EAAA,KAAA;EAM/B,SAAA,MAAA,EAAA,MAAA;CAAe;AAgBhC;;;AACW,UAzDM,qBAyDN,CAAA,gBAzD4C,YAyD5C,CAAA,CAAA;EACO;EAAf,SAAA,MAAA,EAxDgB,OAwDhB;EAAc;0BAtDS,cAAwB;;;;kCAIhB;;;;;;;;;UAUjB,+BAA+B;;mBAE7B;;SAGV,WAAqB;;;;;;;;;sBAWR,cAA0B;;;;;iBAM/B;;;;;;;;;;cAgBJ,uBAAwB,uBAC1B,sBAAsB,aAC9B,eAAe"}
|
|
@@ -38,7 +38,7 @@ const make = (options) => {
|
|
|
38
38
|
reason: "Transaction has already been processed"
|
|
39
39
|
};
|
|
40
40
|
const currentState = _document.get();
|
|
41
|
-
const tempDoc = make$1(schema, {
|
|
41
|
+
const tempDoc = make$1(schema, { initialState: currentState });
|
|
42
42
|
try {
|
|
43
43
|
tempDoc.apply(transaction.ops);
|
|
44
44
|
return { valid: true };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerDocument.mjs","names":["Document.make","_transactionOrder: string[]","Transaction.isEmpty"],"sources":["../../src/server/ServerDocument.ts"],"sourcesContent":["import * as Document from \"../Document\";\nimport * as Transaction from \"../Transaction\";\nimport type * as Primitive from \"../Primitive\";\n\n// =============================================================================\n// Server Message Types (matching client's Transport expectations)\n// =============================================================================\n\n/**\n * Message sent when broadcasting a committed transaction.\n */\nexport interface TransactionMessage {\n readonly type: \"transaction\";\n readonly transaction: Transaction.Transaction;\n /** Server-assigned version number for ordering */\n readonly version: number;\n}\n\n/**\n * Message sent when a transaction is rejected.\n */\nexport interface ErrorMessage {\n readonly type: \"error\";\n readonly transactionId: string;\n readonly reason: string;\n}\n\n/**\n * Message sent as a full state snapshot.\n */\nexport interface SnapshotMessage {\n readonly type: \"snapshot\";\n readonly state: unknown;\n readonly version: number;\n}\n\n/**\n * Union of all server messages that can be broadcast.\n */\nexport type ServerMessage = TransactionMessage | ErrorMessage | SnapshotMessage;\n\n// =============================================================================\n// Submit Result Types\n// =============================================================================\n\n/**\n * Result of submitting a transaction to the server.\n */\nexport type SubmitResult =\n | { readonly success: true; readonly version: number }\n | { readonly success: false; readonly reason: string };\n\n// =============================================================================\n// Server Document Types\n// =============================================================================\n\n/**\n * Options for creating a ServerDocument.\n */\nexport interface ServerDocumentOptions<TSchema extends Primitive.AnyPrimitive> {\n /** The schema defining the document structure */\n readonly schema: TSchema;\n /** Initial state (optional, will use schema defaults if not provided) */\n readonly initialState?: Primitive.InferState<TSchema>;\n /** Initial version number (optional, defaults to 0) */\n readonly initialVersion?: number;\n /** Called when a transaction is successfully applied and should be broadcast */\n readonly onBroadcast: (message: TransactionMessage) => void;\n /** Called when a transaction is rejected (optional, for logging/metrics) */\n readonly onRejection?: (transactionId: string, reason: string) => void;\n /** Maximum number of processed transaction IDs to track for deduplication */\n readonly maxTransactionHistory?: number;\n}\n\n/**\n * A ServerDocument maintains the authoritative state and processes client transactions.\n */\nexport interface ServerDocument<TSchema extends Primitive.AnyPrimitive> {\n /** The schema defining this document's structure */\n readonly schema: TSchema;\n\n /** Returns the current authoritative state */\n get(): Primitive.InferState<TSchema> | undefined;\n\n /** Returns the current version number */\n getVersion(): number;\n\n /**\n * Submits a transaction for processing.\n * Validates and applies the transaction if valid, or rejects it with a reason.\n * @param transaction - The transaction to process\n * @returns SubmitResult indicating success with version or failure with reason\n */\n submit(transaction: Transaction.Transaction): SubmitResult;\n\n /**\n * Returns a snapshot of the current state and version.\n * Used to initialize new clients or resync after drift.\n */\n getSnapshot(): SnapshotMessage;\n\n /**\n * Checks if a transaction has already been processed.\n * @param transactionId - The transaction ID to check\n */\n hasProcessed(transactionId: string): boolean;\n}\n\n// =============================================================================\n// Server Document Implementation\n// =============================================================================\n\n/**\n * Creates a new ServerDocument for the given schema.\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n options: ServerDocumentOptions<TSchema>\n): ServerDocument<TSchema> => {\n const {\n schema,\n initialState,\n initialVersion = 0,\n onBroadcast,\n onRejection,\n maxTransactionHistory = 1000,\n } = options;\n\n // ==========================================================================\n // Internal State\n // ==========================================================================\n\n // The authoritative document\n let _document = Document.make(schema, { initial: initialState });\n\n // Current version number (incremented on each successful transaction)\n let _version = initialVersion;\n\n // Track processed transaction IDs for deduplication\n const _processedTransactions = new Set<string>();\n const _transactionOrder: string[] = [];\n\n // ==========================================================================\n // Helper Functions\n // ==========================================================================\n\n /**\n * Records a transaction as processed, maintaining the history limit.\n */\n const recordTransaction = (transactionId: string): void => {\n _processedTransactions.add(transactionId);\n _transactionOrder.push(transactionId);\n\n // Evict oldest transactions if over limit\n while (_transactionOrder.length > maxTransactionHistory) {\n const oldest = _transactionOrder.shift();\n if (oldest) {\n _processedTransactions.delete(oldest);\n }\n }\n };\n\n /**\n * Validates that the transaction can be applied to the current state.\n * Creates a temporary document and attempts to apply the operations.\n */\n const validateTransaction = (\n transaction: Transaction.Transaction\n ): { valid: true } | { valid: false; reason: string } => {\n // Check for empty transaction\n if (Transaction.isEmpty(transaction)) {\n return { valid: false, reason: \"Transaction is empty\" };\n }\n\n // Check for duplicate transaction\n if (_processedTransactions.has(transaction.id)) {\n return { valid: false, reason: \"Transaction has already been processed\" };\n }\n\n // Create a temporary document with current state to test the operations\n const currentState = _document.get();\n const tempDoc = Document.make(schema, { initial: currentState });\n\n try {\n // Attempt to apply all operations\n tempDoc.apply(transaction.ops);\n return { valid: true };\n } catch (error) {\n // Operations failed to apply\n const message = error instanceof Error ? error.message : String(error);\n return { valid: false, reason: message };\n }\n };\n\n // ==========================================================================\n // Public API\n // ==========================================================================\n\n const serverDocument: ServerDocument<TSchema> = {\n schema,\n\n get: (): Primitive.InferState<TSchema> | undefined => {\n return _document.get();\n },\n\n getVersion: (): number => {\n return _version;\n },\n\n submit: (transaction: Transaction.Transaction): SubmitResult => {\n // Validate the transaction\n const validation = validateTransaction(transaction);\n\n if (!validation.valid) {\n // Notify rejection callback if provided\n onRejection?.(transaction.id, validation.reason);\n\n return {\n success: false,\n reason: validation.reason,\n };\n }\n\n // Apply the transaction to the authoritative state\n try {\n _document.apply(transaction.ops);\n } catch (error) {\n // This shouldn't happen since we validated, but handle gracefully\n const reason = error instanceof Error ? error.message : String(error);\n onRejection?.(transaction.id, reason);\n return { success: false, reason };\n }\n\n // Increment version\n _version += 1;\n\n // Record as processed\n recordTransaction(transaction.id);\n\n // Broadcast the confirmed transaction\n const message: TransactionMessage = {\n type: \"transaction\",\n transaction,\n version: _version,\n };\n onBroadcast(message);\n\n return {\n success: true,\n version: _version,\n };\n },\n\n getSnapshot: (): SnapshotMessage => {\n return {\n type: \"snapshot\",\n state: _document.get(),\n version: _version,\n };\n },\n\n hasProcessed: (transactionId: string): boolean => {\n return _processedTransactions.has(transactionId);\n },\n };\n\n return serverDocument;\n};\n"],"mappings":";;;;;;;;;AAmHA,MAAa,QACX,YAC4B;CAC5B,MAAM,EACJ,QACA,cACA,iBAAiB,GACjB,aACA,aACA,wBAAwB,QACtB;CAOJ,IAAI,YAAYA,OAAc,QAAQ,EAAE,SAAS,cAAc,CAAC;CAGhE,IAAI,WAAW;CAGf,MAAM,yCAAyB,IAAI,KAAa;CAChD,MAAMC,oBAA8B,EAAE;;;;CAStC,MAAM,qBAAqB,kBAAgC;AACzD,yBAAuB,IAAI,cAAc;AACzC,oBAAkB,KAAK,cAAc;AAGrC,SAAO,kBAAkB,SAAS,uBAAuB;GACvD,MAAM,SAAS,kBAAkB,OAAO;AACxC,OAAI,OACF,wBAAuB,OAAO,OAAO;;;;;;;CAS3C,MAAM,uBACJ,gBACuD;AAEvD,MAAIC,QAAoB,YAAY,CAClC,QAAO;GAAE,OAAO;GAAO,QAAQ;GAAwB;AAIzD,MAAI,uBAAuB,IAAI,YAAY,GAAG,CAC5C,QAAO;GAAE,OAAO;GAAO,QAAQ;GAA0C;EAI3E,MAAM,eAAe,UAAU,KAAK;EACpC,MAAM,UAAUF,OAAc,QAAQ,EAAE,SAAS,cAAc,CAAC;AAEhE,MAAI;AAEF,WAAQ,MAAM,YAAY,IAAI;AAC9B,UAAO,EAAE,OAAO,MAAM;WACf,OAAO;AAGd,UAAO;IAAE,OAAO;IAAO,QADP,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9B;;;AA4E5C,QApEgD;EAC9C;EAEA,WAAsD;AACpD,UAAO,UAAU,KAAK;;EAGxB,kBAA0B;AACxB,UAAO;;EAGT,SAAS,gBAAuD;GAE9D,MAAM,aAAa,oBAAoB,YAAY;AAEnD,OAAI,CAAC,WAAW,OAAO;AAErB,kEAAc,YAAY,IAAI,WAAW,OAAO;AAEhD,WAAO;KACL,SAAS;KACT,QAAQ,WAAW;KACpB;;AAIH,OAAI;AACF,cAAU,MAAM,YAAY,IAAI;YACzB,OAAO;IAEd,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACrE,kEAAc,YAAY,IAAI,OAAO;AACrC,WAAO;KAAE,SAAS;KAAO;KAAQ;;AAInC,eAAY;AAGZ,qBAAkB,YAAY,GAAG;AAQjC,eALoC;IAClC,MAAM;IACN;IACA,SAAS;IACV,CACmB;AAEpB,UAAO;IACL,SAAS;IACT,SAAS;IACV;;EAGH,mBAAoC;AAClC,UAAO;IACL,MAAM;IACN,OAAO,UAAU,KAAK;IACtB,SAAS;IACV;;EAGH,eAAe,kBAAmC;AAChD,UAAO,uBAAuB,IAAI,cAAc;;EAEnD"}
|
|
1
|
+
{"version":3,"file":"ServerDocument.mjs","names":["Document.make","_transactionOrder: string[]","Transaction.isEmpty"],"sources":["../../src/server/ServerDocument.ts"],"sourcesContent":["import * as Document from \"../Document\";\nimport * as Transaction from \"../Transaction\";\nimport type * as Primitive from \"../Primitive\";\n\n// =============================================================================\n// Server Message Types (matching client's Transport expectations)\n// =============================================================================\n\n/**\n * Message sent when broadcasting a committed transaction.\n */\nexport interface TransactionMessage {\n readonly type: \"transaction\";\n readonly transaction: Transaction.Transaction;\n /** Server-assigned version number for ordering */\n readonly version: number;\n}\n\n/**\n * Message sent when a transaction is rejected.\n */\nexport interface ErrorMessage {\n readonly type: \"error\";\n readonly transactionId: string;\n readonly reason: string;\n}\n\n/**\n * Message sent as a full state snapshot.\n */\nexport interface SnapshotMessage {\n readonly type: \"snapshot\";\n readonly state: unknown;\n readonly version: number;\n}\n\n/**\n * Union of all server messages that can be broadcast.\n */\nexport type ServerMessage = TransactionMessage | ErrorMessage | SnapshotMessage;\n\n// =============================================================================\n// Submit Result Types\n// =============================================================================\n\n/**\n * Result of submitting a transaction to the server.\n */\nexport type SubmitResult =\n | { readonly success: true; readonly version: number }\n | { readonly success: false; readonly reason: string };\n\n// =============================================================================\n// Server Document Types\n// =============================================================================\n\n/**\n * Options for creating a ServerDocument.\n */\nexport interface ServerDocumentOptions<TSchema extends Primitive.AnyPrimitive> {\n /** The schema defining the document structure */\n readonly schema: TSchema;\n /** Initial value (optional, will use schema defaults if not provided) - uses set input format */\n readonly initialState?: Primitive.InferSetInput<TSchema>;\n /** Initial version number (optional, defaults to 0) */\n readonly initialVersion?: number;\n /** Called when a transaction is successfully applied and should be broadcast */\n readonly onBroadcast: (message: TransactionMessage) => void;\n /** Called when a transaction is rejected (optional, for logging/metrics) */\n readonly onRejection?: (transactionId: string, reason: string) => void;\n /** Maximum number of processed transaction IDs to track for deduplication */\n readonly maxTransactionHistory?: number;\n}\n\n/**\n * A ServerDocument maintains the authoritative state and processes client transactions.\n */\nexport interface ServerDocument<TSchema extends Primitive.AnyPrimitive> {\n /** The schema defining this document's structure */\n readonly schema: TSchema;\n\n /** Returns the current authoritative state */\n get(): Primitive.InferState<TSchema> | undefined;\n\n /** Returns the current version number */\n getVersion(): number;\n\n /**\n * Submits a transaction for processing.\n * Validates and applies the transaction if valid, or rejects it with a reason.\n * @param transaction - The transaction to process\n * @returns SubmitResult indicating success with version or failure with reason\n */\n submit(transaction: Transaction.Transaction): SubmitResult;\n\n /**\n * Returns a snapshot of the current state and version.\n * Used to initialize new clients or resync after drift.\n */\n getSnapshot(): SnapshotMessage;\n\n /**\n * Checks if a transaction has already been processed.\n * @param transactionId - The transaction ID to check\n */\n hasProcessed(transactionId: string): boolean;\n}\n\n// =============================================================================\n// Server Document Implementation\n// =============================================================================\n\n/**\n * Creates a new ServerDocument for the given schema.\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n options: ServerDocumentOptions<TSchema>\n): ServerDocument<TSchema> => {\n const {\n schema,\n initialState,\n initialVersion = 0,\n onBroadcast,\n onRejection,\n maxTransactionHistory = 1000,\n } = options;\n\n // ==========================================================================\n // Internal State\n // ==========================================================================\n\n // The authoritative document\n let _document = Document.make(schema, { initial: initialState });\n\n // Current version number (incremented on each successful transaction)\n let _version = initialVersion;\n\n // Track processed transaction IDs for deduplication\n const _processedTransactions = new Set<string>();\n const _transactionOrder: string[] = [];\n\n // ==========================================================================\n // Helper Functions\n // ==========================================================================\n\n /**\n * Records a transaction as processed, maintaining the history limit.\n */\n const recordTransaction = (transactionId: string): void => {\n _processedTransactions.add(transactionId);\n _transactionOrder.push(transactionId);\n\n // Evict oldest transactions if over limit\n while (_transactionOrder.length > maxTransactionHistory) {\n const oldest = _transactionOrder.shift();\n if (oldest) {\n _processedTransactions.delete(oldest);\n }\n }\n };\n\n /**\n * Validates that the transaction can be applied to the current state.\n * Creates a temporary document and attempts to apply the operations.\n */\n const validateTransaction = (\n transaction: Transaction.Transaction\n ): { valid: true } | { valid: false; reason: string } => {\n // Check for empty transaction\n if (Transaction.isEmpty(transaction)) {\n return { valid: false, reason: \"Transaction is empty\" };\n }\n\n // Check for duplicate transaction\n if (_processedTransactions.has(transaction.id)) {\n return { valid: false, reason: \"Transaction has already been processed\" };\n }\n\n // Create a temporary document with current state to test the operations\n // Use initialState (not initial) since currentState is already in flat state format\n const currentState = _document.get();\n const tempDoc = Document.make(schema, { initialState: currentState });\n\n try {\n // Attempt to apply all operations\n tempDoc.apply(transaction.ops);\n return { valid: true };\n } catch (error) {\n // Operations failed to apply\n const message = error instanceof Error ? error.message : String(error);\n return { valid: false, reason: message };\n }\n };\n\n // ==========================================================================\n // Public API\n // ==========================================================================\n\n const serverDocument: ServerDocument<TSchema> = {\n schema,\n\n get: (): Primitive.InferState<TSchema> | undefined => {\n return _document.get();\n },\n\n getVersion: (): number => {\n return _version;\n },\n\n submit: (transaction: Transaction.Transaction): SubmitResult => {\n // Validate the transaction\n const validation = validateTransaction(transaction);\n\n if (!validation.valid) {\n // Notify rejection callback if provided\n onRejection?.(transaction.id, validation.reason);\n\n return {\n success: false,\n reason: validation.reason,\n };\n }\n\n // Apply the transaction to the authoritative state\n try {\n _document.apply(transaction.ops);\n } catch (error) {\n // This shouldn't happen since we validated, but handle gracefully\n const reason = error instanceof Error ? error.message : String(error);\n onRejection?.(transaction.id, reason);\n return { success: false, reason };\n }\n\n // Increment version\n _version += 1;\n\n // Record as processed\n recordTransaction(transaction.id);\n\n // Broadcast the confirmed transaction\n const message: TransactionMessage = {\n type: \"transaction\",\n transaction,\n version: _version,\n };\n onBroadcast(message);\n\n return {\n success: true,\n version: _version,\n };\n },\n\n getSnapshot: (): SnapshotMessage => {\n return {\n type: \"snapshot\",\n state: _document.get(),\n version: _version,\n };\n },\n\n hasProcessed: (transactionId: string): boolean => {\n return _processedTransactions.has(transactionId);\n },\n };\n\n return serverDocument;\n};\n"],"mappings":";;;;;;;;;AAmHA,MAAa,QACX,YAC4B;CAC5B,MAAM,EACJ,QACA,cACA,iBAAiB,GACjB,aACA,aACA,wBAAwB,QACtB;CAOJ,IAAI,YAAYA,OAAc,QAAQ,EAAE,SAAS,cAAc,CAAC;CAGhE,IAAI,WAAW;CAGf,MAAM,yCAAyB,IAAI,KAAa;CAChD,MAAMC,oBAA8B,EAAE;;;;CAStC,MAAM,qBAAqB,kBAAgC;AACzD,yBAAuB,IAAI,cAAc;AACzC,oBAAkB,KAAK,cAAc;AAGrC,SAAO,kBAAkB,SAAS,uBAAuB;GACvD,MAAM,SAAS,kBAAkB,OAAO;AACxC,OAAI,OACF,wBAAuB,OAAO,OAAO;;;;;;;CAS3C,MAAM,uBACJ,gBACuD;AAEvD,MAAIC,QAAoB,YAAY,CAClC,QAAO;GAAE,OAAO;GAAO,QAAQ;GAAwB;AAIzD,MAAI,uBAAuB,IAAI,YAAY,GAAG,CAC5C,QAAO;GAAE,OAAO;GAAO,QAAQ;GAA0C;EAK3E,MAAM,eAAe,UAAU,KAAK;EACpC,MAAM,UAAUF,OAAc,QAAQ,EAAE,cAAc,cAAc,CAAC;AAErE,MAAI;AAEF,WAAQ,MAAM,YAAY,IAAI;AAC9B,UAAO,EAAE,OAAO,MAAM;WACf,OAAO;AAGd,UAAO;IAAE,OAAO;IAAO,QADP,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9B;;;AA4E5C,QApEgD;EAC9C;EAEA,WAAsD;AACpD,UAAO,UAAU,KAAK;;EAGxB,kBAA0B;AACxB,UAAO;;EAGT,SAAS,gBAAuD;GAE9D,MAAM,aAAa,oBAAoB,YAAY;AAEnD,OAAI,CAAC,WAAW,OAAO;AAErB,kEAAc,YAAY,IAAI,WAAW,OAAO;AAEhD,WAAO;KACL,SAAS;KACT,QAAQ,WAAW;KACpB;;AAIH,OAAI;AACF,cAAU,MAAM,YAAY,IAAI;YACzB,OAAO;IAEd,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACrE,kEAAc,YAAY,IAAI,OAAO;AACrC,WAAO;KAAE,SAAS;KAAO;KAAQ;;AAInC,eAAY;AAGZ,qBAAkB,YAAY,GAAG;AAQjC,eALoC;IAClC,MAAM;IACN;IACA,SAAS;IACV,CACmB;AAEpB,UAAO;IACL,SAAS;IACT,SAAS;IACV;;EAGH,mBAAoC;AAClC,UAAO;IACL,MAAM;IACN,OAAO,UAAU,KAAK;IACtB,SAAS;IACV;;EAGH,eAAe,kBAAmC;AAChD,UAAO,uBAAuB,IAAI,cAAc;;EAEnD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voidhash/mimic",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"typescript": "5.8.3",
|
|
32
32
|
"vite-tsconfig-paths": "^5.1.4",
|
|
33
33
|
"vitest": "^3.2.4",
|
|
34
|
-
"@voidhash/tsconfig": "0.0.
|
|
34
|
+
"@voidhash/tsconfig": "0.0.5"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"effect": "^3.19.12"
|