Type-safe ReScript bindings for Graphology, a robust and multipurpose JavaScript graph library.
This library provides comprehensive ReScript bindings to Graphology's graph data structures and algorithms, including:
- Graph Creation & Manipulation: Directed, undirected, multi-graphs with full CRUD operations
- Algorithms: Shortest path (Dijkstra, A*, unweighted), simple paths, graph traversal (BFS, DFS)
- Layout: Circular, circle pack, rotation, and more
- Generators: Built-in graph generators (karate club, Erdős-Rényi, etc.)
- Import/Export: GEXF and SVG format support
- Native Iterator Support: Leverages JavaScript's native Iterator protocol
yarn add @dsiu/rescript-graphology graphologyAdd to your rescript.json:
{
"dependencies": ["@dsiu/rescript-graphology"]
}open Graphology
// Create a graph module with concrete types
module G = Graph.MakeGraph({
type node = string
type edge = string
})
// Create and populate a graph
let g = G.makeGraph()
g->G.addNode("Alice")
g->G.addNode("Bob")
g->G.addEdge("Alice", "Bob", ~attr={"weight": 1.0})
// Traverse the graph
g->G.Traversal.bfs((node, attributes, depth) => {
Console.log3("Visiting", node, depth)
})
// Find shortest path (returns Nullable.t<array<node>>)
let path = g->G.ShortestPath.Dijkstra.bidirectional(
"Alice",
"Bob",
~weight=#Attr("weight")
)
// Handle nullable result
switch path->Nullable.toOption {
| Some(p) => Console.log2("Path found:", p)
| None => Console.log("No path exists")
}
// Apply layout and export
G.Layout.Circular.assign(g)
g->G.SVG.render("./graph.svg", ~settings={
margin: 20,
width: 800,
height: 600
}, () => Console.log("Graph saved!"))The library uses a functor-based design for type safety:
module G = Graph.MakeGraph({
type node = string // or int, (int, int), custom types, etc.
type edge = string
})This ensures all operations on your graph maintain type consistency. All algorithm modules (ShortestPath, Layout, Traversal, etc.) are automatically available through the instantiated graph module.
- Directed, undirected, and mixed graphs
- Multi-graphs (multiple edges between nodes)
- Self-loops support
- Node and edge CRUD operations with attributes
- Graph, node, and edge attribute management
- Import/export serialization
- Iterator support for nodes, edges, and neighbors
- Shortest Path: Dijkstra, A*, unweighted (bidirectional & single-source)
- Simple Path: Simple path finding algorithms
- Traversal: BFS, DFS from node or full graph
- Circular, CirclePack, Rotation
- Utility functions for layout collection and manipulation
- Graph generators (complete, path, cycle, clique, star, etc.)
- Key renaming and updating
- Graph merging utilities (mergeClique, mergePath, mergeStar, mergeCycle)
- GEXF format (read/write with custom formatters)
- SVG rendering with customizable settings
All bindings have been verified against the official Graphology API (as of 2025-11-25). Key points:
Some functions return Nullable.t because they can return null/undefined:
- Find operations:
findNode,findEdge,findNeighbor→Nullable.t<T> - Shortest paths: All
bidirectionalfunctions →Nullable.t<array<node>>
// Example: Handle nullable results
let node = g->G.NodesIter.findNode((n, _) => n == "Alice")
switch node->Nullable.toOption {
| Some(n) => Console.log2("Found:", n)
| None => Console.log("Not found")
}Different iteration methods have different callback signatures:
- Node iteration:
(node, attributes) => ... - Edge iteration:
(edge, attributes, source, target, sourceAttributes, targetAttributes, undirected) => ... - Neighbor iteration:
(neighbor, attributes) => ...⚠️ Note: NOT edge information!
- Graphology Documentation
- ReScript Documentation
- See
src/Demo.resfor comprehensive usage examples
# Install dependencies
yarn install
# Build
yarn build
# Watch mode
yarn watch
# Clean
yarn clean
# Run tests
yarn test
# Run demo
node src/Demo.res.mjsThis project has comprehensive test coverage with 532 passing tests across all modules:
- Graph operations (core API)
- Node, Edge, and Neighbor iteration
- Shortest path algorithms
- Traversal algorithms (BFS/DFS)
- Layout algorithms
- Graph generators
- Utility functions
- GEXF import/export
- SVG rendering
Test files use Jest with @glennsl/rescript-jest. They should:
- Be placed in the
__tests__directory - Follow the naming convention
*_Test.res - Use the ReScript Jest bindings for assertions
- Have only one
expectper test (use tuples for multiple values)
Example test:
open Jest
open Expect
describe("Graph Tests", () => {
test("creates a graph", () => {
module G = Graph.MakeGraph({
type node = string
type edge = string
})
let g = G.makeGraph()
g->G.addNode("Alice")
expect(g->G.hasNode("Alice"))->toBe(true)
})
test("handles nullable find results", () => {
module G = Graph.MakeGraph({
type node = string
type edge = string
})
let g = G.makeGraph()
g->G.addNode("Alice")
let found = g->G.NodesIter.findNode((n, _) => n == "Alice")
expect(found)->toEqual(Nullable.make("Alice"))
})
})- ReScript v12.x or later
- Graphology v0.26.0 or later
- Node.js with ES module support
MIT
Danny Siu [email protected]
Contributions are welcome! Please feel free to submit issues or pull requests.