@statelyai/graph 0.13.0 → 2.0.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.
Files changed (57) hide show
  1. package/README.md +57 -26
  2. package/dist/{adjacency-list-Ca0VjKIf.mjs → adjacency-list-GeL1Cu-L.mjs} +5 -3
  3. package/dist/{algorithms-BlM-qoJb.d.mts → algorithms-CsGNehct.d.mts} +137 -2
  4. package/dist/{algorithms-BNDQcHU3.mjs → algorithms-DF1pSQGv.mjs} +1494 -357
  5. package/dist/algorithms.d.mts +2 -2
  6. package/dist/algorithms.mjs +2 -2
  7. package/dist/{converter-Dspillnn.mjs → converter-DyCJJfTe.mjs} +2 -2
  8. package/dist/{edge-list-gKe8-iRa.mjs → edge-list-BcZ0h6zz.mjs} +1 -1
  9. package/dist/format-support.mjs +67 -11
  10. package/dist/formats/adjacency-list/index.d.mts +1 -1
  11. package/dist/formats/adjacency-list/index.mjs +1 -1
  12. package/dist/formats/converter/index.d.mts +1 -60
  13. package/dist/formats/converter/index.mjs +1 -1
  14. package/dist/formats/cytoscape/index.d.mts +1 -1
  15. package/dist/formats/cytoscape/index.mjs +5 -3
  16. package/dist/formats/d2/index.d.mts +109 -0
  17. package/dist/formats/d2/index.mjs +1100 -0
  18. package/dist/formats/d3/index.d.mts +2 -2
  19. package/dist/formats/d3/index.mjs +5 -3
  20. package/dist/formats/dot/index.d.mts +1 -1
  21. package/dist/formats/dot/index.mjs +24 -8
  22. package/dist/formats/edge-list/index.d.mts +1 -1
  23. package/dist/formats/edge-list/index.mjs +1 -1
  24. package/dist/formats/elk/index.d.mts +1 -1
  25. package/dist/formats/elk/index.mjs +23 -16
  26. package/dist/formats/gexf/index.d.mts +1 -1
  27. package/dist/formats/gexf/index.mjs +30 -17
  28. package/dist/formats/gml/index.d.mts +1 -1
  29. package/dist/formats/gml/index.mjs +22 -13
  30. package/dist/formats/graphml/index.d.mts +1 -1
  31. package/dist/formats/graphml/index.mjs +83 -25
  32. package/dist/formats/jgf/index.d.mts +1 -1
  33. package/dist/formats/jgf/index.mjs +6 -3
  34. package/dist/formats/mermaid/index.d.mts +1 -1
  35. package/dist/formats/mermaid/index.mjs +57 -20
  36. package/dist/formats/tgf/index.d.mts +1 -1
  37. package/dist/formats/tgf/index.mjs +2 -2
  38. package/dist/formats/xyflow/index.d.mts +1 -1
  39. package/dist/formats/xyflow/index.mjs +33 -6
  40. package/dist/index-D51lJnt2.d.mts +61 -0
  41. package/dist/index-DWmo1mIp.d.mts +697 -0
  42. package/dist/index.d.mts +6 -631
  43. package/dist/index.mjs +144 -295
  44. package/dist/mode-D8OnHFBk.mjs +15 -0
  45. package/dist/queries-BfXeTXRf.d.mts +547 -0
  46. package/dist/queries-KirMDR7e.mjs +980 -0
  47. package/dist/queries.d.mts +1 -514
  48. package/dist/queries.mjs +1 -766
  49. package/dist/schemas.d.mts +21 -10
  50. package/dist/schemas.mjs +35 -86
  51. package/dist/{types-CnZ01raw.d.mts → types-DNYdIU21.d.mts} +83 -11
  52. package/dist/validate-TtH-x3JV.mjs +190 -0
  53. package/package.json +14 -3
  54. package/schemas/edge.schema.json +11 -0
  55. package/schemas/graph.schema.json +24 -3
  56. package/schemas/node.schema.json +6 -0
  57. package/dist/indexing-DUl3kTqm.mjs +0 -137
@@ -0,0 +1,697 @@
1
+ import { E as NodeUpdate, F as VisualGraphConfig, H as WeightedWalkOptions, O as PortConfig, P as VisualGraph, S as GraphStep, T as NodeConfig, V as WalkOptions, _ as GraphMode, c as EntitiesConfig, d as Graph, f as GraphConfig, i as DeleteNodeOptions, j as TransitionOptions, l as EntitiesUpdate, m as GraphEdge, o as EdgeConfig, p as GraphDiff, r as CoverageStats, s as EdgeUpdate, v as GraphNode, x as GraphPort, y as GraphPatch } from "./types-DNYdIU21.mjs";
2
+
3
+ //#region src/graph.d.ts
4
+
5
+ /**
6
+ * Create a resolved graph port from a config. Fills in defaults.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const port = createGraphPort({ name: 'output', direction: 'out' });
11
+ * // { name: 'output', direction: 'out', data: null }
12
+ * ```
13
+ */
14
+ declare function createGraphPort<P = any>(config: PortConfig<P>): GraphPort<P>;
15
+ /**
16
+ * Create a resolved graph node from a config. Fills in defaults.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const node = createGraphNode({ id: 'a', data: { label: 'hi' } });
21
+ * // { type: 'node', id: 'a', label: '', data: { label: 'hi' } }
22
+ * ```
23
+ */
24
+ declare function createGraphNode<N = any, P = any>(config: NodeConfig<N, P>): GraphNode<N, P>;
25
+ /**
26
+ * Create a resolved graph edge from a config. Fills in defaults.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const edge = createGraphEdge({ id: 'e1', sourceId: 'a', targetId: 'b' });
31
+ * // { type: 'edge', id: 'e1', sourceId: 'a', targetId: 'b', label: null, data: null }
32
+ * ```
33
+ */
34
+ declare function createGraphEdge<T = any>(config: EdgeConfig<T>): GraphEdge<T>;
35
+ /**
36
+ * Create a graph from a config. Resolves defaults for all fields.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const graph = createGraph({
41
+ * nodes: [{ id: 'a' }, { id: 'b' }],
42
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
43
+ * });
44
+ * ```
45
+ */
46
+ declare function createGraph<N = any, E = any, G = any, P = any>(config?: GraphConfig<N, E, G, P>): Graph<N, E, G, P>;
47
+ /**
48
+ * Create a visual graph with required position/size on all nodes and edges.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const graph = createVisualGraph({
53
+ * nodes: [{ id: 'a', x: 0, y: 0, width: 100, height: 50 }],
54
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'a', x: 0, y: 0, width: 0, height: 0 }],
55
+ * });
56
+ * // graph.nodes[0].x === 0
57
+ * ```
58
+ */
59
+ declare function createVisualGraph<N = any, E = any, G = any, P = any>(config?: VisualGraphConfig<N, E, G, P>): VisualGraph<N, E, G, P>;
60
+ /**
61
+ * Create a graph by BFS exploration of a transition function.
62
+ * Each unique state becomes a node; each (state, event) -> nextState becomes an edge.
63
+ *
64
+ * - Node IDs are determined by `serializeState` (default: `JSON.stringify`).
65
+ * - Edge IDs use the format `sourceId|serializedEvent|targetId` for uniqueness
66
+ * and debuggability. Edge labels are just the serialized event string.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * const graph = createGraphFromTransition(
71
+ * (state, event) => {
72
+ * if (state === 'green' && event === 'TIMER') return 'yellow';
73
+ * if (state === 'yellow' && event === 'TIMER') return 'red';
74
+ * if (state === 'red' && event === 'TIMER') return 'green';
75
+ * return state;
76
+ * },
77
+ * {
78
+ * initialState: 'green',
79
+ * events: ['TIMER'],
80
+ * serializeState: (s) => s,
81
+ * serializeEvent: (e) => e,
82
+ * },
83
+ * );
84
+ * // graph.nodes.length === 3
85
+ * ```
86
+ */
87
+ declare function createGraphFromTransition<TState, TEvent>(transition: (state: TState, event: TEvent) => TState, options: TransitionOptions<TState, TEvent>): Graph<TState, TEvent>;
88
+ /**
89
+ * Get a node by id, or `undefined` if not found.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * const graph = createGraph({ nodes: [{ id: 'a' }] });
94
+ * const node = getNode(graph, 'a'); // GraphNode
95
+ * const missing = getNode(graph, 'z'); // undefined
96
+ * ```
97
+ */
98
+ declare function getNode<N>(graph: Graph<N>, id: string): GraphNode<N> | undefined;
99
+ /**
100
+ * Get an edge by id, or `undefined` if not found.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * const graph = createGraph({
105
+ * nodes: [{ id: 'a' }, { id: 'b' }],
106
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
107
+ * });
108
+ * const edge = getEdge(graph, 'e1'); // GraphEdge
109
+ * const missing = getEdge(graph, 'z'); // undefined
110
+ * ```
111
+ */
112
+ declare function getEdge<N, E>(graph: Graph<N, E>, id: string): GraphEdge<E> | undefined;
113
+ /**
114
+ * Check if a node exists in the graph.
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * const graph = createGraph({ nodes: [{ id: 'a' }] });
119
+ * hasNode(graph, 'a'); // true
120
+ * hasNode(graph, 'z'); // false
121
+ * ```
122
+ */
123
+ declare function hasNode(graph: Graph, id: string): boolean;
124
+ /**
125
+ * Check if an edge exists in the graph.
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * const graph = createGraph({
130
+ * nodes: [{ id: 'a' }, { id: 'b' }],
131
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
132
+ * });
133
+ * hasEdge(graph, 'e1'); // true
134
+ * hasEdge(graph, 'z'); // false
135
+ * ```
136
+ */
137
+ declare function hasEdge(graph: Graph, id: string): boolean;
138
+ /**
139
+ * **Mutable.** Add a node to the graph. Mutates `graph.nodes` in place.
140
+ * @returns The resolved node that was added.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * const graph = createGraph();
145
+ * const node = addNode(graph, { id: 'a', label: 'Node A' });
146
+ * // graph.nodes.length === 1
147
+ * ```
148
+ */
149
+ declare function addNode<N, P = any>(graph: Graph<N, any, any, P>, config: NodeConfig<N, P>): GraphNode<N, P>;
150
+ /**
151
+ * **Mutable.** Add an edge to the graph. Mutates `graph.edges` in place.
152
+ * @returns The resolved edge that was added.
153
+ *
154
+ * @example
155
+ * ```ts
156
+ * const graph = createGraph({ nodes: [{ id: 'a' }, { id: 'b' }] });
157
+ * const edge = addEdge(graph, { id: 'e1', sourceId: 'a', targetId: 'b' });
158
+ * // graph.edges.length === 1
159
+ * ```
160
+ */
161
+ declare function addEdge<N, E>(graph: Graph<N, E>, config: EdgeConfig<E>): GraphEdge<E>;
162
+ /**
163
+ * **Mutable.** Delete a node and its connected edges. Mutates `graph.nodes`
164
+ * and `graph.edges` in place.
165
+ *
166
+ * By default, children are deleted recursively.
167
+ * With `{ reparent: true }`, children are re-parented to the deleted node's parent.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * const graph = createGraph({
172
+ * nodes: [{ id: 'a' }, { id: 'b' }],
173
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
174
+ * });
175
+ * deleteNode(graph, 'a');
176
+ * // graph.nodes.length === 1, edge e1 also removed
177
+ * ```
178
+ */
179
+ declare function deleteNode(graph: Graph, id: string, opts?: DeleteNodeOptions): void;
180
+ /**
181
+ * **Mutable.** Delete an edge. Mutates `graph.edges` in place.
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * const graph = createGraph({
186
+ * nodes: [{ id: 'a' }, { id: 'b' }],
187
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
188
+ * });
189
+ * deleteEdge(graph, 'e1');
190
+ * // graph.edges.length === 0
191
+ * ```
192
+ */
193
+ declare function deleteEdge(graph: Graph, id: string): void;
194
+ /**
195
+ * **Mutable.** Update a node in place.
196
+ * Optional fields (`x`, `y`, `width`, `height`, `shape`, `color`, `style`,
197
+ * `ports`) accept `null` to unset; `undefined` leaves them unchanged.
198
+ * @returns The updated node.
199
+ *
200
+ * @example
201
+ * ```ts
202
+ * const graph = createGraph({ nodes: [{ id: 'a', label: 'old' }] });
203
+ * const updated = updateNode(graph, 'a', { label: 'new', x: 100 });
204
+ * // updated.label === 'new', updated.x === 100
205
+ * ```
206
+ */
207
+ declare function updateNode<N, P = any>(graph: Graph<N, any, any, P>, id: string, update: NodeUpdate<N, P>): GraphNode<N, P>;
208
+ /**
209
+ * **Mutable.** Update an edge in place.
210
+ * Optional fields (`weight`, `mode`, `sourcePort`, `targetPort`, `x`, `y`,
211
+ * `width`, `height`, `color`, `style`) accept `null` to unset; `undefined`
212
+ * leaves them unchanged.
213
+ * @returns The updated edge.
214
+ *
215
+ * @example
216
+ * ```ts
217
+ * const graph = createGraph({
218
+ * nodes: [{ id: 'a' }, { id: 'b' }],
219
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b', label: 'old' }],
220
+ * });
221
+ * const updated = updateEdge(graph, 'e1', { label: 'new', weight: 2 });
222
+ * // updated.label === 'new', updated.weight === 2
223
+ * ```
224
+ */
225
+ declare function updateEdge<N, E>(graph: Graph<N, E>, id: string, update: EdgeUpdate<E>): GraphEdge<E>;
226
+ /**
227
+ * **Mutable.** Add multiple nodes and edges to the graph.
228
+ * Nodes are added first, then edges (so edges can reference new nodes).
229
+ *
230
+ * @example
231
+ * ```ts
232
+ * const graph = createGraph();
233
+ * addEntities(graph, {
234
+ * nodes: [{ id: 'a' }, { id: 'b' }],
235
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
236
+ * });
237
+ * // graph.nodes.length === 2, graph.edges.length === 1
238
+ * ```
239
+ */
240
+ declare function addEntities<N, E>(graph: Graph<N, E>, entities: EntitiesConfig<N, E>): void;
241
+ /**
242
+ * **Mutable.** Delete entities by id(s). Automatically detects whether each id
243
+ * is a node or edge. Node deletions cascade to children and connected edges.
244
+ *
245
+ * @example
246
+ * ```ts
247
+ * const graph = createGraph({
248
+ * nodes: [{ id: 'a' }, { id: 'b' }],
249
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
250
+ * });
251
+ * deleteEntities(graph, ['a', 'e1']);
252
+ * // graph.nodes.length === 1, graph.edges.length === 0
253
+ * ```
254
+ */
255
+ declare function deleteEntities(graph: Graph, ids: string | string[], opts?: DeleteNodeOptions): void;
256
+ /**
257
+ * **Mutable.** Update multiple nodes and edges in place.
258
+ * Each entry must include an `id` to identify which entity to update.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * const graph = createGraph({
263
+ * nodes: [{ id: 'a', label: 'old' }],
264
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'a', label: 'old' }],
265
+ * });
266
+ * updateEntities(graph, {
267
+ * nodes: [{ id: 'a', label: 'new' }],
268
+ * edges: [{ id: 'e1', label: 'new' }],
269
+ * });
270
+ * ```
271
+ */
272
+ declare function updateEntities<N, E>(graph: Graph<N, E>, updates: EntitiesUpdate<N, E>): void;
273
+ /**
274
+ * OOP wrapper around a plain `Graph` object.
275
+ * Delegates to the standalone mutable functions.
276
+ *
277
+ * @example
278
+ * ```ts
279
+ * const instance = new GraphInstance({
280
+ * nodes: [{ id: 'a' }, { id: 'b' }],
281
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
282
+ * });
283
+ * instance.addNode({ id: 'c' });
284
+ * instance.hasNode('c'); // true
285
+ * instance.toJSON(); // plain Graph object
286
+ * ```
287
+ */
288
+ declare class GraphInstance<N = any, E = any, G = any, P = any> {
289
+ graph: Graph<N, E, G, P>;
290
+ constructor(config?: GraphConfig<N, E, G, P>);
291
+ /**
292
+ * Wrap an existing plain graph object.
293
+ *
294
+ * @example
295
+ * ```ts
296
+ * const graph = createGraph({ nodes: [{ id: 'a' }] });
297
+ * const instance = GraphInstance.from(graph);
298
+ * instance.hasNode('a'); // true
299
+ * ```
300
+ */
301
+ static from<N = any, E = any, G = any, P = any>(graph: Graph<N, E, G, P>): GraphInstance<N, E, G, P>;
302
+ get id(): string;
303
+ /** Default directedness for all edges. */
304
+ get mode(): GraphMode;
305
+ get nodes(): GraphNode<N, P>[];
306
+ get edges(): GraphEdge<E>[];
307
+ get data(): G;
308
+ getNode(id: string): GraphNode<N, any> | undefined;
309
+ getEdge(id: string): GraphEdge<E> | undefined;
310
+ hasNode(id: string): boolean;
311
+ hasEdge(id: string): boolean;
312
+ addNode(config: NodeConfig<N, P>): GraphNode<N, P>;
313
+ addEdge(config: EdgeConfig<E>): GraphEdge<E>;
314
+ deleteNode(id: string, opts?: DeleteNodeOptions): void;
315
+ deleteEdge(id: string): void;
316
+ updateNode(id: string, update: NodeUpdate<N, P>): GraphNode<N, P>;
317
+ updateEdge(id: string, update: EdgeUpdate<E>): GraphEdge<E>;
318
+ addEntities(entities: EntitiesConfig<N, E, P>): void;
319
+ deleteEntities(ids: string | string[], opts?: DeleteNodeOptions): void;
320
+ updateEntities(updates: EntitiesUpdate<N, E, P>): void;
321
+ toJSON(): Graph<N, E, G, P>;
322
+ }
323
+ //#endregion
324
+ //#region src/mode.d.ts
325
+ /**
326
+ * Resolve an edge's effective directedness. Falls back to the graph's
327
+ * {@link Graph.mode} when the edge has no per-edge override.
328
+ */
329
+ declare function getEdgeMode(graph: Graph, edge: GraphEdge): GraphMode;
330
+ /** Whether an edge points only from source to target. */
331
+ declare function isEdgeDirected(graph: Graph, edge: GraphEdge): boolean;
332
+ //#endregion
333
+ //#region src/validate.d.ts
334
+ /**
335
+ * A structural problem found in a graph by {@link getGraphIssues}.
336
+ */
337
+ interface GraphIssue {
338
+ /** Stable machine-readable code, e.g. `'duplicate-node-id'`. */
339
+ code: string;
340
+ /** What is wrong, which entity is affected, and how to fix it. */
341
+ message: string;
342
+ /** Location of the offending value, e.g. `['nodes', 0, 'id']`. */
343
+ path?: (string | number)[];
344
+ }
345
+ /**
346
+ * Validates the structural invariants of a graph and returns the issues
347
+ * found, or `[]` when the graph is valid. Pure — never throws, never mutates.
348
+ *
349
+ * This is the recommended gate for untrusted or imported graphs (e.g. parsed
350
+ * from a file or received over the wire) before handing them to queries and
351
+ * algorithms: the mutation APIs (`addNode`, `addEdge`, `updateNode`, …)
352
+ * validate incrementally, but `createGraph` does **not** — it accepts
353
+ * dangling `parentId`/edge references and even `parentId` cycles as-is.
354
+ *
355
+ * For Zod-based shape validation of arbitrary unknown values, see
356
+ * `validateGraph` in `@statelyai/graph/schemas` (which reuses these checks).
357
+ *
358
+ * Issue codes: `duplicate-node-id`, `duplicate-edge-id`,
359
+ * `missing-initial-node`, `missing-parent`, `missing-node-initial`,
360
+ * `duplicate-port-name`, `parent-cycle`, `dangling-edge-endpoint`,
361
+ * `missing-source-port`, `missing-target-port`.
362
+ *
363
+ * @example
364
+ * ```ts
365
+ * const graph = createGraph({
366
+ * nodes: [{ id: 'a', parentId: 'ghost' }],
367
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
368
+ * });
369
+ * getGraphIssues(graph);
370
+ * // => [
371
+ * // { code: 'missing-parent', message: '...', path: ['nodes', 0, 'parentId'] },
372
+ * // { code: 'dangling-edge-endpoint', message: '...', path: ['edges', 0, 'targetId'] },
373
+ * // ]
374
+ * ```
375
+ */
376
+ declare function getGraphIssues(graph: Graph): GraphIssue[];
377
+ //#endregion
378
+ //#region src/indexing.d.ts
379
+ /**
380
+ * Clear the cached index. Call this if you mutate fields of existing
381
+ * nodes/edges in place (e.g. `edge.targetId = 'a'`) — such mutations are not
382
+ * auto-detected. Array replacement and length changes are auto-detected.
383
+ *
384
+ * @example
385
+ * ```ts
386
+ * import { createGraph, invalidateIndex, getIndex } from '@statelyai/graph';
387
+ *
388
+ * const graph = createGraph({
389
+ * nodes: [{ id: 'a' }, { id: 'b' }],
390
+ * edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
391
+ * });
392
+ * graph.edges[0].targetId = 'a'; // in-place field mutation
393
+ * invalidateIndex(graph); // forces rebuild on next getIndex()
394
+ * ```
395
+ */
396
+ declare function invalidateIndex(graph: Graph): void;
397
+ //#endregion
398
+ //#region src/equivalence.d.ts
399
+ declare const LAYOUT_KEYS: {
400
+ node: readonly ["x", "y", "width", "height", "style", "color", "shape"];
401
+ edge: readonly ["x", "y", "width", "height", "style", "color"];
402
+ };
403
+ /**
404
+ * Compare two entities on a given set of keys.
405
+ * If `keys` is omitted or empty, compares all own keys of `a`.
406
+ *
407
+ * @example
408
+ * ```ts
409
+ * import { createGraphNode, areEntitiesEqual, LAYOUT_KEYS } from '@statelyai/graph';
410
+ *
411
+ * const a = createGraphNode({ id: 'n1', label: 'hello', x: 0 });
412
+ * const b = createGraphNode({ id: 'n1', label: 'hello', x: 100 });
413
+ *
414
+ * areEntitiesEqual(a, b, LAYOUT_KEYS.node); // false (x differs)
415
+ * areEntitiesEqual(a, b, NON_LAYOUT_KEYS.node); // true
416
+ * areEntitiesEqual(a, b); // false (compares all keys)
417
+ * ```
418
+ */
419
+ declare function areEntitiesEqual<T extends GraphNode | GraphEdge>(a: T, b: T, keys?: readonly (keyof T)[]): boolean;
420
+ /**
421
+ * Compare two entities on layout keys only (position, size, style, color, shape).
422
+ *
423
+ * @example
424
+ * ```ts
425
+ * import { createGraphNode, isLayoutEqual } from '@statelyai/graph';
426
+ *
427
+ * const a = createGraphNode({ id: 'n1', x: 0, y: 0 });
428
+ * const b = createGraphNode({ id: 'n1', x: 100, y: 200 });
429
+ *
430
+ * isLayoutEqual(a, b); // false
431
+ * ```
432
+ */
433
+ declare function isLayoutEqual<T extends GraphNode | GraphEdge>(a: T, b: T): boolean;
434
+ /**
435
+ * Compare two entities on non-layout keys only (id, data, connections, labels, etc.).
436
+ *
437
+ * @example
438
+ * ```ts
439
+ * import { createGraphNode, isNonLayoutEqual } from '@statelyai/graph';
440
+ *
441
+ * const a = createGraphNode({ id: 'n1', label: 'hello', x: 0 });
442
+ * const b = createGraphNode({ id: 'n1', label: 'hello', x: 100 });
443
+ *
444
+ * isNonLayoutEqual(a, b); // true (layout changed, but non-layout didn't)
445
+ * ```
446
+ */
447
+ declare function isNonLayoutEqual<T extends GraphNode | GraphEdge>(a: T, b: T): boolean;
448
+ //#endregion
449
+ //#region src/diff.d.ts
450
+ /**
451
+ * Compute a structured diff from graph `a` to graph `b` by matching IDs.
452
+ *
453
+ * @example
454
+ * ```ts
455
+ * import { createGraph, getDiff } from '@statelyai/graph';
456
+ *
457
+ * const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
458
+ * const b = createGraph({ nodes: [{ id: 'n1', label: 'hello' }, { id: 'n2' }], edges: [] });
459
+ *
460
+ * const diff = getDiff(a, b);
461
+ * // diff.nodes.added → [{ id: 'n2' }]
462
+ * // diff.nodes.updated → [{ id: 'n1', old: { label: '' }, new: { label: 'hello' } }]
463
+ * ```
464
+ */
465
+ declare function getDiff<N, E>(a: Graph<N, E>, b: Graph<N, E>): GraphDiff<N, E>;
466
+ /**
467
+ * Check if a diff has zero changes.
468
+ *
469
+ * @example
470
+ * ```ts
471
+ * import { createGraph, getDiff, isEmptyDiff } from '@statelyai/graph';
472
+ *
473
+ * const g = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
474
+ * const diff = getDiff(g, g);
475
+ * isEmptyDiff(diff); // true
476
+ * ```
477
+ */
478
+ declare function isEmptyDiff(diff: GraphDiff): boolean;
479
+ /**
480
+ * Invert a diff: swap added/removed, swap old/new in updates.
481
+ *
482
+ * @example
483
+ * ```ts
484
+ * import { createGraph, getDiff, invertDiff } from '@statelyai/graph';
485
+ *
486
+ * const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
487
+ * const b = createGraph({ nodes: [{ id: 'n2' }], edges: [] });
488
+ *
489
+ * const diff = getDiff(a, b);
490
+ * const inv = invertDiff(diff);
491
+ * // inv.nodes.added contains n1 (was removed)
492
+ * // inv.nodes.removed contains n2 (was added)
493
+ * ```
494
+ */
495
+ declare function invertDiff<N, E>(diff: GraphDiff<N, E>): GraphDiff<N, E>;
496
+ /**
497
+ * Compute an ordered patch list from graph `a` to graph `b`.
498
+ * Order (see {@link toPatches}): add nodes → update edges → delete edges →
499
+ * delete nodes → add edges → update nodes.
500
+ *
501
+ * @example
502
+ * ```ts
503
+ * import { createGraph, getPatches } from '@statelyai/graph';
504
+ *
505
+ * const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
506
+ * const b = createGraph({ nodes: [{ id: 'n1' }, { id: 'n2' }], edges: [] });
507
+ *
508
+ * const patches = getPatches(a, b);
509
+ * // patches → [{ op: 'addNode', node: { id: 'n2' } }]
510
+ * ```
511
+ */
512
+ declare function getPatches<N, E>(a: Graph<N, E>, b: Graph<N, E>): GraphPatch<N, E>[];
513
+ /**
514
+ * **Mutable.** Apply patches to a graph in order.
515
+ * Delegates to addNode/deleteNode/updateNode/addEdge/deleteEdge/updateEdge.
516
+ *
517
+ * @example
518
+ * ```ts
519
+ * import { createGraph, getPatches, applyPatches } from '@statelyai/graph';
520
+ *
521
+ * const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
522
+ * const b = createGraph({ nodes: [{ id: 'n1' }, { id: 'n2' }], edges: [] });
523
+ *
524
+ * const patches = getPatches(a, b);
525
+ * applyPatches(a, patches);
526
+ * // a now contains both n1 and n2
527
+ * ```
528
+ */
529
+ declare function applyPatches<N, E>(graph: Graph<N, E>, patches: GraphPatch<N, E>[]): void;
530
+ /**
531
+ * Flatten a structured diff into an ordered patch list.
532
+ * Order: add nodes → update edges → delete edges → delete nodes → add edges → update nodes.
533
+ * This avoids cascading deletes removing edges that are being updated,
534
+ * and ensures new nodes exist before edges reference them.
535
+ *
536
+ * @example
537
+ * ```ts
538
+ * import { createGraph, getDiff, toPatches } from '@statelyai/graph';
539
+ *
540
+ * const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
541
+ * const b = createGraph({ nodes: [{ id: 'n2' }], edges: [] });
542
+ *
543
+ * const diff = getDiff(a, b);
544
+ * const patches = toPatches(diff);
545
+ * // patches → [{ op: 'addNode', ... }, { op: 'deleteNode', ... }]
546
+ * ```
547
+ */
548
+ declare function toPatches<N, E>(diff: GraphDiff<N, E>): GraphPatch<N, E>[];
549
+ /**
550
+ * Group a patch list into a structured diff.
551
+ *
552
+ * @example
553
+ * ```ts
554
+ * import { createGraph, getPatches, toDiff } from '@statelyai/graph';
555
+ *
556
+ * const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
557
+ * const b = createGraph({ nodes: [{ id: 'n1' }, { id: 'n2' }], edges: [] });
558
+ *
559
+ * const patches = getPatches(a, b);
560
+ * const diff = toDiff(patches);
561
+ * // diff.nodes.added → [{ id: 'n2' }]
562
+ * ```
563
+ */
564
+ declare function toDiff<N, E>(patches: GraphPatch<N, E>[]): GraphDiff<N, E>;
565
+ //#endregion
566
+ //#region src/transforms.d.ts
567
+ /**
568
+ * Flattens a hierarchical graph into a flat graph with only leaf nodes.
569
+ *
570
+ * - Edges targeting a compound node resolve to its initial child (recursively).
571
+ * - Edges originating from a compound node expand to all leaf descendants.
572
+ * - Only leaf nodes (nodes with no children) appear in the result.
573
+ * - Duplicate edges (same source + target) are deduplicated.
574
+ *
575
+ * @example
576
+ * ```ts
577
+ * import { createGraph, flatten } from '@statelyai/graph';
578
+ *
579
+ * const graph = createGraph({
580
+ * nodes: [
581
+ * { id: 'parent', initialNodeId: 'child1' },
582
+ * { id: 'child1', parentId: 'parent' },
583
+ * { id: 'child2', parentId: 'parent' },
584
+ * { id: 'other' },
585
+ * ],
586
+ * edges: [{ id: 'e1', sourceId: 'other', targetId: 'parent' }],
587
+ * });
588
+ *
589
+ * const flat = flatten(graph);
590
+ * // flat.nodes → [child1, child2, other] (leaf nodes only)
591
+ * // flat.edges → edge from 'other' → 'child1' (resolved via initialNodeId)
592
+ * ```
593
+ */
594
+ declare function flatten<N, E, G>(graph: Graph<N, E, G>): Graph<N, E, G>;
595
+ /**
596
+ * Returns the induced subgraph containing only the given node IDs
597
+ * and edges whose endpoints are both in the set.
598
+ *
599
+ * Parent references to nodes outside the set are removed.
600
+ *
601
+ * @example
602
+ * ```ts
603
+ * import { createGraph, getSubgraph } from '@statelyai/graph';
604
+ *
605
+ * const graph = createGraph({
606
+ * nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
607
+ * edges: [
608
+ * { id: 'ab', sourceId: 'a', targetId: 'b' },
609
+ * { id: 'bc', sourceId: 'b', targetId: 'c' },
610
+ * ],
611
+ * });
612
+ *
613
+ * const sub = getSubgraph(graph, ['a', 'b']);
614
+ * // sub.nodes: [a, b], sub.edges: [ab]
615
+ * ```
616
+ */
617
+ declare function getSubgraph<N, E, G>(graph: Graph<N, E, G>, nodeIds: string[]): Graph<N, E, G>;
618
+ /**
619
+ * Returns a new graph with all edge directions flipped (source ↔ target).
620
+ * Optionally filters which edges to include.
621
+ *
622
+ * @example
623
+ * ```ts
624
+ * import { createGraph, reverseGraph } from '@statelyai/graph';
625
+ *
626
+ * const graph = createGraph({
627
+ * nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
628
+ * edges: [
629
+ * { id: 'ab', sourceId: 'a', targetId: 'b' },
630
+ * { id: 'bc', sourceId: 'b', targetId: 'c' },
631
+ * ],
632
+ * });
633
+ *
634
+ * const rev = reverseGraph(graph);
635
+ * // rev edges: b→a, c→b
636
+ *
637
+ * const filtered = reverseGraph(graph, (e) => e.id !== 'bc');
638
+ * // filtered edges: b→a (only ab reversed, bc excluded)
639
+ * ```
640
+ */
641
+ declare function reverseGraph<N, E, G>(graph: Graph<N, E, G>, filterEdge?: (edge: GraphEdge<E>) => boolean): Graph<N, E, G>;
642
+ //#endregion
643
+ //#region src/walks.d.ts
644
+ /**
645
+ * Random walk. At each node, picks a uniformly random traversable edge
646
+ * (outgoing edges, plus non-directed edges both ways).
647
+ * Yields steps indefinitely (may revisit nodes) until a sink node is reached.
648
+ */
649
+ declare function genRandomWalk<N, E>(graph: Graph<N, E>, options?: WalkOptions<E>): Generator<GraphStep<N, E>>;
650
+ /**
651
+ * Weighted random walk. Edge selection probability proportional to weight.
652
+ */
653
+ declare function genWeightedRandomWalk<N, E>(graph: Graph<N, E>, options?: WeightedWalkOptions<E>): Generator<GraphStep<N, E>>;
654
+ /**
655
+ * Quick random walk targeting unvisited edges.
656
+ * If unvisited traversable edges exist at the current node, picks one randomly.
657
+ * Otherwise, walks the fewest-hop path (BFS, honoring `filter` and edge modes)
658
+ * to the nearest unvisited edge. Ends when no unvisited edge is reachable.
659
+ */
660
+ declare function genQuickRandomWalk<N, E>(graph: Graph<N, E>, options?: WalkOptions<E>): Generator<GraphStep<N, E>>;
661
+ /**
662
+ * Walk a predefined sequence of edge IDs.
663
+ * Validates each edge exists and connects from the current position.
664
+ * Edges whose effective mode is not `'directed'` may be traversed
665
+ * target → source as well.
666
+ */
667
+ declare function genPredefinedWalk<N, E>(graph: Graph<N, E>, edgeIds: string[], options?: Pick<WalkOptions<E>, 'from'>): Generator<GraphStep<N, E>>;
668
+ /**
669
+ * Yield at most `n` steps from the source generator.
670
+ */
671
+ declare function takeSteps<N, E>(gen: Generator<GraphStep<N, E>>, n: number): Generator<GraphStep<N, E>>;
672
+ /**
673
+ * Yield steps until a specific node is reached.
674
+ */
675
+ declare function takeUntilNode<N, E>(gen: Generator<GraphStep<N, E>>, nodeId: string): Generator<GraphStep<N, E>>;
676
+ /**
677
+ * Yield steps until a specific edge is traversed.
678
+ */
679
+ declare function takeUntilEdge<N, E>(gen: Generator<GraphStep<N, E>>, edgeId: string): Generator<GraphStep<N, E>>;
680
+ /**
681
+ * Yield steps until node coverage reaches the target (0–1).
682
+ */
683
+ declare function takeUntilNodeCoverage<N, E>(gen: Generator<GraphStep<N, E>>, graph: Graph<N, E>, coverage: number, options?: {
684
+ from?: string;
685
+ }): Generator<GraphStep<N, E>>;
686
+ /**
687
+ * Yield steps until edge coverage reaches the target (0–1).
688
+ */
689
+ declare function takeUntilEdgeCoverage<N, E>(gen: Generator<GraphStep<N, E>>, graph: Graph<N, E>, coverage: number): Generator<GraphStep<N, E>>;
690
+ /**
691
+ * Compute coverage statistics for a completed walk.
692
+ */
693
+ declare function getCoverage<N, E>(graph: Graph<N, E>, steps: GraphStep<N, E>[], options?: {
694
+ from?: string;
695
+ }): CoverageStats;
696
+ //#endregion
697
+ export { GraphInstance as A, deleteEdge as B, isLayoutEqual as C, getGraphIssues as D, GraphIssue as E, createGraphEdge as F, hasEdge as G, deleteNode as H, createGraphFromTransition as I, updateEntities as J, hasNode as K, createGraphNode as L, addEntities as M, addNode as N, getEdgeMode as O, createGraph as P, createGraphPort as R, areEntitiesEqual as S, invalidateIndex as T, getEdge as U, deleteEntities as V, getNode as W, updateNode as Y, invertDiff as _, getCoverage as a, toPatches as b, takeUntilEdgeCoverage as c, flatten as d, getSubgraph as f, getPatches as g, getDiff as h, genWeightedRandomWalk as i, addEdge as j, isEdgeDirected as k, takeUntilNode as l, applyPatches as m, genQuickRandomWalk as n, takeSteps as o, reverseGraph as p, updateEdge as q, genRandomWalk as r, takeUntilEdge as s, genPredefinedWalk as t, takeUntilNodeCoverage as u, isEmptyDiff as v, isNonLayoutEqual as w, LAYOUT_KEYS as x, toDiff as y, createVisualGraph as z };