@statelyai/graph 0.1.0 → 0.3.1

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 (52) hide show
  1. package/README.md +65 -15
  2. package/dist/{adjacency-list-CXpOCibq.mjs → adjacency-list-ITO40kmn.mjs} +34 -1
  3. package/dist/{algorithms-R35X6ro4.mjs → algorithms-NWSB2RWj.mjs} +753 -19
  4. package/dist/algorithms.d.mts +488 -11
  5. package/dist/algorithms.mjs +2 -2
  6. package/dist/converter-CchokMDg.mjs +67 -0
  7. package/dist/edge-list-CgX6bBIF.mjs +71 -0
  8. package/dist/formats/adjacency-list/index.d.mts +44 -0
  9. package/dist/formats/adjacency-list/index.mjs +3 -0
  10. package/dist/formats/converter/index.d.mts +61 -0
  11. package/dist/formats/converter/index.mjs +3 -0
  12. package/dist/formats/cytoscape/index.d.mts +83 -0
  13. package/dist/formats/cytoscape/index.mjs +135 -0
  14. package/dist/formats/d3/index.d.mts +68 -0
  15. package/dist/formats/d3/index.mjs +111 -0
  16. package/dist/formats/dot/index.d.mts +63 -0
  17. package/dist/formats/dot/index.mjs +288 -0
  18. package/dist/formats/edge-list/index.d.mts +43 -0
  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 +65 -0
  23. package/dist/formats/gml/index.mjs +291 -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 +79 -0
  27. package/dist/formats/jgf/index.mjs +134 -0
  28. package/dist/formats/mermaid/index.d.mts +381 -0
  29. package/dist/formats/mermaid/index.mjs +2237 -0
  30. package/dist/formats/tgf/index.d.mts +54 -0
  31. package/dist/formats/tgf/index.mjs +111 -0
  32. package/dist/index.d.mts +332 -21
  33. package/dist/index.mjs +117 -13
  34. package/dist/{indexing-BHg1VhqN.mjs → indexing-eNDrXdDA.mjs} +31 -2
  35. package/dist/queries.d.mts +430 -9
  36. package/dist/queries.mjs +472 -9
  37. package/dist/{types-XV3S5Jnh.d.mts → types-BDXC1O5b.d.mts} +37 -2
  38. package/package.json +43 -17
  39. package/dist/adjacency-list-DW-lAUe8.d.mts +0 -10
  40. package/dist/dot-BRtq3e3c.mjs +0 -59
  41. package/dist/dot-HmJeUMsj.d.mts +0 -6
  42. package/dist/edge-list-BRujEnnU.mjs +0 -39
  43. package/dist/edge-list-CJmfoNu2.d.mts +0 -10
  44. package/dist/formats/adjacency-list.d.mts +0 -2
  45. package/dist/formats/adjacency-list.mjs +0 -3
  46. package/dist/formats/dot.d.mts +0 -2
  47. package/dist/formats/dot.mjs +0 -3
  48. package/dist/formats/edge-list.d.mts +0 -2
  49. package/dist/formats/edge-list.mjs +0 -3
  50. package/dist/formats/graphml.d.mts +0 -2
  51. package/dist/formats/graphml.mjs +0 -3
  52. package/dist/graphml-CMjPzSfY.d.mts +0 -7
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,20 @@
1
- //#region src/formats/adjacency-list.ts
1
+ //#region src/formats/adjacency-list/index.ts
2
+ /**
3
+ * Converts a graph to an adjacency list representation.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { createGraph, toAdjacencyList } from '@statelyai/graph';
8
+ *
9
+ * const graph = createGraph({
10
+ * nodes: { a: {}, b: {}, c: {} },
11
+ * edges: [{ source: 'a', target: 'b' }, { source: 'a', target: 'c' }],
12
+ * });
13
+ *
14
+ * toAdjacencyList(graph);
15
+ * // { a: ['b', 'c'], b: [], c: [] }
16
+ * ```
17
+ */
2
18
  function toAdjacencyList(graph) {
3
19
  const adj = {};
4
20
  for (const node of graph.nodes) adj[node.id] = [];
@@ -8,6 +24,23 @@ function toAdjacencyList(graph) {
8
24
  }
9
25
  return adj;
10
26
  }
27
+ /**
28
+ * Parses an adjacency list into a graph.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { fromAdjacencyList } from '@statelyai/graph';
33
+ *
34
+ * const graph = fromAdjacencyList({
35
+ * a: ['b', 'c'],
36
+ * b: ['c'],
37
+ * c: [],
38
+ * });
39
+ *
40
+ * graph.nodes; // [{id: 'a', ...}, {id: 'b', ...}, {id: 'c', ...}]
41
+ * graph.edges; // [{sourceId: 'a', targetId: 'b', ...}, ...]
42
+ * ```
43
+ */
11
44
  function fromAdjacencyList(adj, options) {
12
45
  const directed = options?.directed ?? true;
13
46
  const seen = /* @__PURE__ */ new Set();