UNPKG

kaabalah

Version:

The de-facto library for any esoteric calculations and tooling

1 lines 54.7 kB
{"version":3,"sources":["../src/core/topology.ts","../src/core/workspace.ts"],"names":["id"],"mappings":"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","sourcesContent":["import { SPHERES } from \"./constants\";\nimport { createTree } from \"./factory\";\nimport { SystemKey } from \"./systems/registry\";\nimport {\n id,\n KaabalahTypes,\n Node,\n NodeData,\n NodeId,\n NodeType,\n parseId,\n} from \"./types\";\nimport { TreeOfLife } from \"./tree-of-life\";\n\nexport type TreeTopologySphereName =\n (typeof TREE_TOPOLOGY_SPHERE_NAMES)[number];\nexport type TreeTopologySphereId = NodeId<KaabalahTypes.SPHERE>;\nexport type TreeTopologyPathId = NodeId<KaabalahTypes.PATH>;\nexport type TreeTopologySphereRole = \"sephirah\" | \"hidden\";\nexport type TreeTopologyRouteKey = \"lightning\" | \"serpent\";\nexport type TreeTopologyRouteDirection = \"descending\" | \"ascending\";\n\nexport const TREE_TOPOLOGY_SPHERE_NAMES = [\n SPHERES.KETHER,\n SPHERES.CHOKHMAH,\n SPHERES.BINAH,\n SPHERES.DAATH,\n SPHERES.CHESED,\n SPHERES.GEBURAH,\n SPHERES.TIPHARETH,\n SPHERES.NETZACH,\n SPHERES.HOD,\n SPHERES.YESOD,\n SPHERES.MALKUTH,\n] as const;\n\nexport const TREE_TOPOLOGY_SPHERE_IDS = TREE_TOPOLOGY_SPHERE_NAMES.map(\n (name) => id(KaabalahTypes.SPHERE, name)\n) as readonly TreeTopologySphereId[];\n\nexport const TREE_TOPOLOGY_PATH_IDS = Array.from(\n { length: 22 },\n (_, index) => id(KaabalahTypes.PATH, index + 1)\n) as readonly TreeTopologyPathId[];\n\nconst TREE_TOPOLOGY_SPHERE_NUMBERS = {\n [SPHERES.KETHER]: 1,\n [SPHERES.CHOKHMAH]: 2,\n [SPHERES.BINAH]: 3,\n [SPHERES.DAATH]: 11,\n [SPHERES.CHESED]: 4,\n [SPHERES.GEBURAH]: 5,\n [SPHERES.TIPHARETH]: 6,\n [SPHERES.NETZACH]: 7,\n [SPHERES.HOD]: 8,\n [SPHERES.YESOD]: 9,\n [SPHERES.MALKUTH]: 10,\n} as const satisfies Record<TreeTopologySphereName, number>;\n\nexport const TREE_TOPOLOGY_LIGHTNING_SPHERE_NAMES = [\n SPHERES.KETHER,\n SPHERES.CHOKHMAH,\n SPHERES.BINAH,\n SPHERES.CHESED,\n SPHERES.GEBURAH,\n SPHERES.TIPHARETH,\n SPHERES.NETZACH,\n SPHERES.HOD,\n SPHERES.YESOD,\n SPHERES.MALKUTH,\n] as const satisfies readonly TreeTopologySphereName[];\n\nexport interface TreeTopologySphere {\n id: TreeTopologySphereId;\n name: TreeTopologySphereName;\n number: number;\n role: TreeTopologySphereRole;\n data?: NodeData<KaabalahTypes.SPHERE>;\n}\n\nexport interface TreeTopologyPath {\n id: TreeTopologyPathId;\n number: number;\n from: TreeTopologySphere;\n to: TreeTopologySphere;\n data: NodeData<KaabalahTypes.PATH>;\n}\n\nexport interface TreeTopologyAdjacentSphere {\n sphere: TreeTopologySphere;\n path: TreeTopologyPath;\n direction: \"forward\" | \"reverse\";\n}\n\nexport interface TreeTopologyRouteSegment {\n index: number;\n from: TreeTopologySphere;\n to: TreeTopologySphere;\n path?: TreeTopologyPath;\n isConnected: boolean;\n}\n\nexport interface TreeTopologyRouteTarget {\n targetId: TreeTopologySphereId | TreeTopologyPathId;\n targetType: \"sphere\" | \"path\";\n}\n\nexport interface TreeTopologyRoute {\n key: TreeTopologyRouteKey;\n name: string;\n direction: TreeTopologyRouteDirection;\n spheres: readonly TreeTopologySphere[];\n segments: readonly TreeTopologyRouteSegment[];\n isFullyConnected: boolean;\n missingSegments: readonly TreeTopologyRouteSegment[];\n targets: readonly TreeTopologyRouteTarget[];\n targetIds: readonly (TreeTopologySphereId | TreeTopologyPathId)[];\n}\n\nexport type TreeTopologySphereLookup =\n | TreeTopologySphereName\n | TreeTopologySphereId\n | {\n id?: TreeTopologySphereId;\n name?: TreeTopologySphereName | string;\n number?: number;\n };\n\nexport type TreeTopologyPathLookup =\n | number\n | TreeTopologyPathId\n | {\n id?: TreeTopologyPathId;\n number?: number;\n between?: readonly [TreeTopologySphereLookup, TreeTopologySphereLookup];\n };\n\nexport interface TreeTopologyOptions {\n system?: SystemKey;\n tree?: TreeOfLife;\n}\n\nexport interface GetTreeTopologySpheresOptions {\n includeDaath?: boolean;\n}\n\nfunction isNodeType<T extends NodeType>(\n node: Node<NodeType>,\n type: T\n): node is Node<T> {\n return node.type === type;\n}\n\nfunction cloneSphereData(data?: NodeData<KaabalahTypes.SPHERE>) {\n return data ? { ...data } : undefined;\n}\n\nfunction clonePathData(data: NodeData<KaabalahTypes.PATH>) {\n return { ...data };\n}\n\nfunction parsePathNumber(pathId: TreeTopologyPathId) {\n const parsed = Number.parseInt(parseId(pathId), 10);\n\n if (!Number.isInteger(parsed)) {\n throw new Error(`Invalid tree path id: ${pathId}`);\n }\n\n return parsed;\n}\n\nfunction normalizeName(value: string) {\n return value.trim().toLowerCase();\n}\n\nfunction pairKey(left: TreeTopologySphereId, right: TreeTopologySphereId) {\n return [String(left), String(right)].sort().join(\"|\");\n}\n\nfunction routeNames() {\n return [...TREE_TOPOLOGY_LIGHTNING_SPHERE_NAMES];\n}\n\nfunction routeDescriptor(key: TreeTopologyRouteKey) {\n return key === \"lightning\"\n ? {\n name: \"Lightning Path\",\n direction: \"descending\" as const,\n }\n : {\n name: \"Serpent Path\",\n direction: \"ascending\" as const,\n };\n}\n\nfunction routeTargetList(segments: readonly TreeTopologyRouteSegment[]) {\n if (segments.length === 0) {\n return [] as TreeTopologyRouteTarget[];\n }\n\n const targets: TreeTopologyRouteTarget[] = [\n { targetId: segments[0].from.id, targetType: \"sphere\" },\n ];\n\n for (const segment of segments) {\n if (segment.path) {\n targets.push({ targetId: segment.path.id, targetType: \"path\" });\n }\n\n targets.push({ targetId: segment.to.id, targetType: \"sphere\" });\n }\n\n return targets;\n}\n\nexport class TreeTopology {\n public readonly system: SystemKey;\n\n private readonly spheres: readonly TreeTopologySphere[];\n private readonly paths: readonly TreeTopologyPath[];\n private readonly spheresById = new Map<\n TreeTopologySphereId,\n TreeTopologySphere\n >();\n private readonly spheresByName = new Map<string, TreeTopologySphere>();\n private readonly spheresByNumber = new Map<number, TreeTopologySphere>();\n private readonly pathsById = new Map<TreeTopologyPathId, TreeTopologyPath>();\n private readonly pathsByNumber = new Map<number, TreeTopologyPath>();\n private readonly pathsBySpherePair = new Map<string, TreeTopologyPath>();\n private readonly routesByKey = new Map<\n TreeTopologyRouteKey,\n TreeTopologyRoute\n >();\n\n constructor({\n system,\n spheres,\n paths,\n }: {\n system: SystemKey;\n spheres: readonly TreeTopologySphere[];\n paths: readonly TreeTopologyPath[];\n }) {\n this.system = system;\n this.spheres = spheres.map((sphere) =>\n Object.freeze({\n ...sphere,\n data: cloneSphereData(sphere.data),\n })\n );\n\n for (const sphere of this.spheres) {\n this.spheresById.set(sphere.id, sphere);\n this.spheresByName.set(normalizeName(sphere.name), sphere);\n this.spheresByNumber.set(sphere.number, sphere);\n }\n\n this.paths = paths.map((path) => {\n const from = this.spheresById.get(path.from.id);\n const to = this.spheresById.get(path.to.id);\n\n if (!from || !to) {\n throw new Error(\n `Tree topology path ${path.id} references unknown spheres.`\n );\n }\n\n return Object.freeze({\n ...path,\n from,\n to,\n data: clonePathData(path.data),\n });\n });\n\n for (const path of this.paths) {\n this.pathsById.set(path.id, path);\n this.pathsByNumber.set(path.number, path);\n this.pathsBySpherePair.set(pairKey(path.from.id, path.to.id), path);\n }\n\n for (const key of [\"lightning\", \"serpent\"] as const) {\n this.routesByKey.set(key, this.buildRoute(key));\n }\n }\n\n getSpheres(options: GetTreeTopologySpheresOptions = {}) {\n const includeDaath = options.includeDaath ?? true;\n\n return includeDaath\n ? [...this.spheres]\n : this.spheres.filter((sphere) => sphere.name !== SPHERES.DAATH);\n }\n\n getPrimarySpheres() {\n return this.getSpheres({ includeDaath: false });\n }\n\n getSphere(lookup: TreeTopologySphereLookup) {\n if (typeof lookup === \"string\") {\n if (lookup.startsWith(`${KaabalahTypes.SPHERE}:`)) {\n return this.spheresById.get(lookup as TreeTopologySphereId);\n }\n\n return this.spheresByName.get(normalizeName(lookup));\n }\n\n if (lookup.id) {\n return this.spheresById.get(lookup.id);\n }\n\n if (lookup.number) {\n return this.spheresByNumber.get(lookup.number);\n }\n\n if (lookup.name) {\n return this.spheresByName.get(normalizeName(lookup.name));\n }\n\n return undefined;\n }\n\n getPaths() {\n return [...this.paths];\n }\n\n getPath(lookup: TreeTopologyPathLookup) {\n if (typeof lookup === \"number\") {\n return this.pathsByNumber.get(lookup);\n }\n\n if (typeof lookup === \"string\") {\n return this.pathsById.get(lookup as TreeTopologyPathId);\n }\n\n if (lookup.id) {\n return this.pathsById.get(lookup.id);\n }\n\n if (lookup.number) {\n return this.pathsByNumber.get(lookup.number);\n }\n\n if (lookup.between) {\n return this.getPathBetween(lookup.between[0], lookup.between[1]);\n }\n\n return undefined;\n }\n\n getPathBetween(\n first: TreeTopologySphereLookup,\n second: TreeTopologySphereLookup\n ) {\n const firstSphere = this.getSphere(first);\n const secondSphere = this.getSphere(second);\n\n if (!firstSphere || !secondSphere) {\n return undefined;\n }\n\n return this.pathsBySpherePair.get(pairKey(firstSphere.id, secondSphere.id));\n }\n\n getAdjacentSpheres(\n sphereLookup: TreeTopologySphereLookup\n ): TreeTopologyAdjacentSphere[] {\n const sphere = this.getSphere(sphereLookup);\n\n if (!sphere) {\n return [];\n }\n\n return this.paths\n .filter((path) => path.from.id === sphere.id || path.to.id === sphere.id)\n .map((path) => {\n const isForward = path.from.id === sphere.id;\n\n return {\n sphere: isForward ? path.to : path.from,\n path,\n direction: isForward ? \"forward\" : \"reverse\",\n };\n });\n }\n\n getRoutes() {\n return [...this.routesByKey.values()];\n }\n\n getRoute(key: TreeTopologyRouteKey) {\n return this.routesByKey.get(key);\n }\n\n nextInRoute(\n routeKey: TreeTopologyRouteKey,\n sphereLookup: TreeTopologySphereLookup\n ) {\n const route = this.getRoute(routeKey);\n const sphere = this.getSphere(sphereLookup);\n\n if (!route || !sphere) {\n return undefined;\n }\n\n const index = route.spheres.findIndex(\n (routeSphere) => routeSphere.id === sphere.id\n );\n\n return index >= 0 ? route.spheres[index + 1] : undefined;\n }\n\n previousInRoute(\n routeKey: TreeTopologyRouteKey,\n sphereLookup: TreeTopologySphereLookup\n ) {\n const route = this.getRoute(routeKey);\n const sphere = this.getSphere(sphereLookup);\n\n if (!route || !sphere) {\n return undefined;\n }\n\n const index = route.spheres.findIndex(\n (routeSphere) => routeSphere.id === sphere.id\n );\n\n return index > 0 ? route.spheres[index - 1] : undefined;\n }\n\n private buildRoute(key: TreeTopologyRouteKey): TreeTopologyRoute {\n const descriptor = routeDescriptor(key);\n const names = routeNames();\n const orderedNames = key === \"serpent\" ? names.reverse() : names;\n const spheres = orderedNames.map((name) => {\n const sphere = this.getSphere(name);\n\n if (!sphere) {\n throw new Error(\n `Tree topology route \"${key}\" references missing sphere \"${name}\" in ${this.system}.`\n );\n }\n\n return sphere;\n });\n const segments: TreeTopologyRouteSegment[] = [];\n\n for (let index = 0; index < spheres.length - 1; index++) {\n const from = spheres[index];\n const to = spheres[index + 1];\n const path = this.getPathBetween(from.name, to.name);\n\n segments.push({\n index,\n from,\n to,\n path,\n isConnected: Boolean(path),\n });\n }\n\n const targets = routeTargetList(segments);\n const missingSegments = segments.filter((segment) => !segment.isConnected);\n\n return Object.freeze({\n key,\n name: descriptor.name,\n direction: descriptor.direction,\n spheres: Object.freeze([...spheres]),\n segments: Object.freeze(segments),\n isFullyConnected: missingSegments.length === 0,\n missingSegments: Object.freeze(missingSegments),\n targets: Object.freeze(targets),\n targetIds: Object.freeze(targets.map((target) => target.targetId)),\n });\n }\n}\n\nexport function getTreeTopology(options: TreeTopologyOptions = {}) {\n const system = options.system ?? options.tree?.activeSystem ?? \"kaabalah\";\n const tree = options.tree ?? createTree({ system });\n const spheres: TreeTopologySphere[] = [];\n\n for (const sphereId of TREE_TOPOLOGY_SPHERE_IDS) {\n const sphereNode = tree.getNode(sphereId);\n\n if (!sphereNode) {\n continue;\n }\n\n const name = parseId(sphereId) as TreeTopologySphereName;\n\n spheres.push({\n id: sphereId,\n name,\n number: TREE_TOPOLOGY_SPHERE_NUMBERS[name],\n role: name === SPHERES.DAATH ? \"hidden\" : \"sephirah\",\n data: cloneSphereData(sphereNode.data),\n });\n }\n\n const spheresById = new Map(spheres.map((sphere) => [sphere.id, sphere]));\n const paths = tree\n .getNodes()\n .filter((node): node is Node<KaabalahTypes.PATH> =>\n isNodeType(node, KaabalahTypes.PATH)\n )\n .map((pathNode) => {\n if (!pathNode.data?.from || !pathNode.data?.to) {\n throw new Error(`Tree topology path ${pathNode.id} is missing endpoints.`);\n }\n\n const from = spheresById.get(pathNode.data.from);\n const to = spheresById.get(pathNode.data.to);\n\n if (!from || !to) {\n throw new Error(\n `Tree topology path ${pathNode.id} references unknown spheres.`\n );\n }\n\n return {\n id: pathNode.id,\n number: parsePathNumber(pathNode.id),\n from,\n to,\n data: clonePathData(pathNode.data),\n } satisfies TreeTopologyPath;\n })\n .sort((left, right) => left.number - right.number);\n\n return new TreeTopology({\n system,\n spheres,\n paths,\n });\n}\n","import {\n CorrespondenceEdge,\n CorrespondenceMap,\n CorrespondenceMatch,\n CorrespondenceMetadata,\n CorrespondenceSource,\n CorrespondenceStep,\n TreeNote,\n TreeNoteTarget,\n TreeOverlay,\n TreeWorkspaceDescriptor,\n makeCorrespondenceId,\n} from \"./correspondence-model\";\nimport { createTree, TreeOptions } from \"./factory\";\nimport { TreeOfLife } from \"./tree-of-life\";\nimport { Node, NodeId, NodeType } from \"./types\";\n\nexport interface TreeCorrespondenceQueryOptions<T extends NodeType = NodeType> {\n type?: T | readonly T[];\n depth?: number;\n includeSelf?: boolean;\n limit?: number;\n}\n\nexport interface TreeFindNodesOptions<T extends NodeType = NodeType> {\n type?: T | readonly T[];\n ids?: readonly NodeId<T>[];\n search?: string;\n predicate?: (node: Node<T>) => boolean;\n}\n\nexport interface TreeVisualRequest {\n nodeId: NodeId<NodeType>;\n kind?: string;\n [key: string]: unknown;\n}\n\nexport interface TreeVisualResult {\n kind: string;\n nodeId: NodeId<NodeType>;\n [key: string]: unknown;\n}\n\nexport type TreeVisualResolver = (input: {\n request: TreeVisualRequest;\n workspace: TreeWorkspace;\n}) => TreeVisualResult | undefined;\n\nexport interface CreateTreeWorkspaceOptions {\n base?: TreeWorkspace | TreeOfLife;\n overlays?: TreeOverlay[];\n descriptor?: TreeWorkspaceDescriptor;\n visualResolvers?: TreeVisualResolver[];\n}\n\ntype TreeGraphData = {\n descriptor: TreeWorkspaceDescriptor;\n nodesById: Map<NodeId<NodeType>, Node<NodeType>>;\n nodeIdsByType: Map<NodeType, NodeId<NodeType>[]>;\n edgesById: Map<string, CorrespondenceEdge>;\n edgeIdsByNodeId: Map<NodeId<NodeType>, string[]>;\n notesById: Map<string, TreeNote>;\n noteIdsByNodeId: Map<NodeId<NodeType>, string[]>;\n noteIdsByCorrespondenceId: Map<string, string[]>;\n};\n\nfunction cloneNode<T extends NodeType>(node: Node<T>): Node<T> {\n return Object.freeze({\n id: node.id,\n type: node.type,\n name: node.name,\n data:\n node.data && typeof node.data === \"object\"\n ? ({ ...node.data } as Node<T>[\"data\"])\n : node.data,\n });\n}\n\nfunction cloneMetadata(metadata?: CorrespondenceMetadata) {\n if (!metadata) {\n return undefined;\n }\n\n return {\n ...metadata,\n tags: metadata.tags ? [...metadata.tags] : undefined,\n attributes: metadata.attributes ? { ...metadata.attributes } : undefined,\n };\n}\n\nfunction cloneSource(source: CorrespondenceSource): CorrespondenceSource {\n if (source.kind === \"bridge\") {\n return {\n ...source,\n parts: [...source.parts],\n };\n }\n\n return { ...source };\n}\n\nfunction cloneEdge(edge: CorrespondenceEdge): CorrespondenceEdge {\n return Object.freeze({\n ...edge,\n metadata: cloneMetadata(edge.metadata),\n sources: edge.sources.map(cloneSource),\n });\n}\n\nfunction cloneNote(note: TreeNote): TreeNote {\n return Object.freeze({\n ...note,\n target: { ...note.target },\n metadata: note.metadata ? { ...note.metadata } : undefined,\n });\n}\n\nfunction mergeMetadata(\n current?: CorrespondenceMetadata,\n next?: CorrespondenceMetadata\n) {\n if (!current) {\n return cloneMetadata(next);\n }\n\n if (!next) {\n return cloneMetadata(current);\n }\n\n return {\n ...current,\n ...next,\n tags: [...new Set([...(current.tags ?? []), ...(next.tags ?? [])])],\n attributes: {\n ...(current.attributes ?? {}),\n ...(next.attributes ?? {}),\n },\n };\n}\n\nfunction mergeSources(\n current: readonly CorrespondenceSource[],\n next: CorrespondenceSource\n) {\n const seen = new Set<string>();\n const merged: CorrespondenceSource[] = [];\n\n for (const source of [...current, next]) {\n const key = JSON.stringify(source);\n\n if (seen.has(key)) {\n continue;\n }\n\n seen.add(key);\n merged.push(cloneSource(source));\n }\n\n return merged;\n}\n\nfunction normalizeTypes<T extends NodeType>(\n type?: T | readonly T[]\n): Set<NodeType> | undefined {\n if (!type) {\n return undefined;\n }\n\n return new Set(Array.isArray(type) ? type : [type]);\n}\n\nfunction sortNodes<T extends NodeType>(nodes: Node<T>[]) {\n return [...nodes].sort((left, right) => {\n if (left.type !== right.type) {\n return left.type.localeCompare(right.type);\n }\n\n const leftLabel = String(left.name ?? left.id);\n const rightLabel = String(right.name ?? right.id);\n\n return leftLabel.localeCompare(rightLabel);\n });\n}\n\nfunction sortMatches<T extends NodeType>(matches: CorrespondenceMatch<T>[]) {\n return [...matches].sort((left, right) => {\n if (left.distance !== right.distance) {\n return left.distance - right.distance;\n }\n\n if (left.node.type !== right.node.type) {\n return left.node.type.localeCompare(right.node.type);\n }\n\n const leftLabel = String(left.node.name ?? left.node.id);\n const rightLabel = String(right.node.name ?? right.node.id);\n\n return leftLabel.localeCompare(rightLabel);\n });\n}\n\nfunction createGraphData(\n descriptor: TreeWorkspaceDescriptor,\n nodes: Iterable<Node<NodeType>>,\n edges: Iterable<CorrespondenceEdge>,\n notes: Iterable<TreeNote>\n): TreeGraphData {\n const nodesById = new Map<NodeId<NodeType>, Node<NodeType>>();\n const nodeIdsByType = new Map<NodeType, NodeId<NodeType>[]>();\n const edgesById = new Map<string, CorrespondenceEdge>();\n const edgeIdsByNodeId = new Map<NodeId<NodeType>, string[]>();\n const notesById = new Map<string, TreeNote>();\n const noteIdsByNodeId = new Map<NodeId<NodeType>, string[]>();\n const noteIdsByCorrespondenceId = new Map<string, string[]>();\n\n for (const node of nodes) {\n const clonedNode = cloneNode(node);\n\n nodesById.set(clonedNode.id, clonedNode);\n\n const typedIds = nodeIdsByType.get(clonedNode.type) ?? [];\n typedIds.push(clonedNode.id as NodeId<NodeType>);\n nodeIdsByType.set(clonedNode.type, typedIds);\n }\n\n for (const edge of edges) {\n const clonedEdge = cloneEdge(edge);\n\n edgesById.set(clonedEdge.id, clonedEdge);\n\n const leftEdges = edgeIdsByNodeId.get(clonedEdge.left) ?? [];\n leftEdges.push(clonedEdge.id);\n edgeIdsByNodeId.set(clonedEdge.left, leftEdges);\n\n const rightEdges = edgeIdsByNodeId.get(clonedEdge.right) ?? [];\n rightEdges.push(clonedEdge.id);\n edgeIdsByNodeId.set(clonedEdge.right, rightEdges);\n }\n\n for (const note of notes) {\n const clonedNote = cloneNote(note);\n notesById.set(clonedNote.id, clonedNote);\n\n if (clonedNote.target.kind === \"node\") {\n const nodeNoteIds = noteIdsByNodeId.get(clonedNote.target.nodeId) ?? [];\n nodeNoteIds.push(clonedNote.id);\n noteIdsByNodeId.set(clonedNote.target.nodeId, nodeNoteIds);\n continue;\n }\n\n const edgeId = makeCorrespondenceId(\n clonedNote.target.left,\n clonedNote.target.right\n );\n const correspondenceNoteIds =\n noteIdsByCorrespondenceId.get(edgeId) ?? [];\n correspondenceNoteIds.push(clonedNote.id);\n noteIdsByCorrespondenceId.set(edgeId, correspondenceNoteIds);\n }\n\n for (const ids of nodeIdsByType.values()) {\n ids.sort((left, right) => String(left).localeCompare(String(right)));\n }\n\n for (const ids of edgeIdsByNodeId.values()) {\n ids.sort((left, right) => left.localeCompare(right));\n }\n\n for (const ids of noteIdsByNodeId.values()) {\n ids.sort((left, right) => left.localeCompare(right));\n }\n\n for (const ids of noteIdsByCorrespondenceId.values()) {\n ids.sort((left, right) => left.localeCompare(right));\n }\n\n return {\n descriptor: Object.freeze({ ...descriptor }),\n nodesById,\n nodeIdsByType,\n edgesById,\n edgeIdsByNodeId,\n notesById,\n noteIdsByNodeId,\n noteIdsByCorrespondenceId,\n };\n}\n\nfunction normalizeBase(base?: TreeWorkspace | TreeOfLife) {\n if (!base) {\n return {\n descriptor: {},\n nodes: [] as Node<NodeType>[],\n edges: [] as CorrespondenceEdge[],\n notes: [] as TreeNote[],\n };\n }\n\n if (base instanceof TreeWorkspace) {\n return {\n descriptor: base.descriptor,\n nodes: base.getNodes(),\n edges: base.getEdges(),\n notes: base.getNotes(),\n };\n }\n\n return {\n descriptor: {\n system: base.activeSystem ?? undefined,\n parts: base.loadedParts.filter((part) => part !== \"base\"),\n },\n nodes: base.getNodes(),\n edges: base.getEdges(),\n notes: [] as TreeNote[],\n };\n}\n\nfunction applyOverlays(\n base: ReturnType<typeof normalizeBase>,\n overlays: TreeOverlay[]\n) {\n const nodesById = new Map<NodeId<NodeType>, Node<NodeType>>();\n const edgesById = new Map<string, CorrespondenceEdge>();\n const notes: TreeNote[] = [];\n\n for (const node of base.nodes) {\n nodesById.set(node.id as NodeId<NodeType>, cloneNode(node));\n }\n\n for (const edge of base.edges) {\n edgesById.set(edge.id, cloneEdge(edge));\n }\n\n for (const note of base.notes) {\n notes.push(cloneNote(note));\n }\n\n for (const overlay of overlays) {\n for (const node of overlay.nodes ?? []) {\n const existing = nodesById.get(node.id as NodeId<NodeType>);\n\n if (existing && existing.type !== node.type) {\n throw new Error(\n `Overlay ${overlay.id} tried to upsert ${node.id} with a different type`\n );\n }\n\n nodesById.set(\n node.id as NodeId<NodeType>,\n cloneNode(\n existing\n ? {\n ...existing,\n ...node,\n data: {\n ...(existing.data ?? {}),\n ...(node.data ?? {}),\n } as Node<NodeType>[\"data\"],\n }\n : node\n )\n );\n }\n\n for (const correspondence of overlay.correspondences ?? []) {\n if (\n !nodesById.has(correspondence.left) ||\n !nodesById.has(correspondence.right)\n ) {\n throw new Error(\n `Overlay ${overlay.id} references unknown nodes in ${correspondence.left} <-> ${correspondence.right}`\n );\n }\n\n const edgeId = makeCorrespondenceId(\n correspondence.left,\n correspondence.right\n );\n\n if (correspondence.op === \"remove\") {\n edgesById.delete(edgeId);\n continue;\n }\n\n const existingEdge = edgesById.get(edgeId);\n const overlaySource: CorrespondenceSource = {\n kind: \"overlay\",\n overlayId: overlay.id,\n label: overlay.name,\n };\n\n if (!existingEdge) {\n if (correspondence.op !== \"add\") {\n throw new Error(\n `Overlay ${overlay.id} cannot annotate missing correspondence ${edgeId}`\n );\n }\n\n edgesById.set(\n edgeId,\n cloneEdge({\n id: edgeId,\n left: correspondence.left,\n right: correspondence.right,\n metadata: cloneMetadata(correspondence.metadata),\n sources: [overlaySource],\n })\n );\n continue;\n }\n\n edgesById.set(\n edgeId,\n cloneEdge({\n ...existingEdge,\n metadata: mergeMetadata(existingEdge.metadata, correspondence.metadata),\n sources: mergeSources(existingEdge.sources, overlaySource),\n })\n );\n }\n\n for (const note of overlay.notes ?? []) {\n notes.push(\n cloneNote({\n ...note,\n metadata: note.metadata ? { ...note.metadata } : undefined,\n })\n );\n }\n }\n\n const filteredNotes = notes.filter((note) => {\n if (note.target.kind === \"node\") {\n return nodesById.has(note.target.nodeId);\n }\n\n return edgesById.has(\n makeCorrespondenceId(note.target.left, note.target.right)\n );\n });\n\n return {\n nodes: [...nodesById.values()],\n edges: [...edgesById.values()],\n notes: filteredNotes,\n };\n}\n\nfunction reconstructPath(\n startId: NodeId<NodeType>,\n targetId: NodeId<NodeType>,\n previous: Map<NodeId<NodeType>, { from: NodeId<NodeType>; edgeId: string }>,\n edgesById: Map<string, CorrespondenceEdge>\n) {\n const steps: CorrespondenceStep[] = [];\n let current = targetId;\n\n while (current !== startId) {\n const link = previous.get(current);\n\n if (!link) {\n break;\n }\n\n const edge = edgesById.get(link.edgeId);\n\n if (!edge) {\n break;\n }\n\n steps.push({\n from: link.from,\n to: current,\n edge,\n });\n current = link.from;\n }\n\n return steps.reverse();\n}\n\nfunction buildCanonicalDescriptor(opts: TreeOptions, cacheKey: string) {\n return {\n id: `canonical:${cacheKey}`,\n name: \"Canonical Tree\",\n system: opts.system,\n parts: [...(opts.parts ?? [])],\n cacheKey,\n } satisfies TreeWorkspaceDescriptor;\n}\n\nconst canonicalTreeCache = new Map<string, TreeWorkspace>();\n\nexport class TreeWorkspace {\n public readonly descriptor: TreeWorkspaceDescriptor;\n\n constructor(\n private readonly graph: TreeGraphData,\n private readonly visualResolvers: readonly TreeVisualResolver[] = []\n ) {\n this.descriptor = graph.descriptor;\n }\n\n getNode<T extends NodeType>(id: NodeId<T>) {\n return this.graph.nodesById.get(id as NodeId<NodeType>) as\n | Node<T>\n | undefined;\n }\n\n hasNode(id: NodeId<NodeType>) {\n return this.graph.nodesById.has(id);\n }\n\n getNodes<T extends NodeType>(type?: T): Node<T>[] {\n if (!type) {\n return sortNodes(\n [...this.graph.nodesById.values()] as Node<T>[]\n );\n }\n\n const ids = this.graph.nodeIdsByType.get(type) ?? [];\n\n return ids\n .map((id) => this.graph.nodesById.get(id) as Node<T> | undefined)\n .filter((node): node is Node<T> => Boolean(node));\n }\n\n findNodes<T extends NodeType = NodeType>(\n options: TreeFindNodesOptions<T> = {}\n ): Node<T>[] {\n const typeFilter = normalizeTypes(options.type);\n const search = options.search?.trim().toLowerCase();\n\n const candidates = options.ids\n ? options.ids\n .map((id) => this.graph.nodesById.get(id as NodeId<NodeType>))\n .filter((node): node is Node<NodeType> => Boolean(node))\n : typeFilter\n ? [...typeFilter].flatMap((type) => this.getNodes(type))\n : this.getNodes();\n\n return sortNodes(\n candidates.filter((node): node is Node<T> => {\n if (typeFilter && !typeFilter.has(node.type)) {\n return false;\n }\n\n if (search) {\n const haystacks = [\n String(node.id).toLowerCase(),\n String(node.name ?? \"\").toLowerCase(),\n ];\n\n if (!haystacks.some((value) => value.includes(search))) {\n return false;\n }\n }\n\n return options.predicate ? options.predicate(node as Node<T>) : true;\n })\n );\n }\n\n getEdge(left: NodeId<NodeType>, right: NodeId<NodeType>) {\n return this.graph.edgesById.get(makeCorrespondenceId(left, right));\n }\n\n getEdges(nodeId?: NodeId<NodeType>) {\n if (!nodeId) {\n return [...this.graph.edgesById.values()];\n }\n\n return (this.graph.edgeIdsByNodeId.get(nodeId) ?? [])\n .map((edgeId) => this.graph.edgesById.get(edgeId))\n .filter((edge): edge is CorrespondenceEdge => Boolean(edge));\n }\n\n getNotes(target?: TreeNoteTarget) {\n if (!target) {\n return [...this.graph.notesById.values()];\n }\n\n if (target.kind === \"node\") {\n return (this.graph.noteIdsByNodeId.get(target.nodeId) ?? [])\n .map((noteId) => this.graph.notesById.get(noteId))\n .filter((note): note is TreeNote => Boolean(note));\n }\n\n const edgeId = makeCorrespondenceId(target.left, target.right);\n\n return (this.graph.noteIdsByCorrespondenceId.get(edgeId) ?? [])\n .