0.3.10 • Published 5 months ago

@api-client/graph v0.3.10

Weekly downloads
-
License
cc-by-4.0
Repository
github
Last release
5 months ago

@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/graph

Basic 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: true

Graph 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 a to b then another edge from b to a is always set
      • When setting edge from a to a then no other edges are set.
  • 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 graph

Installing Dependencies

npm install

Running Tests

npm test

Design 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.
0.3.9

5 months ago

0.3.10

5 months ago

0.3.0

6 months ago

0.2.1

8 months ago

0.2.0

8 months ago

0.3.6

6 months ago

0.3.5

6 months ago

0.3.8

5 months ago

0.3.7

5 months ago

0.3.2

6 months ago

0.2.3

6 months ago

0.3.1

6 months ago

0.2.2

8 months ago

0.3.4

6 months ago

0.3.3

6 months ago

0.1.0

4 years ago