npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hpcc-js/wasm-graphviz

v1.28.0

Published

hpcc-js - WASM Graphviz

Downloads

399,967

Readme


title: Graphviz description: WebAssembly wrapper for the Graphviz graph visualization library outline: deep

@hpcc-js/wasm-graphviz

This package provides a WebAssembly wrapper around the Graphviz library. This allows for the rendering of DOT language graphs directly within a browser or NodeJS type environment.

Installation

::: code-group

npm install @hpcc-js/wasm-graphviz
yarn add @hpcc-js/wasm-graphviz
pnpm add @hpcc-js/wasm-graphviz

:::

Quick Start

import { Graphviz } from "@hpcc-js/wasm-graphviz";

const graphviz = await Graphviz.load();
const svg = graphviz.dot(`digraph { a -> b; }`);
document.body.innerHTML = svg;

Programmatic Graph Construction

Instead of writing DOT source by hand you can build graphs programmatically using createGraph. The resulting Graph object can be rendered directly via graph.layout() or serialised to DOT first with graph.write() / graph.toDot().

Attribute names and values follow Graphviz itself; see the official Graphviz attribute reference for the supported graph, node, edge, and cluster attributes.

Existing DOT can also be parsed into a mutable graph with read, and any programmatic graph can be written back to DOT with write (toDot is an alias).

Basic usage

import { Graphviz } from "@hpcc-js/wasm-graphviz";

const graphviz = await Graphviz.load();

// createGraph returns a Graph; always call delete() when done (or use `using`)
using graph = graphviz.createGraph("G");

graph
  .addNode("a")
  .addNode("b")
  .addEdge("a", "b")
  .setNodeAttr("a", "shape", "box")
  .setNodeAttr("a", "color", "red")
  .setGraphAttr("rankdir", "LR");

// Render directly — no DOT round-trip needed
const svg = graph.layout("svg", "dot");
document.body.innerHTML = svg;

One-shot JSON init objects

You can also create graphs, clusters, nodes, and edges from a single object that includes their attributes.

using graph = graphviz.createGraph({
  name: "G",
  type: "directed",
  attrs: { rankdir: "LR" }
});

{
  using cluster = graph.addSubgraph({
    name: "cluster_0",
    attrs: { label: "Group A", style: "filled", color: "lightgrey" }
  });

  cluster.addNode({
    name: "a",
    attrs: { shape: "box", color: "red" },
    htmlAttrs: { label: "<B>A</B>" }
  });

  cluster.addEdge({
    tail: "a",
    head: "b",
    attrs: { label: "hello" }
  });
}
using graph = graphviz.read(`digraph G { a -> b [label="hello"] }`);
graph.setGraphAttr("rankdir", "LR");
const dot = graph.write();

Graph types

// "directed" (default) | "undirected" | "strict directed" | "strict undirected"
using graph = graphviz.createGraph("G", "undirected");
graph.addEdge("x", "y");

Mutating a graph between layouts

Nodes, edges, subgraphs, and attributes can all be removed after an initial layout() call, allowing the graph to be updated and re-rendered without rebuilding from scratch.

using graph = graphviz.createGraph("G");
graph.addEdge("a", "b").addEdge("b", "c");
const svg1 = graph.layout(); // initial render

// Remove the middle node (also removes its edges), add a direct edge
graph.removeNode("b").addEdge("a", "c");
const svg2 = graph.layout(); // updated render

The full set of mutation methods on Graph:

| Method | Effect | | --------------------------------------- | ------------------------------------------------------------------- | | removeNode(name) | Removes the node and all its edges from the root graph | | removeEdge(tail, head, key?) | Removes a single edge | | removeSubgraph(name) | Dissolves a cluster boundary (nodes/edges remain in the root graph) | | removeGraphAttr(attr) | Resets a graph-level attribute to its default | | removeNodeAttr(node, attr) | Resets a node attribute to its default | | removeEdgeAttr(tail, head, key, attr) | Resets an edge attribute to its default |

Subgraph has the same removeNode / removeEdge pair (scoped to the subgraph only — root graph is unaffected) plus removeAttr / removeNodeAttr / removeEdgeAttr.

Existence checks and graph traversal

Graph and Subgraph expose methods for querying membership and iterating the contents of a graph without serialising to DOT.

Existence checks

using graph = graphviz.createGraph("G");
graph.addNode("alice");
graph.addEdge("alice", "bob");
graph.addSubgraph("cluster_a");

graph.hasNode("alice"); // true
graph.hasNode("charlie"); // false
graph.hasEdge("alice", "bob"); // true  (key defaults to "")
graph.hasEdge("bob", "alice"); // false (directed)
graph.hasSubgraph("cluster_a"); // true

Count queries

graph.nodeCount(); // number of nodes
graph.edgeCount(); // number of edges
graph.subgraphCount(); // number of direct subgraphs

Reading attributes

graph.setNodeAttr("alice", "color", "red");
graph.setEdgeAttr("alice", "bob", "", "label", "hello");
graph.setGraphAttr("rankdir", "LR");

graph.getNodeAttr("alice", "color"); // "red"
graph.getEdgeAttr("alice", "bob", "", "label"); // "hello"
graph.getGraphAttr("rankdir"); // "LR"
graph.getNodeAttr("alice", "missing"); // "" (unknown attr)

// Omit the value to reset an attribute to Graphviz's default empty value.
graph.setNodeAttr("alice", "color");
graph.getNodeAttr("alice", "color"); // ""

// Pass a final defaultValue argument to declare Graphviz's default for unset objects.
graph.addNode("charlie");
graph.setNodeAttr("alice", "color", "red", "blue");
graph.getNodeAttr("charlie", "color"); // "blue"

// Or declare defaults directly for graph, node, and edge attributes.
graph.setDefaultNodeAttr("shape", "box");
graph.setDefaultEdgeAttr("color", "red");

// Use HTML-like attributes for Graphviz HTML labels.
graph.setNodeHtmlAttr("alice", "label", "<B>Alice</B>");

Node / edge / subgraph lists

// Returns string[]
const nodes = graph.nodeNames();
const subgraphs = graph.subgraphNames();

// Returns EdgeInfo[] — { tail: string, head: string, key: string }
const allEdges = graph.edges(); // every edge exactly once
const outgoing = graph.outEdges("alice"); // edges leaving alice
const incoming = graph.inEdges("bob"); // edges entering bob
const incident = graph.nodeEdges("alice"); // all edges on alice (in + out)

Subgraph exposes the same traversal API (scoped to the subgraph's node/edge set), except hasSubgraph / subgraphCount / subgraphNames which are only on Graph.

Subgraphs and clusters

Names beginning with "cluster" are drawn as bounded rectangles by most layout engines.

using graph = graphviz.createGraph("G");

// Each Subgraph wrapper also needs to be deleted (or use `using`)
{
  using cluster = graph.addSubgraph("cluster_0");
  cluster
    .setAttr("label", "My Cluster")
    .setAttr("style", "filled")
    .setAttr("color", "lightblue")
    .addEdge("a", "b");
}

const svg = graph.layout();

Memory management

Every Graph and Subgraph wraps a native WASM object. You must release it when finished to avoid memory leaks:

  • Preferred — using keyword (TypeScript ≥ 5.2 with "target": "ES2022" or later):

    {
      using graph = graphviz.createGraph("G");
      // ... graph is automatically deleted when the block exits
    }
  • Manual delete():

    const graph = graphviz.createGraph("G");
    try {
      // ...
    } finally {
      graph.delete();
    }

Subgraph wrappers follow the same rule. The underlying subgraph data is owned by the parent Graph and freed automatically when the parent is deleted; only the thin JS wrapper needs an explicit delete() / using block.

Reference