@dxos/app-graph 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +1350 -686
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1349 -686
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/atoms.d.ts +8 -0
- package/dist/types/src/atoms.d.ts.map +1 -0
- package/dist/types/src/graph-builder.d.ts +112 -66
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +187 -221
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +6 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/node-matcher.d.ts +218 -0
- package/dist/types/src/node-matcher.d.ts.map +1 -0
- package/dist/types/src/node-matcher.test.d.ts +2 -0
- package/dist/types/src/node-matcher.test.d.ts.map +1 -0
- package/dist/types/src/node.d.ts +42 -5
- package/dist/types/src/node.d.ts.map +1 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +24 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +36 -34
- package/src/atoms.ts +25 -0
- package/src/graph-builder.test.ts +626 -119
- package/src/graph-builder.ts +667 -288
- package/src/graph.test.ts +429 -121
- package/src/graph.ts +1041 -403
- package/src/index.ts +9 -3
- package/src/node-matcher.test.ts +301 -0
- package/src/node-matcher.ts +282 -0
- package/src/node.ts +53 -8
- package/src/stories/EchoGraph.stories.tsx +158 -119
- package/src/stories/Tree.tsx +1 -1
- package/src/util.ts +55 -0
- package/dist/types/src/experimental/graph-projections.test.d.ts +0 -25
- package/dist/types/src/experimental/graph-projections.test.d.ts.map +0 -1
- package/dist/types/src/signals-integration.test.d.ts +0 -2
- package/dist/types/src/signals-integration.test.d.ts.map +0 -1
- package/dist/types/src/testing.d.ts +0 -5
- package/dist/types/src/testing.d.ts.map +0 -1
- package/src/experimental/graph-projections.test.ts +0 -56
- package/src/signals-integration.test.ts +0 -218
- package/src/testing.ts +0 -20
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/graph.ts", "../../../src/graph-builder.ts", "../../../src/node.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Registry, Rx } from '@effect-rx/rx-react';\nimport * as Function from 'effect/Function';\nimport * as Option from 'effect/Option';\nimport * as Record from 'effect/Record';\n\nimport { Event, Trigger } from '@dxos/async';\nimport { todo } from '@dxos/debug';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { type MakeOptional, isNonNullable } from '@dxos/util';\n\nimport { type Action, type ActionGroup, type Node, type NodeArg, type Relation } from './node';\n\nconst graphSymbol = Symbol('graph');\ntype DeepWriteable<T> = { -readonly [K in keyof T]: T[K] extends object ? DeepWriteable<T[K]> : T[K] };\ntype NodeInternal = DeepWriteable<Node> & { [graphSymbol]: Graph };\n\n/**\n * Get the Graph a Node is currently associated with.\n */\nexport const getGraph = (node: Node): Graph => {\n const graph = (node as NodeInternal)[graphSymbol];\n invariant(graph, 'Node is not associated with a graph.');\n return graph;\n};\n\nexport const ROOT_ID = 'root';\nexport const ROOT_TYPE = 'dxos.org/type/GraphRoot';\nexport const ACTION_TYPE = 'dxos.org/type/GraphAction';\nexport const ACTION_GROUP_TYPE = 'dxos.org/type/GraphActionGroup';\n\nexport type GraphTraversalOptions = {\n /**\n * A callback which is called for each node visited during traversal.\n *\n * If the callback returns `false`, traversal is stops recursing.\n */\n visitor: (node: Node, path: string[]) => boolean | void;\n\n /**\n * The node to start traversing from.\n *\n * @default ROOT_ID\n */\n source?: string;\n\n /**\n * The relation to traverse graph edges.\n *\n * @default 'outbound'\n */\n relation?: Relation;\n};\n\nexport type GraphParams = {\n registry?: Registry.Registry;\n nodes?: MakeOptional<Node, 'data' | 'cacheable'>[];\n edges?: Record<string, Edges>;\n onExpand?: Graph['_onExpand'];\n onInitialize?: Graph['_onInitialize'];\n onRemoveNode?: Graph['_onRemoveNode'];\n};\n\nexport type Edge = { source: string; target: string };\nexport type Edges = { inbound: string[]; outbound: string[] };\n\nexport interface ReadableGraph {\n /**\n * Event emitted when a node is changed.\n */\n onNodeChanged: Event<{ id: string; node: Option.Option<Node> }>;\n\n /**\n * Convert the graph to a JSON object.\n */\n toJSON(id?: string): object;\n\n json(id?: string): Rx.Rx<any>;\n\n /**\n * Get the rx key for the node with the given id.\n */\n node(id: string): Rx.Rx<Option.Option<Node>>;\n\n /**\n * Get the rx key for the node with the given id.\n */\n nodeOrThrow(id: string): Rx.Rx<Node>;\n\n /**\n * Get the rx key for the connections of the node with the given id.\n */\n connections(id: string, relation?: Relation): Rx.Rx<Node[]>;\n\n /**\n * Get the rx key for the actions of the node with the given id.\n */\n actions(id: string): Rx.Rx<(Action | ActionGroup)[]>;\n\n /**\n * Get the rx key for the edges of the node with the given id.\n */\n edges(id: string): Rx.Rx<Edges>;\n\n /**\n * Alias for `getNodeOrThrow(ROOT_ID)`.\n */\n get root(): Node;\n\n /**\n * Get the node with the given id from the graph's registry.\n */\n getNode(id: string): Option.Option<Node>;\n\n /**\n * Get the node with the given id from the graph's registry.\n *\n * @throws If the node is Option.none().\n */\n getNodeOrThrow(id: string): Node;\n\n /**\n * Get all nodes connected to the node with the given id by the given relation from the graph's registry.\n */\n getConnections(id: string, relation?: Relation): Node[];\n\n /**\n * Get all actions connected to the node with the given id from the graph's registry.\n */\n getActions(id: string): Node[];\n\n /**\n * Get the edges from the node with the given id from the graph's registry.\n */\n getEdges(id: string): Edges;\n\n /**\n * Recursive depth-first traversal of the graph.\n *\n * @param options.node The node to start traversing from.\n * @param options.relation The relation to traverse graph edges.\n * @param options.visitor A callback which is called for each node visited during traversal.\n */\n traverse(options: GraphTraversalOptions, path?: string[]): void;\n\n /**\n * Get the path between two nodes in the graph.\n */\n getPath(params: { source?: string; target: string }): Option.Option<string[]>;\n\n /**\n * Wait for the path between two nodes in the graph to be established.\n */\n waitForPath(\n params: { source?: string; target: string },\n options?: { timeout?: number; interval?: number },\n ): Promise<string[]>;\n}\n\nexport interface ExpandableGraph extends ReadableGraph {\n /**\n * Initialize a node in the graph.\n *\n * Fires the `onInitialize` callback to provide initial data for a node.\n */\n initialize(id: string): Promise<void>;\n\n /**\n * Expand a node in the graph.\n *\n * Fires the `onExpand` callback to add connections to the node.\n */\n expand(id: string, relation?: Relation): void;\n\n /**\n * Sort the edges of the node with the given id.\n */\n sortEdges(id: string, relation: Relation, order: string[]): void;\n}\n\nexport interface WritableGraph extends ExpandableGraph {\n /**\n * Add nodes to the graph.\n */\n addNodes(nodes: NodeArg<any, Record<string, any>>[]): void;\n\n /**\n * Add a node to the graph.\n */\n addNode(node: NodeArg<any, Record<string, any>>): void;\n\n /**\n * Remove nodes from the graph.\n */\n removeNodes(ids: string[], edges?: boolean): void;\n\n /**\n * Remove a node from the graph.\n */\n removeNode(id: string, edges?: boolean): void;\n\n /**\n * Add edges to the graph.\n */\n addEdges(edges: Edge[]): void;\n\n /**\n * Add an edge to the graph.\n */\n addEdge(edge: Edge): void;\n\n /**\n * Remove edges from the graph.\n */\n removeEdges(edges: Edge[], removeOrphans?: boolean): void;\n\n /**\n * Remove an edge from the graph.\n */\n removeEdge(edge: Edge, removeOrphans?: boolean): void;\n}\n\n/**\n * The Graph represents the user interface information architecture of the application constructed via plugins.\n */\nexport class Graph implements WritableGraph {\n readonly onNodeChanged = new Event<{ id: string; node: Option.Option<Node> }>();\n\n private readonly _onExpand?: (id: string, relation: Relation) => void;\n private readonly _onInitialize?: (id: string) => Promise<void>;\n private readonly _onRemoveNode?: (id: string) => void;\n\n private readonly _registry: Registry.Registry;\n private readonly _expanded = Record.empty<string, boolean>();\n private readonly _initialized = Record.empty<string, boolean>();\n private readonly _initialEdges = Record.empty<string, Edges>();\n private readonly _initialNodes = Record.fromEntries([\n [ROOT_ID, this._constructNode({ id: ROOT_ID, type: ROOT_TYPE, data: null, properties: {} })],\n ]);\n\n /** @internal */\n readonly _node = Rx.family<string, Rx.Writable<Option.Option<Node>>>((id) => {\n const initial = Option.flatten(Record.get(this._initialNodes, id));\n return Rx.make<Option.Option<Node>>(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:node:${id}`));\n });\n\n private readonly _nodeOrThrow = Rx.family<string, Rx.Rx<Node>>((id) => {\n return Rx.make((get) => {\n const node = get(this._node(id));\n invariant(Option.isSome(node), `Node not available: ${id}`);\n return node.value;\n });\n });\n\n private readonly _edges = Rx.family<string, Rx.Writable<Edges>>((id) => {\n const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({ inbound: [], outbound: [] })));\n return Rx.make<Edges>(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:edges:${id}`));\n });\n\n // NOTE: Currently the argument to the family needs to be referentially stable for the rx to be referentially stable.\n // TODO(wittjosiah): Rx feature request, support for something akin to `ComplexMap` to allow for complex arguments.\n private readonly _connections = Rx.family<string, Rx.Rx<Node[]>>((key) => {\n return Rx.make((get) => {\n const [id, relation] = key.split('$');\n const edges = get(this._edges(id));\n return edges[relation as Relation]\n .map((id) => get(this._node(id)))\n .filter(Option.isSome)\n .map((o) => o.value);\n }).pipe(Rx.withLabel(`graph:connections:${key}`));\n });\n\n private readonly _actions = Rx.family<string, Rx.Rx<(Action | ActionGroup)[]>>((id) => {\n return Rx.make((get) => {\n return get(this._connections(`${id}$outbound`)).filter(\n (node) => node.type === ACTION_TYPE || node.type === ACTION_GROUP_TYPE,\n );\n }).pipe(Rx.withLabel(`graph:actions:${id}`));\n });\n\n private readonly _json = Rx.family<string, Rx.Rx<any>>((id) => {\n return Rx.make((get) => {\n const toJSON = (node: Node, seen: string[] = []): any => {\n const nodes = get(this.connections(node.id));\n const obj: Record<string, any> = {\n id: node.id.length > 32 ? `${node.id.slice(0, 32)}...` : node.id,\n type: node.type,\n };\n if (node.properties.label) {\n obj.label = node.properties.label;\n }\n if (nodes.length) {\n obj.nodes = nodes\n .map((n) => {\n // Break cycles.\n const nextSeen = [...seen, node.id];\n return nextSeen.includes(n.id) ? undefined : toJSON(n, nextSeen);\n })\n .filter(isNonNullable);\n }\n return obj;\n };\n\n const root = get(this.nodeOrThrow(id));\n return toJSON(root);\n }).pipe(Rx.withLabel(`graph:json:${id}`));\n });\n\n constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode }: GraphParams = {}) {\n this._registry = registry ?? Registry.make();\n this._onInitialize = onInitialize;\n this._onExpand = onExpand;\n this._onRemoveNode = onRemoveNode;\n\n if (nodes) {\n nodes.forEach((node) => {\n Record.set(this._initialNodes, node.id, this._constructNode(node));\n });\n }\n\n if (edges) {\n Object.entries(edges).forEach(([source, edges]) => {\n Record.set(this._initialEdges, source, edges);\n });\n }\n }\n\n toJSON(id = ROOT_ID) {\n return this._registry.get(this._json(id));\n }\n\n json(id = ROOT_ID) {\n return this._json(id);\n }\n\n node(id: string): Rx.Rx<Option.Option<Node>> {\n return this._node(id);\n }\n\n nodeOrThrow(id: string): Rx.Rx<Node> {\n return this._nodeOrThrow(id);\n }\n\n connections(id: string, relation: Relation = 'outbound'): Rx.Rx<Node[]> {\n return this._connections(`${id}$${relation}`);\n }\n\n actions(id: string) {\n return this._actions(id);\n }\n\n edges(id: string): Rx.Rx<Edges> {\n return this._edges(id);\n }\n\n get root() {\n return this.getNodeOrThrow(ROOT_ID);\n }\n\n getNode(id: string): Option.Option<Node> {\n return this._registry.get(this.node(id));\n }\n\n getNodeOrThrow(id: string): Node {\n return this._registry.get(this.nodeOrThrow(id));\n }\n\n getConnections(id: string, relation: Relation = 'outbound'): Node[] {\n return this._registry.get(this.connections(id, relation));\n }\n\n getActions(id: string): Node[] {\n return this._registry.get(this.actions(id));\n }\n\n getEdges(id: string): Edges {\n return this._registry.get(this.edges(id));\n }\n\n async initialize(id: string) {\n const initialized = Record.get(this._initialized, id).pipe(Option.getOrElse(() => false));\n log('initialize', { id, initialized });\n if (!initialized) {\n await this._onInitialize?.(id);\n Record.set(this._initialized, id, true);\n }\n }\n\n expand(id: string, relation: Relation = 'outbound'): void {\n const key = `${id}$${relation}`;\n const expanded = Record.get(this._expanded, key).pipe(Option.getOrElse(() => false));\n log('expand', { key, expanded });\n if (!expanded) {\n this._onExpand?.(id, relation);\n Record.set(this._expanded, key, true);\n }\n }\n\n addNodes(nodes: NodeArg<any, Record<string, any>>[]): void {\n Rx.batch(() => {\n nodes.map((node) => this.addNode(node));\n });\n }\n\n addNode({ nodes, edges, ...nodeArg }: NodeArg<any, Record<string, any>>): void {\n const { id, type, data = null, properties = {} } = nodeArg;\n const nodeRx = this._node(id);\n const node = this._registry.get(nodeRx);\n Option.match(node, {\n onSome: (node) => {\n const typeChanged = node.type !== type;\n const dataChanged = node.data !== data;\n const propertiesChanged = Object.keys(properties).some((key) => node.properties[key] !== properties[key]);\n log('existing node', { id, typeChanged, dataChanged, propertiesChanged });\n if (typeChanged || dataChanged || propertiesChanged) {\n log('updating node', { id, type, data, properties });\n const newNode = Option.some({ ...node, type, data, properties: { ...node.properties, ...properties } });\n this._registry.set(nodeRx, newNode);\n this.onNodeChanged.emit({ id, node: newNode });\n }\n },\n onNone: () => {\n log('new node', { id, type, data, properties });\n const newNode = this._constructNode({ id, type, data, properties });\n this._registry.set(nodeRx, newNode);\n this.onNodeChanged.emit({ id, node: newNode });\n },\n });\n\n if (nodes) {\n // Rx.batch(() => {\n this.addNodes(nodes);\n const _edges = nodes.map((node) => ({ source: id, target: node.id }));\n this.addEdges(_edges);\n // });\n }\n\n if (edges) {\n todo();\n }\n }\n\n removeNodes(ids: string[], edges = false): void {\n Rx.batch(() => {\n ids.map((id) => this.removeNode(id, edges));\n });\n }\n\n removeNode(id: string, edges = false): void {\n const nodeRx = this._node(id);\n // TODO(wittjosiah): Is there a way to mark these rx values for garbage collection?\n this._registry.set(nodeRx, Option.none());\n this.onNodeChanged.emit({ id, node: Option.none() });\n // TODO(wittjosiah): Reset expanded and initialized flags?\n\n if (edges) {\n const { inbound, outbound } = this._registry.get(this._edges(id));\n const edges = [\n ...inbound.map((source) => ({ source, target: id })),\n ...outbound.map((target) => ({ source: id, target })),\n ];\n this.removeEdges(edges);\n }\n\n this._onRemoveNode?.(id);\n }\n\n addEdges(edges: Edge[]): void {\n Rx.batch(() => {\n edges.map((edge) => this.addEdge(edge));\n });\n }\n\n addEdge(edgeArg: Edge): void {\n const sourceRx = this._edges(edgeArg.source);\n const source = this._registry.get(sourceRx);\n if (!source.outbound.includes(edgeArg.target)) {\n log('add outbound edge', { source: edgeArg.source, target: edgeArg.target });\n this._registry.set(sourceRx, { inbound: source.inbound, outbound: [...source.outbound, edgeArg.target] });\n }\n\n const targetRx = this._edges(edgeArg.target);\n const target = this._registry.get(targetRx);\n if (!target.inbound.includes(edgeArg.source)) {\n log('add inbound edge', { source: edgeArg.source, target: edgeArg.target });\n this._registry.set(targetRx, { inbound: [...target.inbound, edgeArg.source], outbound: target.outbound });\n }\n }\n\n removeEdges(edges: Edge[], removeOrphans = false): void {\n Rx.batch(() => {\n edges.map((edge) => this.removeEdge(edge, removeOrphans));\n });\n }\n\n removeEdge(edgeArg: Edge, removeOrphans = false): void {\n const sourceRx = this._edges(edgeArg.source);\n const source = this._registry.get(sourceRx);\n if (source.outbound.includes(edgeArg.target)) {\n this._registry.set(sourceRx, {\n inbound: source.inbound,\n outbound: source.outbound.filter((id) => id !== edgeArg.target),\n });\n }\n\n const targetRx = this._edges(edgeArg.target);\n const target = this._registry.get(targetRx);\n if (target.inbound.includes(edgeArg.source)) {\n this._registry.set(targetRx, {\n inbound: target.inbound.filter((id) => id !== edgeArg.source),\n outbound: target.outbound,\n });\n }\n\n if (removeOrphans) {\n const source = this._registry.get(sourceRx);\n const target = this._registry.get(targetRx);\n if (source.outbound.length === 0 && source.inbound.length === 0 && edgeArg.source !== ROOT_ID) {\n this.removeNodes([edgeArg.source]);\n }\n if (target.outbound.length === 0 && target.inbound.length === 0 && edgeArg.target !== ROOT_ID) {\n this.removeNodes([edgeArg.target]);\n }\n }\n }\n\n sortEdges(id: string, relation: Relation, order: string[]): void {\n const edgesRx = this._edges(id);\n const edges = this._registry.get(edgesRx);\n const unsorted = edges[relation].filter((id) => !order.includes(id)) ?? [];\n const sorted = order.filter((id) => edges[relation].includes(id)) ?? [];\n edges[relation].splice(0, edges[relation].length, ...[...sorted, ...unsorted]);\n this._registry.set(edgesRx, edges);\n }\n\n traverse({ visitor, source = ROOT_ID, relation = 'outbound' }: GraphTraversalOptions, path: string[] = []): void {\n // Break cycles.\n if (path.includes(source)) {\n return;\n }\n\n const node = this.getNodeOrThrow(source);\n const shouldContinue = visitor(node, [...path, source]);\n if (shouldContinue === false) {\n return;\n }\n\n Object.values(this.getConnections(source, relation)).forEach((child) =>\n this.traverse({ source: child.id, relation, visitor }, [...path, source]),\n );\n }\n\n getPath({ source = 'root', target }: { source?: string; target: string }): Option.Option<string[]> {\n return Function.pipe(\n this.getNode(source),\n Option.flatMap((node) => {\n let found: Option.Option<string[]> = Option.none();\n this.traverse({\n source: node.id,\n visitor: (node, path) => {\n if (Option.isSome(found)) {\n return false;\n }\n\n if (node.id === target) {\n found = Option.some(path);\n }\n },\n });\n\n return found;\n }),\n );\n }\n\n async waitForPath(\n params: { source?: string; target: string },\n { timeout = 5_000, interval = 500 }: { timeout?: number; interval?: number } = {},\n ): Promise<string[]> {\n const path = this.getPath(params);\n if (Option.isSome(path)) {\n return path.value;\n }\n\n const trigger = new Trigger<string[]>();\n const i = setInterval(() => {\n const path = this.getPath(params);\n if (Option.isSome(path)) {\n trigger.wake(path.value);\n }\n }, interval);\n\n return trigger.wait({ timeout }).finally(() => clearInterval(i));\n }\n\n /** @internal */\n _constructNode(node: NodeArg<any>): Option.Option<Node> {\n return Option.some({ [graphSymbol]: this, data: null, properties: {}, ...node });\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Registry, Rx } from '@effect-rx/rx-react';\nimport { effect } from '@preact/signals-core';\nimport * as Array from 'effect/Array';\nimport * as Function from 'effect/Function';\nimport * as Option from 'effect/Option';\nimport * as Record from 'effect/Record';\n\nimport { type CleanupFn, type MulticastObservable, type Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { type MaybePromise, type Position, byPosition, getDebugName, isNode, isNonNullable } from '@dxos/util';\n\nimport { ACTION_GROUP_TYPE, ACTION_TYPE, type ExpandableGraph, Graph, type GraphParams, ROOT_ID } from './graph';\nimport { type ActionData, type Node, type NodeArg, type Relation, actionGroupSymbol } from './node';\n\n/**\n * Graph builder extension for adding nodes to the graph based on a node id.\n */\nexport type ResolverExtension = (id: string) => Rx.Rx<NodeArg<any> | null>;\n\n/**\n * Graph builder extension for adding nodes to the graph based on a connection to an existing node.\n *\n * @param params.node The existing node the returned nodes will be connected to.\n */\nexport type ConnectorExtension = (node: Rx.Rx<Option.Option<Node>>) => Rx.Rx<NodeArg<any>[]>;\n\n/**\n * Constrained case of the connector extension for more easily adding actions to the graph.\n */\nexport type ActionsExtension = (\n node: Rx.Rx<Option.Option<Node>>,\n) => Rx.Rx<Omit<NodeArg<ActionData>, 'type' | 'nodes' | 'edges'>[]>;\n\n/**\n * Constrained case of the connector extension for more easily adding action groups to the graph.\n */\nexport type ActionGroupsExtension = (\n node: Rx.Rx<Option.Option<Node>>,\n) => Rx.Rx<Omit<NodeArg<typeof actionGroupSymbol>, 'type' | 'data' | 'nodes' | 'edges'>[]>;\n\n/**\n * A graph builder extension is used to add nodes to the graph.\n *\n * @param params.id The unique id of the extension.\n * @param params.relation The relation the graph is being expanded from the existing node.\n * @param params.position Affects the order the extensions are processed in.\n * @param params.resolver A function to add nodes to the graph based on just the node id.\n * @param params.connector A function to add nodes to the graph based on a connection to an existing node.\n * @param params.actions A function to add actions to the graph based on a connection to an existing node.\n * @param params.actionGroups A function to add action groups to the graph based on a connection to an existing node.\n */\nexport type CreateExtensionOptions = {\n id: string;\n relation?: Relation;\n position?: Position;\n resolver?: ResolverExtension;\n connector?: ConnectorExtension;\n actions?: ActionsExtension;\n actionGroups?: ActionGroupsExtension;\n};\n\n/**\n * Create a graph builder extension.\n */\nexport const createExtension = (extension: CreateExtensionOptions): BuilderExtension[] => {\n const {\n id,\n position = 'static',\n relation = 'outbound',\n resolver: _resolver,\n connector: _connector,\n actions: _actions,\n actionGroups: _actionGroups,\n } = extension;\n const getId = (key: string) => `${id}/${key}`;\n\n const resolver =\n _resolver && Rx.family((id: string) => _resolver(id).pipe(Rx.withLabel(`graph-builder:_resolver:${id}`)));\n\n const connector =\n _connector &&\n Rx.family((node: Rx.Rx<Option.Option<Node>>) =>\n _connector(node).pipe(Rx.withLabel(`graph-builder:_connector:${id}`)),\n );\n\n const actionGroups =\n _actionGroups &&\n Rx.family((node: Rx.Rx<Option.Option<Node>>) =>\n _actionGroups(node).pipe(Rx.withLabel(`graph-builder:_actionGroups:${id}`)),\n );\n\n const actions =\n _actions &&\n Rx.family((node: Rx.Rx<Option.Option<Node>>) => _actions(node).pipe(Rx.withLabel(`graph-builder:_actions:${id}`)));\n\n return [\n resolver ? { id: getId('resolver'), position, resolver } : undefined,\n connector\n ? ({\n id: getId('connector'),\n position,\n relation,\n connector: Rx.family((node) =>\n Rx.make((get) => {\n try {\n return get(connector(node));\n } catch {\n log.warn('Error in connector', { id: getId('connector'), node });\n return [];\n }\n }).pipe(Rx.withLabel(`graph-builder:connector:${id}`)),\n ),\n } satisfies BuilderExtension)\n : undefined,\n actionGroups\n ? ({\n id: getId('actionGroups'),\n position,\n relation: 'outbound',\n connector: Rx.family((node) =>\n Rx.make((get) => {\n try {\n return get(actionGroups(node)).map((arg) => ({\n ...arg,\n data: actionGroupSymbol,\n type: ACTION_GROUP_TYPE,\n }));\n } catch {\n log.warn('Error in actionGroups', { id: getId('actionGroups'), node });\n return [];\n }\n }).pipe(Rx.withLabel(`graph-builder:connector:actionGroups:${id}`)),\n ),\n } satisfies BuilderExtension)\n : undefined,\n actions\n ? ({\n id: getId('actions'),\n position,\n relation: 'outbound',\n connector: Rx.family((node) =>\n Rx.make((get) => {\n try {\n return get(actions(node)).map((arg) => ({ ...arg, type: ACTION_TYPE }));\n } catch {\n log.warn('Error in actions', { id: getId('actions'), node });\n return [];\n }\n }).pipe(Rx.withLabel(`graph-builder:connector:actions:${id}`)),\n ),\n } satisfies BuilderExtension)\n : undefined,\n ].filter(isNonNullable);\n};\n\nexport type GraphBuilderTraverseOptions = {\n visitor: (node: Node, path: string[]) => MaybePromise<boolean | void>;\n registry?: Registry.Registry;\n source?: string;\n relation?: Relation;\n};\n\nexport type BuilderExtension = Readonly<{\n id: string;\n position: Position;\n relation?: Relation; // Only for connector.\n resolver?: ResolverExtension;\n connector?: (node: Rx.Rx<Option.Option<Node>>) => Rx.Rx<NodeArg<any>[]>;\n}>;\n\nexport type BuilderExtensions = BuilderExtension | BuilderExtension[] | BuilderExtensions[];\n\nexport const flattenExtensions = (extension: BuilderExtensions, acc: BuilderExtension[] = []): BuilderExtension[] => {\n if (Array.isArray(extension)) {\n return [...acc, ...extension.flatMap((ext) => flattenExtensions(ext, acc))];\n } else {\n return [...acc, extension];\n }\n};\n\n/**\n * The builder provides an extensible way to compose the construction of the graph.\n */\n// TODO(wittjosiah): Add api for setting subscription set and/or radius.\n// Should unsubscribe from nodes that are not in the set/radius.\n// Should track LRU nodes that are not in the set/radius and remove them beyond a certain threshold.\nexport class GraphBuilder {\n // TODO(wittjosiah): Use Context.\n private readonly _subscriptions = new Map<string, CleanupFn>();\n private readonly _extensions = Rx.make(Record.empty<string, BuilderExtension>()).pipe(\n Rx.keepAlive,\n Rx.withLabel('graph-builder:extensions'),\n );\n private readonly _initialized: Record<string, Trigger> = {};\n private readonly _registry: Registry.Registry;\n private readonly _graph: Graph;\n\n constructor({ registry, ...params }: Pick<GraphParams, 'registry' | 'nodes' | 'edges'> = {}) {\n this._registry = registry ?? Registry.make();\n this._graph = new Graph({\n ...params,\n registry: this._registry,\n onExpand: (id, relation) => this._onExpand(id, relation),\n onInitialize: (id) => this._onInitialize(id),\n onRemoveNode: (id) => this._onRemoveNode(id),\n });\n }\n\n static from(pickle?: string, registry?: Registry.Registry): GraphBuilder {\n if (!pickle) {\n return new GraphBuilder({ registry });\n }\n\n const { nodes, edges } = JSON.parse(pickle);\n return new GraphBuilder({ nodes, edges, registry });\n }\n\n get graph(): ExpandableGraph {\n return this._graph;\n }\n\n get extensions() {\n return this._extensions;\n }\n\n addExtension(extensions: BuilderExtensions): GraphBuilder {\n flattenExtensions(extensions).forEach((extension) => {\n const extensions = this._registry.get(this._extensions);\n this._registry.set(this._extensions, Record.set(extensions, extension.id, extension));\n });\n return this;\n }\n\n removeExtension(id: string): GraphBuilder {\n const extensions = this._registry.get(this._extensions);\n this._registry.set(this._extensions, Record.remove(extensions, id));\n return this;\n }\n\n async explore(\n // TODO(wittjosiah): Currently defaulting to new registry.\n // Currently unsure about how to handle nodes which are expanded in the background.\n // This seems like a good place to start.\n { registry = Registry.make(), source = ROOT_ID, relation = 'outbound', visitor }: GraphBuilderTraverseOptions,\n path: string[] = [],\n ): Promise<void> {\n // Break cycles.\n if (path.includes(source)) {\n return;\n }\n\n // TODO(wittjosiah): This is a workaround for esm not working in the test runner.\n // Switching to vitest is blocked by having node esm versions of echo-schema & echo-signals.\n if (!isNode()) {\n const { yieldOrContinue } = await import('main-thread-scheduling');\n await yieldOrContinue('idle');\n }\n\n const node = registry.get(this._graph.nodeOrThrow(source));\n const shouldContinue = await visitor(node, [...path, node.id]);\n if (shouldContinue === false) {\n return;\n }\n\n const nodes = Object.values(this._registry.get(this._extensions))\n .filter((extension) => relation === (extension.relation ?? 'outbound'))\n .map((extension) => extension.connector)\n .filter(isNonNullable)\n .flatMap((connector) => registry.get(connector(this._graph.node(source))));\n\n await Promise.all(\n nodes.map((nodeArg) => {\n registry.set(this._graph._node(nodeArg.id), this._graph._constructNode(nodeArg));\n return this.explore({ registry, source: nodeArg.id, relation, visitor }, [...path, node.id]);\n }),\n );\n\n if (registry !== this._registry) {\n registry.reset();\n registry.dispose();\n }\n }\n\n destroy(): void {\n this._subscriptions.forEach((unsubscribe) => unsubscribe());\n this._subscriptions.clear();\n }\n\n private readonly _resolvers = Rx.family<string, Rx.Rx<Option.Option<NodeArg<any>>>>((id) => {\n return Rx.make((get) => {\n return Function.pipe(\n get(this._extensions),\n Record.values,\n Array.sortBy(byPosition),\n Array.map(({ resolver }) => resolver),\n Array.filter(isNonNullable),\n Array.map((resolver) => get(resolver(id))),\n Array.filter(isNonNullable),\n Array.head,\n );\n });\n });\n\n private readonly _connectors = Rx.family<string, Rx.Rx<NodeArg<any>[]>>((key) => {\n return Rx.make((get) => {\n const [id, relation] = key.split('+');\n const node = this._graph.node(id);\n\n return Function.pipe(\n get(this._extensions),\n Record.values,\n // TODO(wittjosiah): Sort on write rather than read.\n Array.sortBy(byPosition),\n Array.filter(({ relation: _relation = 'outbound' }) => _relation === relation),\n Array.map(({ connector }) => connector?.(node)),\n Array.filter(isNonNullable),\n Array.flatMap((result) => get(result)),\n );\n }).pipe(Rx.withLabel(`graph-builder:connectors:${key}`));\n });\n\n private _onExpand(id: string, relation: Relation): void {\n log('onExpand', { id, relation, registry: getDebugName(this._registry) });\n const connectors = this._connectors(`${id}+${relation}`);\n\n let previous: string[] = [];\n const cancel = this._registry.subscribe(\n connectors,\n (nodes) => {\n const ids = nodes.map((n) => n.id);\n const removed = previous.filter((id) => !ids.includes(id));\n previous = ids;\n\n log('update', { id, relation, ids, removed });\n const update = () => {\n Rx.batch(() => {\n this._graph.removeEdges(\n removed.map((target) => ({ source: id, target })),\n true,\n );\n this._graph.addNodes(nodes);\n this._graph.addEdges(\n nodes.map((node) =>\n relation === 'outbound' ? { source: id, target: node.id } : { source: node.id, target: id },\n ),\n );\n this._graph.sortEdges(\n id,\n relation,\n nodes.map(({ id }) => id),\n );\n });\n };\n\n // TODO(wittjosiah): Remove `requestAnimationFrame` once we have a better solution.\n // This is a workaround to avoid a race condition where the graph is updated during React render.\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(update);\n } else {\n update();\n }\n },\n { immediate: true },\n );\n\n this._subscriptions.set(id, cancel);\n }\n\n // TODO(wittjosiah): If the same node is added by a connector, the resolver should probably cancel itself?\n private async _onInitialize(id: string) {\n log('onInitialize', { id });\n const resolver = this._resolvers(id);\n\n const cancel = this._registry.subscribe(\n resolver,\n (node) => {\n const trigger = this._initialized[id];\n Option.match(node, {\n onSome: (node) => {\n this._graph.addNodes([node]);\n trigger?.wake();\n },\n onNone: () => {\n trigger?.wake();\n this._graph.removeNodes([id]);\n },\n });\n },\n { immediate: true },\n );\n\n this._subscriptions.set(id, cancel);\n }\n\n private _onRemoveNode(id: string): void {\n this._subscriptions.get(id)?.();\n this._subscriptions.delete(id);\n }\n}\n\n/**\n * Creates an Rx.Rx<T> from a callback which accesses signals.\n * Will return a new rx instance each time.\n */\nexport const rxFromSignal = <T>(cb: () => T): Rx.Rx<T> => {\n return Rx.make((get) => {\n const dispose = effect(() => {\n get.setSelf(cb());\n });\n\n get.addFinalizer(() => dispose());\n\n return cb();\n });\n};\n\nconst observableFamily = Rx.family((observable: MulticastObservable<any>) => {\n return Rx.make((get) => {\n const subscription = observable.subscribe((value) => get.setSelf(value));\n\n get.addFinalizer(() => subscription.unsubscribe());\n\n return observable.get();\n });\n});\n\n/**\n * Creates an Rx.Rx<T> from a MulticastObservable<T>\n * Will return the same rx instance for the same observable.\n */\nexport const rxFromObservable = <T>(observable: MulticastObservable<T>): Rx.Rx<T> => {\n return observableFamily(observable) as Rx.Rx<T>;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type MakeOptional, type MaybePromise } from '@dxos/util';\n\nimport { ACTION_GROUP_TYPE, ACTION_TYPE } from './graph';\n\n/**\n * Represents a node in the graph.\n */\n// TODO(wittjosiah): Use Effect Schema.\n// TODO(burdon): Rename GraphNode. Node is already in the global namespace.\nexport type Node<TData = any, TProperties extends Record<string, any> = Record<string, any>> = Readonly<{\n /**\n * Globally unique ID.\n */\n // TODO(burdon): Allow string array, which is concatenated.\n id: string;\n\n /**\n * Typename of the data the node represents.\n */\n type: string;\n\n /**\n * Keys in of the properties which should be cached.\n * If defined, the node will be included in the cache.\n * If undefined, the node will not be included in the cache.\n */\n cacheable?: string[];\n\n /**\n * Properties of the node relevant to displaying the node.\n */\n properties: Readonly<TProperties>;\n\n /**\n * Data the node represents.\n */\n // TODO(burdon): Type system (e.g., minimally provide identifier string vs. TypedObject vs. Graph mixin type system)?\n // type field would prevent convoluted sniffing of object properties. And allow direct pass-through for ECHO TypedObjects.\n data: TData;\n}>;\n\nexport type NodeFilter<TData = any, TProperties extends Record<string, any> = Record<string, any>> = (\n node: Node<unknown, Record<string, any>>,\n connectedNode: Node,\n) => node is Node<TData, TProperties>;\n\nexport type Relation = 'outbound' | 'inbound';\n\nexport const isGraphNode = (data: unknown): data is Node =>\n data && typeof data === 'object' && 'id' in data && 'properties' in data && data.properties\n ? typeof data.properties === 'object' && 'data' in data\n : false;\n\nexport type NodeArg<TData, TProperties extends Record<string, any> = Record<string, any>> = MakeOptional<\n Node<TData, TProperties>,\n 'data' | 'properties' | 'cacheable'\n> & {\n /** Will automatically add nodes with an edge from this node to each. */\n nodes?: NodeArg<unknown>[];\n\n /** Will automatically add specified edges. */\n edges?: [string, Relation][];\n};\n\n//\n// Actions\n//\n\nexport type InvokeParams = {\n /** Node the invoked action is connected to. */\n parent?: Node;\n\n caller?: string;\n};\n\nexport type ActionData = (params?: InvokeParams) => MaybePromise<void>;\n\nexport type Action<TProperties extends Record<string, any> = Record<string, any>> = Readonly<\n Omit<Node<ActionData, TProperties>, 'properties'> & {\n properties: Readonly<TProperties>;\n }\n>;\n\nexport const isAction = (data: unknown): data is Action =>\n isGraphNode(data) ? typeof data.data === 'function' && data.type === ACTION_TYPE : false;\n\nexport const actionGroupSymbol = Symbol('ActionGroup');\n\nexport type ActionGroup<TProperties extends Record<string, any> = Record<string, any>> = Readonly<\n Omit<Node<typeof actionGroupSymbol, TProperties>, 'properties'> & {\n properties: Readonly<TProperties>;\n }\n>;\n\nexport const isActionGroup = (data: unknown): data is ActionGroup =>\n isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ACTION_GROUP_TYPE : false;\n\nexport type ActionLike = Action | ActionGroup;\n\nexport const isActionLike = (data: unknown): data is Action | ActionGroup => isAction(data) || isActionGroup(data);\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["
|
|
3
|
+
"sources": ["../../../src/atoms.ts", "../../../src/graph.ts", "../../../src/node.ts", "../../../src/util.ts", "../../../src/graph-builder.ts", "../../../src/node-matcher.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom } from '@effect-atom/atom-react';\n\nimport { type MulticastObservable } from '@dxos/async';\n\nconst observableFamily = Atom.family((observable: MulticastObservable<any>) => {\n return Atom.make((get) => {\n const subscription = observable.subscribe((value) => get.setSelf(value));\n\n get.addFinalizer(() => subscription.unsubscribe());\n\n return observable.get();\n });\n});\n\n/**\n * Creates an Atom.Atom<T> from a MulticastObservable<T>\n * Will return the same atom instance for the same observable.\n */\nexport const fromObservable = <T>(observable: MulticastObservable<T>): Atom.Atom<T> => {\n return observableFamily(observable) as Atom.Atom<T>;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { Atom, Registry } from '@effect-atom/atom-react';\nimport * as Function from 'effect/Function';\nimport * as Option from 'effect/Option';\nimport * as Pipeable from 'effect/Pipeable';\nimport * as Record from 'effect/Record';\n\nimport { Event, Trigger } from '@dxos/async';\nimport { todo } from '@dxos/debug';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { type MakeOptional, isNonNullable } from '@dxos/util';\n\nimport * as Node from './node';\nimport { Separators, normalizeRelation, shallowEqual } from './util';\n\nconst graphSymbol = Symbol('graph');\n\ntype DeepWriteable<T> = {\n -readonly [K in keyof T]: T[K] extends object ? DeepWriteable<T[K]> : T[K];\n};\n\ntype NodeInternal = DeepWriteable<Node.Node> & { [graphSymbol]: GraphImpl };\n\n/**\n * Get the Graph a Node is currently associated with.\n */\nexport const getGraph = (node: Node.Node): Graph => {\n const graph = (node as NodeInternal)[graphSymbol];\n invariant(graph, 'Node is not associated with a graph.');\n return graph as Graph;\n};\n\nexport type GraphTraversalOptions = {\n /**\n * A callback which is called for each node visited during traversal.\n *\n * If the callback returns `false`, traversal is stops recursing.\n */\n visitor: (node: Node.Node, path: string[]) => boolean | void;\n\n /**\n * The node to start traversing from.\n *\n * @default ROOT_ID\n */\n source?: string;\n\n /** The relation to traverse graph edges. */\n relation: Node.RelationInput;\n};\n\nexport type GraphProps = {\n registry?: Registry.Registry;\n nodes?: MakeOptional<Node.Node, 'data' | 'cacheable'>[];\n edges?: Record<string, Edges>;\n onExpand?: (id: string, relation: Node.Relation) => void;\n onInitialize?: (id: string) => Promise<void>;\n onRemoveNode?: (id: string) => void;\n};\n\nexport type Edge = { source: string; target: string; relation: Node.RelationInput };\nexport type Edges = Record<string, string[]>;\n\n/**\n * Identifier denoting a Graph.\n */\nexport const GraphTypeId: unique symbol = Symbol.for('@dxos/app-graph/Graph');\nexport type GraphTypeId = typeof GraphTypeId;\n\n/**\n * Identifier for the graph kind discriminator.\n */\nexport const GraphKind: unique symbol = Symbol.for('@dxos/app-graph/GraphKind');\nexport type GraphKind = typeof GraphKind;\n\nexport type GraphKindType = 'readable' | 'expandable' | 'writable';\n\nexport interface BaseGraph extends Pipeable.Pipeable {\n readonly [GraphTypeId]: GraphTypeId;\n readonly [GraphKind]: GraphKindType;\n /**\n * Event emitted when a node is changed.\n */\n readonly onNodeChanged: Event<{ id: string; node: Option.Option<Node.Node> }>;\n /**\n * Get the atom key for the JSON representation of the graph.\n */\n json(id?: string): Atom.Atom<any>;\n /**\n * Get the atom key for the node with the given id.\n */\n node(id: string): Atom.Atom<Option.Option<Node.Node>>;\n /**\n * Get the atom key for the node with the given id.\n */\n nodeOrThrow(id: string): Atom.Atom<Node.Node>;\n /**\n * Get the atom key for the connections of the node with the given id.\n */\n connections(id: string, relation: Node.RelationInput): Atom.Atom<Node.Node[]>;\n /**\n * Get the atom key for the actions of the node with the given id.\n */\n actions(id: string): Atom.Atom<(Node.Action | Node.ActionGroup)[]>;\n /**\n * Get the atom key for the edges of the node with the given id.\n */\n edges(id: string): Atom.Atom<Edges>;\n}\n\nexport type ReadableGraph = BaseGraph & { readonly [GraphKind]: 'readable' | 'expandable' | 'writable' };\nexport type ExpandableGraph = BaseGraph & { readonly [GraphKind]: 'expandable' | 'writable' };\nexport type WritableGraph = BaseGraph & { readonly [GraphKind]: 'writable' };\n\n/**\n * Graph interface.\n */\nexport type Graph = WritableGraph;\n\n/**\n * The Graph represents the user interface information architecture of the application constructed via plugins.\n * @internal\n */\nclass GraphImpl implements WritableGraph {\n readonly [GraphTypeId]: GraphTypeId = GraphTypeId;\n readonly [GraphKind] = 'writable' as const;\n\n pipe() {\n // eslint-disable-next-line prefer-rest-params\n return Pipeable.pipeArguments(this, arguments);\n }\n\n readonly onNodeChanged = new Event<{\n id: string;\n node: Option.Option<Node.Node>;\n }>();\n\n readonly _onExpand?: GraphProps['onExpand'];\n readonly _onInitialize?: GraphProps['onInitialize'];\n readonly _onRemoveNode?: GraphProps['onRemoveNode'];\n\n readonly _registry: Registry.Registry;\n readonly _expanded = Record.empty<string, boolean>();\n readonly _pendingExpands = new Set<string>();\n readonly _initialized = Record.empty<string, boolean>();\n readonly _initialEdges = Record.empty<string, Edges>();\n readonly _initialNodes = Record.fromEntries([\n [\n Node.RootId,\n this._constructNode({\n id: Node.RootId,\n type: Node.RootType,\n data: null,\n properties: {},\n }),\n ],\n ]);\n\n /** @internal */\n readonly _node = Atom.family<string, Atom.Writable<Option.Option<Node.Node>>>((id) => {\n const initial = Option.flatten(Record.get(this._initialNodes, id));\n return Atom.make<Option.Option<Node.Node>>(initial).pipe(Atom.keepAlive, Atom.withLabel(`graph:node:${id}`));\n });\n\n readonly _nodeOrThrow = Atom.family<string, Atom.Atom<Node.Node>>((id) => {\n return Atom.make((get) => {\n const node = get(this._node(id));\n invariant(Option.isSome(node), `Node not available: ${id}`);\n return node.value;\n });\n });\n\n readonly _edges = Atom.family<string, Atom.Writable<Edges>>((id) => {\n const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({}) as Edges));\n return Atom.make<Edges>(initial).pipe(Atom.keepAlive, Atom.withLabel(`graph:edges:${id}`));\n });\n\n // NOTE: Currently the argument to the family needs to be referentially stable for the atom to be referentially stable.\n // TODO(wittjosiah): Atom feature request, support for something akin to `ComplexMap` to allow for complex arguments.\n readonly _connections = Atom.family<string, Atom.Atom<Node.Node[]>>((key) => {\n return Atom.make((get) => {\n const { id, relation } = relationFromConnectionKey(key);\n const edges = get(this._edges(id));\n return (edges[relationKey(relation)] ?? [])\n .map((id) => get(this._node(id)))\n .filter(Option.isSome)\n .map((o) => o.value);\n }).pipe(Atom.withLabel(`graph:connections:${key}`));\n });\n\n readonly _actions = Atom.family<string, Atom.Atom<(Node.Action | Node.ActionGroup)[]>>((id) => {\n return Atom.make((get) => {\n return get(this._connections(connectionKey(id, Node.actionRelation()))) as (Node.Action | Node.ActionGroup)[];\n }).pipe(Atom.withLabel(`graph:actions:${id}`));\n });\n\n readonly _json = Atom.family<string, Atom.Atom<any>>((id) => {\n return Atom.make((get) => {\n const toJSON = (node: Node.Node, seen: string[] = []): any => {\n const nodes = get(this._connections(connectionKey(node.id, 'child')));\n const obj: Record<string, any> = {\n id: node.id,\n type: node.type,\n };\n if (node.properties.label) {\n obj.label = node.properties.label;\n }\n if (nodes.length) {\n obj.nodes = nodes\n .map((n: Node.Node) => {\n // Break cycles.\n const nextSeen = [...seen, node.id];\n return nextSeen.includes(n.id) ? undefined : toJSON(n, nextSeen);\n })\n .filter(isNonNullable);\n }\n return obj;\n };\n\n const root = get(this._nodeOrThrow(id));\n return toJSON(root);\n }).pipe(Atom.withLabel(`graph:json:${id}`));\n });\n\n constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode }: GraphProps = {}) {\n this._registry = registry ?? Registry.make();\n this._onInitialize = onInitialize;\n this._onExpand = onExpand;\n this._onRemoveNode = onRemoveNode;\n\n if (nodes) {\n nodes.forEach((node) => {\n Record.set(this._initialNodes, node.id, this._constructNode(node));\n });\n }\n\n if (edges) {\n Object.entries(edges).forEach(([source, edges]) => {\n Record.set(this._initialEdges, source, edges);\n });\n }\n }\n\n json(id = Node.RootId): Atom.Atom<any> {\n return jsonImpl(this, id);\n }\n\n node(id: string): Atom.Atom<Option.Option<Node.Node>> {\n return nodeImpl(this, id);\n }\n\n nodeOrThrow(id: string): Atom.Atom<Node.Node> {\n return nodeOrThrowImpl(this, id);\n }\n\n connections(id: string, relation: Node.RelationInput): Atom.Atom<Node.Node[]> {\n return connectionsImpl(this, id, relation);\n }\n\n actions(id: string): Atom.Atom<(Node.Action | Node.ActionGroup)[]> {\n return actionsImpl(this, id);\n }\n\n edges(id: string): Atom.Atom<Edges> {\n return edgesImpl(this, id);\n }\n\n /** @internal */\n _constructNode(node: Node.NodeArg<any>): Option.Option<Node.Node> {\n return Option.some({\n [graphSymbol]: this,\n data: null,\n properties: {},\n ...node,\n });\n }\n}\n\n/**\n * Internal helper to access GraphImpl internals.\n * @internal\n */\nconst getInternal = (graph: BaseGraph): GraphImpl => {\n return graph as unknown as GraphImpl;\n};\n\n/**\n * Convert the graph to a JSON object.\n */\nexport const toJSON = (graph: BaseGraph, id = Node.RootId): object => {\n const internal = getInternal(graph);\n return internal._registry.get(internal._json(id));\n};\n\n/**\n * Implementation helper for json.\n */\nconst jsonImpl = (graph: BaseGraph, id = Node.RootId): Atom.Atom<any> => {\n const internal = getInternal(graph);\n return internal._json(id);\n};\n\n/**\n * Implementation helper for node.\n */\nconst nodeImpl = (graph: BaseGraph, id: string): Atom.Atom<Option.Option<Node.Node>> => {\n const internal = getInternal(graph);\n return internal._node(id);\n};\n\n/**\n * Implementation helper for nodeOrThrow.\n */\nconst nodeOrThrowImpl = (graph: BaseGraph, id: string): Atom.Atom<Node.Node> => {\n const internal = getInternal(graph);\n return internal._nodeOrThrow(id);\n};\n\n/**\n * Implementation helper for connections.\n */\nconst connectionsImpl = (graph: BaseGraph, id: string, relation: Node.RelationInput): Atom.Atom<Node.Node[]> => {\n const internal = getInternal(graph);\n return internal._connections(connectionKey(id, relation));\n};\n\n/**\n * Implementation helper for actions.\n */\nconst actionsImpl = (graph: BaseGraph, id: string): Atom.Atom<(Node.Action | Node.ActionGroup)[]> => {\n const internal = getInternal(graph);\n return internal._actions(id);\n};\n\n/**\n * Implementation helper for edges.\n */\nconst edgesImpl = (graph: BaseGraph, id: string): Atom.Atom<Edges> => {\n const internal = getInternal(graph);\n return internal._edges(id);\n};\n\n/**\n * Implementation helper for getNode.\n */\nconst getNodeImpl = (graph: BaseGraph, id: string): Option.Option<Node.Node> => {\n const internal = getInternal(graph);\n return internal._registry.get(nodeImpl(graph, id));\n};\n\n/**\n * Get the node with the given id from the graph's registry.\n */\nexport function getNode(graph: BaseGraph, id: string): Option.Option<Node.Node>;\nexport function getNode(id: string): (graph: BaseGraph) => Option.Option<Node.Node>;\nexport function getNode(\n graphOrId: BaseGraph | string,\n id?: string,\n): Option.Option<Node.Node> | ((graph: BaseGraph) => Option.Option<Node.Node>) {\n if (typeof graphOrId === 'string') {\n // Curried: getNode(id)\n const id = graphOrId;\n return (graph: BaseGraph) => getNodeImpl(graph, id);\n } else {\n // Direct: getNode(graph, id)\n const graph = graphOrId;\n return getNodeImpl(graph, id!);\n }\n}\n\n/**\n * Implementation helper for getNodeOrThrow.\n */\nconst getNodeOrThrowImpl = (graph: BaseGraph, id: string): Node.Node => {\n const internal = getInternal(graph);\n return internal._registry.get(nodeOrThrowImpl(graph, id));\n};\n\n/**\n * Get the node with the given id from the graph's registry.\n *\n * @throws If the node is Option.none().\n */\nexport function getNodeOrThrow(graph: BaseGraph, id: string): Node.Node;\nexport function getNodeOrThrow(id: string): (graph: BaseGraph) => Node.Node;\nexport function getNodeOrThrow(\n graphOrId: BaseGraph | string,\n id?: string,\n): Node.Node | ((graph: BaseGraph) => Node.Node) {\n if (typeof graphOrId === 'string') {\n // Curried: getNodeOrThrow(id)\n const id = graphOrId;\n return (graph: BaseGraph) => getNodeOrThrowImpl(graph, id);\n } else {\n // Direct: getNodeOrThrow(graph, id)\n const graph = graphOrId;\n return getNodeOrThrowImpl(graph, id!);\n }\n}\n\n/**\n * Get the root node of the graph.\n * This is an alias for `getNodeOrThrow(graph, ROOT_ID)`.\n */\nexport function getRoot(graph: BaseGraph): Node.Node {\n return getNodeOrThrowImpl(graph, Node.RootId);\n}\n\n/**\n * Implementation helper for getConnections.\n */\nconst getConnectionsImpl = (graph: BaseGraph, id: string, relation: Node.RelationInput): Node.Node[] => {\n const internal = getInternal(graph);\n return internal._registry.get(connectionsImpl(graph, id, relation));\n};\n\n/**\n * Get all nodes connected to the node with the given id by the given relation from the graph's registry.\n */\nexport function getConnections(graph: BaseGraph, id: string, relation: Node.RelationInput): Node.Node[];\nexport function getConnections(id: string, relation: Node.RelationInput): (graph: BaseGraph) => Node.Node[];\nexport function getConnections(\n graphOrId: BaseGraph | string,\n idOrRelation: string | Node.RelationInput,\n relation?: Node.RelationInput,\n): Node.Node[] | ((graph: BaseGraph) => Node.Node[]) {\n if (typeof graphOrId === 'string') {\n // Curried: getConnections(id, relation)\n const id = graphOrId;\n const rel = idOrRelation as Node.RelationInput;\n return (graph: BaseGraph) => getConnectionsImpl(graph, id, rel);\n } else {\n // Direct: getConnections(graph, id, relation)\n const graph = graphOrId;\n const id = idOrRelation as string;\n invariant(relation !== undefined, 'Relation is required.');\n const rel = relation;\n return getConnectionsImpl(graph, id, rel);\n }\n}\n\n/**\n * Implementation helper for getActions.\n */\nconst getActionsImpl = (graph: BaseGraph, id: string): Node.Node[] => {\n const internal = getInternal(graph);\n return internal._registry.get(actionsImpl(graph, id));\n};\n\n/**\n * Get all actions connected to the node with the given id from the graph's registry.\n */\nexport function getActions(graph: BaseGraph, id: string): Node.Node[];\nexport function getActions(id: string): (graph: BaseGraph) => Node.Node[];\nexport function getActions(\n graphOrId: BaseGraph | string,\n id?: string,\n): Node.Node[] | ((graph: BaseGraph) => Node.Node[]) {\n if (typeof graphOrId === 'string') {\n // Curried: getActions(id)\n const id = graphOrId;\n return (graph: BaseGraph) => getActionsImpl(graph, id);\n } else {\n // Direct: getActions(graph, id)\n const graph = graphOrId;\n return getActionsImpl(graph, id!);\n }\n}\n\n/**\n * Implementation helper for getEdges.\n */\nconst getEdgesImpl = (graph: BaseGraph, id: string): Edges => {\n const internal = getInternal(graph);\n return internal._registry.get(edgesImpl(graph, id));\n};\n\n/**\n * Get the edges from the node with the given id from the graph's registry.\n */\nexport function getEdges(graph: BaseGraph, id: string): Edges;\nexport function getEdges(id: string): (graph: BaseGraph) => Edges;\nexport function getEdges(graphOrId: BaseGraph | string, id?: string): Edges | ((graph: BaseGraph) => Edges) {\n if (typeof graphOrId === 'string') {\n // Curried: getEdges(id)\n const id = graphOrId;\n return (graph: BaseGraph) => getEdgesImpl(graph, id);\n } else {\n // Direct: getEdges(graph, id)\n const graph = graphOrId;\n return getEdgesImpl(graph, id!);\n }\n}\n\n/**\n * Recursive depth-first traversal of the graph.\n */\n/**\n * Implementation helper for traverse.\n */\nconst traverseImpl = (graph: BaseGraph, options: GraphTraversalOptions, path: string[] = []): void => {\n const { visitor, source = Node.RootId, relation } = options;\n // Break cycles.\n if (path.includes(source)) {\n return;\n }\n\n const node = getNodeOrThrow(graph, source);\n const shouldContinue = visitor(node, [...path, source]);\n if (shouldContinue === false) {\n return;\n }\n\n Object.values(getConnections(graph, source, relation)).forEach((child) =>\n traverseImpl(graph, { source: child.id, relation, visitor }, [...path, source]),\n );\n};\n\n/**\n * Traverse the graph with the given options.\n */\nexport function traverse(graph: BaseGraph, options: GraphTraversalOptions, path?: string[]): void;\nexport function traverse(options: GraphTraversalOptions, path?: string[]): (graph: BaseGraph) => void;\nexport function traverse(\n graphOrOptions: BaseGraph | GraphTraversalOptions,\n optionsOrPath?: GraphTraversalOptions | string[],\n path?: string[],\n): void | ((graph: BaseGraph) => void) {\n if (typeof graphOrOptions === 'object' && 'visitor' in graphOrOptions) {\n // Curried: traverse(options, path?)\n const options = graphOrOptions as GraphTraversalOptions;\n const pathArg = Array.isArray(optionsOrPath) ? optionsOrPath : undefined;\n return (graph: BaseGraph) => traverseImpl(graph, options, pathArg);\n } else {\n // Direct: traverse(graph, options, path?)\n const graph = graphOrOptions as BaseGraph;\n const options = optionsOrPath as GraphTraversalOptions;\n const pathArg = path ?? (Array.isArray(optionsOrPath) ? optionsOrPath : undefined);\n return traverseImpl(graph, options, pathArg);\n }\n}\n\n/**\n * Implementation helper for getPath.\n */\nconst getPathImpl = (graph: BaseGraph, params: { source?: string; target: string }): Option.Option<string[]> => {\n return Function.pipe(\n getNode(graph, params.source ?? 'root'),\n Option.flatMap((node) => {\n let found: Option.Option<string[]> = Option.none();\n traverseImpl(graph, {\n source: node.id,\n relation: 'child',\n visitor: (node, path) => {\n if (Option.isSome(found)) {\n return false;\n }\n\n if (node.id === params.target) {\n found = Option.some(path);\n }\n },\n });\n\n return found;\n }),\n );\n};\n\n/**\n * Get the path between two nodes in the graph.\n */\nexport function getPath(graph: BaseGraph, params: { source?: string; target: string }): Option.Option<string[]>;\nexport function getPath(params: { source?: string; target: string }): (graph: BaseGraph) => Option.Option<string[]>;\nexport function getPath(\n graphOrParams: BaseGraph | { source?: string; target: string },\n params?: { source?: string; target: string },\n): Option.Option<string[]> | ((graph: BaseGraph) => Option.Option<string[]>) {\n if (params === undefined && typeof graphOrParams === 'object' && 'target' in graphOrParams) {\n // Curried: getPath(params)\n const params = graphOrParams as { source?: string; target: string };\n return (graph: BaseGraph) => getPathImpl(graph, params);\n } else {\n // Direct: getPath(graph, params)\n const graph = graphOrParams as BaseGraph;\n return getPathImpl(graph, params!);\n }\n}\n\n/**\n * Implementation helper for waitForPath.\n */\nconst waitForPathImpl = (\n graph: BaseGraph,\n params: { source?: string; target: string },\n options?: { timeout?: number; interval?: number },\n): Promise<string[]> => {\n const { timeout = 5_000, interval = 500 } = options ?? {};\n const path = getPathImpl(graph, params);\n if (Option.isSome(path)) {\n return Promise.resolve(path.value);\n }\n\n const trigger = new Trigger<string[]>();\n const i = setInterval(() => {\n const path = getPathImpl(graph, params);\n if (Option.isSome(path)) {\n trigger.wake(path.value);\n }\n }, interval);\n\n return trigger.wait({ timeout }).finally(() => clearInterval(i));\n};\n\n/**\n * Wait for the path between two nodes in the graph to be established.\n */\nexport function waitForPath(\n graph: BaseGraph,\n params: { source?: string; target: string },\n options?: { timeout?: number; interval?: number },\n): Promise<string[]>;\nexport function waitForPath(\n params: { source?: string; target: string },\n options?: { timeout?: number; interval?: number },\n): (graph: BaseGraph) => Promise<string[]>;\nexport function waitForPath(\n graphOrParams: BaseGraph | { source?: string; target: string },\n paramsOrOptions?: { source?: string; target: string } | { timeout?: number; interval?: number },\n options?: { timeout?: number; interval?: number },\n): Promise<string[]> | ((graph: BaseGraph) => Promise<string[]>) {\n if (typeof graphOrParams === 'object' && 'target' in graphOrParams) {\n // Curried: waitForPath(params, options?)\n const params = graphOrParams as { source?: string; target: string };\n const opts = typeof paramsOrOptions === 'object' && !('target' in paramsOrOptions) ? paramsOrOptions : undefined;\n return (graph: BaseGraph) => waitForPathImpl(graph, params, opts);\n } else {\n // Direct: waitForPath(graph, params, options?)\n const graph = graphOrParams as BaseGraph;\n const params = paramsOrOptions as { source?: string; target: string };\n return waitForPathImpl(graph, params, options);\n }\n}\n\n/**\n * Implementation helper for initialize.\n */\nconst initializeImpl = async <T extends ExpandableGraph | WritableGraph>(graph: T, id: string): Promise<T> => {\n const internal = getInternal(graph);\n const initialized = Record.get(internal._initialized, id).pipe(Option.getOrElse(() => false));\n log('initialize', { id, initialized });\n if (!initialized) {\n Record.set(internal._initialized, id, true);\n await internal._onInitialize?.(id);\n }\n return graph;\n};\n\n/**\n * Initialize a node in the graph.\n *\n * Fires the `onInitialize` callback to provide initial data for a node.\n */\nexport function initialize<T extends ExpandableGraph | WritableGraph>(graph: T, id: string): Promise<T>;\nexport function initialize(id: string): <T extends ExpandableGraph | WritableGraph>(graph: T) => Promise<T>;\nexport function initialize<T extends ExpandableGraph | WritableGraph>(\n graphOrId: T | string,\n id?: string,\n): Promise<T> | (<T extends ExpandableGraph | WritableGraph>(graph: T) => Promise<T>) {\n if (typeof graphOrId === 'string') {\n // Curried: initialize(id)\n const id = graphOrId;\n return <T extends ExpandableGraph | WritableGraph>(graph: T) => initializeImpl(graph, id);\n } else {\n // Direct: initialize(graph, id)\n const graph = graphOrId;\n return initializeImpl(graph, id!);\n }\n}\n\n/**\n * Implementation helper for expand.\n * If the node does not exist yet, the expand is recorded as pending and applied when the node is added.\n */\nconst expandImpl = <T extends ExpandableGraph | WritableGraph>(\n graph: T,\n id: string,\n relation: Node.RelationInput,\n): T => {\n const internal = getInternal(graph);\n const normalizedRelation = normalizeRelation(relation);\n const key = `${id}${Separators.primary}${relationKey(normalizedRelation)}`;\n const nodeOpt = internal._registry.get(internal._node(id));\n if (Option.isNone(nodeOpt)) {\n // Node not yet in graph: record expand to run when the node is added.\n internal._pendingExpands.add(key);\n log('expand', { key, deferred: true });\n return graph;\n }\n\n const expanded = Record.get(internal._expanded, key).pipe(Option.getOrElse(() => false));\n log('expand', { key, expanded });\n if (!expanded) {\n Record.set(internal._expanded, key, true);\n internal._onExpand?.(id, normalizedRelation);\n }\n return graph;\n};\n\n/**\n * Expand a node in the graph.\n *\n * Fires the `onExpand` callback to add connections to the node.\n */\nexport function expand<T extends ExpandableGraph | WritableGraph>(\n graph: T,\n id: string,\n relation: Node.RelationInput,\n): T;\nexport function expand(\n id: string,\n relation: Node.RelationInput,\n): <T extends ExpandableGraph | WritableGraph>(graph: T) => T;\nexport function expand<T extends ExpandableGraph | WritableGraph>(\n graphOrId: T | string,\n idOrRelation: string | Node.RelationInput,\n relation?: Node.RelationInput,\n): T | (<T extends ExpandableGraph | WritableGraph>(graph: T) => T) {\n if (typeof graphOrId === 'string') {\n // Curried: expand(id, relation)\n const id = graphOrId;\n const rel = idOrRelation as Node.RelationInput;\n return <T extends ExpandableGraph | WritableGraph>(graph: T) => expandImpl(graph, id, rel);\n } else {\n // Direct: expand(graph, id, relation)\n const graph = graphOrId;\n const id = idOrRelation as string;\n invariant(relation !== undefined, 'Relation is required.');\n const rel = relation;\n return expandImpl(graph, id, rel);\n }\n}\n\n/**\n * Implementation helper for sortEdges.\n */\nconst sortEdgesImpl = <T extends ExpandableGraph | WritableGraph>(\n graph: T,\n id: string,\n relation: Node.RelationInput,\n order: string[],\n): T => {\n const internal = getInternal(graph);\n const edgesAtom = internal._edges(id);\n const edges = internal._registry.get(edgesAtom);\n const relationId = relationKey(relation);\n const current = edges[relationId] ?? [];\n const unsorted = current.filter((id) => !order.includes(id));\n const sorted = order.filter((id) => current.includes(id));\n const newOrder = [...sorted, ...unsorted];\n if (newOrder.length === current.length && newOrder.every((id, i) => id === current[i])) {\n return graph;\n }\n internal._registry.set(edgesAtom, {\n ...edges,\n [relationId]: newOrder,\n });\n return graph;\n};\n\n/**\n * Sort the edges of the node with the given id.\n */\nexport function sortEdges<T extends ExpandableGraph | WritableGraph>(\n graph: T,\n id: string,\n relation: Node.RelationInput,\n order: string[],\n): T;\nexport function sortEdges(\n id: string,\n relation: Node.RelationInput,\n order: string[],\n): <T extends ExpandableGraph | WritableGraph>(graph: T) => T;\nexport function sortEdges<T extends ExpandableGraph | WritableGraph>(\n graphOrId: T | string,\n idOrRelation?: string | Node.RelationInput,\n relationOrOrder?: Node.RelationInput | string[],\n order?: string[],\n): T | (<T extends ExpandableGraph | WritableGraph>(graph: T) => T) {\n if (typeof graphOrId === 'string') {\n // Curried: sortEdges(id, relation, order)\n const id = graphOrId;\n const relation = idOrRelation as Node.RelationInput;\n const order = relationOrOrder as string[];\n return <T extends ExpandableGraph | WritableGraph>(graph: T) => sortEdgesImpl(graph, id, relation, order);\n } else {\n // Direct: sortEdges(graph, id, relation, order)\n const graph = graphOrId;\n const id = idOrRelation as string;\n const relation = relationOrOrder as Node.RelationInput;\n return sortEdgesImpl(graph, id, relation, order!);\n }\n}\n\n/**\n * Implementation helper for addNodes.\n */\nconst addNodesImpl = <T extends WritableGraph>(graph: T, nodes: Node.NodeArg<any, Record<string, any>>[]): T => {\n Atom.batch(() => {\n nodes.map((node) => addNodeImpl(graph, node));\n });\n return graph;\n};\n\n/**\n * Add nodes to the graph.\n */\nexport function addNodes<T extends WritableGraph>(graph: T, nodes: Node.NodeArg<any, Record<string, any>>[]): T;\nexport function addNodes(nodes: Node.NodeArg<any, Record<string, any>>[]): <T extends WritableGraph>(graph: T) => T;\nexport function addNodes<T extends WritableGraph>(\n graphOrNodes: T | Node.NodeArg<any, Record<string, any>>[],\n nodes?: Node.NodeArg<any, Record<string, any>>[],\n): T | (<T extends WritableGraph>(graph: T) => T) {\n if (nodes === undefined) {\n // Curried: addNodes(nodes)\n const nodes = graphOrNodes as Node.NodeArg<any, Record<string, any>>[];\n return <T extends WritableGraph>(graph: T) => addNodesImpl(graph, nodes);\n } else {\n // Direct: addNodes(graph, nodes)\n const graph = graphOrNodes as T;\n return addNodesImpl(graph, nodes);\n }\n}\n\n/**\n * Implementation helper for addNode.\n */\nconst addNodeImpl = <T extends WritableGraph>(graph: T, nodeArg: Node.NodeArg<any, Record<string, any>>): T => {\n const internal = getInternal(graph);\n // Extract known NodeArg fields, preserve any extra fields (like _actionContext) in rest.\n const {\n nodes,\n edges,\n id,\n type,\n data = null,\n properties = {},\n ...rest\n } = nodeArg as Node.NodeArg<any> & {\n _actionContext?: Node.ActionContext;\n };\n const nodeAtom = internal._node(id);\n const existingNode = internal._registry.get(nodeAtom);\n Option.match(existingNode, {\n onSome: (existing) => {\n const typeChanged = existing.type !== type;\n const dataChanged = !shallowEqual(existing.data, data);\n const propertiesChanged = Object.keys(properties).some((key) => existing.properties[key] !== properties[key]);\n log('existing node', {\n id,\n typeChanged,\n dataChanged,\n propertiesChanged,\n });\n if (typeChanged || dataChanged || propertiesChanged) {\n log('updating node', { id, type, data, properties });\n const newNode = Option.some({\n ...existing,\n ...rest,\n type,\n data,\n properties: { ...existing.properties, ...properties },\n });\n internal._registry.set(nodeAtom, newNode);\n graph.onNodeChanged.emit({ id, node: newNode });\n }\n },\n onNone: () => {\n log('new node', { id, type, data, properties });\n const newNode = internal._constructNode({ id, type, data, properties, ...rest });\n internal._registry.set(nodeAtom, newNode);\n graph.onNodeChanged.emit({ id, node: newNode });\n\n // Apply any expands that were deferred because this node did not exist yet.\n const prefix = `${id}${Separators.primary}`;\n const toApply = [...internal._pendingExpands].filter((k) => k.startsWith(prefix));\n for (const pendingKey of toApply) {\n internal._pendingExpands.delete(pendingKey);\n const relation = relationFromKey(pendingKey.slice(prefix.length));\n Record.set(internal._expanded, pendingKey, true);\n internal._onExpand?.(id, relation);\n }\n },\n });\n\n if (nodes) {\n addNodesImpl(graph, nodes);\n const _edges = nodes.map((node) => ({ source: id, target: node.id, relation: 'child' as const }));\n addEdgesImpl(graph, _edges);\n }\n\n if (edges) {\n todo();\n }\n return graph;\n};\n\n/**\n * Add a node to the graph.\n */\nexport function addNode<T extends WritableGraph>(graph: T, nodeArg: Node.NodeArg<any, Record<string, any>>): T;\nexport function addNode(nodeArg: Node.NodeArg<any, Record<string, any>>): <T extends WritableGraph>(graph: T) => T;\nexport function addNode<T extends WritableGraph>(\n graphOrNodeArg: T | Node.NodeArg<any, Record<string, any>>,\n nodeArg?: Node.NodeArg<any, Record<string, any>>,\n): T | (<T extends WritableGraph>(graph: T) => T) {\n if (nodeArg === undefined) {\n // Curried: addNode(nodeArg)\n const nodeArg = graphOrNodeArg as Node.NodeArg<any, Record<string, any>>;\n return <T extends WritableGraph>(graph: T) => addNodeImpl(graph, nodeArg);\n } else {\n // Direct: addNode(graph, nodeArg)\n const graph = graphOrNodeArg as T;\n return addNodeImpl(graph, nodeArg);\n }\n}\n\n/**\n * Implementation helper for removeNodes.\n */\nconst removeNodesImpl = <T extends WritableGraph>(graph: T, ids: string[], edges = false): T => {\n Atom.batch(() => {\n ids.map((id) => removeNodeImpl(graph, id, edges));\n });\n return graph;\n};\n\n/**\n * Remove nodes from the graph.\n */\nexport function removeNodes<T extends WritableGraph>(graph: T, ids: string[], edges?: boolean): T;\nexport function removeNodes(ids: string[], edges?: boolean): <T extends WritableGraph>(graph: T) => T;\nexport function removeNodes<T extends WritableGraph>(\n graphOrIds: T | string[],\n idsOrEdges?: string[] | boolean,\n edges?: boolean,\n): T | (<T extends WritableGraph>(graph: T) => T) {\n if (Array.isArray(graphOrIds)) {\n // Curried: removeNodes(ids, edges?)\n const ids = graphOrIds;\n const edgesArg = typeof idsOrEdges === 'boolean' ? idsOrEdges : false;\n return <T extends WritableGraph>(graph: T) => removeNodesImpl(graph, ids, edgesArg);\n } else {\n // Direct: removeNodes(graph, ids, edges?)\n const graph = graphOrIds;\n const ids = idsOrEdges as string[];\n const edgesArg = edges ?? false;\n return removeNodesImpl(graph, ids, edgesArg);\n }\n}\n\n/**\n * Implementation helper for removeNode.\n */\nconst removeNodeImpl = <T extends WritableGraph>(graph: T, id: string, edges = false): T => {\n const internal = getInternal(graph);\n const nodeAtom = internal._node(id);\n // TODO(wittjosiah): Is there a way to mark these atom values for garbage collection?\n internal._registry.set(nodeAtom, Option.none());\n graph.onNodeChanged.emit({ id, node: Option.none() });\n // TODO(wittjosiah): Reset expanded and initialized flags?\n\n if (edges) {\n const nodeEdges = internal._registry.get(internal._edges(id));\n const edgesToRemove: Edge[] = [];\n for (const [relationKeyValue, relatedIds] of Object.entries(nodeEdges)) {\n const relation = relationFromKey(relationKeyValue);\n const isInboundRelation = relation.direction === 'inbound';\n for (const relatedId of relatedIds) {\n if (isInboundRelation) {\n // Inbound edge lists store source node IDs; reconstruct the canonical outbound edge.\n edgesToRemove.push({ source: relatedId, target: id, relation: inverseRelation(relation) });\n } else {\n edgesToRemove.push({ source: id, target: relatedId, relation });\n }\n }\n }\n removeEdgesImpl(graph, edgesToRemove);\n }\n\n internal._onRemoveNode?.(id);\n return graph;\n};\n\n/**\n * Remove a node from the graph.\n */\nexport function removeNode<T extends WritableGraph>(graph: T, id: string, edges?: boolean): T;\nexport function removeNode(id: string, edges?: boolean): <T extends WritableGraph>(graph: T) => T;\nexport function removeNode<T extends WritableGraph>(\n graphOrId: T | string,\n idOrEdges?: string | boolean,\n edges?: boolean,\n): T | (<T extends WritableGraph>(graph: T) => T) {\n if (typeof graphOrId === 'string') {\n // Curried: removeNode(id, edges?)\n const id = graphOrId;\n const edgesArg = typeof idOrEdges === 'boolean' ? idOrEdges : false;\n return <T extends WritableGraph>(graph: T) => removeNodeImpl(graph, id, edgesArg);\n } else {\n // Direct: removeNode(graph, id, edges?)\n const graph = graphOrId;\n const id = idOrEdges as string;\n const edgesArg = edges ?? false;\n return removeNodeImpl(graph, id, edgesArg);\n }\n}\n\n/**\n * Implementation helper for addEdges.\n */\nconst addEdgesImpl = <T extends WritableGraph>(graph: T, edges: Edge[]): T => {\n Atom.batch(() => {\n edges.map((edge) => addEdgeImpl(graph, edge));\n });\n return graph;\n};\n\n/**\n * Add edges to the graph.\n */\nexport function addEdges<T extends WritableGraph>(graph: T, edges: Edge[]): T;\nexport function addEdges(edges: Edge[]): <T extends WritableGraph>(graph: T) => T;\nexport function addEdges<T extends WritableGraph>(\n graphOrEdges: T | Edge[],\n edges?: Edge[],\n): T | (<T extends WritableGraph>(graph: T) => T) {\n if (edges === undefined) {\n // Curried: addEdges(edges)\n const edges = graphOrEdges as Edge[];\n return <T extends WritableGraph>(graph: T) => addEdgesImpl(graph, edges);\n } else {\n // Direct: addEdges(graph, edges)\n const graph = graphOrEdges as T;\n return addEdgesImpl(graph, edges);\n }\n}\n\n/**\n * Implementation helper for addEdge.\n */\nconst addEdgeImpl = <T extends WritableGraph>(graph: T, edgeArg: Edge): T => {\n const relation = normalizeRelation(edgeArg.relation);\n const relationId = relationKey(relation);\n const inverse = inverseRelation(relation);\n const inverseId = relationKey(inverse);\n const internal = getInternal(graph);\n\n const sourceAtom = internal._edges(edgeArg.source);\n const source = internal._registry.get(sourceAtom);\n const sourceList = source[relationId] ?? [];\n if (!sourceList.includes(edgeArg.target)) {\n log('add edge', { source: edgeArg.source, target: edgeArg.target, relation: relationId });\n internal._registry.set(sourceAtom, { ...source, [relationId]: [...sourceList, edgeArg.target] });\n }\n\n const targetAtom = internal._edges(edgeArg.target);\n const target = internal._registry.get(targetAtom);\n const targetList = target[inverseId] ?? [];\n if (!targetList.includes(edgeArg.source)) {\n log('add inverse edge', { source: edgeArg.source, target: edgeArg.target, relation: inverseId });\n internal._registry.set(targetAtom, { ...target, [inverseId]: [...targetList, edgeArg.source] });\n }\n\n return graph;\n};\n\n/**\n * Add an edge to the graph.\n */\nexport function addEdge<T extends WritableGraph>(graph: T, edgeArg: Edge): T;\nexport function addEdge(edgeArg: Edge): <T extends WritableGraph>(graph: T) => T;\nexport function addEdge<T extends WritableGraph>(\n graphOrEdgeArg: T | Edge,\n edgeArg?: Edge,\n): T | (<T extends WritableGraph>(graph: T) => T) {\n if (edgeArg === undefined) {\n // Curried: addEdge(edgeArg)\n const edgeArg = graphOrEdgeArg as Edge;\n return <T extends WritableGraph>(graph: T) => addEdgeImpl(graph, edgeArg);\n } else {\n // Direct: addEdge(graph, edgeArg)\n const graph = graphOrEdgeArg as T;\n return addEdgeImpl(graph, edgeArg);\n }\n}\n\n/**\n * Implementation helper for removeEdges.\n */\nconst removeEdgesImpl = <T extends WritableGraph>(graph: T, edges: Edge[], removeOrphans = false): T => {\n Atom.batch(() => {\n edges.map((edge) => removeEdgeImpl(graph, edge, removeOrphans));\n });\n return graph;\n};\n\n/**\n * Remove edges from the graph.\n */\nexport function removeEdges<T extends WritableGraph>(graph: T, edges: Edge[], removeOrphans?: boolean): T;\nexport function removeEdges(edges: Edge[], removeOrphans?: boolean): <T extends WritableGraph>(graph: T) => T;\nexport function removeEdges<T extends WritableGraph>(\n graphOrEdges: T | Edge[],\n edgesOrRemoveOrphans?: Edge[] | boolean,\n removeOrphans?: boolean,\n): T | (<T extends WritableGraph>(graph: T) => T) {\n if (Array.isArray(graphOrEdges)) {\n // Curried: removeEdges(edges, removeOrphans?)\n const edges = graphOrEdges;\n const removeOrphansArg = typeof edgesOrRemoveOrphans === 'boolean' ? edgesOrRemoveOrphans : false;\n return <T extends WritableGraph>(graph: T) => removeEdgesImpl(graph, edges, removeOrphansArg);\n } else {\n // Direct: removeEdges(graph, edges, removeOrphans?)\n const graph = graphOrEdges;\n const edges = edgesOrRemoveOrphans as Edge[];\n const removeOrphansArg = removeOrphans ?? false;\n return removeEdgesImpl(graph, edges, removeOrphansArg);\n }\n}\n\n/**\n * Implementation helper for removeEdge.\n */\nconst removeEdgeImpl = <T extends WritableGraph>(graph: T, edgeArg: Edge, removeOrphans = false): T => {\n const relation = normalizeRelation(edgeArg.relation);\n const relationId = relationKey(relation);\n const inverse = inverseRelation(relation);\n const inverseId = relationKey(inverse);\n const internal = getInternal(graph);\n\n const sourceAtom = internal._edges(edgeArg.source);\n const source = internal._registry.get(sourceAtom);\n const sourceList = source[relationId] ?? [];\n if (sourceList.includes(edgeArg.target)) {\n internal._registry.set(sourceAtom, { ...source, [relationId]: sourceList.filter((id) => id !== edgeArg.target) });\n }\n\n const targetAtom = internal._edges(edgeArg.target);\n const target = internal._registry.get(targetAtom);\n const targetList = target[inverseId] ?? [];\n if (targetList.includes(edgeArg.source)) {\n internal._registry.set(targetAtom, { ...target, [inverseId]: targetList.filter((id) => id !== edgeArg.source) });\n }\n\n if (removeOrphans) {\n const sourceAfter = internal._registry.get(sourceAtom);\n const targetAfter = internal._registry.get(targetAtom);\n const isEmpty = (edges: Edges) => Object.values(edges).every((ids) => ids.length === 0);\n if (isEmpty(sourceAfter) && edgeArg.source !== Node.RootId) {\n removeNodesImpl(graph, [edgeArg.source]);\n }\n if (isEmpty(targetAfter) && edgeArg.target !== Node.RootId) {\n removeNodesImpl(graph, [edgeArg.target]);\n }\n }\n return graph;\n};\n\n/**\n * Remove an edge from the graph.\n */\nexport function removeEdge<T extends WritableGraph>(graph: T, edgeArg: Edge, removeOrphans?: boolean): T;\nexport function removeEdge(edgeArg: Edge, removeOrphans?: boolean): <T extends WritableGraph>(graph: T) => T;\nexport function removeEdge<T extends WritableGraph>(\n graphOrEdgeArg: T | Edge,\n edgeArgOrRemoveOrphans?: Edge | boolean,\n removeOrphans?: boolean,\n): T | (<T extends WritableGraph>(graph: T) => T) {\n if (\n edgeArgOrRemoveOrphans === undefined ||\n typeof edgeArgOrRemoveOrphans === 'boolean' ||\n 'source' in graphOrEdgeArg\n ) {\n // Curried: removeEdge(edgeArg, removeOrphans?)\n const edgeArg = graphOrEdgeArg as Edge;\n const removeOrphansArg = typeof edgeArgOrRemoveOrphans === 'boolean' ? edgeArgOrRemoveOrphans : false;\n return <T extends WritableGraph>(graph: T) => removeEdgeImpl(graph, edgeArg, removeOrphansArg);\n } else {\n // Direct: removeEdge(graph, edgeArg, removeOrphans?)\n const graph = graphOrEdgeArg as T;\n const edgeArg = edgeArgOrRemoveOrphans as Edge;\n const removeOrphansArg = removeOrphans ?? false;\n return removeEdgeImpl(graph, edgeArg, removeOrphansArg);\n }\n}\n\n/**\n * Creates a new Graph instance.\n */\nexport const make = (params?: GraphProps): Graph => {\n return new GraphImpl(params);\n};\n\n//\n// Utilities\n//\n\nexport const relationKey = (relation: Node.RelationInput): string => {\n const normalized = normalizeRelation(relation);\n return `${normalized.kind}${Separators.secondary}${normalized.direction}`;\n};\n\nexport const relationFromKey = (encoded: string): Node.Relation => {\n const separatorIndex = encoded.lastIndexOf(Separators.secondary);\n invariant(separatorIndex > 0 && separatorIndex < encoded.length - 1, `Invalid relation key: ${encoded}`);\n const kind = encoded.slice(0, separatorIndex);\n const directionRaw = encoded.slice(separatorIndex + 1);\n invariant(directionRaw === 'outbound' || directionRaw === 'inbound', `Invalid relation direction: ${directionRaw}`);\n return Node.relation(kind, directionRaw);\n};\n\nconst connectionKey = (id: string, relation: Node.RelationInput): string =>\n `${id}${Separators.primary}${relationKey(relation)}`;\n\nconst relationFromConnectionKey = (key: string): { id: string; relation: Node.Relation } => {\n const separatorIndex = key.indexOf(Separators.primary);\n invariant(separatorIndex > 0 && separatorIndex < key.length - 1, `Invalid connection key: ${key}`);\n const id = key.slice(0, separatorIndex);\n const encodedRelation = key.slice(separatorIndex + 1);\n return { id, relation: relationFromKey(encodedRelation) };\n};\n\nconst inverseRelation = (relation: Node.RelationInput): Node.Relation => {\n const normalized = normalizeRelation(relation);\n return Node.relation(normalized.kind, normalized.direction === 'outbound' ? 'inbound' : 'outbound');\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport type * as Context from 'effect/Context';\nimport type * as Effect from 'effect/Effect';\n\nimport { type MakeOptional } from '@dxos/util';\n\n/**\n * Root node ID.\n */\nexport const RootId = 'root';\n\n/**\n * Root node type.\n */\nexport const RootType = 'dxos.org/type/GraphRoot';\n\n/**\n * Action node type.\n */\nexport const ActionType = 'dxos.org/type/GraphAction';\n\n/**\n * Action group node type.\n */\nexport const ActionGroupType = 'dxos.org/type/GraphActionGroup';\n\n/**\n * Represents a node in the graph.\n */\n// TODO(wittjosiah): Use Effect Schema.\n// TODO(burdon): Rename GraphNode. Node is already in the global namespace.\nexport type Node<TData = any, TProperties extends Record<string, any> = Record<string, any>> = Readonly<{\n /**\n * Globally unique ID.\n */\n // TODO(burdon): Allow string array, which is concatenated.\n id: string;\n\n /**\n * Typename of the data the node represents.\n */\n type: string;\n\n /**\n * Keys in of the properties which should be cached.\n * If defined, the node will be included in the cache.\n * If undefined, the node will not be included in the cache.\n */\n cacheable?: string[];\n\n /**\n * Properties of the node relevant to displaying the node.\n */\n properties: Readonly<TProperties>;\n\n /**\n * Data the node represents.\n */\n // TODO(burdon): Type system (e.g., minimally provide identifier string vs. TypedObject vs. Graph mixin type system)?\n // type field would prevent convoluted sniffing of object properties. And allow direct pass-through for ECHO TypedObjects.\n data: TData;\n}>;\n\nexport type NodeFilter<TData = any, TProperties extends Record<string, any> = Record<string, any>> = (\n node: Node<unknown, Record<string, any>>,\n connectedNode: Node,\n) => node is Node<TData, TProperties>;\n\nexport type RelationDirection = 'outbound' | 'inbound';\n\nexport type Relation = Readonly<{\n kind: string;\n direction: RelationDirection;\n}>;\n\nexport type RelationInput = Relation | string;\n\nexport const relation = (kind: string, direction: RelationDirection = 'outbound'): Relation => ({ kind, direction });\n// TODO(wittjosiah): Consider moving these helpers out of the core API.\nexport const childRelation = (direction: RelationDirection = 'outbound'): Relation => relation('child', direction);\nexport const actionRelation = (direction: RelationDirection = 'outbound'): Relation => relation('action', direction);\n\nexport const isGraphNode = (data: unknown): data is Node =>\n data && typeof data === 'object' && 'id' in data && 'properties' in data && data.properties\n ? typeof data.properties === 'object' && 'data' in data\n : false;\n\nexport type NodeArg<TData, TProperties extends Record<string, any> = Record<string, any>> = MakeOptional<\n Node<TData, TProperties>,\n 'data' | 'properties' | 'cacheable'\n> & {\n /** Will automatically add nodes with an edge from this node to each. */\n nodes?: NodeArg<unknown>[];\n\n /** Will automatically add specified edges. */\n edges?: [string, RelationInput][];\n};\n\n//\n// Actions\n//\n\nexport type InvokeProps = {\n /** Node the invoked action is connected to. */\n parent?: Node;\n\n caller?: string;\n};\n\n/**\n * Action data is an Effect-returning function.\n * The Effect is provided with captured context at execution time.\n */\nexport type ActionData<R = never> = (params?: InvokeProps) => Effect.Effect<any, Error, R>;\n\n/**\n * Context captured at extension creation time.\n * Automatically provided to action Effects at execution.\n */\nexport type ActionContext = Context.Context<any>;\n\nexport type Action<TProperties extends Record<string, any> = Record<string, any>> = Readonly<\n Omit<Node<ActionData, TProperties>, 'properties'> & {\n properties: Readonly<TProperties>;\n /** Captured context from extension creation. Provided automatically at action execution. */\n _actionContext?: ActionContext;\n }\n>;\n\nexport const isAction = (data: unknown): data is Action =>\n isGraphNode(data) ? typeof data.data === 'function' && data.type === ActionType : false;\n\nexport const actionGroupSymbol = Symbol('ActionGroup');\n\nexport type ActionGroup<TProperties extends Record<string, any> = Record<string, any>> = Readonly<\n Omit<Node<typeof actionGroupSymbol, TProperties>, 'properties'> & {\n properties: Readonly<TProperties>;\n }\n>;\n\nexport const isActionGroup = (data: unknown): data is ActionGroup =>\n isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ActionGroupType : false;\n\nexport type ActionLike = Action | ActionGroup;\n\nexport const isActionLike = (data: unknown): data is Action | ActionGroup => isAction(data) || isActionGroup(data);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Node from './node';\n\n/**\n * Key separators for compound string keys used across the app-graph package.\n * `primary` separates top-level components (e.g., node ID from relation).\n * `secondary` separates sub-components within an encoded value (e.g., relation kind from direction).\n * Two distinct characters are needed because secondary separators appear inside primary-separated fields.\n */\nexport const Separators = {\n primary: '\\u0001',\n secondary: '\\u0002',\n} as const;\n\n/**\n * Normalize a relation input to a full Relation object.\n */\nexport const normalizeRelation = (relation?: Node.RelationInput): Node.Relation =>\n relation == null ? Node.childRelation() : typeof relation === 'string' ? Node.relation(relation) : relation;\n\n/**\n * Shallow-compare two values: same reference, or same own-keys with === values.\n */\nexport const shallowEqual = (a: unknown, b: unknown): boolean => {\n if (a === b) return true;\n if (a == null || b == null || typeof a !== 'object' || typeof b !== 'object') return false;\n const keysA = Object.keys(a as Record<string, unknown>);\n const keysB = Object.keys(b as Record<string, unknown>);\n if (keysA.length !== keysB.length) {\n return false;\n }\n return keysA.every((k) => (a as Record<string, unknown>)[k] === (b as Record<string, unknown>)[k]);\n};\n\n/**\n * Returns true if two NodeArg arrays are semantically identical (same id, type, data, properties per index).\n */\nexport const nodeArgsUnchanged = (prev: Node.NodeArg<any>[], next: Node.NodeArg<any>[]): boolean => {\n if (prev.length !== next.length) {\n return false;\n }\n\n return prev.every((prevNode, idx) => {\n const nextNode = next[idx];\n return (\n prevNode.id === nextNode.id &&\n prevNode.type === nextNode.type &&\n shallowEqual(prevNode.data, nextNode.data) &&\n shallowEqual(prevNode.properties, nextNode.properties)\n );\n });\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom, Registry } from '@effect-atom/atom-react';\nimport * as Array from 'effect/Array';\nimport type * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Function from 'effect/Function';\nimport * as Option from 'effect/Option';\nimport * as Pipeable from 'effect/Pipeable';\nimport * as Record from 'effect/Record';\nimport type * as Schema from 'effect/Schema';\nimport { scheduleTask, yieldOrContinue } from 'main-thread-scheduling';\n\nimport { type CleanupFn, type Trigger } from '@dxos/async';\nimport { type Entity, type Type } from '@dxos/echo';\nimport { log } from '@dxos/log';\nimport { type MaybePromise, type Position, byPosition, getDebugName, isNonNullable } from '@dxos/util';\n\nimport * as Graph from './graph';\nimport * as Node from './node';\nimport * as NodeMatcher from './node-matcher';\nimport { Separators, nodeArgsUnchanged, normalizeRelation } from './util';\n\n//\n// Extension Types\n//\n\n/**\n * Graph builder extension for adding nodes to the graph based on a node id.\n */\nexport type ResolverExtension = (id: string) => Atom.Atom<Node.NodeArg<any> | null>;\n\n/**\n * Graph builder extension for adding nodes to the graph based on a connection to an existing node.\n *\n * @param params.node The existing node the returned nodes will be connected to.\n */\nexport type ConnectorExtension = (node: Atom.Atom<Option.Option<Node.Node>>) => Atom.Atom<Node.NodeArg<any>[]>;\n\n/**\n * Constrained case of the connector extension for more easily adding actions to the graph.\n */\nexport type ActionsExtension = (\n node: Atom.Atom<Option.Option<Node.Node>>,\n) => Atom.Atom<Omit<Node.NodeArg<Node.ActionData<any>>, 'type' | 'nodes' | 'edges'>[]>;\n\n/**\n * Constrained case of the connector extension for more easily adding action groups to the graph.\n */\nexport type ActionGroupsExtension = (\n node: Atom.Atom<Option.Option<Node.Node>>,\n) => Atom.Atom<Omit<Node.NodeArg<typeof Node.actionGroupSymbol>, 'type' | 'data' | 'nodes' | 'edges'>[]>;\n\nexport type BuilderExtension = Readonly<{\n id: string;\n position: Position;\n relation?: Node.RelationInput;\n resolver?: ResolverExtension;\n connector?: (node: Atom.Atom<Option.Option<Node.Node>>) => Atom.Atom<Node.NodeArg<any>[]>;\n}>;\n\nexport type BuilderExtensions = BuilderExtension | BuilderExtension[] | BuilderExtensions[];\n\n//\n// GraphBuilder Core\n//\n\nexport type GraphBuilderTraverseOptions = {\n visitor: (node: Node.Node, path: string[]) => MaybePromise<boolean | void>;\n registry?: Registry.Registry;\n source?: string;\n relation: Node.RelationInput;\n};\n\n/**\n * Identifier denoting a GraphBuilder.\n */\nexport const GraphBuilderTypeId: unique symbol = Symbol.for('@dxos/app-graph/GraphBuilder');\nexport type GraphBuilderTypeId = typeof GraphBuilderTypeId;\n\n/**\n * GraphBuilder interface.\n */\nexport interface GraphBuilder extends Pipeable.Pipeable {\n readonly [GraphBuilderTypeId]: GraphBuilderTypeId;\n readonly graph: Graph.ExpandableGraph;\n readonly extensions: Atom.Atom<Record<string, BuilderExtension>>;\n}\n\n/**\n * The builder provides an extensible way to compose the construction of the graph.\n * @internal\n */\n// TODO(wittjosiah): Add api for setting subscription set and/or radius.\n// Should unsubscribe from nodes that are not in the set/radius.\n// Should track LRU nodes that are not in the set/radius and remove them beyond a certain threshold.\nclass GraphBuilderImpl implements GraphBuilder {\n readonly [GraphBuilderTypeId]: GraphBuilderTypeId = GraphBuilderTypeId;\n\n pipe() {\n // eslint-disable-next-line prefer-rest-params\n return Pipeable.pipeArguments(this, arguments);\n }\n\n // TODO(wittjosiah): Use Context.\n readonly _subscriptions = new Map<string, CleanupFn>();\n readonly _dirtyConnectors = new Map<\n string,\n {\n nodes: Node.NodeArg<any>[];\n previous: string[];\n }\n >();\n readonly _connectorPrevious = new Map<string, string[]>();\n readonly _connectorPreviousArgs = new Map<string, Node.NodeArg<any>[]>();\n _flushScheduled = false;\n _flushPromise: Promise<void> = Promise.resolve();\n readonly _extensions = Atom.make(Record.empty<string, BuilderExtension>()).pipe(\n Atom.keepAlive,\n Atom.withLabel('graph-builder:extensions'),\n );\n readonly _initialized: Record<string, Trigger> = {};\n readonly _registry: Registry.Registry;\n readonly _graph: Graph.Graph & {\n _node: (id: string) => Atom.Writable<Option.Option<Node.Node>>;\n _constructNode: (node: Node.NodeArg<any>) => Option.Option<Node.Node>;\n };\n\n constructor({ registry, ...params }: Pick<Graph.GraphProps, 'registry' | 'nodes' | 'edges'> = {}) {\n this._registry = registry ?? Registry.make();\n const graph = Graph.make({\n ...params,\n registry: this._registry,\n onExpand: (id, relation) => this._onExpand(id, relation),\n onInitialize: (id) => this._onInitialize(id),\n onRemoveNode: (id) => this._onRemoveNode(id),\n });\n // Access internal methods via type assertion since GraphBuilder needs them\n this._graph = graph as Graph.Graph & {\n _node: (id: string) => Atom.Writable<Option.Option<Node.Node>>;\n _constructNode: (node: Node.NodeArg<any>) => Option.Option<Node.Node>;\n };\n }\n\n get graph(): Graph.ExpandableGraph {\n return this._graph;\n }\n\n get extensions() {\n return this._extensions;\n }\n\n /** Apply a set of node changes for a single connector key. */\n private _applyConnectorUpdate(key: string, nodes: Node.NodeArg<any>[], previous: string[]): void {\n const { id, relation } = relationFromConnectorKey(key);\n const ids = nodes.map((node) => node.id);\n const removed = previous.filter((pid) => !ids.includes(pid));\n this._connectorPrevious.set(key, ids);\n this._connectorPreviousArgs.set(key, nodes);\n\n Graph.removeEdges(\n this._graph,\n removed.map((target) => ({ source: id, target, relation })),\n true,\n );\n Graph.addNodes(this._graph, nodes);\n Graph.addEdges(\n this._graph,\n nodes.map((node) => ({ source: id, target: node.id, relation })),\n );\n if (ids.length > 0) {\n const sortedIds = [...nodes]\n .sort((a, b) =>\n byPosition(a.properties ?? ({} as { position?: Position }), b.properties ?? ({} as { position?: Position })),\n )\n .map((n) => n.id);\n Graph.sortEdges(this._graph, id, relation, sortedIds);\n }\n }\n\n private _scheduleDirtyFlush(): void {\n if (!this._flushScheduled) {\n this._flushScheduled = true;\n this._flushPromise = scheduleTask(\n () => {\n this._flushScheduled = false;\n while (this._dirtyConnectors.size > 0) {\n const entries = [...this._dirtyConnectors.entries()];\n this._dirtyConnectors.clear();\n\n Atom.batch(() => {\n for (const [key, { nodes, previous }] of entries) {\n this._applyConnectorUpdate(key, nodes, previous);\n }\n });\n }\n },\n { strategy: 'smooth' },\n );\n }\n }\n\n private readonly _resolvers = Atom.family<string, Atom.Atom<Option.Option<Node.NodeArg<any>>>>((id) => {\n return Atom.make((get) => {\n return Function.pipe(\n get(this._extensions),\n Record.values,\n Array.sortBy(byPosition),\n Array.map(({ resolver }) => resolver),\n Array.filter(isNonNullable),\n Array.map((resolver) => get(resolver(id))),\n Array.filter(isNonNullable),\n Array.head,\n );\n });\n });\n\n private readonly _connectors = Atom.family<string, Atom.Atom<Node.NodeArg<any>[]>>((key) => {\n return Atom.make((get) => {\n const { id, relation } = relationFromConnectorKey(key);\n const node = this._graph.node(id);\n\n const sourceNode = Option.getOrElse(get(node), () => undefined);\n if (!sourceNode) {\n return [];\n }\n\n const extensions = Function.pipe(\n get(this._extensions),\n Record.values,\n Array.sortBy(byPosition),\n Array.filter(\n (ext): ext is BuilderExtension & { connector: NonNullable<BuilderExtension['connector']> } =>\n Graph.relationKey(ext.relation ?? 'child') === Graph.relationKey(relation) && ext.connector != null,\n ),\n );\n\n const nodes: Node.NodeArg<any>[] = [];\n for (const ext of extensions) {\n const result = get(ext.connector(node));\n nodes.push(...result);\n }\n\n return nodes;\n }).pipe(Atom.withLabel(`graph-builder:connectors:${key}`));\n });\n\n private _onExpand(id: string, relation: Node.Relation): void {\n log('onExpand', { id, relation, registry: getDebugName(this._registry) });\n this._expandRelation(id, relation);\n\n // TODO(wittjosiah): Remove. This is for backwards compatibility.\n if (relation.kind === 'child' && relation.direction === 'outbound') {\n Graph.expand(this._graph, id, 'action');\n }\n }\n\n private _expandRelation(id: string, relation: Node.RelationInput): void {\n const key = connectorKey(id, relation);\n const connectors = this._connectors(key);\n\n const cancel = this._registry.subscribe(\n connectors,\n (nodes) => {\n const previous = this._connectorPrevious.get(key) ?? [];\n const ids = nodes.map((n) => n.id);\n\n if (ids.length === previous.length && ids.every((nodeId, idx) => nodeId === previous[idx])) {\n const prevArgs = this._connectorPreviousArgs.get(key);\n if (prevArgs && nodeArgsUnchanged(prevArgs, nodes)) {\n return;\n }\n }\n\n log('update', { id, relation, ids });\n this._dirtyConnectors.set(key, { nodes, previous });\n this._scheduleDirtyFlush();\n },\n { immediate: true },\n );\n\n this._subscriptions.set(subscriptionKey(id, 'expand', key), cancel);\n }\n\n // TODO(wittjosiah): If the same node is added by a connector, the resolver should probably cancel itself?\n private async _onInitialize(id: string) {\n log('onInitialize', { id });\n const resolver = this._resolvers(id);\n\n const cancel = this._registry.subscribe(\n resolver,\n (node) => {\n const trigger = this._initialized[id];\n Option.match(node, {\n onSome: (node) => {\n Graph.addNodes(this._graph, [node]);\n trigger?.wake();\n },\n onNone: () => {\n trigger?.wake();\n Graph.removeNodes(this._graph, [id]);\n },\n });\n },\n { immediate: true },\n );\n\n this._subscriptions.set(subscriptionKey(id, 'init'), cancel);\n }\n\n private _onRemoveNode(id: string): void {\n const prefix = `${id}${Separators.primary}`;\n for (const [key, cleanup] of this._subscriptions) {\n if (key.startsWith(prefix)) {\n cleanup();\n this._subscriptions.delete(key);\n }\n }\n }\n}\n\n/**\n * Creates a new GraphBuilder instance.\n */\nexport const make = (params?: Pick<Graph.GraphProps, 'registry' | 'nodes' | 'edges'>): GraphBuilder => {\n return new GraphBuilderImpl(params);\n};\n\n/**\n * Creates a GraphBuilder from a serialized pickle string.\n */\nexport const from = (pickle?: string, registry?: Registry.Registry): GraphBuilder => {\n if (!pickle) {\n return make({ registry });\n }\n\n const { nodes, edges } = JSON.parse(pickle);\n return make({ nodes, edges, registry });\n};\n\n/**\n * Implementation helper for addExtension.\n */\nconst addExtensionImpl = (builder: GraphBuilder, extensions: BuilderExtensions): GraphBuilder => {\n const internal = builder as GraphBuilderImpl;\n flattenExtensions(extensions).forEach((extension) => {\n const extensions = internal._registry.get(internal._extensions);\n internal._registry.set(internal._extensions, Record.set(extensions, extension.id, extension));\n });\n return builder;\n};\n\n/**\n * Add extensions to the graph builder.\n */\nexport function addExtension(builder: GraphBuilder, extensions: BuilderExtensions): GraphBuilder;\nexport function addExtension(extensions: BuilderExtensions): (builder: GraphBuilder) => GraphBuilder;\nexport function addExtension(\n builderOrExtensions: GraphBuilder | BuilderExtensions,\n extensions?: BuilderExtensions,\n): GraphBuilder | ((builder: GraphBuilder) => GraphBuilder) {\n if (extensions === undefined) {\n // Curried: addExtension(extensions)\n const extensions = builderOrExtensions as BuilderExtensions;\n return (builder: GraphBuilder) => addExtensionImpl(builder, extensions);\n } else {\n // Direct: addExtension(builder, extensions)\n const builder = builderOrExtensions as GraphBuilder;\n return addExtensionImpl(builder, extensions);\n }\n}\n\n/**\n * Implementation helper for removeExtension.\n */\nconst removeExtensionImpl = (builder: GraphBuilder, id: string): GraphBuilder => {\n const internal = builder as GraphBuilderImpl;\n const extensions = internal._registry.get(internal._extensions);\n internal._registry.set(internal._extensions, Record.remove(extensions, id));\n return builder;\n};\n\n/**\n * Remove an extension from the graph builder.\n */\nexport function removeExtension(builder: GraphBuilder, id: string): GraphBuilder;\nexport function removeExtension(id: string): (builder: GraphBuilder) => GraphBuilder;\nexport function removeExtension(\n builderOrId: GraphBuilder | string,\n id?: string,\n): GraphBuilder | ((builder: GraphBuilder) => GraphBuilder) {\n if (typeof builderOrId === 'string') {\n // Curried: removeExtension(id)\n const id = builderOrId;\n return (builder: GraphBuilder) => removeExtensionImpl(builder, id);\n } else {\n // Direct: removeExtension(builder, id)\n const builder = builderOrId;\n return removeExtensionImpl(builder, id!);\n }\n}\n\n/**\n * Implementation helper for explore.\n */\nconst exploreImpl = async (\n builder: GraphBuilder,\n options: GraphBuilderTraverseOptions,\n path: string[] = [],\n): Promise<void> => {\n const internal = builder as GraphBuilderImpl;\n const { registry = Registry.make(), source = Node.RootId, relation, visitor } = options;\n // Break cycles.\n if (path.includes(source)) {\n return;\n }\n\n await yieldOrContinue('idle');\n\n const node = registry.get(internal._graph.nodeOrThrow(source));\n const shouldContinue = await visitor(node, [...path, node.id]);\n if (shouldContinue === false) {\n return;\n }\n\n const nodes = Object.values(internal._registry.get(internal._extensions))\n .filter((extension) => Graph.relationKey(extension.relation ?? 'child') === Graph.relationKey(relation))\n .map((extension) => extension.connector)\n .filter(isNonNullable)\n .flatMap((connector) => registry.get(connector(internal._graph.node(source))));\n\n await Promise.all(\n nodes.map((nodeArg) => {\n registry.set(internal._graph._node(nodeArg.id), internal._graph._constructNode(nodeArg));\n return exploreImpl(builder, { registry, source: nodeArg.id, relation, visitor }, [...path, node.id]);\n }),\n );\n\n if (registry !== internal._registry) {\n registry.reset();\n registry.dispose();\n }\n};\n\n/**\n * Explore the graph by traversing it with the given options.\n */\nexport function explore(builder: GraphBuilder, options: GraphBuilderTraverseOptions, path?: string[]): Promise<void>;\nexport function explore(\n options: GraphBuilderTraverseOptions,\n path?: string[],\n): (builder: GraphBuilder) => Promise<void>;\nexport function explore(\n builderOrOptions: GraphBuilder | GraphBuilderTraverseOptions,\n optionsOrPath?: GraphBuilderTraverseOptions | string[],\n path?: string[],\n): Promise<void> | ((builder: GraphBuilder) => Promise<void>) {\n if (typeof builderOrOptions === 'object' && 'visitor' in builderOrOptions) {\n // Curried: explore(options, path?)\n const options = builderOrOptions as GraphBuilderTraverseOptions;\n const path = Array.isArray(optionsOrPath) ? optionsOrPath : undefined;\n return (builder: GraphBuilder) => exploreImpl(builder, options, path);\n } else {\n // Direct: explore(builder, options, path?)\n const builder = builderOrOptions as GraphBuilder;\n const options = optionsOrPath as GraphBuilderTraverseOptions;\n const pathArg = path ?? (Array.isArray(optionsOrPath) ? optionsOrPath : undefined);\n return exploreImpl(builder, options, pathArg);\n }\n}\n\n/**\n * Implementation helper for destroy.\n */\nconst destroyImpl = (builder: GraphBuilder): void => {\n const internal = builder as GraphBuilderImpl;\n internal._subscriptions.forEach((unsubscribe) => unsubscribe());\n internal._subscriptions.clear();\n};\n\n/**\n * Destroy the graph builder and clean up resources.\n */\nexport function destroy(builder: GraphBuilder): void;\nexport function destroy(): (builder: GraphBuilder) => void;\nexport function destroy(builder?: GraphBuilder): void | ((builder: GraphBuilder) => void) {\n if (builder === undefined) {\n // Curried: destroy()\n return (builder: GraphBuilder) => destroyImpl(builder);\n } else {\n // Direct: destroy(builder)\n return destroyImpl(builder);\n }\n}\n\n/**\n * Wait for all pending connector updates to be flushed.\n */\nexport const flush = (builder: GraphBuilder): Promise<void> => {\n return (builder as GraphBuilderImpl)._flushPromise;\n};\n\n//\n// Extension Creation\n//\n\n/**\n * A graph builder extension is used to add nodes to the graph.\n *\n * @param params.id The unique id of the extension.\n * @param params.relation The relation the graph is being expanded from the existing node.\n * @param params.position Affects the order the extensions are processed in.\n * @param params.resolver A function to add nodes to the graph based on just the node id.\n * @param params.connector A function to add nodes to the graph based on a connection to an existing node.\n * @param params.actions A function to add actions to the graph based on a connection to an existing node.\n * @param params.actionGroups A function to add action groups to the graph based on a connection to an existing node.\n */\nexport type CreateExtensionRawOptions = {\n id: string;\n relation?: Node.RelationInput;\n position?: Position;\n resolver?: ResolverExtension;\n connector?: ConnectorExtension;\n actions?: ActionsExtension;\n actionGroups?: ActionGroupsExtension;\n};\n\n/**\n * Create a graph builder extension (low-level API that works directly with Atoms).\n */\nexport const createExtensionRaw = (extension: CreateExtensionRawOptions): BuilderExtension[] => {\n const {\n id,\n position = 'static',\n relation = 'child',\n resolver: _resolver,\n connector: _connector,\n actions: _actions,\n actionGroups: _actionGroups,\n } = extension;\n const normalizedRelation = normalizeRelation(relation);\n const getId = (key: string) => `${id}/${key}`;\n\n const resolver =\n _resolver && Atom.family((id: string) => _resolver(id).pipe(Atom.withLabel(`graph-builder:_resolver:${id}`)));\n\n const connector =\n _connector &&\n Atom.family((node: Atom.Atom<Option.Option<Node.Node>>) =>\n _connector(node).pipe(Atom.withLabel(`graph-builder:_connector:${id}`)),\n );\n\n const actionGroups =\n _actionGroups &&\n Atom.family((node: Atom.Atom<Option.Option<Node.Node>>) =>\n _actionGroups(node).pipe(Atom.withLabel(`graph-builder:_actionGroups:${id}`)),\n );\n\n const actions =\n _actions &&\n Atom.family((node: Atom.Atom<Option.Option<Node.Node>>) =>\n _actions(node).pipe(Atom.withLabel(`graph-builder:_actions:${id}`)),\n );\n\n return [\n resolver ? { id: getId('resolver'), position, resolver } : undefined,\n connector\n ? ({\n id: getId('connector'),\n position,\n relation: normalizedRelation,\n connector: Atom.family((node) =>\n Atom.make((get) => {\n try {\n return get(connector(node));\n } catch (error) {\n log.warn('Error in connector', { id: getId('connector'), node, error });\n return [];\n }\n }).pipe(Atom.withLabel(`graph-builder:connector:${id}`)),\n ),\n } satisfies BuilderExtension)\n : undefined,\n actionGroups\n ? ({\n id: getId('actionGroups'),\n position,\n relation: Node.actionRelation(),\n connector: Atom.family((node) =>\n Atom.make((get) => {\n try {\n return get(actionGroups(node)).map((arg) => ({\n ...arg,\n data: Node.actionGroupSymbol,\n type: Node.ActionGroupType,\n }));\n } catch (error) {\n log.warn('Error in actionGroups', { id: getId('actionGroups'), node, error });\n return [];\n }\n }).pipe(Atom.withLabel(`graph-builder:connector:actionGroups:${id}`)),\n ),\n } satisfies BuilderExtension)\n : undefined,\n actions\n ? ({\n id: getId('actions'),\n position,\n relation: Node.actionRelation(),\n connector: Atom.family((node) =>\n Atom.make((get) => {\n try {\n return get(actions(node)).map((arg) => ({ ...arg, type: Node.ActionType }));\n } catch (error) {\n log.warn('Error in actions', { id: getId('actions'), node, error });\n return [];\n }\n }).pipe(Atom.withLabel(`graph-builder:connector:actions:${id}`)),\n ),\n } satisfies BuilderExtension)\n : undefined,\n ].filter(isNonNullable);\n};\n\n/**\n * Options for creating a graph builder extension with simplified API.\n * All callbacks must return Effects for dependency injection.\n * Effects may fail - errors are caught, logged, and the extension returns empty results.\n */\nexport type CreateExtensionOptions<TMatched = Node.Node, R = never> = {\n id: string;\n match: (node: Node.Node) => Option.Option<TMatched>;\n actions?: (\n matched: TMatched,\n get: Atom.Context,\n ) => Effect.Effect<Omit<Node.NodeArg<Node.ActionData<any>, any>, 'type'>[], Error, R>;\n connector?: (matched: TMatched, get: Atom.Context) => Effect.Effect<Node.NodeArg<any, any>[], Error, R>;\n resolver?: (id: string, get: Atom.Context) => Effect.Effect<Node.NodeArg<any, any> | null, Error, R>;\n relation?: Node.RelationInput;\n position?: Position;\n};\n\n/**\n * Run an Effect synchronously with the provided context.\n * If the effect fails, logs the error and returns the fallback value.\n * @internal\n */\nconst runEffectSyncWithFallback = <T, R>(\n effect: Effect.Effect<T, Error, R>,\n context: Context.Context<R>,\n extensionId: string,\n fallback: T,\n): T => {\n return Effect.runSync(\n effect.pipe(\n Effect.provide(context),\n Effect.catchAll((error) => {\n log.warn('Extension failed', { extension: extensionId, error });\n return Effect.succeed(fallback);\n }),\n ),\n );\n};\n\n/**\n * Create a graph builder extension with simplified API.\n * Returns an Effect to allow callbacks to access services via dependency injection.\n */\nexport const createExtension = <TMatched = Node.Node, R = never>(\n options: CreateExtensionOptions<TMatched, R>,\n): Effect.Effect<BuilderExtension[], never, R> =>\n Effect.map(Effect.context<R>(), (context) => {\n const { id, match, actions, connector, resolver, relation, position } = options;\n\n const connectorExtension = connector ? createConnectorWithRuntime(id, match, connector, context) : undefined;\n\n const actionsExtension = actions\n ? (node: Atom.Atom<Option.Option<Node.Node>>) =>\n Atom.make((get) =>\n Function.pipe(\n get(node),\n Option.flatMap(match),\n Option.map((matched) =>\n runEffectSyncWithFallback(actions(matched, get), context, id, []).map((action) => ({\n ...action,\n // Attach captured context for action execution.\n _actionContext: context,\n })),\n ),\n Option.getOrElse(() => []),\n ),\n )\n : undefined;\n\n const resolverExtension = resolver\n ? (nodeId: string) =>\n Atom.make((get) => runEffectSyncWithFallback(resolver(nodeId, get), context, id, null) ?? null)\n : undefined;\n\n return createExtensionRaw({\n id,\n relation,\n position,\n connector: connectorExtension,\n actions: actionsExtension,\n resolver: resolverExtension,\n });\n });\n\n/**\n * Create a connector extension from a matcher and factory function.\n * The factory's data type is inferred from the matcher's return type.\n */\nexport const createConnector = <TData>(\n matcher: (node: Node.Node) => Option.Option<TData>,\n factory: (data: TData, get: Atom.Context) => Node.NodeArg<any>[],\n): ConnectorExtension => {\n return (node: Atom.Atom<Option.Option<Node.Node>>) =>\n Atom.make((get) =>\n Function.pipe(\n get(node),\n Option.flatMap(matcher),\n Option.map((data) => factory(data, get)),\n Option.getOrElse(() => []),\n ),\n );\n};\n\n/**\n * Create a connector extension from a matcher and factory function with Effect support.\n * The factory must return an Effect. Errors are caught and logged.\n * @internal\n */\nconst createConnectorWithRuntime = <TData, R>(\n extensionId: string,\n matcher: (node: Node.Node) => Option.Option<TData>,\n factory: (data: TData, get: Atom.Context) => Effect.Effect<Node.NodeArg<any>[], Error, R>,\n context: Context.Context<R>,\n): ConnectorExtension => {\n return (node: Atom.Atom<Option.Option<Node.Node>>) =>\n Atom.make((get) =>\n Function.pipe(\n get(node),\n Option.flatMap(matcher),\n Option.map((data) => runEffectSyncWithFallback(factory(data, get), context, extensionId, [])),\n Option.getOrElse(() => []),\n ),\n );\n};\n\n/**\n * Options for creating a type-based extension.\n * All callbacks must return Effects for dependency injection.\n * Effects may fail - errors are caught, logged, and the extension returns empty results.\n */\nexport type CreateTypeExtensionOptions<T extends Type.AnyEntity = Type.AnyEntity, R = never> = {\n id: string;\n type: T;\n actions?: (\n object: Entity.Entity<Schema.Schema.Type<T>>,\n get: Atom.Context,\n ) => Effect.Effect<Omit<Node.NodeArg<Node.ActionData<any>>, 'type'>[], Error, R>;\n connector?: (\n object: Entity.Entity<Schema.Schema.Type<T>>,\n get: Atom.Context,\n ) => Effect.Effect<Node.NodeArg<any>[], Error, R>;\n relation?: Node.RelationInput;\n position?: Position;\n};\n\n/**\n * Create an extension that matches nodes by schema type.\n * The entity type is inferred from the schema type and works for both object and relation schemas.\n * Returns an Effect to allow callbacks to access services via dependency injection.\n */\nexport const createTypeExtension = <T extends Type.AnyEntity, R = never>(\n options: CreateTypeExtensionOptions<T, R>,\n): Effect.Effect<BuilderExtension[], never, R> => {\n const { id, type, actions, connector, relation, position } = options;\n return createExtension<Entity.Entity<Schema.Schema.Type<T>>, R>({\n id,\n match: NodeMatcher.whenEchoType(type),\n actions,\n connector,\n relation,\n position,\n });\n};\n\n//\n// Extension Utilities\n//\n\nconst connectorKey = (id: string, relation: Node.RelationInput): string =>\n `${id}${Separators.primary}${Graph.relationKey(relation)}`;\n\nconst relationFromConnectorKey = (key: string): { id: string; relation: Node.Relation } => {\n const separatorIndex = key.indexOf(Separators.primary);\n const id = key.slice(0, separatorIndex);\n return { id, relation: Graph.relationFromKey(key.slice(separatorIndex + 1)) };\n};\n\nconst subscriptionKey = (id: string, kind: string, detail?: string): string =>\n detail != null\n ? `${id}${Separators.primary}${kind}${Separators.primary}${detail}`\n : `${id}${Separators.primary}${kind}`;\n\nexport const flattenExtensions = (extension: BuilderExtensions, acc: BuilderExtension[] = []): BuilderExtension[] => {\n if (Array.isArray(extension)) {\n return [...acc, ...extension.flatMap((ext) => flattenExtensions(ext, acc))];\n } else {\n return [...acc, extension];\n }\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Option from 'effect/Option';\nimport type * as Schema from 'effect/Schema';\n\nimport { type Entity, Obj, type Type } from '@dxos/echo';\n\nimport * as Node from './node';\n\n/**\n * Type for a node matcher function that returns an Option of the matched data.\n * Matchers are used to filter and transform nodes in the app graph.\n *\n * @template TData - The type of data returned when the matcher succeeds.\n * Defaults to Node.Node, but can be a more specific type (e.g., an ECHO entity).\n */\nexport type NodeMatcher<TData = Node.Node> = (node: Node.Node) => Option.Option<TData>;\n\n//\n// Basic Node Matchers\n//\n\n/**\n * Matches the root node of the graph.\n *\n * @returns Option.some(node) if the node is the root, Option.none() otherwise.\n *\n * @example\n * ```ts\n * GraphBuilder.createExtension({\n * id: 'my-extension',\n * match: NodeMatcher.whenRoot,\n * connector: (node) => Effect.succeed([...]),\n * });\n * ```\n */\nexport const whenRoot = (node: Node.Node): Option.Option<Node.Node> =>\n node.id === Node.RootId ? Option.some(node) : Option.none();\n\n/**\n * Matches a node by its exact ID.\n *\n * @param id - The node ID to match against.\n * @returns A matcher that returns Option.some(node) if IDs match, Option.none() otherwise.\n *\n * @example\n * ```ts\n * GraphBuilder.createExtension({\n * id: 'spaces-extension',\n * match: NodeMatcher.whenId('spaces'),\n * connector: (node) => Effect.succeed([...]),\n * });\n * ```\n */\nexport const whenId =\n (id: string) =>\n (node: Node.Node): Option.Option<Node.Node> =>\n node.id === id ? Option.some(node) : Option.none();\n\n/**\n * Matches a node by its type string (the `node.type` property).\n *\n * @param type - The node type string to match against.\n * @returns A matcher that returns Option.some(node) if types match, Option.none() otherwise.\n *\n * @example\n * ```ts\n * GraphBuilder.createExtension({\n * id: 'space-settings-extension',\n * match: NodeMatcher.whenNodeType('dxos.org/plugin/space/settings'),\n * connector: (node) => Effect.succeed([...]),\n * });\n * ```\n */\nexport const whenNodeType =\n (type: string) =>\n (node: Node.Node): Option.Option<Node.Node> =>\n node.type === type ? Option.some(node) : Option.none();\n\n//\n// ECHO Data Matchers\n//\n\n/**\n * Matches a node whose data is an instance of the given ECHO schema type.\n * Returns the **typed entity data** (not the node) for direct use in callbacks.\n *\n * Use this when you need to work directly with the typed ECHO entity in your\n * connector or actions callback.\n *\n * @template T - The ECHO schema type to match against.\n * @param type - The ECHO schema (e.g., `Collection.Collection`, `Document.Document`).\n * @returns A matcher that returns Option.some(entity) if the data matches, Option.none() otherwise.\n *\n * @example\n * ```ts\n * GraphBuilder.createExtension({\n * id: 'collection-extension',\n * match: NodeMatcher.whenEchoType(Collection.Collection),\n * connector: (collection) => {\n * // `collection` is typed as Collection.Collection\n * return Effect.succeed(collection.objects.map(...));\n * },\n * });\n * ```\n *\n * @see {@link whenEchoTypeMatches} - Use instead when composing with whenAll/whenAny.\n */\nexport const whenEchoType =\n <T extends Type.AnyEntity>(type: T): NodeMatcher<Entity.Entity<Schema.Schema.Type<T>>> =>\n (node: Node.Node): Option.Option<Entity.Entity<Schema.Schema.Type<T>>> =>\n Obj.instanceOf(type, node.data) ? Option.some(node.data) : Option.none();\n\n/**\n * Matches a node whose data is any ECHO object.\n * Returns the **object data** (not the node) for direct use in callbacks.\n *\n * Use this when you need to work with any ECHO object regardless of its specific type.\n *\n * @returns Option.some(object) if the node's data is an ECHO object, Option.none() otherwise.\n *\n * @example\n * ```ts\n * GraphBuilder.createExtension({\n * id: 'object-settings',\n * match: NodeMatcher.whenEchoObject,\n * connector: (object) => {\n * // `object` is typed as Obj.Unknown\n * const id = Obj.getDXN(object).toString();\n * return Effect.succeed([{ id: `${id}/settings`, ... }]);\n * },\n * });\n * ```\n *\n * @see {@link whenEchoObjectMatches} - Use instead when composing with whenAll/whenAny.\n */\nexport const whenEchoObject = (node: Node.Node): Option.Option<Obj.Unknown> =>\n Obj.isObject(node.data) ? Option.some(node.data) : Option.none();\n\n//\n// Composition Matchers\n//\n\n/**\n * Composes multiple matchers with AND logic - all matchers must match for success.\n * Returns the **node** (not the matched data) to enable further composition.\n *\n * @param matchers - The matchers to combine. All must return Option.some for success.\n * @returns A matcher that returns Option.some(node) if all match, Option.none() otherwise.\n *\n * @example\n * ```ts\n * // Match ECHO objects that are NOT Channels\n * const whenCommentable = NodeMatcher.whenAll(\n * NodeMatcher.whenEchoObjectMatches,\n * NodeMatcher.whenNot(NodeMatcher.whenEchoTypeMatches(Channel.Channel)),\n * );\n * ```\n */\nexport const whenAll =\n (...matchers: NodeMatcher[]): NodeMatcher =>\n (node: Node.Node): Option.Option<Node.Node> => {\n for (const candidate of matchers) {\n if (Option.isNone(candidate(node))) {\n return Option.none();\n }\n }\n return Option.some(node);\n };\n\n/**\n * Composes multiple matchers with OR logic - at least one matcher must match.\n * Returns the **node** (not the matched data) to enable further composition.\n *\n * @param matchers - The matchers to combine. At least one must return Option.some.\n * @returns A matcher that returns Option.some(node) if any match, Option.none() otherwise.\n *\n * @example\n * ```ts\n * // Match nodes that are either Sequences or Prompts\n * const whenInvocable = NodeMatcher.whenAny(\n * NodeMatcher.whenEchoTypeMatches(Sequence),\n * NodeMatcher.whenEchoTypeMatches(Prompt.Prompt),\n * );\n * ```\n */\nexport const whenAny =\n (...matchers: NodeMatcher[]): NodeMatcher =>\n (node: Node.Node): Option.Option<Node.Node> => {\n for (const candidate of matchers) {\n if (Option.isSome(candidate(node))) {\n return Option.some(node);\n }\n }\n return Option.none();\n };\n\n/**\n * Matches a node whose data is an instance of the given ECHO schema type.\n * Returns the **node** (not the data) to enable composition with whenAll/whenAny/whenNot.\n *\n * Use this instead of {@link whenEchoType} when you need to combine matchers.\n * The difference is what's returned:\n * - `whenEchoType` returns the typed entity (for direct use)\n * - `whenEchoTypeMatches` returns the node (for composition)\n *\n * @template T - The ECHO schema type to match against.\n * @param type - The ECHO schema (e.g., `Channel.Channel`, `Document.Document`).\n * @returns A matcher that returns Option.some(node) if the data matches, Option.none() otherwise.\n *\n * @example\n * ```ts\n * // Use with whenAny for OR logic\n * const whenPresentable = NodeMatcher.whenAny(\n * NodeMatcher.whenEchoTypeMatches(Collection.Collection),\n * NodeMatcher.whenEchoTypeMatches(Markdown.Document),\n * );\n *\n * // Use with whenNot for exclusion\n * const whenNotChannel = NodeMatcher.whenNot(\n * NodeMatcher.whenEchoTypeMatches(Channel.Channel),\n * );\n * ```\n *\n * @see {@link whenEchoType} - Use instead when you need the typed entity directly.\n */\nexport const whenEchoTypeMatches =\n <T extends Type.AnyEntity>(type: T): NodeMatcher =>\n (node: Node.Node): Option.Option<Node.Node> =>\n Obj.instanceOf(type, node.data) ? Option.some(node) : Option.none();\n\n/**\n * Matches a node whose data is any ECHO object.\n * Returns the **node** (not the data) to enable composition with whenAll/whenAny/whenNot.\n *\n * Use this instead of {@link whenEchoObject} when you need to combine matchers.\n * The difference is what's returned:\n * - `whenEchoObject` returns the object data (for direct use)\n * - `whenEchoObjectMatches` returns the node (for composition)\n *\n * @returns Option.some(node) if the node's data is an ECHO object, Option.none() otherwise.\n *\n * @example\n * ```ts\n * // Match ECHO objects that are not system types\n * const whenUserObject = NodeMatcher.whenAll(\n * NodeMatcher.whenEchoObjectMatches,\n * NodeMatcher.whenNot(NodeMatcher.whenEchoTypeMatches(SystemType)),\n * );\n * ```\n *\n * @see {@link whenEchoObject} - Use instead when you need the object data directly.\n */\nexport const whenEchoObjectMatches = (node: Node.Node): Option.Option<Node.Node> =>\n Obj.isObject(node.data) ? Option.some(node) : Option.none();\n\n/**\n * Negates a matcher - matches when the given matcher does NOT match.\n * Useful for exclusion patterns like \"any object EXCEPT type X\".\n *\n * @param matcher - The matcher to negate.\n * @returns A matcher that returns Option.some(node) if the input matcher returns none,\n * and Option.none() if the input matcher returns some.\n *\n * @example\n * ```ts\n * // Match any ECHO object that is NOT a Channel\n * const whenCommentable = NodeMatcher.whenAll(\n * NodeMatcher.whenEchoObjectMatches,\n * NodeMatcher.whenNot(NodeMatcher.whenEchoTypeMatches(Channel.Channel)),\n * );\n *\n * // Match any node that is NOT the root\n * const whenNotRoot = NodeMatcher.whenNot(NodeMatcher.whenRoot);\n * ```\n */\nexport const whenNot =\n (matcher: NodeMatcher): NodeMatcher =>\n (node: Node.Node): Option.Option<Node.Node> =>\n Option.isNone(matcher(node)) ? Option.some(node) : Option.none();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Atom", "observableFamily", "Atom", "family", "observable", "make", "get", "subscription", "subscribe", "value", "setSelf", "addFinalizer", "unsubscribe", "fromObservable", "Atom", "Registry", "Function", "Option", "Pipeable", "Record", "Event", "Trigger", "todo", "invariant", "log", "isNonNullable", "RootId", "RootType", "ActionType", "ActionGroupType", "relation", "kind", "direction", "childRelation", "actionRelation", "isGraphNode", "data", "properties", "isAction", "type", "actionGroupSymbol", "Symbol", "isActionGroup", "isActionLike", "Separators", "primary", "secondary", "normalizeRelation", "relation", "childRelation", "shallowEqual", "a", "b", "keysA", "Object", "keys", "keysB", "length", "every", "k", "nodeArgsUnchanged", "prev", "next", "prevNode", "idx", "nextNode", "id", "type", "data", "properties", "graphSymbol", "Symbol", "getGraph", "node", "graph", "invariant", "GraphTypeId", "for", "GraphKind", "GraphImpl", "pipe", "pipeArguments", "arguments", "onNodeChanged", "Event", "_onExpand", "_onInitialize", "_onRemoveNode", "_registry", "_expanded", "empty", "_pendingExpands", "Set", "_initialized", "_initialEdges", "_initialNodes", "fromEntries", "RootId", "_constructNode", "id", "type", "RootType", "data", "properties", "_node", "Atom", "family", "initial", "flatten", "get", "make", "keepAlive", "withLabel", "_nodeOrThrow", "isSome", "value", "_edges", "getOrElse", "_connections", "key", "relation", "relationFromConnectionKey", "edges", "relationKey", "map", "filter", "o", "_actions", "connectionKey", "actionRelation", "_json", "toJSON", "seen", "nodes", "obj", "label", "length", "n", "nextSeen", "includes", "undefined", "isNonNullable", "root", "registry", "onInitialize", "onExpand", "onRemoveNode", "Registry", "forEach", "Record", "set", "Object", "entries", "source", "json", "jsonImpl", "nodeImpl", "nodeOrThrow", "nodeOrThrowImpl", "connections", "connectionsImpl", "actions", "actionsImpl", "edgesImpl", "some", "getInternal", "internal", "getNodeImpl", "getNode", "graphOrId", "getNodeOrThrowImpl", "getNodeOrThrow", "getRoot", "getConnectionsImpl", "getConnections", "idOrRelation", "rel", "getActionsImpl", "getActions", "getEdgesImpl", "getEdges", "traverseImpl", "options", "path", "visitor", "shouldContinue", "values", "child", "traverse", "graphOrOptions", "optionsOrPath", "pathArg", "Array", "isArray", "getPathImpl", "params", "flatMap", "found", "none", "target", "getPath", "graphOrParams", "waitForPathImpl", "timeout", "interval", "Promise", "resolve", "trigger", "Trigger", "i", "setInterval", "wake", "wait", "finally", "clearInterval", "waitForPath", "paramsOrOptions", "opts", "initializeImpl", "initialized", "log", "initialize", "expandImpl", "normalizedRelation", "normalizeRelation", "Separators", "primary", "nodeOpt", "isNone", "add", "deferred", "expanded", "expand", "sortEdgesImpl", "order", "edgesAtom", "relationId", "current", "unsorted", "sorted", "newOrder", "every", "sortEdges", "relationOrOrder", "addNodesImpl", "batch", "addNodeImpl", "addNodes", "graphOrNodes", "nodeArg", "rest", "nodeAtom", "existingNode", "Option", "match", "onSome", "existing", "typeChanged", "dataChanged", "shallowEqual", "propertiesChanged", "keys", "newNode", "emit", "onNone", "prefix", "toApply", "k", "startsWith", "pendingKey", "delete", "relationFromKey", "slice", "addEdgesImpl", "todo", "addNode", "graphOrNodeArg", "removeNodesImpl", "ids", "removeNodeImpl", "removeNodes", "graphOrIds", "idsOrEdges", "edgesArg", "nodeEdges", "edgesToRemove", "relationKeyValue", "relatedIds", "isInboundRelation", "direction", "relatedId", "push", "inverseRelation", "removeEdgesImpl", "removeNode", "idOrEdges", "edge", "addEdgeImpl", "addEdges", "graphOrEdges", "edgeArg", "inverse", "inverseId", "sourceAtom", "sourceList", "targetAtom", "targetList", "addEdge", "graphOrEdgeArg", "removeOrphans", "removeEdgeImpl", "removeEdges", "edgesOrRemoveOrphans", "removeOrphansArg", "sourceAfter", "targetAfter", "isEmpty", "removeEdge", "edgeArgOrRemoveOrphans", "normalized", "kind", "secondary", "encoded", "separatorIndex", "lastIndexOf", "directionRaw", "indexOf", "encodedRelation", "make", "Atom", "Registry", "Array", "Effect", "Function", "Option", "Pipeable", "Record", "scheduleTask", "yieldOrContinue", "log", "byPosition", "getDebugName", "isNonNullable", "Option", "Obj", "whenRoot", "node", "id", "RootId", "some", "none", "whenId", "whenNodeType", "type", "whenEchoType", "Obj", "instanceOf", "data", "whenEchoObject", "isObject", "whenAll", "matchers", "candidate", "isNone", "whenAny", "isSome", "whenEchoTypeMatches", "whenEchoObjectMatches", "whenNot", "matcher", "GraphBuilderTypeId", "Symbol", "for", "GraphBuilderImpl", "pipe", "pipeArguments", "arguments", "_subscriptions", "Map", "_dirtyConnectors", "_connectorPrevious", "_connectorPreviousArgs", "_flushScheduled", "_flushPromise", "Promise", "resolve", "_extensions", "Atom", "make", "empty", "keepAlive", "withLabel", "_initialized", "_registry", "_graph", "registry", "params", "Registry", "graph", "onExpand", "id", "relation", "_onExpand", "onInitialize", "_onInitialize", "onRemoveNode", "_onRemoveNode", "extensions", "_applyConnectorUpdate", "key", "nodes", "previous", "relationFromConnectorKey", "ids", "map", "node", "removed", "filter", "pid", "includes", "set", "Graph", "removeEdges", "target", "source", "addNodes", "addEdges", "length", "sortedIds", "sort", "a", "b", "byPosition", "properties", "n", "sortEdges", "_scheduleDirtyFlush", "scheduleTask", "size", "entries", "clear", "batch", "strategy", "_resolvers", "family", "get", "values", "sortBy", "resolver", "isNonNullable", "head", "_connectors", "sourceNode", "getOrElse", "undefined", "ext", "relationKey", "connector", "result", "push", "log", "getDebugName", "_expandRelation", "kind", "direction", "expand", "connectorKey", "connectors", "cancel", "subscribe", "every", "nodeId", "idx", "prevArgs", "nodeArgsUnchanged", "immediate", "subscriptionKey", "trigger", "Option", "match", "onSome", "wake", "onNone", "removeNodes", "prefix", "Separators", "primary", "cleanup", "startsWith", "delete", "from", "pickle", "edges", "JSON", "parse", "addExtensionImpl", "builder", "internal", "flattenExtensions", "forEach", "extension", "addExtension", "builderOrExtensions", "removeExtensionImpl", "remove", "removeExtension", "builderOrId", "exploreImpl", "options", "path", "RootId", "visitor", "yieldOrContinue", "nodeOrThrow", "shouldContinue", "Object", "flatMap", "all", "nodeArg", "_node", "_constructNode", "reset", "dispose", "explore", "builderOrOptions", "optionsOrPath", "isArray", "pathArg", "destroyImpl", "unsubscribe", "destroy", "flush", "createExtensionRaw", "position", "_resolver", "_connector", "actions", "_actions", "actionGroups", "_actionGroups", "normalizedRelation", "normalizeRelation", "getId", "error", "warn", "actionRelation", "arg", "data", "actionGroupSymbol", "type", "ActionGroupType", "ActionType", "runEffectSyncWithFallback", "effect", "context", "extensionId", "fallback", "runSync", "provide", "catchAll", "succeed", "createExtension", "connectorExtension", "createConnectorWithRuntime", "actionsExtension", "matched", "action", "_actionContext", "resolverExtension", "createConnector", "matcher", "factory", "createTypeExtension", "whenEchoType", "separatorIndex", "indexOf", "slice", "relationFromKey", "detail", "acc"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/graph.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/atoms.ts":{"bytes":2433,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true}],"format":"esm"},"src/node.ts":{"bytes":9295,"imports":[],"format":"esm"},"src/util.ts":{"bytes":6181,"imports":[{"path":"src/node.ts","kind":"import-statement","original":"./node"}],"format":"esm"},"src/graph.ts":{"bytes":125283,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"effect/Function","kind":"import-statement","external":true},{"path":"effect/Option","kind":"import-statement","external":true},{"path":"effect/Pipeable","kind":"import-statement","external":true},{"path":"effect/Record","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"src/node.ts","kind":"import-statement","original":"./node"},{"path":"src/util.ts","kind":"import-statement","original":"./util"}],"format":"esm"},"src/node-matcher.ts":{"bytes":24097,"imports":[{"path":"effect/Option","kind":"import-statement","external":true},{"path":"@dxos/echo","kind":"import-statement","external":true},{"path":"src/node.ts","kind":"import-statement","original":"./node"}],"format":"esm"},"src/graph-builder.ts":{"bytes":81364,"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"effect/Array","kind":"import-statement","external":true},{"path":"effect/Effect","kind":"import-statement","external":true},{"path":"effect/Function","kind":"import-statement","external":true},{"path":"effect/Option","kind":"import-statement","external":true},{"path":"effect/Pipeable","kind":"import-statement","external":true},{"path":"effect/Record","kind":"import-statement","external":true},{"path":"main-thread-scheduling","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"src/graph.ts","kind":"import-statement","original":"./graph"},{"path":"src/node.ts","kind":"import-statement","original":"./node"},{"path":"src/node-matcher.ts","kind":"import-statement","original":"./node-matcher"},{"path":"src/util.ts","kind":"import-statement","original":"./util"}],"format":"esm"},"src/index.ts":{"bytes":1468,"imports":[{"path":"src/atoms.ts","kind":"import-statement","original":"./atoms"},{"path":"src/graph.ts","kind":"import-statement","original":"./graph"},{"path":"src/graph-builder.ts","kind":"import-statement","original":"./graph-builder"},{"path":"src/node.ts","kind":"import-statement","original":"./node"},{"path":"src/node-matcher.ts","kind":"import-statement","original":"./node-matcher"}],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":131873},"dist/lib/browser/index.mjs":{"imports":[{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"effect/Function","kind":"import-statement","external":true},{"path":"effect/Option","kind":"import-statement","external":true},{"path":"effect/Pipeable","kind":"import-statement","external":true},{"path":"effect/Record","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@effect-atom/atom-react","kind":"import-statement","external":true},{"path":"effect/Array","kind":"import-statement","external":true},{"path":"effect/Effect","kind":"import-statement","external":true},{"path":"effect/Function","kind":"import-statement","external":true},{"path":"effect/Option","kind":"import-statement","external":true},{"path":"effect/Pipeable","kind":"import-statement","external":true},{"path":"effect/Record","kind":"import-statement","external":true},{"path":"main-thread-scheduling","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"effect/Option","kind":"import-statement","external":true},{"path":"@dxos/echo","kind":"import-statement","external":true}],"exports":["CreateAtom","Graph","GraphBuilder","Node","NodeMatcher"],"entryPoint":"src/index.ts","inputs":{"src/atoms.ts":{"bytesInOutput":481},"src/index.ts":{"bytesInOutput":0},"src/graph.ts":{"bytesInOutput":27229},"src/node.ts":{"bytesInOutput":1418},"src/util.ts":{"bytesInOutput":884},"src/graph-builder.ts":{"bytesInOutput":16871},"src/node-matcher.ts":{"bytesInOutput":1682}},"bytes":49096}}}
|