@statelyai/graph 0.3.0 → 0.4.0
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/README.md +12 -11
- package/dist/{adjacency-list-A4_Eiwj3.mjs → adjacency-list-Bv4tfiM3.mjs} +33 -0
- package/dist/{algorithms-DBU7nmIV.mjs → algorithms-CnTmuX9t.mjs} +682 -24
- package/dist/algorithms.d.mts +479 -10
- package/dist/algorithms.mjs +1 -1
- package/dist/converter-C5DlzzHs.mjs +67 -0
- package/dist/{edge-list-DuHMz8hf.mjs → edge-list-R1SUbHwe.mjs} +32 -0
- package/dist/formats/adjacency-list/index.d.mts +35 -1
- package/dist/formats/adjacency-list/index.mjs +1 -1
- package/dist/formats/converter/index.d.mts +37 -3
- package/dist/formats/converter/index.mjs +1 -1
- package/dist/formats/cytoscape/index.d.mts +50 -2
- package/dist/formats/cytoscape/index.mjs +53 -5
- package/dist/formats/d3/index.d.mts +48 -2
- package/dist/formats/d3/index.mjs +48 -2
- package/dist/formats/dot/index.d.mts +56 -2
- package/dist/formats/dot/index.mjs +55 -2
- package/dist/formats/edge-list/index.d.mts +34 -1
- package/dist/formats/edge-list/index.mjs +1 -1
- package/dist/formats/gexf/index.d.mts +1 -1
- package/dist/formats/gexf/index.mjs +5 -5
- package/dist/formats/gml/index.d.mts +58 -2
- package/dist/formats/gml/index.mjs +59 -4
- package/dist/formats/graphml/index.d.mts +1 -1
- package/dist/formats/graphml/index.mjs +2 -2
- package/dist/formats/jgf/index.d.mts +51 -2
- package/dist/formats/jgf/index.mjs +54 -5
- package/dist/formats/mermaid/index.d.mts +201 -8
- package/dist/formats/mermaid/index.mjs +365 -26
- package/dist/formats/tgf/index.d.mts +47 -2
- package/dist/formats/tgf/index.mjs +46 -2
- package/dist/formats/xyflow/index.d.mts +73 -0
- package/dist/formats/xyflow/index.mjs +133 -0
- package/dist/index.d.mts +320 -14
- package/dist/index.mjs +117 -9
- package/dist/{indexing-BFFVMnjF.mjs → indexing-DitHphT7.mjs} +37 -7
- package/dist/queries.d.mts +353 -8
- package/dist/queries.mjs +359 -15
- package/dist/{types-B6Tpeerk.d.mts → types-Bq_fmLwW.d.mts} +15 -4
- package/package.json +3 -1
- package/dist/converter-DnbeyE_p.mjs +0 -33
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { o as invalidateIndex, t as getIndex } from "./indexing-
|
|
2
|
-
import { A as addNode, B as hasNode, C as isAcyclic, D as GraphInstance, E as joinPaths, F as deleteEntities, H as updateEntities, I as deleteNode, L as getEdge, M as createGraphFromTransition, N as createVisualGraph, O as addEdge, P as deleteEdge, R as getNode, S as hasPath, T as isTree, U as updateNode, V as updateEdge, _ as getShortestPaths, a as genPreorders, b as getStronglyConnectedComponents, c as getAllPairsShortestPaths, d as getMinimumSpanningTree, f as getPostorder, g as getShortestPath, h as getPreorders, i as genPostorders, j as createGraph, k as addEntities, l as getConnectedComponents, m as getPreorder, n as dfs, o as genShortestPaths, p as getPostorders, r as genCycles, s as genSimplePaths, t as bfs, u as getCycles, v as getSimplePath, w as isConnected, x as getTopologicalSort, y as getSimplePaths, z as hasEdge } from "./algorithms-
|
|
1
|
+
import { o as invalidateIndex, t as getIndex } from "./indexing-DitHphT7.mjs";
|
|
2
|
+
import { A as addNode, B as hasNode, C as isAcyclic, D as GraphInstance, E as joinPaths, F as deleteEntities, H as updateEntities, I as deleteNode, L as getEdge, M as createGraphFromTransition, N as createVisualGraph, O as addEdge, P as deleteEdge, R as getNode, S as hasPath, T as isTree, U as updateNode, V as updateEdge, _ as getShortestPaths, a as genPreorders, b as getStronglyConnectedComponents, c as getAllPairsShortestPaths, d as getMinimumSpanningTree, f as getPostorder, g as getShortestPath, h as getPreorders, i as genPostorders, j as createGraph, k as addEntities, l as getConnectedComponents, m as getPreorder, n as dfs, o as genShortestPaths, p as getPostorders, r as genCycles, s as genSimplePaths, t as bfs, u as getCycles, v as getSimplePath, w as isConnected, x as getTopologicalSort, y as getSimplePaths, z as hasEdge } from "./algorithms-CnTmuX9t.mjs";
|
|
3
3
|
import { getAncestors, getChildren, getDegree, getDepth, getDescendants, getEdgeBetween, getEdgesOf, getInDegree, getInEdges, getLCA, getNeighbors, getOutDegree, getOutEdges, getParent, getPredecessors, getRelativeDistance, getRelativeDistanceMap, getRoots, getSiblings, getSinks, getSources, getSuccessors, isCompound, isLeaf } from "./queries.mjs";
|
|
4
|
-
import { n as createFormatConverter } from "./converter-
|
|
4
|
+
import { n as createFormatConverter } from "./converter-C5DlzzHs.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/diff.ts
|
|
7
7
|
function nodeToConfig(node) {
|
|
8
8
|
const config = { id: node.id };
|
|
9
|
-
if (node.parentId
|
|
10
|
-
if (node.initialNodeId
|
|
9
|
+
if (node.parentId) config.parentId = node.parentId;
|
|
10
|
+
if (node.initialNodeId) config.initialNodeId = node.initialNodeId;
|
|
11
11
|
if (node.label !== "") config.label = node.label;
|
|
12
12
|
if (node.data !== void 0) config.data = node.data;
|
|
13
13
|
if (node.x !== void 0) config.x = node.x;
|
|
@@ -67,7 +67,21 @@ const EDGE_COMPARE_KEYS = [
|
|
|
67
67
|
"color",
|
|
68
68
|
"style"
|
|
69
69
|
];
|
|
70
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Compute a structured diff from graph `a` to graph `b` by matching IDs.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { createGraph, getDiff } from '@statelyai/graph';
|
|
76
|
+
*
|
|
77
|
+
* const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
78
|
+
* const b = createGraph({ nodes: [{ id: 'n1', label: 'hello' }, { id: 'n2' }], edges: [] });
|
|
79
|
+
*
|
|
80
|
+
* const diff = getDiff(a, b);
|
|
81
|
+
* // diff.nodes.added → [{ id: 'n2' }]
|
|
82
|
+
* // diff.nodes.updated → [{ id: 'n1', old: { label: '' }, new: { label: 'hello' } }]
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
71
85
|
function getDiff(a, b) {
|
|
72
86
|
const aNodeMap = new Map(a.nodes.map((n) => [n.id, n]));
|
|
73
87
|
const bNodeMap = new Map(b.nodes.map((n) => [n.id, n]));
|
|
@@ -123,11 +137,37 @@ function getDiff(a, b) {
|
|
|
123
137
|
for (const [id, edgeA] of aEdgeMap) if (!bEdgeMap.has(id)) diff.edges.removed.push(edgeToConfig(edgeA));
|
|
124
138
|
return diff;
|
|
125
139
|
}
|
|
126
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* Check if a diff has zero changes.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* import { createGraph, getDiff, isEmptyDiff } from '@statelyai/graph';
|
|
146
|
+
*
|
|
147
|
+
* const g = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
148
|
+
* const diff = getDiff(g, g);
|
|
149
|
+
* isEmptyDiff(diff); // true
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
127
152
|
function isEmptyDiff(diff) {
|
|
128
153
|
return diff.nodes.added.length === 0 && diff.nodes.removed.length === 0 && diff.nodes.updated.length === 0 && diff.edges.added.length === 0 && diff.edges.removed.length === 0 && diff.edges.updated.length === 0;
|
|
129
154
|
}
|
|
130
|
-
/**
|
|
155
|
+
/**
|
|
156
|
+
* Invert a diff: swap added/removed, swap old/new in updates.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { createGraph, getDiff, invertDiff } from '@statelyai/graph';
|
|
161
|
+
*
|
|
162
|
+
* const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
163
|
+
* const b = createGraph({ nodes: [{ id: 'n2' }], edges: [] });
|
|
164
|
+
*
|
|
165
|
+
* const diff = getDiff(a, b);
|
|
166
|
+
* const inv = invertDiff(diff);
|
|
167
|
+
* // inv.nodes.added contains n1 (was removed)
|
|
168
|
+
* // inv.nodes.removed contains n2 (was added)
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
131
171
|
function invertDiff(diff) {
|
|
132
172
|
return {
|
|
133
173
|
nodes: {
|
|
@@ -153,6 +193,17 @@ function invertDiff(diff) {
|
|
|
153
193
|
/**
|
|
154
194
|
* Compute an ordered patch list from graph `a` to graph `b`.
|
|
155
195
|
* Order: delete edges → delete nodes → add nodes → add edges → update nodes → update edges.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* import { createGraph, getPatches } from '@statelyai/graph';
|
|
200
|
+
*
|
|
201
|
+
* const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
202
|
+
* const b = createGraph({ nodes: [{ id: 'n1' }, { id: 'n2' }], edges: [] });
|
|
203
|
+
*
|
|
204
|
+
* const patches = getPatches(a, b);
|
|
205
|
+
* // patches → [{ op: 'addNode', node: { id: 'n2' } }]
|
|
206
|
+
* ```
|
|
156
207
|
*/
|
|
157
208
|
function getPatches(a, b) {
|
|
158
209
|
return toPatches(getDiff(a, b));
|
|
@@ -160,6 +211,18 @@ function getPatches(a, b) {
|
|
|
160
211
|
/**
|
|
161
212
|
* **Mutable.** Apply patches to a graph in order.
|
|
162
213
|
* Delegates to addNode/deleteNode/updateNode/addEdge/deleteEdge/updateEdge.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* import { createGraph, getPatches, applyPatches } from '@statelyai/graph';
|
|
218
|
+
*
|
|
219
|
+
* const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
220
|
+
* const b = createGraph({ nodes: [{ id: 'n1' }, { id: 'n2' }], edges: [] });
|
|
221
|
+
*
|
|
222
|
+
* const patches = getPatches(a, b);
|
|
223
|
+
* applyPatches(a, patches);
|
|
224
|
+
* // a now contains both n1 and n2
|
|
225
|
+
* ```
|
|
163
226
|
*/
|
|
164
227
|
function applyPatches(graph, patches) {
|
|
165
228
|
for (const patch of patches) switch (patch.op) {
|
|
@@ -188,6 +251,18 @@ function applyPatches(graph, patches) {
|
|
|
188
251
|
* Order: add nodes → update edges → delete edges → delete nodes → add edges → update nodes.
|
|
189
252
|
* This avoids cascading deletes removing edges that are being updated,
|
|
190
253
|
* and ensures new nodes exist before edges reference them.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* import { createGraph, getDiff, toPatches } from '@statelyai/graph';
|
|
258
|
+
*
|
|
259
|
+
* const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
260
|
+
* const b = createGraph({ nodes: [{ id: 'n2' }], edges: [] });
|
|
261
|
+
*
|
|
262
|
+
* const diff = getDiff(a, b);
|
|
263
|
+
* const patches = toPatches(diff);
|
|
264
|
+
* // patches → [{ op: 'addNode', ... }, { op: 'deleteNode', ... }]
|
|
265
|
+
* ```
|
|
191
266
|
*/
|
|
192
267
|
function toPatches(diff) {
|
|
193
268
|
const patches = [];
|
|
@@ -227,7 +302,21 @@ function toPatches(diff) {
|
|
|
227
302
|
}
|
|
228
303
|
return patches;
|
|
229
304
|
}
|
|
230
|
-
/**
|
|
305
|
+
/**
|
|
306
|
+
* Group a patch list into a structured diff.
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* import { createGraph, getPatches, toDiff } from '@statelyai/graph';
|
|
311
|
+
*
|
|
312
|
+
* const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
313
|
+
* const b = createGraph({ nodes: [{ id: 'n1' }, { id: 'n2' }], edges: [] });
|
|
314
|
+
*
|
|
315
|
+
* const patches = getPatches(a, b);
|
|
316
|
+
* const diff = toDiff(patches);
|
|
317
|
+
* // diff.nodes.added → [{ id: 'n2' }]
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
231
320
|
function toDiff(patches) {
|
|
232
321
|
const diff = {
|
|
233
322
|
nodes: {
|
|
@@ -287,6 +376,25 @@ function toDiff(patches) {
|
|
|
287
376
|
* - Edges originating from a compound node expand to all leaf descendants.
|
|
288
377
|
* - Only leaf nodes (nodes with no children) appear in the result.
|
|
289
378
|
* - Duplicate edges (same source + target) are deduplicated.
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* ```ts
|
|
382
|
+
* import { createGraph, flatten } from '@statelyai/graph';
|
|
383
|
+
*
|
|
384
|
+
* const graph = createGraph({
|
|
385
|
+
* nodes: [
|
|
386
|
+
* { id: 'parent', initialNodeId: 'child1' },
|
|
387
|
+
* { id: 'child1', parentId: 'parent' },
|
|
388
|
+
* { id: 'child2', parentId: 'parent' },
|
|
389
|
+
* { id: 'other' },
|
|
390
|
+
* ],
|
|
391
|
+
* edges: [{ id: 'e1', sourceId: 'other', targetId: 'parent' }],
|
|
392
|
+
* });
|
|
393
|
+
*
|
|
394
|
+
* const flat = flatten(graph);
|
|
395
|
+
* // flat.nodes → [child1, child2, other] (leaf nodes only)
|
|
396
|
+
* // flat.edges → edge from 'other' → 'child1' (resolved via initialNodeId)
|
|
397
|
+
* ```
|
|
290
398
|
*/
|
|
291
399
|
function flatten(graph) {
|
|
292
400
|
const idx = getIndex(graph);
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
//#region src/indexing.ts
|
|
2
2
|
const indexes = /* @__PURE__ */ new WeakMap();
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Get or lazily build the index for a graph.
|
|
5
|
+
* Auto-rebuilds when node/edge count changes.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { createGraph, getIndex } from '@statelyai/graph';
|
|
10
|
+
*
|
|
11
|
+
* const graph = createGraph({
|
|
12
|
+
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
13
|
+
* edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* const idx = getIndex(graph);
|
|
17
|
+
* idx.nodeById.get('a'); // 0
|
|
18
|
+
* idx.outEdges.get('a'); // ['e1']
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
4
21
|
function getIndex(graph) {
|
|
5
22
|
let idx = indexes.get(graph);
|
|
6
23
|
if (!idx || idx.nodeCount !== graph.nodes.length || idx.edgeCount !== graph.edges.length) {
|
|
@@ -9,7 +26,19 @@ function getIndex(graph) {
|
|
|
9
26
|
}
|
|
10
27
|
return idx;
|
|
11
28
|
}
|
|
12
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Clear the cached index. Call this if you mutate graph.nodes/edges directly.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* import { createGraph, invalidateIndex, getIndex } from '@statelyai/graph';
|
|
35
|
+
*
|
|
36
|
+
* const graph = createGraph({ nodes: [{ id: 'a' }], edges: [] });
|
|
37
|
+
* // manually mutate nodes array
|
|
38
|
+
* graph.nodes.push({ type: 'node', id: 'b', parentId: null, initialNodeId: null, label: '', data: undefined });
|
|
39
|
+
* invalidateIndex(graph); // forces rebuild on next getIndex()
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
13
42
|
function invalidateIndex(graph) {
|
|
14
43
|
indexes.delete(graph);
|
|
15
44
|
}
|
|
@@ -24,7 +53,7 @@ function buildIndex(graph) {
|
|
|
24
53
|
nodeById.set(n.id, i);
|
|
25
54
|
outEdges.set(n.id, []);
|
|
26
55
|
inEdges.set(n.id, []);
|
|
27
|
-
const parent = n.parentId;
|
|
56
|
+
const parent = n.parentId ?? null;
|
|
28
57
|
if (!childNodes.has(parent)) childNodes.set(parent, []);
|
|
29
58
|
childNodes.get(parent).push(n.id);
|
|
30
59
|
}
|
|
@@ -48,7 +77,7 @@ function indexAddNode(idx, node, arrayIndex) {
|
|
|
48
77
|
idx.nodeById.set(node.id, arrayIndex);
|
|
49
78
|
idx.outEdges.set(node.id, []);
|
|
50
79
|
idx.inEdges.set(node.id, []);
|
|
51
|
-
const parent = node.parentId;
|
|
80
|
+
const parent = node.parentId ?? null;
|
|
52
81
|
if (!idx.childNodes.has(parent)) idx.childNodes.set(parent, []);
|
|
53
82
|
idx.childNodes.get(parent).push(node.id);
|
|
54
83
|
idx.nodeCount++;
|
|
@@ -61,13 +90,14 @@ function indexAddEdge(idx, edge, arrayIndex) {
|
|
|
61
90
|
}
|
|
62
91
|
/** Update childNodes index when a node's parentId changes. */
|
|
63
92
|
function indexReparentNode(idx, nodeId, oldParentId, newParentId) {
|
|
64
|
-
const oldSiblings = idx.childNodes.get(oldParentId);
|
|
93
|
+
const oldSiblings = idx.childNodes.get(oldParentId ?? null);
|
|
65
94
|
if (oldSiblings) {
|
|
66
95
|
const pos = oldSiblings.indexOf(nodeId);
|
|
67
96
|
if (pos !== -1) oldSiblings.splice(pos, 1);
|
|
68
97
|
}
|
|
69
|
-
|
|
70
|
-
idx.childNodes.
|
|
98
|
+
const np = newParentId ?? null;
|
|
99
|
+
if (!idx.childNodes.has(np)) idx.childNodes.set(np, []);
|
|
100
|
+
idx.childNodes.get(np).push(nodeId);
|
|
71
101
|
}
|
|
72
102
|
/** Update adjacency lists when an edge's sourceId/targetId changes. */
|
|
73
103
|
function indexUpdateEdgeEndpoints(idx, edgeId, oldSourceId, oldTargetId, newSourceId, newTargetId) {
|
package/dist/queries.d.mts
CHANGED
|
@@ -1,32 +1,347 @@
|
|
|
1
|
-
import { c as Graph, d as GraphEdge, p as GraphNode } from "./types-
|
|
1
|
+
import { c as Graph, d as GraphEdge, p as GraphNode } from "./types-Bq_fmLwW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/queries.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns all edges (incoming + outgoing) connected to a node.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const graph = createGraph({
|
|
11
|
+
* nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
|
|
12
|
+
* edges: [
|
|
13
|
+
* { id: 'e1', sourceId: 'a', targetId: 'b' },
|
|
14
|
+
* { id: 'e2', sourceId: 'c', targetId: 'b' },
|
|
15
|
+
* ],
|
|
16
|
+
* });
|
|
17
|
+
* getEdgesOf(graph, 'b');
|
|
18
|
+
* // => [edge e1, edge e2]
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
4
21
|
declare function getEdgesOf<E>(graph: Graph<any, E>, nodeId: string): GraphEdge<E>[];
|
|
22
|
+
/**
|
|
23
|
+
* Returns incoming edges to a node.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const graph = createGraph({
|
|
28
|
+
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
29
|
+
* edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
|
|
30
|
+
* });
|
|
31
|
+
* getInEdges(graph, 'b');
|
|
32
|
+
* // => [edge e1]
|
|
33
|
+
* getInEdges(graph, 'a');
|
|
34
|
+
* // => []
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
5
37
|
declare function getInEdges<E>(graph: Graph<any, E>, nodeId: string): GraphEdge<E>[];
|
|
38
|
+
/**
|
|
39
|
+
* Returns outgoing edges from a node.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const graph = createGraph({
|
|
44
|
+
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
45
|
+
* edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
|
|
46
|
+
* });
|
|
47
|
+
* getOutEdges(graph, 'a');
|
|
48
|
+
* // => [edge e1]
|
|
49
|
+
* getOutEdges(graph, 'b');
|
|
50
|
+
* // => []
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
6
53
|
declare function getOutEdges<E>(graph: Graph<any, E>, nodeId: string): GraphEdge<E>[];
|
|
54
|
+
/**
|
|
55
|
+
* Returns the edge from `sourceId` to `targetId`, or `undefined` if none exists.
|
|
56
|
+
* For undirected graphs, checks both directions.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const graph = createGraph({
|
|
61
|
+
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
62
|
+
* edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
|
|
63
|
+
* });
|
|
64
|
+
* getEdgeBetween(graph, 'a', 'b');
|
|
65
|
+
* // => edge e1
|
|
66
|
+
* getEdgeBetween(graph, 'b', 'a');
|
|
67
|
+
* // => undefined (directed graph)
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
7
70
|
declare function getEdgeBetween<E>(graph: Graph<any, E>, sourceId: string, targetId: string): GraphEdge<E> | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Returns direct successor nodes (targets of outgoing edges).
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const graph = createGraph({
|
|
77
|
+
* nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
|
|
78
|
+
* edges: [
|
|
79
|
+
* { id: 'e1', sourceId: 'a', targetId: 'b' },
|
|
80
|
+
* { id: 'e2', sourceId: 'a', targetId: 'c' },
|
|
81
|
+
* ],
|
|
82
|
+
* });
|
|
83
|
+
* getSuccessors(graph, 'a');
|
|
84
|
+
* // => [node b, node c]
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
8
87
|
declare function getSuccessors<N>(graph: Graph<N>, nodeId: string): GraphNode<N>[];
|
|
88
|
+
/**
|
|
89
|
+
* Returns direct predecessor nodes (sources of incoming edges).
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const graph = createGraph({
|
|
94
|
+
* nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
|
|
95
|
+
* edges: [
|
|
96
|
+
* { id: 'e1', sourceId: 'a', targetId: 'c' },
|
|
97
|
+
* { id: 'e2', sourceId: 'b', targetId: 'c' },
|
|
98
|
+
* ],
|
|
99
|
+
* });
|
|
100
|
+
* getPredecessors(graph, 'c');
|
|
101
|
+
* // => [node a, node b]
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
9
104
|
declare function getPredecessors<N>(graph: Graph<N>, nodeId: string): GraphNode<N>[];
|
|
105
|
+
/**
|
|
106
|
+
* Returns all neighbor nodes (successors + predecessors).
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const graph = createGraph({
|
|
111
|
+
* nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
|
|
112
|
+
* edges: [
|
|
113
|
+
* { id: 'e1', sourceId: 'a', targetId: 'b' },
|
|
114
|
+
* { id: 'e2', sourceId: 'c', targetId: 'b' },
|
|
115
|
+
* ],
|
|
116
|
+
* });
|
|
117
|
+
* getNeighbors(graph, 'b');
|
|
118
|
+
* // => [node a, node c]
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
10
121
|
declare function getNeighbors<N>(graph: Graph<N>, nodeId: string): GraphNode<N>[];
|
|
122
|
+
/**
|
|
123
|
+
* Returns the total degree of a node (inDegree + outDegree).
|
|
124
|
+
* For undirected graphs, each edge is counted once.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* const graph = createGraph({
|
|
129
|
+
* nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
|
|
130
|
+
* edges: [
|
|
131
|
+
* { id: 'e1', sourceId: 'a', targetId: 'b' },
|
|
132
|
+
* { id: 'e2', sourceId: 'c', targetId: 'b' },
|
|
133
|
+
* ],
|
|
134
|
+
* });
|
|
135
|
+
* getDegree(graph, 'b'); // => 2
|
|
136
|
+
* getDegree(graph, 'a'); // => 1
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
11
139
|
declare function getDegree(graph: Graph, nodeId: string): number;
|
|
140
|
+
/**
|
|
141
|
+
* Returns the in-degree of a node (number of incoming edges).
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* const graph = createGraph({
|
|
146
|
+
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
147
|
+
* edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
|
|
148
|
+
* });
|
|
149
|
+
* getInDegree(graph, 'b'); // => 1
|
|
150
|
+
* getInDegree(graph, 'a'); // => 0
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
12
153
|
declare function getInDegree(graph: Graph, nodeId: string): number;
|
|
154
|
+
/**
|
|
155
|
+
* Returns the out-degree of a node (number of outgoing edges).
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* const graph = createGraph({
|
|
160
|
+
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
161
|
+
* edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
|
|
162
|
+
* });
|
|
163
|
+
* getOutDegree(graph, 'a'); // => 1
|
|
164
|
+
* getOutDegree(graph, 'b'); // => 0
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
13
167
|
declare function getOutDegree(graph: Graph, nodeId: string): number;
|
|
168
|
+
/**
|
|
169
|
+
* Returns direct children of a node in the hierarchy.
|
|
170
|
+
* Pass `null` to get root-level nodes.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* const graph = createGraph({
|
|
175
|
+
* nodes: [
|
|
176
|
+
* { id: 'parent' },
|
|
177
|
+
* { id: 'child1', parentId: 'parent' },
|
|
178
|
+
* { id: 'child2', parentId: 'parent' },
|
|
179
|
+
* ],
|
|
180
|
+
* });
|
|
181
|
+
* getChildren(graph, 'parent');
|
|
182
|
+
* // => [node child1, node child2]
|
|
183
|
+
* getChildren(graph, null);
|
|
184
|
+
* // => [node parent]
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
14
187
|
declare function getChildren<N>(graph: Graph<N>, nodeId: string | null): GraphNode<N>[];
|
|
188
|
+
/**
|
|
189
|
+
* Returns the parent node in the hierarchy, or `undefined` if root-level.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* const graph = createGraph({
|
|
194
|
+
* nodes: [
|
|
195
|
+
* { id: 'parent' },
|
|
196
|
+
* { id: 'child', parentId: 'parent' },
|
|
197
|
+
* ],
|
|
198
|
+
* });
|
|
199
|
+
* getParent(graph, 'child');
|
|
200
|
+
* // => node parent
|
|
201
|
+
* getParent(graph, 'parent');
|
|
202
|
+
* // => undefined
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
15
205
|
declare function getParent<N>(graph: Graph<N>, nodeId: string): GraphNode<N> | undefined;
|
|
206
|
+
/**
|
|
207
|
+
* Returns all ancestors from the node up to the root (nearest parent first).
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* const graph = createGraph({
|
|
212
|
+
* nodes: [
|
|
213
|
+
* { id: 'root' },
|
|
214
|
+
* { id: 'mid', parentId: 'root' },
|
|
215
|
+
* { id: 'leaf', parentId: 'mid' },
|
|
216
|
+
* ],
|
|
217
|
+
* });
|
|
218
|
+
* getAncestors(graph, 'leaf');
|
|
219
|
+
* // => [node mid, node root]
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
16
222
|
declare function getAncestors<N>(graph: Graph<N>, nodeId: string): GraphNode<N>[];
|
|
223
|
+
/**
|
|
224
|
+
* Returns all descendants recursively (depth-first).
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* const graph = createGraph({
|
|
229
|
+
* nodes: [
|
|
230
|
+
* { id: 'root' },
|
|
231
|
+
* { id: 'child', parentId: 'root' },
|
|
232
|
+
* { id: 'grandchild', parentId: 'child' },
|
|
233
|
+
* ],
|
|
234
|
+
* });
|
|
235
|
+
* getDescendants(graph, 'root');
|
|
236
|
+
* // => [node child, node grandchild]
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
17
239
|
declare function getDescendants<N>(graph: Graph<N>, nodeId: string): GraphNode<N>[];
|
|
240
|
+
/**
|
|
241
|
+
* Returns all root nodes (nodes with no parent).
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* const graph = createGraph({
|
|
246
|
+
* nodes: [
|
|
247
|
+
* { id: 'root1' },
|
|
248
|
+
* { id: 'root2' },
|
|
249
|
+
* { id: 'child', parentId: 'root1' },
|
|
250
|
+
* ],
|
|
251
|
+
* });
|
|
252
|
+
* getRoots(graph);
|
|
253
|
+
* // => [node root1, node root2]
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
18
256
|
declare function getRoots<N>(graph: Graph<N>): GraphNode<N>[];
|
|
19
|
-
/**
|
|
257
|
+
/**
|
|
258
|
+
* Whether a node has children (is a compound/group node).
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* const graph = createGraph({
|
|
263
|
+
* nodes: [
|
|
264
|
+
* { id: 'parent' },
|
|
265
|
+
* { id: 'child', parentId: 'parent' },
|
|
266
|
+
* ],
|
|
267
|
+
* });
|
|
268
|
+
* isCompound(graph, 'parent'); // => true
|
|
269
|
+
* isCompound(graph, 'child'); // => false
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
20
272
|
declare function isCompound(graph: Graph, nodeId: string): boolean;
|
|
21
|
-
/**
|
|
273
|
+
/**
|
|
274
|
+
* Whether a node has no children (is a leaf/atomic node).
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```ts
|
|
278
|
+
* const graph = createGraph({
|
|
279
|
+
* nodes: [
|
|
280
|
+
* { id: 'parent' },
|
|
281
|
+
* { id: 'child', parentId: 'parent' },
|
|
282
|
+
* ],
|
|
283
|
+
* });
|
|
284
|
+
* isLeaf(graph, 'child'); // => true
|
|
285
|
+
* isLeaf(graph, 'parent'); // => false
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
22
288
|
declare function isLeaf(graph: Graph, nodeId: string): boolean;
|
|
23
|
-
/**
|
|
289
|
+
/**
|
|
290
|
+
* Depth of a node in the hierarchy (root = 0).
|
|
291
|
+
* Returns -1 if the node is not found.
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```ts
|
|
295
|
+
* const graph = createGraph({
|
|
296
|
+
* nodes: [
|
|
297
|
+
* { id: 'root' },
|
|
298
|
+
* { id: 'child', parentId: 'root' },
|
|
299
|
+
* { id: 'grandchild', parentId: 'child' },
|
|
300
|
+
* ],
|
|
301
|
+
* });
|
|
302
|
+
* getDepth(graph, 'root'); // => 0
|
|
303
|
+
* getDepth(graph, 'child'); // => 1
|
|
304
|
+
* getDepth(graph, 'grandchild'); // => 2
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
24
307
|
declare function getDepth(graph: Graph, nodeId: string): number;
|
|
25
|
-
/**
|
|
308
|
+
/**
|
|
309
|
+
* Sibling nodes (same parentId, excluding the node itself).
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* const graph = createGraph({
|
|
314
|
+
* nodes: [
|
|
315
|
+
* { id: 'parent' },
|
|
316
|
+
* { id: 'a', parentId: 'parent' },
|
|
317
|
+
* { id: 'b', parentId: 'parent' },
|
|
318
|
+
* { id: 'c', parentId: 'parent' },
|
|
319
|
+
* ],
|
|
320
|
+
* });
|
|
321
|
+
* getSiblings(graph, 'a');
|
|
322
|
+
* // => [node b, node c]
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
26
325
|
declare function getSiblings<N>(graph: Graph<N>, nodeId: string): GraphNode<N>[];
|
|
27
326
|
/**
|
|
28
|
-
* Least Common Ancestor
|
|
327
|
+
* Least Common Ancestor -- deepest proper ancestor of all given nodes.
|
|
29
328
|
* A proper ancestor excludes the input nodes themselves.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```ts
|
|
332
|
+
* const graph = createGraph({
|
|
333
|
+
* nodes: [
|
|
334
|
+
* { id: 'root' },
|
|
335
|
+
* { id: 'a', parentId: 'root' },
|
|
336
|
+
* { id: 'b', parentId: 'root' },
|
|
337
|
+
* { id: 'a1', parentId: 'a' },
|
|
338
|
+
* ],
|
|
339
|
+
* });
|
|
340
|
+
* getLCA(graph, 'a1', 'b');
|
|
341
|
+
* // => node root
|
|
342
|
+
* getLCA(graph, 'a', 'b');
|
|
343
|
+
* // => node root
|
|
344
|
+
* ```
|
|
30
345
|
*/
|
|
31
346
|
declare function getLCA<N>(graph: Graph<N>, ...nodeIds: string[]): GraphNode<N> | undefined;
|
|
32
347
|
/**
|
|
@@ -105,9 +420,39 @@ declare function getRelativeDistanceMap(graph: Graph, parentId: string | null):
|
|
|
105
420
|
* ```
|
|
106
421
|
*/
|
|
107
422
|
declare function getRelativeDistance(graph: Graph, nodeId: string): number | undefined;
|
|
108
|
-
/**
|
|
423
|
+
/**
|
|
424
|
+
* Nodes with no incoming edges (inDegree 0).
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```ts
|
|
428
|
+
* const graph = createGraph({
|
|
429
|
+
* nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
|
|
430
|
+
* edges: [
|
|
431
|
+
* { id: 'e1', sourceId: 'a', targetId: 'b' },
|
|
432
|
+
* { id: 'e2', sourceId: 'b', targetId: 'c' },
|
|
433
|
+
* ],
|
|
434
|
+
* });
|
|
435
|
+
* getSources(graph);
|
|
436
|
+
* // => [node a]
|
|
437
|
+
* ```
|
|
438
|
+
*/
|
|
109
439
|
declare function getSources<N>(graph: Graph<N>): GraphNode<N>[];
|
|
110
|
-
/**
|
|
440
|
+
/**
|
|
441
|
+
* Nodes with no outgoing edges (outDegree 0).
|
|
442
|
+
*
|
|
443
|
+
* @example
|
|
444
|
+
* ```ts
|
|
445
|
+
* const graph = createGraph({
|
|
446
|
+
* nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
|
|
447
|
+
* edges: [
|
|
448
|
+
* { id: 'e1', sourceId: 'a', targetId: 'b' },
|
|
449
|
+
* { id: 'e2', sourceId: 'b', targetId: 'c' },
|
|
450
|
+
* ],
|
|
451
|
+
* });
|
|
452
|
+
* getSinks(graph);
|
|
453
|
+
* // => [node c]
|
|
454
|
+
* ```
|
|
455
|
+
*/
|
|
111
456
|
declare function getSinks<N>(graph: Graph<N>): GraphNode<N>[];
|
|
112
457
|
//#endregion
|
|
113
458
|
export { getAncestors, getChildren, getDegree, getDepth, getDescendants, getEdgeBetween, getEdgesOf, getInDegree, getInEdges, getLCA, getNeighbors, getOutDegree, getOutEdges, getParent, getPredecessors, getRelativeDistance, getRelativeDistanceMap, getRoots, getSiblings, getSinks, getSources, getSuccessors, isCompound, isLeaf };
|