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

p-graph

v2.0.0

Published

Run a promise graph with concurrency control

Downloads

146,297

Readme

p-graph

Run a promise graph with concurrency control.

Install

$ npm install p-graph

p-graph does not have a strict Node version requirement, but the syntax used is currently intended to remain compatible with Node 14+.

Usage

The PGraph class takes in a map (or record) of nodes and a list of dependencies.

import { PGraph, type DependencyList, type PGraphNodeRecord } from "p-graph";

// Mapping from node IDs to definitions (can be either an object or map).
// `run` functions can be sync or async. Nodes can optionally define a `priority`.
// (Alternatively, you can omit the `run` functions here and specify a single
// function to `pGraph.run()`.)
const nodeMap: PGraphNodeRecord = {
  putOnShirt: { run: () => console.log("put on your shirt") },
  putOnShorts: { run: () => console.log("put on your shorts") },
  putOnJacket: { run: () => console.log("put on your jacket") },
  putOnShoes: { run: () => console.log("put on your shoes") },
  tieShoes: { run: () => console.log("tie your shoes") },
};

// List of tuples describing dependencies (edges) between node IDs:
// the first task must complete before the second one begins.
const dependencies: DependencyList = [
  // You need to put your shoes on before you tie them!
  ["putOnShoes", "tieShoes"],
  ["putOnShirt", "putOnJacket"],
  ["putOnShorts", "putOnJacket"],
  ["putOnShorts", "putOnShoes"],
];

// Run the tasks (log to console) in dependency order
await new PGraph(nodeMap, dependencies).run();

// Alternative API: reuse a single run() function
const simpleNodeMap: PGraphNodeRecord = {
  putOnShirt: {},
  putOnShorts: {},
  putOnJacket: {},
  putOnShoes: {},
  tieShoes: {},
};
await new PGraph(simpleNodeMap, dependencies).run({
  run: (taskId) => console.log(taskId),
});

If a task fails, the graph will throw a PGraphError wrapping the original error(s). See run() comments for more details.

Concurrency

There are some contexts where you may want to limit the number of functions running concurrently. One example would be to prevent overloading the CPU with too many parallel tasks. The concurrency argument to run will limit the number of functions that start running at a given time. If no concurrency option is set, the concurrency is not limited and tasks are run as soon as they are unblocked.

await pGraph(graph).run({ concurrency: 3 });

Priority

By default, tasks are considered to all be equally important, so they're equally likely to be picked to run once all the tasks they depend on are complete. To control the ordering of tasks, use the priority option when defining a task node. Tasks will always execute in dependency order, but unblocked tasks with a higher priority will be favored over those with a lower priority.

const nodeMap: PGraphNodeRecord = {
  highPri: { run: () => Promise.resolve(), priority: 10 },
  lowPri: { run: () => Promise.resolve(), priority: 1 },
  unspecified: { run: () => Promise.resolve() } // treated as 0
}

Breaking changes in v2

  • The default export function and the pGraph function have been removed. Use new PGraph() instead.
  • If a task fails, run() will reject with a single PGraphError instead of an array of errors. The original errors are available under pGraphError.taskErrors. (Note a regular Error may also be thrown if initial validation fails. PGraphError is exported for instanceof checks.)