Skip to content
Effect Days 2026 Get your ticket

Graph

83 exports Added in v3.18.0 Source

Algorithms

astar

Added in v3.18.0 Source

Find the shortest path between two nodes using A* pathfinding algorithm.

A* is an extension of Dijkstra's algorithm that uses a heuristic function to guide the search towards the target, potentially finding paths faster than Dijkstra's. The heuristic must be admissible (never overestimate the actual cost).

Signature

declare function astar<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option<PathResult<E>>

Example

import { Graph, Option } from "effect"
const graph = Graph.directed<{x: number, y: number}, number>((mutable) => {
const a = Graph.addNode(mutable, {x: 0, y: 0})
const b = Graph.addNode(mutable, {x: 1, y: 0})
const c = Graph.addNode(mutable, {x: 2, y: 0})
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, c, 1)
})
// Manhattan distance heuristic
const heuristic = (nodeData: {x: number, y: number}, targetData: {x: number, y: number}) =>
Math.abs(nodeData.x - targetData.x) + Math.abs(nodeData.y - targetData.y)
const result = Graph.astar(graph, { source: 0, target: 2, cost: (edgeData) => edgeData, heuristic })
if (Option.isSome(result)) {
console.log(result.value.path) // [0, 1, 2] - shortest path
console.log(result.value.distance) // 2 - total distance
}

bellmanFord

Added in v3.18.0 Source

Find the shortest path between two nodes using Bellman-Ford algorithm.

Bellman-Ford algorithm can handle negative edge weights and detects negative cycles. It has O(VE) time complexity, slower than Dijkstra's but more versatile. Returns Option.none() if a negative cycle is detected that affects the path.

Signature

declare function bellmanFord<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option<PathResult<E>>

Example

import { Graph, Option } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, -1) // Negative weight allowed
Graph.addEdge(mutable, b, c, 3)
Graph.addEdge(mutable, a, c, 5)
})
const result = Graph.bellmanFord(graph, { source: 0, target: 2, cost: (edgeData) => edgeData })
if (Option.isSome(result)) {
console.log(result.value.path) // [0, 1, 2] - shortest path A->B->C
console.log(result.value.distance) // 2 - total distance
}

Find connected components in an undirected graph. Each component is represented as an array of node indices.

Signature

declare function connectedComponents<N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">): Array<Array<number>>

Example

import { Graph } from "effect"
const graph = Graph.undirected<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
const d = Graph.addNode(mutable, "D")
Graph.addEdge(mutable, a, b, "edge") // Component 1: A-B
Graph.addEdge(mutable, c, d, "edge") // Component 2: C-D
})
const components = Graph.connectedComponents(graph)
console.log(components) // [[0, 1], [2, 3]]

dijkstra

Added in v3.18.0 Source

Find the shortest path between two nodes using Dijkstra's algorithm.

Dijkstra's algorithm works with non-negative edge weights and finds the shortest path from a source node to a target node in O((V + E) log V) time complexity.

Signature

declare function dijkstra<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: DijkstraConfig<E>): Option<PathResult<E>>

Example

import { Graph, Option } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 5)
Graph.addEdge(mutable, a, c, 10)
Graph.addEdge(mutable, b, c, 2)
})
const result = Graph.dijkstra(graph, { source: 0, target: 2, cost: (edgeData) => edgeData })
if (Option.isSome(result)) {
console.log(result.value.path) // [0, 1, 2] - shortest path A->B->C
console.log(result.value.distance) // 7 - total distance
}

floydWarshall

Added in v3.18.0 Source

Find shortest paths between all pairs of nodes using Floyd-Warshall algorithm.

Floyd-Warshall algorithm computes shortest paths between all pairs of nodes in O(V³) time. It can handle negative edge weights and detect negative cycles.

Signature

declare function floydWarshall<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, cost: (edgeData: E) => number): AllPairsResult<E>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 3)
Graph.addEdge(mutable, b, c, 2)
Graph.addEdge(mutable, a, c, 7)
})
const result = Graph.floydWarshall(graph, (edgeData) => edgeData)
const distanceAToC = result.distances.get(0)?.get(2) // 5 (A->B->C)
const pathAToC = result.paths.get(0)?.get(2) // [0, 1, 2]

isAcyclic

Added in v3.18.0 Source

Checks if the graph is acyclic (contains no cycles).

Uses depth-first search to detect back edges, which indicate cycles. For directed graphs, any back edge creates a cycle. For undirected graphs, a back edge that doesn't go to the immediate parent creates a cycle.

Signature

declare function isAcyclic<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): boolean

Example

import { Graph } from "effect"
// Acyclic directed graph (DAG)
const dag = Graph.directed<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, "A->B")
Graph.addEdge(mutable, b, c, "B->C")
})
console.log(Graph.isAcyclic(dag)) // true
// Cyclic directed graph
const cyclic = Graph.directed<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
Graph.addEdge(mutable, a, b, "A->B")
Graph.addEdge(mutable, b, a, "B->A") // Creates cycle
})
console.log(Graph.isAcyclic(cyclic)) // false

isBipartite

Added in v3.18.0 Source

Checks if an undirected graph is bipartite.

A bipartite graph is one whose vertices can be divided into two disjoint sets such that no two vertices within the same set are adjacent. Uses BFS coloring to determine bipartiteness.

Signature

declare function isBipartite<N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">): boolean

Example

import { Graph } from "effect"
// Bipartite graph (alternating coloring possible)
const bipartite = Graph.undirected<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
const d = Graph.addNode(mutable, "D")
Graph.addEdge(mutable, a, b, "edge") // Set 1: {A, C}, Set 2: {B, D}
Graph.addEdge(mutable, b, c, "edge")
Graph.addEdge(mutable, c, d, "edge")
})
console.log(Graph.isBipartite(bipartite)) // true
// Non-bipartite graph (odd cycle)
const triangle = Graph.undirected<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, "edge")
Graph.addEdge(mutable, b, c, "edge")
Graph.addEdge(mutable, c, a, "edge") // Triangle (3-cycle)
})
console.log(Graph.isBipartite(triangle)) // false

Find strongly connected components in a directed graph using Kosaraju's algorithm. Each SCC is represented as an array of node indices.

Signature

declare function stronglyConnectedComponents<N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">): Array<Array<number>>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, "A->B")
Graph.addEdge(mutable, b, c, "B->C")
Graph.addEdge(mutable, c, a, "C->A") // Creates SCC: A-B-C
})
const sccs = Graph.stronglyConnectedComponents(graph)
console.log(sccs) // [[0, 1, 2]]

Constructors

directed

Added in v3.18.0 Source

Creates a directed graph, optionally with initial mutations.

Signature

declare function directed<N, E>(mutate?: (mutable: MutableDirectedGraph<N, E>) => void): DirectedGraph<N, E>

Example

import { Graph } from "effect"
// Directed graph with initial nodes and edges
const graph = Graph.directed<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, "A->B")
Graph.addEdge(mutable, b, c, "B->C")
})

undirected

Added in v3.18.0 Source

Creates an undirected graph, optionally with initial mutations.

Signature

declare function undirected<N, E>(mutate?: (mutable: MutableUndirectedGraph<N, E>) => void): UndirectedGraph<N, E>

Example

import { Graph } from "effect"
// Undirected graph with initial nodes and edges
const graph = Graph.undirected<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, "A-B")
Graph.addEdge(mutable, b, c, "B-C")
})

Errors

GraphError

Added in v3.18.0 Source

Error thrown when a graph operation fails.

Signature

declare class GraphError extends YieldableError<this> & {
readonly _tag: "GraphError";
} & Readonly<{
readonly message: string;
}> {
constructor(args: {
readonly message: string;
});
}

Getters

edgeCount

Added in v3.18.0 Source

Returns the number of edges in the graph.

Signature

declare function edgeCount<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): number

Example

import { Graph } from "effect"
const emptyGraph = Graph.directed<string, number>()
console.log(Graph.edgeCount(emptyGraph)) // 0
const graphWithEdges = Graph.mutate(emptyGraph, (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const nodeC = Graph.addNode(mutable, "Node C")
Graph.addEdge(mutable, nodeA, nodeB, 1)
Graph.addEdge(mutable, nodeB, nodeC, 2)
Graph.addEdge(mutable, nodeC, nodeA, 3)
})
console.log(Graph.edgeCount(graphWithEdges)) // 3

findEdge

Added in v3.18.0 Source

Finds the first edge that matches the given predicate.

Signature

declare function findEdge<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: E, source: number, target: number) => boolean): Option<number>

Example

import { Graph, Option } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const nodeC = Graph.addNode(mutable, "Node C")
Graph.addEdge(mutable, nodeA, nodeB, 10)
Graph.addEdge(mutable, nodeB, nodeC, 20)
})
const result = Graph.findEdge(graph, (data) => data > 15)
console.log(result) // Option.some(1)
const notFound = Graph.findEdge(graph, (data) => data > 100)
console.log(notFound) // Option.none()

findEdges

Added in v3.18.0 Source

Finds all edges that match the given predicate.

Signature

declare function findEdges<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: E, source: number, target: number) => boolean): Array<number>

Example

import { Graph } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const nodeC = Graph.addNode(mutable, "Node C")
Graph.addEdge(mutable, nodeA, nodeB, 10)
Graph.addEdge(mutable, nodeB, nodeC, 20)
Graph.addEdge(mutable, nodeC, nodeA, 30)
})
const result = Graph.findEdges(graph, (data) => data >= 20)
console.log(result) // [1, 2]
const empty = Graph.findEdges(graph, (data) => data > 100)
console.log(empty) // []

findNode

Added in v3.18.0 Source

Finds the first node that matches the given predicate.

Signature

declare function findNode<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: N) => boolean): Option<number>

Example

import { Graph, Option } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
Graph.addNode(mutable, "Node A")
Graph.addNode(mutable, "Node B")
Graph.addNode(mutable, "Node C")
})
const result = Graph.findNode(graph, (data) => data.startsWith("Node B"))
console.log(result) // Option.some(1)
const notFound = Graph.findNode(graph, (data) => data === "Node D")
console.log(notFound) // Option.none()

findNodes

Added in v3.18.0 Source

Finds all nodes that match the given predicate.

Signature

declare function findNodes<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: N) => boolean): Array<number>

Example

import { Graph } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
Graph.addNode(mutable, "Start A")
Graph.addNode(mutable, "Node B")
Graph.addNode(mutable, "Start C")
})
const result = Graph.findNodes(graph, (data) => data.startsWith("Start"))
console.log(result) // [0, 2]
const empty = Graph.findNodes(graph, (data) => data === "Not Found")
console.log(empty) // []

getEdge

Added in v3.18.0 Source

Gets the edge data associated with an edge index, if it exists.

Signature

declare function getEdge<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, edgeIndex: number): Option<Edge<E>>

Example

import { Graph, Option } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
Graph.addEdge(mutable, nodeA, nodeB, 42)
})
const edgeIndex = 0
const edgeData = Graph.getEdge(graph, edgeIndex)
if (Option.isSome(edgeData)) {
console.log(edgeData.value.data) // 42
console.log(edgeData.value.source) // NodeIndex(0)
console.log(edgeData.value.target) // NodeIndex(1)
}

getNode

Added in v3.18.0 Source

Gets the data associated with a node index, if it exists.

Signature

declare function getNode<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: number): Option<N>

Example

import { Graph, Option } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
Graph.addNode(mutable, "Node A")
})
const nodeIndex = 0
const nodeData = Graph.getNode(graph, nodeIndex)
if (Option.isSome(nodeData)) {
console.log(nodeData.value) // "Node A"
}

hasEdge

Added in v3.18.0 Source

Checks if an edge exists between two nodes in the graph.

Signature

declare function hasEdge<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, source: number, target: number): boolean

Example

import { Graph } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const nodeC = Graph.addNode(mutable, "Node C")
Graph.addEdge(mutable, nodeA, nodeB, 42)
})
const nodeA = 0
const nodeB = 1
const nodeC = 2
const hasAB = Graph.hasEdge(graph, nodeA, nodeB)
console.log(hasAB) // true
const hasAC = Graph.hasEdge(graph, nodeA, nodeC)
console.log(hasAC) // false

hasNode

Added in v3.18.0 Source

Checks if a node with the given index exists in the graph.

Signature

declare function hasNode<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: number): boolean

Example

import { Graph } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
Graph.addNode(mutable, "Node A")
})
const nodeIndex = 0
const exists = Graph.hasNode(graph, nodeIndex)
console.log(exists) // true
const nonExistentIndex = 999
const notExists = Graph.hasNode(graph, nonExistentIndex)
console.log(notExists) // false

neighbors

Added in v3.18.0 Source

Returns the neighboring nodes (targets of outgoing edges) for a given node.

Signature

declare function neighbors<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: number): Array<number>

Example

import { Graph } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const nodeC = Graph.addNode(mutable, "Node C")
Graph.addEdge(mutable, nodeA, nodeB, 1)
Graph.addEdge(mutable, nodeA, nodeC, 2)
})
const nodeA = 0
const nodeB = 1
const nodeC = 2
const neighborsA = Graph.neighbors(graph, nodeA)
console.log(neighborsA) // [NodeIndex(1), NodeIndex(2)]
const neighborsB = Graph.neighbors(graph, nodeB)
console.log(neighborsB) // []

nodeCount

Added in v3.18.0 Source

Returns the number of nodes in the graph.

Signature

declare function nodeCount<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): number

Example

import { Graph } from "effect"
const emptyGraph = Graph.directed<string, number>()
console.log(Graph.nodeCount(emptyGraph)) // 0
const graphWithNodes = Graph.mutate(emptyGraph, (mutable) => {
Graph.addNode(mutable, "Node A")
Graph.addNode(mutable, "Node B")
Graph.addNode(mutable, "Node C")
})
console.log(Graph.nodeCount(graphWithNodes)) // 3

Iterators

bfs

Added in v3.18.0 Source

Creates a new BFS iterator with optional configuration.

The iterator maintains a queue of nodes to visit and tracks discovered nodes. It provides lazy evaluation of the breadth-first search.

Signature

declare function bfs<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: SearchConfig): NodeWalker<N>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, c, 1)
})
// Start from a specific node
const bfs1 = Graph.bfs(graph, { start: [0] })
for (const nodeIndex of Graph.indices(bfs1)) {
console.log(nodeIndex) // Traverses in BFS order: 0, 1, 2
}
// Empty iterator (no starting nodes)
const bfs2 = Graph.bfs(graph)
// Can be used programmatically

dfs

Added in v3.18.0 Source

Creates a new DFS iterator with optional configuration.

The iterator maintains a stack of nodes to visit and tracks discovered nodes. It provides lazy evaluation of the depth-first search.

Signature

declare function dfs<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: SearchConfig): NodeWalker<N>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, c, 1)
})
// Start from a specific node
const dfs1 = Graph.dfs(graph, { start: [0] })
for (const nodeIndex of Graph.indices(dfs1)) {
console.log(nodeIndex) // Traverses in DFS order: 0, 1, 2
}
// Empty iterator (no starting nodes)
const dfs2 = Graph.dfs(graph)
// Can be used programmatically

dfsPostOrder

Added in v3.18.0 Source

Creates a new DFS postorder iterator with optional configuration.

The iterator maintains a stack with visit state tracking and emits nodes in postorder (after all descendants have been processed). Essential for dependency resolution and tree destruction algorithms.

Signature

declare function dfsPostOrder<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: SearchConfig): NodeWalker<N>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const root = Graph.addNode(mutable, "root")
const child1 = Graph.addNode(mutable, "child1")
const child2 = Graph.addNode(mutable, "child2")
Graph.addEdge(mutable, root, child1, 1)
Graph.addEdge(mutable, root, child2, 1)
})
// Postorder: children before parents
const postOrder = Graph.dfsPostOrder(graph, { start: [0] })
for (const node of postOrder) {
console.log(node) // 1, 2, 0
}

edges

Added in v3.18.0 Source

Creates an iterator over all edge indices in the graph.

The iterator produces edge indices in the order they were added to the graph. This provides access to all edges regardless of connectivity.

Signature

declare function edges<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): EdgeWalker<E>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, c, 2)
})
const indices = Array.from(Graph.indices(Graph.edges(graph)))
console.log(indices) // [0, 1]

externals

Added in v3.18.0 Source

Creates an iterator over external nodes (nodes without edges in specified direction).

External nodes are nodes that have no outgoing edges (direction="outgoing") or no incoming edges (direction="incoming"). These are useful for finding sources, sinks, or isolated nodes.

Signature

declare function externals<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: ExternalsConfig): NodeWalker<N>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const source = Graph.addNode(mutable, "source") // 0 - no incoming
const middle = Graph.addNode(mutable, "middle") // 1 - has both
const sink = Graph.addNode(mutable, "sink") // 2 - no outgoing
const isolated = Graph.addNode(mutable, "isolated") // 3 - no edges
Graph.addEdge(mutable, source, middle, 1)
Graph.addEdge(mutable, middle, sink, 2)
})
// Nodes with no outgoing edges (sinks + isolated)
const sinks = Array.from(Graph.indices(Graph.externals(graph, { direction: "outgoing" })))
console.log(sinks) // [2, 3]
// Nodes with no incoming edges (sources + isolated)
const sources = Array.from(Graph.indices(Graph.externals(graph, { direction: "incoming" })))
console.log(sources) // [0, 3]

nodes

Added in v3.18.0 Source

Creates an iterator over all node indices in the graph.

The iterator produces node indices in the order they were added to the graph. This provides access to all nodes regardless of connectivity.

Signature

declare function nodes<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): NodeWalker<N>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 1)
})
const indices = Array.from(Graph.indices(Graph.nodes(graph)))
console.log(indices) // [0, 1, 2]

topo

Added in v3.18.0 Source

Creates a new topological sort iterator with optional configuration.

The iterator uses Kahn's algorithm to lazily produce nodes in topological order. Throws an error if the graph contains cycles.

Signature

declare function topo<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: TopoConfig): NodeWalker<N>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, c, 1)
})
// Standard topological sort
const topo1 = Graph.topo(graph)
for (const nodeIndex of Graph.indices(topo1)) {
console.log(nodeIndex) // 0, 1, 2 (topological order)
}
// With initial nodes
const topo2 = Graph.topo(graph, { initials: [0] })
// Throws error for cyclic graph
const cyclicGraph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, a, 2) // Creates cycle
})
try {
Graph.topo(cyclicGraph) // Throws: "Cannot perform topological sort on cyclic graph"
} catch (error) {
console.log((error as Error).message)
}

Models

AllPairsResult interface

Added in v3.18.0 Source

Result of all-pairs shortest path computation.

Signature

interface AllPairsResult<E> {
readonly costs: Map<number, Map<number, Array<E>>>;
readonly distances: Map<number, Map<number, number>>;
readonly paths: Map<number, Map<number, Array<number> | null>>;
}

AstarConfig interface

Added in v3.18.0 Source

Configuration for A* algorithm.

Signature

interface AstarConfig<E, N> {
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
source: number;
target: number;
}

BellmanFordConfig interface

Added in v3.18.0 Source

Configuration for Bellman-Ford algorithm.

Signature

interface BellmanFordConfig<E> {
cost: (edgeData: E) => number;
source: number;
target: number;
}

DijkstraConfig interface

Added in v3.18.0 Source

Configuration for Dijkstra's algorithm.

Signature

interface DijkstraConfig<E> {
cost: (edgeData: E) => number;
source: number;
target: number;
}

DirectedGraph type

Added in v3.18.0 Source

Directed graph type alias.

Signature

type DirectedGraph<N, E> = Graph<N, E, "directed">

Direction type

Added in v3.18.0 Source

Direction for graph traversal, indicating which edges to follow.

Signature

type Direction = "outgoing" | "incoming"

Example

import { Graph } from "effect"
const graph = Graph.directed<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
Graph.addEdge(mutable, a, b, "A->B")
})
// Follow outgoing edges (normal direction)
const outgoingNodes = Array.from(Graph.indices(Graph.dfs(graph, { start: [0], direction: "outgoing" })))
// Follow incoming edges (reverse direction)
const incomingNodes = Array.from(Graph.indices(Graph.dfs(graph, { start: [1], direction: "incoming" })))

Edge

Added in v3.18.0 Source

Edge data containing source, target, and user data.

Signature

declare class Edge<E> extends Class<{
readonly data: E;
readonly source: NodeIndex;
readonly target: NodeIndex;
}> {
constructor<E>(args: {
readonly data: E;
readonly source: number;
readonly target: number;
});
}

EdgeIndex type

Added in v3.18.0 Source

Edge index for edge identification using plain numbers.

Signature

type EdgeIndex = number

EdgeWalker type

Added in v3.18.0 Source

Type alias for edge iteration using Walker. EdgeWalker is represented as Walker<EdgeIndex, Edge>.

Signature

type EdgeWalker<E> = Walker<EdgeIndex, Edge<E>>

ExternalsConfig interface

Added in v3.18.0 Source

Configuration for externals iterator.

Signature

interface ExternalsConfig {
readonly direction?: Direction;
}

Graph interface

Added in v3.18.0 Source

Immutable graph interface.

Signature

interface Graph<out N, out E, T extends Kind = "directed"> extends Proto<N, E> {
readonly mutable: false;
readonly type: T;
}

GraphVizOptions interface

Added in v3.18.0 Source

Configuration options for GraphViz DOT format generation from graphs.

Signature

interface GraphVizOptions<N, E> {
readonly edgeLabel?: (data: E) => string;
readonly graphName?: string;
readonly nodeLabel?: (data: N) => string;
}

Kind type

Added in v3.18.0 Source

Graph type for distinguishing directed and undirected graphs.

Signature

type Kind = "directed" | "undirected"

MermaidDiagramType type

Added in v3.18.0 Source

Mermaid diagram type.

Signature

type MermaidDiagramType = "flowchart" | "graph"

MermaidDirection type

Added in v3.18.0 Source

Mermaid diagram direction types.

Signature

type MermaidDirection = "TB" | "TD" | "BT" | "LR" | "RL"

MermaidNodeShape type

Added in v3.18.0 Source

Mermaid node shape types.

Signature

type MermaidNodeShape = "rectangle" | "rounded" | "circle" | "diamond" | "hexagon" | "stadium" | "subroutine" | "cylindrical"

MermaidOptions interface

Added in v3.18.0 Source

Configuration options for Mermaid diagram generation.

Signature

interface MermaidOptions<N, E> {
readonly diagramType?: MermaidDiagramType;
readonly direction?: MermaidDirection;
readonly edgeLabel?: (data: E) => string;
readonly nodeLabel?: (data: N) => string;
readonly nodeShape?: (data: N) => MermaidNodeShape;
}

MutableDirectedGraph type

Added in v3.18.0 Source

Mutable directed graph type alias.

Signature

type MutableDirectedGraph<N, E> = MutableGraph<N, E, "directed">

MutableGraph interface

Added in v3.18.0 Source

Mutable graph interface.

Signature

interface MutableGraph<out N, out E, T extends Kind = "directed"> extends Proto<N, E> {
readonly mutable: true;
readonly type: T;
}

Mutable undirected graph type alias.

Signature

type MutableUndirectedGraph<N, E> = MutableGraph<N, E, "undirected">

NodeIndex type

Added in v3.18.0 Source

Node index for node identification using plain numbers.

Signature

type NodeIndex = number

NodeWalker type

Added in v3.18.0 Source

Type alias for node iteration using Walker. NodeWalker is represented as Walker<NodeIndex, N>.

Signature

type NodeWalker<N> = Walker<NodeIndex, N>

PathResult interface

Added in v3.18.0 Source

Result of a shortest path computation containing the path and total distance.

Signature

interface PathResult<E> {
readonly costs: Array<E>;
readonly distance: number;
readonly path: Array<number>;
}

Proto interface

Added in v3.18.0 Source

Graph prototype interface.

Signature

interface Proto<out N, out E> extends Iterable<readonly [NodeIndex, N]>, Equal, Pipeable, Inspectable {
readonly "~effect/Graph": "~effect/Graph";
readonly adjacency: Map<number, Array<number>>;
readonly edges: Map<number, Edge<E>>;
isAcyclic: Option<boolean>;
nextEdgeIndex: number;
nextNodeIndex: number;
readonly nodes: Map<number, N>;
readonly reverseAdjacency: Map<number, Array<number>>;
}

SearchConfig interface

Added in v3.18.0 Source

Configuration for graph search iterators.

Signature

interface SearchConfig {
readonly direction?: Direction;
readonly start?: Array<number>;
}

TopoConfig interface

Added in v3.18.0 Source

Configuration options for topological sort iterator.

Signature

interface TopoConfig {
readonly initials?: Array<number>;
}

UndirectedGraph type

Added in v3.18.0 Source

Undirected graph type alias.

Signature

type UndirectedGraph<N, E> = Graph<N, E, "undirected">

Walker

Added in v3.18.0 Source

Concrete class for iterables that produce [NodeIndex, NodeData] tuples.

This class provides a common abstraction for all iterables that return node data, including traversal iterators (DFS, BFS, etc.) and element iterators (nodes, externals). It uses a mapEntry function pattern for flexible iteration and transformation.

Signature

declare class Walker<T, N> implements Iterable<[T, N]> {
constructor<T, N>(visit: <U>(f: (index: T, data: N) => U) => Iterable<U>);
readonly [iterator]: () => Iterator<[T, N]>;
readonly visit: <U>(f: (index: T, data: N) => U) => Iterable<U>;
}

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
Graph.addEdge(mutable, a, b, 1)
})
// Both traversal and element iterators return NodeWalker
const dfsNodes: Graph.NodeWalker<string> = Graph.dfs(graph, { start: [0] })
const allNodes: Graph.NodeWalker<string> = Graph.nodes(graph)
// Common interface for working with node iterables
function processNodes<N>(nodeIterable: Graph.NodeWalker<N>): Array<number> {
return Array.from(Graph.indices(nodeIterable))
}
// Access node data using values() or entries()
const nodeData = Array.from(Graph.values(dfsNodes)) // ["A", "B"]
const nodeEntries = Array.from(Graph.entries(allNodes)) // [[0, "A"], [1, "B"]]

Mutations

addEdge

Added in v3.18.0 Source

Adds a new edge to a mutable graph and returns its index.

Signature

declare function addEdge<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, source: number, target: number, data: E): number

Example

import { Graph } from "effect"
const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const edge = Graph.addEdge(mutable, nodeA, nodeB, 42)
console.log(edge) // EdgeIndex with value 0
})

addNode

Added in v3.18.0 Source

Adds a new node to a mutable graph and returns its index.

Signature

declare function addNode<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, data: N): number

Example

import { Graph } from "effect"
const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
console.log(nodeA) // NodeIndex with value 0
console.log(nodeB) // NodeIndex with value 1
})

beginMutation

Added in v3.18.0 Source

Creates a mutable scope for safe graph mutations by copying the data structure.

Signature

declare function beginMutation<N, E, T extends Kind = "directed">(graph: Graph<N, E, T>): MutableGraph<N, E, T>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>()
const mutable = Graph.beginMutation(graph)
// Now mutable can be safely modified without affecting original graph

endMutation

Added in v3.18.0 Source

Converts a mutable graph back to an immutable graph, ending the mutation scope.

Signature

declare function endMutation<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>): Graph<N, E, T>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>()
const mutable = Graph.beginMutation(graph)
// ... perform mutations on mutable ...
const newGraph = Graph.endMutation(mutable)

mutate

Added in v3.18.0 Source

Performs scoped mutations on a graph, automatically managing the mutation lifecycle.

Signature

declare const mutate: {
<N, E, T extends Kind = "directed">(f: (mutable: MutableGraph<N, E, T>) => void): (graph: Graph<N, E, T>) => Graph<N, E, T>;
<N, E, T extends Kind = "directed">(graph: Graph<N, E, T>, f: (mutable: MutableGraph<N, E, T>) => void): Graph<N, E, T>;
}

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>()
const newGraph = Graph.mutate(graph, (mutable) => {
// Safe mutations go here
// mutable gets automatically converted back to immutable
})

removeEdge

Added in v3.18.0 Source

Removes an edge from a mutable graph.

Signature

declare function removeEdge<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, edgeIndex: number): void

Example

import { Graph } from "effect"
const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const edge = Graph.addEdge(mutable, nodeA, nodeB, 42)
// Remove the edge
Graph.removeEdge(mutable, edge)
})

removeNode

Added in v3.18.0 Source

Removes a node and all its incident edges from a mutable graph.

Signature

declare function removeNode<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, nodeIndex: number): void

Example

import { Graph } from "effect"
const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
Graph.addEdge(mutable, nodeA, nodeB, 42)
// Remove nodeA and all edges connected to it
Graph.removeNode(mutable, nodeA)
})

updateEdge

Added in v3.18.0 Source

Updates a single edge's data by applying a transformation function.

Signature

declare function updateEdge<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, edgeIndex: number, f: (data: E) => E): void

Example

import { Graph } from "effect"
const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const edgeIndex = Graph.addEdge(mutable, nodeA, nodeB, 10)
Graph.updateEdge(mutable, edgeIndex, (data) => data * 2)
})
const edgeData = Graph.getEdge(result, 0)
console.log(edgeData) // Option.some({ source: 0, target: 1, data: 20 })

Queries

Get directed neighbors of a node in a specific direction.

Signature

declare function neighborsDirected<N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, nodeIndex: number, direction: Direction): Array<number>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, string>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
Graph.addEdge(mutable, a, b, "A->B")
})
const nodeA = 0
const nodeB = 1
// Get outgoing neighbors (nodes that nodeA points to)
const outgoing = Graph.neighborsDirected(graph, nodeA, "outgoing")
// Get incoming neighbors (nodes that point to nodeB)
const incoming = Graph.neighborsDirected(graph, nodeB, "incoming")

predecessors

Added in v3.22.0 Source

Returns the incoming neighbor node indices for a node in a directed graph.

Throws a GraphError when used with an undirected graph.

Signature

declare function predecessors<N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, nodeIndex: number): Array<number>

successors

Added in v3.22.0 Source

Returns the outgoing neighbor node indices for a node in a directed graph.

Throws a GraphError when used with an undirected graph.

Signature

declare function successors<N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, nodeIndex: number): Array<number>

Symbol

TypeId

Added in v3.18.0 Source

Unique identifier for Graph instances.

Signature

declare const TypeId: "~effect/Graph"

TypeId type

Added in v3.18.0 Source

Type identifier for Graph instances.

Signature

type TypeId = typeof TypeId

Transformations

filterEdges

Added in v3.18.0 Source

Filters edges by removing those that don't match the predicate. This function modifies the mutable graph in place.

Signature

declare function filterEdges<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, predicate: (data: E) => boolean): void

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 5)
Graph.addEdge(mutable, b, c, 15)
Graph.addEdge(mutable, c, a, 25)
// Keep only edges with weight >= 10
Graph.filterEdges(mutable, (data) => data >= 10)
})
console.log(Graph.edgeCount(graph)) // 2 (edge with weight 5 removed)

filterMapEdges

Added in v3.18.0 Source

Filters and optionally transforms edges in a mutable graph using a predicate function. Edges that return Option.none are removed from the graph.

Signature

declare function filterMapEdges<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: E) => Option<E>): void

Example

import { Graph, Option } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 5)
Graph.addEdge(mutable, b, c, 15)
Graph.addEdge(mutable, c, a, 25)
// Keep only edges with weight >= 10 and double their weight
Graph.filterMapEdges(mutable, (data) =>
data >= 10 ? Option.some(data * 2) : Option.none()
)
})
console.log(Graph.edgeCount(graph)) // 2 (edges with weight 5 removed)

filterMapNodes

Added in v3.18.0 Source

Filters and optionally transforms nodes in a mutable graph using a predicate function. Nodes that return Option.none are removed along with all their connected edges.

Signature

declare function filterMapNodes<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: N) => Option<N>): void

Example

import { Graph, Option } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "active")
const b = Graph.addNode(mutable, "inactive")
const c = Graph.addNode(mutable, "active")
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, c, 2)
// Keep only "active" nodes and transform to uppercase
Graph.filterMapNodes(mutable, (data) =>
data === "active" ? Option.some(data.toUpperCase()) : Option.none()
)
})
console.log(Graph.nodeCount(graph)) // 2 (only "active" nodes remain)

filterNodes

Added in v3.18.0 Source

Filters nodes by removing those that don't match the predicate. This function modifies the mutable graph in place.

Signature

declare function filterNodes<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, predicate: (data: N) => boolean): void

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
Graph.addNode(mutable, "active")
Graph.addNode(mutable, "inactive")
Graph.addNode(mutable, "pending")
Graph.addNode(mutable, "active")
// Keep only "active" nodes
Graph.filterNodes(mutable, (data) => data === "active")
})
console.log(Graph.nodeCount(graph)) // 2 (only "active" nodes remain)

mapEdges

Added in v3.18.0 Source

Transforms all edge data in a mutable graph using the provided mapping function.

Signature

declare function mapEdges<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: E) => E): void

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 10)
Graph.addEdge(mutable, b, c, 20)
Graph.mapEdges(mutable, (data) => data * 2)
})
const edgeData = Graph.getEdge(graph, 0)
console.log(edgeData) // Option.some({ source: 0, target: 1, data: 20 })

mapNodes

Added in v3.18.0 Source

Creates a new graph with transformed node data using the provided mapping function.

Signature

declare function mapNodes<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: N) => N): void

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
Graph.addNode(mutable, "node a")
Graph.addNode(mutable, "node b")
Graph.addNode(mutable, "node c")
Graph.mapNodes(mutable, (data) => data.toUpperCase())
})
const nodeData = Graph.getNode(graph, 0)
console.log(nodeData) // Option.some("NODE A")

reverse

Added in v3.18.0 Source

Reverses all edge directions in a mutable graph by swapping source and target nodes.

Signature

declare function reverse<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>): void

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
const c = Graph.addNode(mutable, "C")
Graph.addEdge(mutable, a, b, 1) // A -> B
Graph.addEdge(mutable, b, c, 2) // B -> C
Graph.reverse(mutable) // Now B -> A, C -> B
})
const edge0 = Graph.getEdge(graph, 0)
console.log(edge0) // Option.some({ source: 1, target: 0, data: 1 }) - B -> A

updateNode

Added in v3.18.0 Source

Updates a single node's data by applying a transformation function.

Signature

declare function updateNode<N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, index: number, f: (data: N) => N): void

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
Graph.addNode(mutable, "Node A")
Graph.addNode(mutable, "Node B")
Graph.updateNode(mutable, 0, (data) => data.toUpperCase())
})
const nodeData = Graph.getNode(graph, 0)
console.log(nodeData) // Option.some("NODE A")

Utilities

entries

Added in v3.18.0 Source

Returns an iterator over [index, data] entries in the walker.

Signature

declare function entries<T, N>(walker: Walker<T, N>): Iterable<[T, N]>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
Graph.addEdge(mutable, a, b, 1)
})
const dfs = Graph.dfs(graph, { start: [0] })
const entries = Array.from(Graph.entries(dfs))
console.log(entries) // [[0, "A"], [1, "B"]]

indices

Added in v3.18.0 Source

Returns an iterator over the indices in the walker.

Signature

declare function indices<T, N>(walker: Walker<T, N>): Iterable<T>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
Graph.addEdge(mutable, a, b, 1)
})
const dfs = Graph.dfs(graph, { start: [0] })
const indices = Array.from(Graph.indices(dfs))
console.log(indices) // [0, 1]

values

Added in v3.18.0 Source

Returns an iterator over the values (data) in the walker.

Signature

declare function values<T, N>(walker: Walker<T, N>): Iterable<N>

Example

import { Graph } from "effect"
const graph = Graph.directed<string, number>((mutable) => {
const a = Graph.addNode(mutable, "A")
const b = Graph.addNode(mutable, "B")
Graph.addEdge(mutable, a, b, 1)
})
const dfs = Graph.dfs(graph, { start: [0] })
const values = Array.from(Graph.values(dfs))
console.log(values) // ["A", "B"]

Utils

toGraphViz

Added in v3.18.0 Source

Exports a graph to GraphViz DOT format for visualization.

Signature

declare function toGraphViz<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, options?: GraphVizOptions<N, E>): string

Example

import { Graph } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const nodeA = Graph.addNode(mutable, "Node A")
const nodeB = Graph.addNode(mutable, "Node B")
const nodeC = Graph.addNode(mutable, "Node C")
Graph.addEdge(mutable, nodeA, nodeB, 1)
Graph.addEdge(mutable, nodeB, nodeC, 2)
Graph.addEdge(mutable, nodeC, nodeA, 3)
})
const dot = Graph.toGraphViz(graph)
console.log(dot)
// digraph G {
// "0" [label="Node A"];
// "1" [label="Node B"];
// "2" [label="Node C"];
// "0" -> "1" [label="1"];
// "1" -> "2" [label="2"];
// "2" -> "0" [label="3"];
// }

toMermaid

Added in v3.18.0 Source

Exports a graph to Mermaid diagram format for visualization.

Signature

declare function toMermaid<N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, options?: MermaidOptions<N, E>): string

Example

import { Graph } from "effect"
const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
const app = Graph.addNode(mutable, "App")
const db = Graph.addNode(mutable, "Database")
const cache = Graph.addNode(mutable, "Cache")
Graph.addEdge(mutable, app, db, 1)
Graph.addEdge(mutable, app, cache, 2)
})
const mermaid = Graph.toMermaid(graph)
console.log(mermaid)
// flowchart TD
// 0["App"]
// 1["Database"]
// 2["Cache"]
// 0 -->|"1"| 1
// 0 -->|"2"| 2