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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@harnessio/pipeline-graph

v1.3.0

Published

A library for generating and interacting with pipeline graphs.

Readme

Pipeline Graph

A library for generating and interacting with pipeline graphs.

pipeline graph

Anatomy

  • Model
  • Container and Content nodes
  • Edges
  • Canvas

Model

Type AnyContainerNodeType us a union of LeafContainerNodeType | ParallelContainerNodeType | SerialContainerNodeType and represent one node. LeafContainerNodeType node does not have children while other have.

Example of the model

const model: AnyContainerNodeType[] = [
  {
    type: 'stage',
    children: [{ type: 'step' }, { type: 'step' }]
  }
]

In order to visualize our model we need container and content nodes.

Container and Content nodes

Container node

Container node is responsible for layout and basic user interaction like adding/deleting nodes. There are three containers: Leaf, Serial and Parallel. Leaf render one Content node, while Serial/Parallel renders itself and children.

Container node anatomy:

  • Metadata - At the very root div we have data-path and data-action attributes which are used for event delegation purpose.
  • Relative positioning - root div has position:relative so we can use absolute position for styling in the content node.
  • Ports - Port is div. It's position is used for calculating and drawing links between ports.
  • Add/Delete containers - are used for capturing mouse hover (via css). They have buttons that appears on mouse hover.

Content node

Content nodes are responsible for the content of the node (like text, icons etc.) and visualizing state (like loading or selection)

Pairing Content and Connection nodes

In order to render our graph we have to pair container and content node. For this we uses NodeContent type.

const nodes: NodeContent[] = [
  // register "step" content node which will render "StepContentNode" inside "leaf" container
  {
    type: "step",
    component: StepContentNode,
    containerType: ContainerNode.leaf
  },
  // register "stage" content node which will render "SerialGroupContentNode" inside "serial" container
  {
    type: "stage",
    component: SerialGroupContentNode
    containerType: ContainerNode.serial,
  }
]

Edges

Connection lines between nodes are drawn using svg paths. Lines are calculated using ports (which are part of container nodes).

Canvas

Library provides pan and pinch-to-zoom out of the box. For creating manual controls for zoom in/out and fit we can use useCanvasContext that exposes increment, decrement and fit functions.

Implementing custom controls example

const { increase, decrease, fit } = useCanvasContext()

return <>
    <button onClick={() => increase()}>+</button>
    <button onClick={() => decrease()}>-</button>
    <button onClick={() => fit()}>FIT</button>
</>