@api-client/graph v0.3.10
@api-client/graph
A powerful and flexible library for working with graphs in JavaScript and TypeScript.
Introduction
@api-client/graph provides a robust set of tools for creating, manipulating, and analyzing graphs. Whether you're building a social network, a dependency tree, or a complex workflow, this library offers the core functionality you need. It's designed to be intuitive for beginners while offering advanced features for experienced developers.
This library is inspired by and builds upon the solid foundation of the dagrejs/graphlib library.
Key Features
- Directed and Undirected Graphs: Create both directed and undirected graphs to model various relationships.
- Node and Edge Management: Easily add, remove, and query nodes and edges.
- Graph Attributes: Store metadata about your graph, nodes, and edges.
- Path Operations: Efficiently work with paths within your graph.
- Layout Algorithms: Built-in support for graph layout, making it easy to visualize your data.
- TypeScript Support: Fully typed for a seamless development experience.
- Compound Graphs: Create graphs with subgraphs.
Getting Started
Installation
Install the library using npm:
npm install --save @api-client/graphBasic Usage
Here's how to create a simple graph, add nodes and edges, and set some attributes:
import { Graph } from '@api-client/graph';
// Create a new directed graph
const g = new Graph({ directed: true });
// Set a graph label (optional)
g.setGraph({ label: "My First Graph" });
// Add nodes with data
g.setNode("a", { label: "Node A", value: 123 });
g.setNode("b", { label: "Node B", value: 456 });
g.setNode("c", { label: "Node C", value: 789 });
// Add edges between nodes with data
g.setEdge("a", "b", { label: "Edge AB", weight: 1 });
g.setEdge("b", "c", { label: "Edge BC", weight: 2 });
g.setEdge("a", "c", { label: "Edge AC", weight: 3 });
// Access node and edge data
console.log(g.node("a")); // Output: { label: "Node A", value: 123 }
console.log(g.edge("a", "b")); // Output: { label: "Edge AB", weight: 1 }
console.log(g.graph()); // Output: { label: "My First Graph" }
// Check if a node or edge exists
console.log(g.hasNode("a")); // Output: true
console.log(g.hasEdge("a", "c")); // Output: true
// Iterate over nodes
g.nodes().forEach(nodeId => {
console.log(`Node ID: ${nodeId}`);
});
// Iterate over edges
g.edges().forEach(edge => {
console.log(`Edge from ${edge.v} to ${edge.w}`);
});Working with Paths
You can easily define paths within your graph:
import { Graph } from '@api-client/graph';
const g = new Graph({ directed: true });
// Set a path of nodes
g.setPath(["a", "b", "c", "d"]);
// This will create the following edges:
// a -> b
// b -> c
// c -> d
console.log(g.hasEdge("a", "b")); // Output: true
console.log(g.hasEdge("b", "c")); // Output: true
console.log(g.hasEdge("c", "d")); // Output: trueGraph Layout
The library includes a powerful layout engine to automatically arrange your graph for visualization:
import { Graph, layout } from '@api-client/graph';
const g = new Graph({ directed: true });
g.setNode('a', { width: 30, height: 20 });
g.setNode('b', { width: 40, height: 30 });
g.setNode('c', { width: 50, height: 25 });
g.setEdge('a', 'b', {});
g.setEdge('b', 'c', {});
layout(g);
// Now the graph 'g' has layout information.
console.log(g.node('a')); // Output: { width: 30, height: 20, x: ..., y: ... }
console.log(g.edge('a', 'b')); // Output: { points: [ { x: ..., y: ... }, { x: ..., y: ... } ] }Compound Graphs
You can create graphs with subgraphs:
import { Graph } from '@api-client/graph';
import layout from '@api-client/graph/layout';
const g = new Graph({ directed: true, compound: true });
g.setNode('a', { width: 100, height: 100 });
g.setNode('b', { width: 40, height: 30 });
g.setNode('c', { width: 50, height: 25 });
g.setParent('b', 'a');
g.setParent('c', 'a');
layout(g);
console.log(g.node('a')); // Output: { width: 100, height: 100, x: ..., y: ... }
console.log(g.node('b')); // Output: { width: 40, height: 30, x: ..., y: ... }
console.log(g.node('c')); // Output: { width: 50, height: 25, x: ..., y: ... }Undirected Graphs
Here are things to keep in mind when working with undirected graphs:
- Double Edges: Whenever an edge between two different nodes is set, a reverse edge is also set.
- Self-reference Exception: When setting an edge to the same node, a reverse edge is never set.
- Examples:
- When setting edge from
atobthen another edge frombtoais always set - When setting edge from
atoathen no other edges are set.
- When setting edge from
- Referenced Values: When an edge value is set, and the value is an object, both set edges will have a reference to the same value. This also includes generated by the default edge function.
- Non-object Values: When setting primitives as an edge value, it is your responsibility to update both edges.
Development
Cloning the Repository
git clone https://github.com/api-client/graph
cd graphInstalling Dependencies
npm installRunning Tests
npm testDesign Choices
- Node/Edge keys - Node and edge keys are always string. This is a performance optimization. If your keys use numbers, translate them to strings first.