@statelyai/graph 0.1.0 → 0.3.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 (49) hide show
  1. package/README.md +65 -15
  2. package/dist/{adjacency-list-CXpOCibq.mjs → adjacency-list-A4_Eiwj3.mjs} +1 -1
  3. package/dist/{algorithms-R35X6ro4.mjs → algorithms-DBU7nmIV.mjs} +83 -2
  4. package/dist/algorithms.d.mts +10 -2
  5. package/dist/algorithms.mjs +2 -2
  6. package/dist/converter-DnbeyE_p.mjs +33 -0
  7. package/dist/{edge-list-BRujEnnU.mjs → edge-list-DuHMz8hf.mjs} +1 -1
  8. package/dist/{adjacency-list-DW-lAUe8.d.mts → formats/adjacency-list/index.d.mts} +3 -3
  9. package/dist/formats/adjacency-list/index.mjs +3 -0
  10. package/dist/formats/converter/index.d.mts +27 -0
  11. package/dist/formats/converter/index.mjs +3 -0
  12. package/dist/formats/cytoscape/index.d.mts +35 -0
  13. package/dist/formats/cytoscape/index.mjs +87 -0
  14. package/dist/formats/d3/index.d.mts +22 -0
  15. package/dist/formats/d3/index.mjs +65 -0
  16. package/dist/formats/dot/index.d.mts +9 -0
  17. package/dist/formats/dot/index.mjs +235 -0
  18. package/dist/{edge-list-CJmfoNu2.d.mts → formats/edge-list/index.d.mts} +3 -3
  19. package/dist/formats/edge-list/index.mjs +3 -0
  20. package/dist/formats/gexf/index.d.mts +9 -0
  21. package/dist/formats/gexf/index.mjs +249 -0
  22. package/dist/formats/gml/index.d.mts +9 -0
  23. package/dist/formats/gml/index.mjs +236 -0
  24. package/dist/formats/graphml/index.d.mts +9 -0
  25. package/dist/{graphml-CUTNRXqd.mjs → formats/graphml/index.mjs} +18 -4
  26. package/dist/formats/jgf/index.d.mts +30 -0
  27. package/dist/formats/jgf/index.mjs +85 -0
  28. package/dist/formats/mermaid/index.d.mts +188 -0
  29. package/dist/formats/mermaid/index.mjs +1898 -0
  30. package/dist/formats/tgf/index.d.mts +9 -0
  31. package/dist/formats/tgf/index.mjs +67 -0
  32. package/dist/index.d.mts +14 -9
  33. package/dist/index.mjs +5 -9
  34. package/dist/queries.d.mts +78 -2
  35. package/dist/queries.mjs +121 -2
  36. package/dist/{types-XV3S5Jnh.d.mts → types-B6Tpeerk.d.mts} +36 -1
  37. package/package.json +43 -17
  38. package/dist/dot-BRtq3e3c.mjs +0 -59
  39. package/dist/dot-HmJeUMsj.d.mts +0 -6
  40. package/dist/formats/adjacency-list.d.mts +0 -2
  41. package/dist/formats/adjacency-list.mjs +0 -3
  42. package/dist/formats/dot.d.mts +0 -2
  43. package/dist/formats/dot.mjs +0 -3
  44. package/dist/formats/edge-list.d.mts +0 -2
  45. package/dist/formats/edge-list.mjs +0 -3
  46. package/dist/formats/graphml.d.mts +0 -2
  47. package/dist/formats/graphml.mjs +0 -3
  48. package/dist/graphml-CMjPzSfY.d.mts +0 -7
  49. /package/dist/{indexing-BHg1VhqN.mjs → indexing-BFFVMnjF.mjs} +0 -0
package/README.md CHANGED
@@ -4,6 +4,18 @@ A TypeScript graph library built on plain JSON objects. Supports directed/undire
4
4
 
5
5
  Made from our experience at [stately.ai](https://stately.ai), where we build visual tools for complex systems.
6
6
 
7
+ ## Why this library?
8
+
9
+ Graph file formats (GEXF, GraphML) define how to _store_ graphs. Visualization libraries (Cytoscape.js, D3) define how to _render_ them. Neither gives you a good way to _work with_ them in between.
10
+
11
+ This library is the computational layer: plain JSON objects in, algorithms and mutations, plain JSON objects out. No classes, no DOM, no rendering engine — just data and functions.
12
+
13
+ ```
14
+ GEXF file → fromGEXF() → Graph → run algorithms, mutate → toCytoscapeJSON() → render
15
+ ```
16
+
17
+ Your `Graph` is a plain object that survives `JSON.stringify`, `structuredClone`, `postMessage`, and `localStorage` without adapters. Format converters are the I/O ports — read from any supported format, do your work, export to whatever your renderer or database expects.
18
+
7
19
  ## Install
8
20
 
9
21
  ```bash
@@ -77,22 +89,41 @@ const diagram = createVisualGraph({
77
89
  });
78
90
  ```
79
91
 
80
- ### Serialization
92
+ ### Format Conversion
81
93
 
82
94
  ```ts
83
- import { toDOT, toGraphML, toAdjacencyList, toEdgeList } from '@statelyai/graph';
95
+ import { toCytoscapeJSON } from '@statelyai/graph/cytoscape';
96
+ import { fromJGF } from '@statelyai/graph/jgf';
97
+ import { toD3Graph } from '@statelyai/graph/d3';
98
+ import { toDOT } from '@statelyai/graph/dot';
99
+ import { toGraphML } from '@statelyai/graph/graphml';
100
+ import { fromGEXF } from '@statelyai/graph/gexf';
101
+
102
+ // Export to web visualization libraries
103
+ const cytoData = toCytoscapeJSON(graph); // Cytoscape.js JSON (compound graphs preserved)
104
+ const d3Data = toD3Graph(graph); // D3.js { nodes, links }
105
+
106
+ // Export to text formats
107
+ const dot = toDOT(graph); // Graphviz DOT
108
+ const xml = toGraphML(graph); // GraphML XML
109
+
110
+ // Import from any format
111
+ const g1 = fromJGF(jsonGraphData); // JSON Graph Format
112
+ const g2 = fromGEXF(gexfXmlString); // GEXF (Gephi)
113
+ ```
84
114
 
85
- console.log(toDOT(graph));
86
- // Logs a Graphviz DOT string
115
+ Each bidirectional format also has a converter object for a unified interface:
87
116
 
88
- console.log(toGraphML(graph));
89
- // Logs a GraphML XML string
117
+ ```ts
118
+ import { createFormatConverter } from '@statelyai/graph';
119
+ import { cytoscapeConverter } from '@statelyai/graph/cytoscape';
90
120
 
91
- console.log(toAdjacencyList(graph));
92
- // Logs an adjacency object, e.g. { a: ['b'], b: ['c'] }
121
+ // Use a built-in converter
122
+ const cyto = cytoscapeConverter.to(graph);
123
+ const back = cytoscapeConverter.from(cyto);
93
124
 
94
- console.log(toEdgeList(graph));
95
- // Logs an array of [sourceId, targetId] pairs, e.g. [['a', 'b'], ['b', 'c']]
125
+ // Create your own
126
+ const myConverter = createFormatConverter(myToFn, myFromFn);
96
127
  ```
97
128
 
98
129
  ## API
@@ -176,15 +207,34 @@ console.log(toEdgeList(graph));
176
207
 
177
208
  Generator variants: `genShortestPaths`, `genSimplePaths`, `genCycles`, `genPreorders`, `genPostorders`.
178
209
 
179
- ### Transforms & Formats
210
+ ### Transforms
180
211
 
181
212
  | Function | Description |
182
213
  |----------|-------------|
183
214
  | `flatten(graph)` | Decompose hierarchy into flat leaf-node graph |
184
- | `toDOT` / `toGraphML` | Export to Graphviz DOT / GraphML |
185
- | `fromGraphML` | Import from GraphML |
186
- | `toAdjacencyList` / `fromAdjacencyList` | Adjacency list conversion |
187
- | `toEdgeList` / `fromEdgeList` | Edge list conversion |
215
+
216
+ ### Formats
217
+
218
+ Import format converters from subpaths (for example, `@statelyai/graph/dot` or `@statelyai/graph/mermaid`).
219
+
220
+ | Format | Export | Import | Compound? | Notes |
221
+ |--------|--------|--------|-----------|-------|
222
+ | **Cytoscape.js JSON** | `toCytoscapeJSON` | `fromCytoscapeJSON` | Yes | `parent` maps to `parentId` |
223
+ | **D3.js JSON** | `toD3Graph` | `fromD3Graph` | No | `{ nodes, links }` for force layouts |
224
+ | **JSON Graph Format** | `toJGF` | `fromJGF` | Yes | Formal spec, metadata-extensible |
225
+ | **GEXF** | `toGEXF` | `fromGEXF` | Yes | Gephi native, `pid` hierarchy, viz module |
226
+ | **GraphML** | `toGraphML` | `fromGraphML` | Yes | XML standard, requires `fast-xml-parser` |
227
+ | **GML** | `toGML` | `fromGML` | Yes | Nested node blocks for hierarchy |
228
+ | **TGF** | `toTGF` | `fromTGF` | No | Minimal (id + label only) |
229
+ | **DOT** | `toDOT` | `fromDOT` | Yes (subgraphs) | Graphviz DOT (`dotparser` peer dep) |
230
+ | **Mermaid** | `toMermaid*` | `fromMermaid*` | Varies by diagram | Sequence, flowchart, state, class, ER, mindmap, block |
231
+ | **Adjacency list** | `toAdjacencyList` | `fromAdjacencyList` | No | `Record<string, string[]>` |
232
+ | **Edge list** | `toEdgeList` | `fromEdgeList` | No | `[source, target][]` |
233
+
234
+ Optional peer deps by format:
235
+ - `@statelyai/graph/gexf` and `@statelyai/graph/graphml` use `fast-xml-parser`
236
+ - `@statelyai/graph/dot` uses `dotparser`
237
+ - Other formats are dependency-free
188
238
 
189
239
  ## License
190
240
 
@@ -1,4 +1,4 @@
1
- //#region src/formats/adjacency-list.ts
1
+ //#region src/formats/adjacency-list/index.ts
2
2
  function toAdjacencyList(graph) {
3
3
  const adj = {};
4
4
  for (const node of graph.nodes) adj[node.id] = [];
@@ -1,4 +1,4 @@
1
- import { a as indexUpdateEdgeEndpoints, i as indexReparentNode, n as indexAddEdge, o as invalidateIndex, r as indexAddNode, t as getIndex } from "./indexing-BHg1VhqN.mjs";
1
+ import { a as indexUpdateEdgeEndpoints, i as indexReparentNode, n as indexAddEdge, o as invalidateIndex, r as indexAddNode, t as getIndex } from "./indexing-BFFVMnjF.mjs";
2
2
 
3
3
  //#region src/graph.ts
4
4
  function resolveNode(config) {
@@ -73,6 +73,72 @@ function createVisualGraph(config) {
73
73
  }))
74
74
  };
75
75
  }
76
+ /**
77
+ * Create a graph by BFS exploration of a transition function.
78
+ * Each unique state becomes a node; each (state, event) → nextState becomes an edge.
79
+ *
80
+ * - Node IDs are determined by `serializeState` (default: `JSON.stringify`).
81
+ * - Edge IDs use the format `sourceId|serializedEvent|targetId` for uniqueness
82
+ * and debuggability. Edge labels are just the serialized event string.
83
+ */
84
+ function createGraphFromTransition(transition, options) {
85
+ const serializeState = options.serializeState ?? JSON.stringify;
86
+ const serializeEvent = options.serializeEvent ?? JSON.stringify;
87
+ const limit = options.limit ?? Infinity;
88
+ const getEvents = typeof options.events === "function" ? options.events : () => options.events;
89
+ const nodes = [];
90
+ const edges = [];
91
+ const visited = /* @__PURE__ */ new Set();
92
+ const edgeSet = /* @__PURE__ */ new Set();
93
+ const queue = [options.initialState];
94
+ const initialStateId = serializeState(options.initialState);
95
+ visited.add(initialStateId);
96
+ nodes.push({
97
+ id: initialStateId,
98
+ label: initialStateId,
99
+ data: options.initialState
100
+ });
101
+ let iterations = 0;
102
+ while (queue.length > 0) {
103
+ const state = queue.shift();
104
+ const stateId = serializeState(state);
105
+ if (++iterations > limit) throw new Error("Traversal limit exceeded");
106
+ if (options.stopWhen?.(state)) continue;
107
+ const events = getEvents(state);
108
+ for (const event of events) {
109
+ const nextState = transition(state, event);
110
+ const nextStateId = serializeState(nextState);
111
+ const eventStr = serializeEvent(event);
112
+ if (!visited.has(nextStateId)) {
113
+ visited.add(nextStateId);
114
+ nodes.push({
115
+ id: nextStateId,
116
+ label: nextStateId,
117
+ data: nextState
118
+ });
119
+ queue.push(nextState);
120
+ }
121
+ const edgeKey = `${stateId}|${eventStr}|${nextStateId}`;
122
+ if (!edgeSet.has(edgeKey)) {
123
+ edgeSet.add(edgeKey);
124
+ edges.push({
125
+ id: edgeKey,
126
+ sourceId: stateId,
127
+ targetId: nextStateId,
128
+ label: eventStr,
129
+ data: event
130
+ });
131
+ }
132
+ }
133
+ }
134
+ return createGraph({
135
+ id: options.id ?? "",
136
+ type: "directed",
137
+ initialNodeId: initialStateId,
138
+ nodes,
139
+ edges
140
+ });
141
+ }
76
142
  /** Get a node by id, or `undefined` if not found. */
77
143
  function getNode(graph, id) {
78
144
  const arrayIdx = getIndex(graph).nodeById.get(id);
@@ -1192,6 +1258,21 @@ function fwReconstruct(graph, prev, idxOf, nodeIds, sourceNode, sourceIdx, targe
1192
1258
  }
1193
1259
  return results;
1194
1260
  }
1261
+ /**
1262
+ * Joins two paths end-to-end. The last node of the head path must equal
1263
+ * the source of the tail path (the overlap node).
1264
+ *
1265
+ * Steps are concatenated: head.steps ++ tail.steps (tail already starts
1266
+ * from the overlap node, so no slicing is needed).
1267
+ */
1268
+ function joinPaths(headPath, tailPath) {
1269
+ const headEnd = headPath.steps.length > 0 ? headPath.steps[headPath.steps.length - 1].node : headPath.source;
1270
+ if (headEnd.id !== tailPath.source.id) throw new Error(`Paths cannot be joined: head path ends at "${headEnd.id}" but tail path starts at "${tailPath.source.id}"`);
1271
+ return {
1272
+ source: headPath.source,
1273
+ steps: [...headPath.steps, ...tailPath.steps]
1274
+ };
1275
+ }
1195
1276
 
1196
1277
  //#endregion
1197
- export { createGraph as A, updateEntities as B, isAcyclic as C, addEdge as D, GraphInstance as E, getEdge as F, getNode as I, hasEdge as L, deleteEdge as M, deleteEntities as N, addEntities as O, deleteNode as P, hasNode as R, hasPath as S, isTree as T, updateNode as V, getShortestPaths as _, genPreorders as a, getStronglyConnectedComponents as b, getAllPairsShortestPaths as c, getMinimumSpanningTree as d, getPostorder as f, getShortestPath as g, getPreorders as h, genPostorders as i, createVisualGraph as j, addNode as k, getConnectedComponents as l, getPreorder as m, dfs as n, genShortestPaths as o, getPostorders as p, genCycles as r, genSimplePaths as s, bfs as t, getCycles as u, getSimplePath as v, isConnected as w, getTopologicalSort as x, getSimplePaths as y, updateEdge as z };
1278
+ export { addNode as A, hasNode as B, isAcyclic as C, GraphInstance as D, joinPaths as E, deleteEntities as F, updateEntities as H, deleteNode as I, getEdge as L, createGraphFromTransition as M, createVisualGraph as N, addEdge as O, deleteEdge as P, getNode as R, hasPath as S, isTree as T, updateNode as U, updateEdge as V, getShortestPaths as _, genPreorders as a, getStronglyConnectedComponents as b, getAllPairsShortestPaths as c, getMinimumSpanningTree as d, getPostorder as f, getShortestPath as g, getPreorders as h, genPostorders as i, createGraph as j, addEntities as k, getConnectedComponents as l, getPreorder as m, dfs as n, genShortestPaths as o, getPostorders as p, genCycles as r, genSimplePaths as s, bfs as t, getCycles as u, getSimplePath as v, isConnected as w, getTopologicalSort as x, getSimplePaths as y, hasEdge as z };
@@ -1,4 +1,4 @@
1
- import { b as SinglePathOptions, c as Graph, f as GraphNode, g as MSTOptions, m as GraphPath, t as AllPairsShortestPathsOptions, x as TraversalOptions, y as PathOptions } from "./types-XV3S5Jnh.mjs";
1
+ import { C as TraversalOptions, _ as MSTOptions, b as PathOptions, c as Graph, h as GraphPath, p as GraphNode, t as AllPairsShortestPathsOptions, x as SinglePathOptions } from "./types-B6Tpeerk.mjs";
2
2
 
3
3
  //#region src/algorithms.d.ts
4
4
  declare function bfs<N>(graph: Graph<N>, startId: string): Generator<GraphNode<N>>;
@@ -78,5 +78,13 @@ declare function getMinimumSpanningTree<N, E>(graph: Graph<N, E>, opts?: MSTOpti
78
78
  * Algorithm 'floyd-warshall': classic O(V³) dynamic programming.
79
79
  */
80
80
  declare function getAllPairsShortestPaths<N, E>(graph: Graph<N, E>, opts?: AllPairsShortestPathsOptions<E>): GraphPath<N, E>[];
81
+ /**
82
+ * Joins two paths end-to-end. The last node of the head path must equal
83
+ * the source of the tail path (the overlap node).
84
+ *
85
+ * Steps are concatenated: head.steps ++ tail.steps (tail already starts
86
+ * from the overlap node, so no slicing is needed).
87
+ */
88
+ declare function joinPaths<N, E>(headPath: GraphPath<N, E>, tailPath: GraphPath<N, E>): GraphPath<N, E>;
81
89
  //#endregion
82
- export { bfs, dfs, genCycles, genPostorders, genPreorders, genShortestPaths, genSimplePaths, getAllPairsShortestPaths, getConnectedComponents, getCycles, getMinimumSpanningTree, getPostorder, getPostorders, getPreorder, getPreorders, getShortestPath, getShortestPaths, getSimplePath, getSimplePaths, getStronglyConnectedComponents, getTopologicalSort, hasPath, isAcyclic, isConnected, isTree };
90
+ export { bfs, dfs, genCycles, genPostorders, genPreorders, genShortestPaths, genSimplePaths, getAllPairsShortestPaths, getConnectedComponents, getCycles, getMinimumSpanningTree, getPostorder, getPostorders, getPreorder, getPreorders, getShortestPath, getShortestPaths, getSimplePath, getSimplePaths, getStronglyConnectedComponents, getTopologicalSort, hasPath, isAcyclic, isConnected, isTree, joinPaths };
@@ -1,3 +1,3 @@
1
- import { C as isAcyclic, S as hasPath, T as isTree, _ 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, 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 } from "./algorithms-R35X6ro4.mjs";
1
+ import { C as isAcyclic, E as joinPaths, S as hasPath, T as isTree, _ 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, 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 } from "./algorithms-DBU7nmIV.mjs";
2
2
 
3
- export { bfs, dfs, genCycles, genPostorders, genPreorders, genShortestPaths, genSimplePaths, getAllPairsShortestPaths, getConnectedComponents, getCycles, getMinimumSpanningTree, getPostorder, getPostorders, getPreorder, getPreorders, getShortestPath, getShortestPaths, getSimplePath, getSimplePaths, getStronglyConnectedComponents, getTopologicalSort, hasPath, isAcyclic, isConnected, isTree };
3
+ export { bfs, dfs, genCycles, genPostorders, genPreorders, genShortestPaths, genSimplePaths, getAllPairsShortestPaths, getConnectedComponents, getCycles, getMinimumSpanningTree, getPostorder, getPostorders, getPreorder, getPreorders, getShortestPath, getShortestPaths, getSimplePath, getSimplePaths, getStronglyConnectedComponents, getTopologicalSort, hasPath, isAcyclic, isConnected, isTree, joinPaths };
@@ -0,0 +1,33 @@
1
+ import { n as toAdjacencyList, t as fromAdjacencyList } from "./adjacency-list-A4_Eiwj3.mjs";
2
+ import { n as toEdgeList, t as fromEdgeList } from "./edge-list-DuHMz8hf.mjs";
3
+
4
+ //#region src/formats/converter/index.ts
5
+ /**
6
+ * Create a `GraphFormatConverter` from a pair of `to`/`from` functions.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { createFormatConverter } from '@statelyai/graph';
11
+ *
12
+ * const yamlConverter = createFormatConverter(
13
+ * (graph) => toYAML(graph),
14
+ * (yaml) => fromYAML(yaml),
15
+ * );
16
+ *
17
+ * const yaml = yamlConverter.to(graph);
18
+ * const graph = yamlConverter.from(yaml);
19
+ * ```
20
+ */
21
+ function createFormatConverter(to, from) {
22
+ return {
23
+ to,
24
+ from
25
+ };
26
+ }
27
+ /** Bidirectional converter for adjacency-list format (`Record<string, string[]>`). */
28
+ const adjacencyListConverter = createFormatConverter(toAdjacencyList, fromAdjacencyList);
29
+ /** Bidirectional converter for edge-list format (`[source, target][]`). */
30
+ const edgeListConverter = createFormatConverter(toEdgeList, fromEdgeList);
31
+
32
+ //#endregion
33
+ export { createFormatConverter as n, edgeListConverter as r, adjacencyListConverter as t };
@@ -1,4 +1,4 @@
1
- //#region src/formats/edge-list.ts
1
+ //#region src/formats/edge-list/index.ts
2
2
  function toEdgeList(graph) {
3
3
  return graph.edges.map((e) => [e.sourceId, e.targetId]);
4
4
  }
@@ -1,10 +1,10 @@
1
- import { c as Graph } from "./types-XV3S5Jnh.mjs";
1
+ import { c as Graph } from "../../types-B6Tpeerk.mjs";
2
2
 
3
- //#region src/formats/adjacency-list.d.ts
3
+ //#region src/formats/adjacency-list/index.d.ts
4
4
  declare function toAdjacencyList(graph: Graph): Record<string, string[]>;
5
5
  declare function fromAdjacencyList(adj: Record<string, string[]>, options?: {
6
6
  directed?: boolean;
7
7
  id?: string;
8
8
  }): Graph;
9
9
  //#endregion
10
- export { toAdjacencyList as n, fromAdjacencyList as t };
10
+ export { fromAdjacencyList, toAdjacencyList };
@@ -0,0 +1,3 @@
1
+ import { n as toAdjacencyList, t as fromAdjacencyList } from "../../adjacency-list-A4_Eiwj3.mjs";
2
+
3
+ export { fromAdjacencyList, toAdjacencyList };
@@ -0,0 +1,27 @@
1
+ import { c as Graph, f as GraphFormatConverter } from "../../types-B6Tpeerk.mjs";
2
+
3
+ //#region src/formats/converter/index.d.ts
4
+
5
+ /**
6
+ * Create a `GraphFormatConverter` from a pair of `to`/`from` functions.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { createFormatConverter } from '@statelyai/graph';
11
+ *
12
+ * const yamlConverter = createFormatConverter(
13
+ * (graph) => toYAML(graph),
14
+ * (yaml) => fromYAML(yaml),
15
+ * );
16
+ *
17
+ * const yaml = yamlConverter.to(graph);
18
+ * const graph = yamlConverter.from(yaml);
19
+ * ```
20
+ */
21
+ declare function createFormatConverter<TSerial>(to: (graph: Graph) => TSerial, from: (input: TSerial) => Graph): GraphFormatConverter<TSerial>;
22
+ /** Bidirectional converter for adjacency-list format (`Record<string, string[]>`). */
23
+ declare const adjacencyListConverter: GraphFormatConverter<Record<string, string[]>>;
24
+ /** Bidirectional converter for edge-list format (`[source, target][]`). */
25
+ declare const edgeListConverter: GraphFormatConverter<[string, string][]>;
26
+ //#endregion
27
+ export { adjacencyListConverter, createFormatConverter, edgeListConverter };
@@ -0,0 +1,3 @@
1
+ import { n as createFormatConverter, r as edgeListConverter, t as adjacencyListConverter } from "../../converter-DnbeyE_p.mjs";
2
+
3
+ export { adjacencyListConverter, createFormatConverter, edgeListConverter };
@@ -0,0 +1,35 @@
1
+ import { c as Graph, f as GraphFormatConverter } from "../../types-B6Tpeerk.mjs";
2
+
3
+ //#region src/formats/cytoscape/index.d.ts
4
+ interface CytoscapeNode {
5
+ data: {
6
+ id: string;
7
+ parent?: string;
8
+ [key: string]: any;
9
+ };
10
+ position?: {
11
+ x: number;
12
+ y: number;
13
+ };
14
+ }
15
+ interface CytoscapeEdge {
16
+ data: {
17
+ id: string;
18
+ source: string;
19
+ target: string;
20
+ [key: string]: any;
21
+ };
22
+ }
23
+ interface CytoscapeJSON {
24
+ data?: Record<string, any>;
25
+ elements: {
26
+ nodes: CytoscapeNode[];
27
+ edges: CytoscapeEdge[];
28
+ };
29
+ }
30
+ declare function toCytoscapeJSON(graph: Graph): CytoscapeJSON;
31
+ declare function fromCytoscapeJSON(cyto: CytoscapeJSON): Graph;
32
+ /** Bidirectional converter for Cytoscape.js JSON format. */
33
+ declare const cytoscapeConverter: GraphFormatConverter<CytoscapeJSON>;
34
+ //#endregion
35
+ export { CytoscapeEdge, CytoscapeJSON, CytoscapeNode, cytoscapeConverter, fromCytoscapeJSON, toCytoscapeJSON };
@@ -0,0 +1,87 @@
1
+ import { n as createFormatConverter } from "../../converter-DnbeyE_p.mjs";
2
+
3
+ //#region src/formats/cytoscape/index.ts
4
+ function toCytoscapeJSON(graph) {
5
+ const graphData = {};
6
+ if (graph.id) graphData.id = graph.id;
7
+ graphData.type = graph.type;
8
+ if (graph.initialNodeId !== null) graphData.initialNodeId = graph.initialNodeId;
9
+ if (graph.data !== void 0) graphData.graphData = graph.data;
10
+ if (graph.direction) graphData.direction = graph.direction;
11
+ return {
12
+ ...Object.keys(graphData).length > 0 && { data: graphData },
13
+ elements: {
14
+ nodes: graph.nodes.map((n) => {
15
+ const data = { id: n.id };
16
+ if (n.parentId !== null) data.parent = n.parentId;
17
+ if (n.label) data.label = n.label;
18
+ if (n.initialNodeId !== null) data.initialNodeId = n.initialNodeId;
19
+ if (n.data !== void 0) data.nodeData = n.data;
20
+ if (n.width !== void 0) data.width = n.width;
21
+ if (n.height !== void 0) data.height = n.height;
22
+ if (n.shape) data.shape = n.shape;
23
+ if (n.color) data.color = n.color;
24
+ const node = { data };
25
+ if (n.x !== void 0 && n.y !== void 0) node.position = {
26
+ x: n.x,
27
+ y: n.y
28
+ };
29
+ return node;
30
+ }),
31
+ edges: graph.edges.map((e) => {
32
+ const data = {
33
+ id: e.id,
34
+ source: e.sourceId,
35
+ target: e.targetId
36
+ };
37
+ if (e.label) data.label = e.label;
38
+ if (e.data !== void 0) data.edgeData = e.data;
39
+ if (e.color) data.color = e.color;
40
+ return { data };
41
+ })
42
+ }
43
+ };
44
+ }
45
+ function fromCytoscapeJSON(cyto) {
46
+ if (!cyto || typeof cyto !== "object") throw new Error("Cytoscape: expected an object");
47
+ if (!cyto.elements || typeof cyto.elements !== "object") throw new Error("Cytoscape: missing \"elements\" property");
48
+ if (!Array.isArray(cyto.elements.nodes)) throw new Error("Cytoscape: \"elements.nodes\" must be an array");
49
+ if (!Array.isArray(cyto.elements.edges)) throw new Error("Cytoscape: \"elements.edges\" must be an array");
50
+ return {
51
+ id: cyto.data?.id ?? "",
52
+ type: cyto.data?.type === "undirected" ? "undirected" : "directed",
53
+ initialNodeId: cyto.data?.initialNodeId ?? null,
54
+ data: cyto.data?.graphData,
55
+ ...cyto.data?.direction && { direction: cyto.data.direction },
56
+ nodes: cyto.elements.nodes.map((n) => ({
57
+ type: "node",
58
+ id: n.data.id,
59
+ parentId: n.data.parent ?? null,
60
+ initialNodeId: n.data.initialNodeId ?? null,
61
+ label: n.data.label ?? "",
62
+ data: n.data.nodeData,
63
+ ...n.position && {
64
+ x: n.position.x,
65
+ y: n.position.y
66
+ },
67
+ ...n.data.width !== void 0 && { width: n.data.width },
68
+ ...n.data.height !== void 0 && { height: n.data.height },
69
+ ...n.data.shape && { shape: n.data.shape },
70
+ ...n.data.color && { color: n.data.color }
71
+ })),
72
+ edges: cyto.elements.edges.map((e, i) => ({
73
+ type: "edge",
74
+ id: e.data.id ?? `e${i}`,
75
+ sourceId: e.data.source,
76
+ targetId: e.data.target,
77
+ label: e.data.label ?? "",
78
+ data: e.data.edgeData,
79
+ ...e.data.color && { color: e.data.color }
80
+ }))
81
+ };
82
+ }
83
+ /** Bidirectional converter for Cytoscape.js JSON format. */
84
+ const cytoscapeConverter = createFormatConverter(toCytoscapeJSON, fromCytoscapeJSON);
85
+
86
+ //#endregion
87
+ export { cytoscapeConverter, fromCytoscapeJSON, toCytoscapeJSON };
@@ -0,0 +1,22 @@
1
+ import { c as Graph, f as GraphFormatConverter } from "../../types-B6Tpeerk.mjs";
2
+
3
+ //#region src/formats/d3/index.d.ts
4
+ interface D3Node {
5
+ id: string;
6
+ [key: string]: any;
7
+ }
8
+ interface D3Link {
9
+ source: string;
10
+ target: string;
11
+ [key: string]: any;
12
+ }
13
+ interface D3Graph {
14
+ nodes: D3Node[];
15
+ links: D3Link[];
16
+ }
17
+ declare function toD3Graph(graph: Graph): D3Graph;
18
+ declare function fromD3Graph(d3: D3Graph): Graph;
19
+ /** Bidirectional converter for D3.js force-directed JSON format. */
20
+ declare const d3Converter: GraphFormatConverter<D3Graph>;
21
+ //#endregion
22
+ export { D3Graph, D3Link, D3Node, d3Converter, fromD3Graph, toD3Graph };
@@ -0,0 +1,65 @@
1
+ import { n as createFormatConverter } from "../../converter-DnbeyE_p.mjs";
2
+
3
+ //#region src/formats/d3/index.ts
4
+ function toD3Graph(graph) {
5
+ return {
6
+ nodes: graph.nodes.map((n) => {
7
+ const node = { id: n.id };
8
+ if (n.label) node.label = n.label;
9
+ if (n.data !== void 0) node.data = n.data;
10
+ if (n.x !== void 0) node.x = n.x;
11
+ if (n.y !== void 0) node.y = n.y;
12
+ if (n.color) node.color = n.color;
13
+ if (n.shape) node.shape = n.shape;
14
+ return node;
15
+ }),
16
+ links: graph.edges.map((e) => {
17
+ const link = {
18
+ source: e.sourceId,
19
+ target: e.targetId
20
+ };
21
+ if (e.id) link.id = e.id;
22
+ if (e.label) link.label = e.label;
23
+ if (e.data !== void 0) link.data = e.data;
24
+ if (e.color) link.color = e.color;
25
+ return link;
26
+ })
27
+ };
28
+ }
29
+ function fromD3Graph(d3) {
30
+ if (!d3 || typeof d3 !== "object") throw new Error("D3: expected an object");
31
+ if (!Array.isArray(d3.nodes)) throw new Error("D3: \"nodes\" must be an array");
32
+ if (!Array.isArray(d3.links)) throw new Error("D3: \"links\" must be an array");
33
+ return {
34
+ id: "",
35
+ type: "directed",
36
+ initialNodeId: null,
37
+ data: void 0,
38
+ nodes: d3.nodes.map((n) => ({
39
+ type: "node",
40
+ id: n.id,
41
+ parentId: null,
42
+ initialNodeId: null,
43
+ label: n.label ?? "",
44
+ data: n.data,
45
+ ...n.x !== void 0 && { x: n.x },
46
+ ...n.y !== void 0 && { y: n.y },
47
+ ...n.color && { color: n.color },
48
+ ...n.shape && { shape: n.shape }
49
+ })),
50
+ edges: d3.links.map((l, i) => ({
51
+ type: "edge",
52
+ id: l.id ?? `e${i}`,
53
+ sourceId: typeof l.source === "string" ? l.source : l.source.id,
54
+ targetId: typeof l.target === "string" ? l.target : l.target.id,
55
+ label: l.label ?? "",
56
+ data: l.data,
57
+ ...l.color && { color: l.color }
58
+ }))
59
+ };
60
+ }
61
+ /** Bidirectional converter for D3.js force-directed JSON format. */
62
+ const d3Converter = createFormatConverter(toD3Graph, fromD3Graph);
63
+
64
+ //#endregion
65
+ export { d3Converter, fromD3Graph, toD3Graph };
@@ -0,0 +1,9 @@
1
+ import { c as Graph, f as GraphFormatConverter } from "../../types-B6Tpeerk.mjs";
2
+
3
+ //#region src/formats/dot/index.d.ts
4
+ declare function toDOT(graph: Graph): string;
5
+ declare function fromDOT(dot: string): Graph;
6
+ /** Bidirectional converter for DOT (Graphviz) format. */
7
+ declare const dotConverter: GraphFormatConverter<string>;
8
+ //#endregion
9
+ export { dotConverter, fromDOT, toDOT };