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

@papit/information

v0.0.9

Published

Discovers the packages in an npm workspace and the dependency graph between them, with build order, source and output folders, and published npm versions. The papit CLIs use it to decide which packages to act on.

Readme

@papit/information

Discovers the packages in an npm workspace and the dependency graph between them, with build order, source and output folders, and published npm versions. The papit CLIs use it to decide which packages to act on.

Logo


Type Tests NPM version


Installation

npm install @papit/information

Usage

Run from anywhere inside a workspace. The graph is built when the module loads:

import { PackageGraph, Information } from "@papit/information";

Information.root.name;      // "@papit/root"
Information.packageName;    // the package you're standing in, e.g. "@papit/html"

const node = PackageGraph.get("@papit/html");
node.location;              // absolute path
node.packageJSON.version;   // "0.0.1"
node.outFolder;             // "lib"
await node.remote();        // latest version on npm, or null

Walk the dependency graph:

PackageGraph.getAncestors("@papit/html").map(n => n.name);    // what it depends on: ["@papit/lexer"]
PackageGraph.getDescendants("@papit/lexer").map(n => n.name); // everything that depends on it

Get build batches for the current package, driven by the CLI flags below:

// node build.js --ancestors   (inside packages/runtime/html)
Information.getBatches().map(batch => batch.map(n => n.name));
// [["@papit/lexer"], ["@papit/html"]]

API

PackageGraph

class PackageGraph {
    static root: PackageNode<RootPackage>
    static nodes: PackageNode[]
    static size: number
    static ERROR: boolean
    static get(name: string): PackageNode | undefined
    static search(location: string, compare?: "start" | "end"): PackageNode | undefined
    static getAncestors(name: string, typeFilter?: string[]): PackageNode[]
    static getDescendants(name: string, typeFilter?: string[]): PackageNode[]
    static getOrder(packages: PackageNode[], typeFilter?: string[], filterCallback?: (node) => boolean): PackageNode[][]
    static add(location: string): PackageNode
    static initialize(): void
}

The workspace root is the nearest folder upwards from process.cwd() whose package.json has workspaces. Every package.json under its packages/ folder becomes a node, except those in an asset/ folder or with papit.skip. Edges come from dependencies that share the root's scope.

| Member | Description | | --- | --- | | nodes | every package, the root included | | ERROR | true if building the graph threw (the error is logged) | | search | first node whose location ends with ("end", default) or is a prefix of ("start") location | | getAncestors | the packages name depends on, transitively. typeFilter limits the edge kinds: dependencies, peerDependencies, devDependencies (default all) | | getDescendants | the packages that depend on name, transitively | | getOrder | topologically sorted batches; packages within a batch don't depend on each other. Packages left out by typeFilter are appended as a last batch | | add | adds the package at location to the graph | | initialize | rebuilds the graph, e.g. after changing directory |

PackageNode

class PackageNode<T = LocalPackage> extends GraphNode {
    name: string
    type: "root" | "local" | "external"
    location: string
    packageJSON: T
    sourceFolder: string
    outFolder: string
    externals: string[]
    entrypoints
    tsconfig
    tsconfigpath: string
    modifiedtime: { current: number, previous: number | undefined }
    remote(): Promise<string | null>
    savePackageJSON(): void
}

| Member | Description | | --- | --- | | sourceFolder / outFolder | relative folders taken from the package's tsconfig | | externals, entrypoints, tsconfig | resolved through @papit/bundle-js | | tsconfigpath | tsconfig.prod.json with --prod (when it exists), else tsconfig.json. Throws if there's none | | modifiedtime | newest mtime across the source folder, package.json and tsconfig.json, plus the one recorded last time. Reading it records current in <root>/.temp/cache.json | | remote() | latest published version from the npm registry, null if unpublished or offline | | savePackageJSON() | writes packageJSON back to disk with 4-space indent |

Information

Static shortcuts for the package the process runs in (found from PWD, falling back to process.cwd()).

| Member | Description | | --- | --- | | root | the workspace root node | | scope | the root name's scope, e.g. @papit | | local | the current directory | | package | the node whose location is the longest prefix of local | | packageName, location, sourceFolder, outFolder | shortcuts on package | | getBatches(args?, filterCallback?) | build batches picked by the CLI flags below | | getPriorityBatches(args?, filterCallback?) | getBatches, with packages that set papit.priority pulled into a first batch ordered by priority (the current package is never pulled). The first batch can be empty |

Remote

Remote.get(name: string): Promise<string | null>
Remote.init(scope: string, size?: number, from?: number): Promise<void>

Looks up latest published versions and caches them in Remote.map. With --allow-global, the first lookup fetches the whole scope in one registry search; otherwise each name is fetched on its own.

CLI flags

Read from @papit/arguments by getBatches, PackageNode and Remote, so every CLI built on them accepts these:

| Flag | Effect | | --- | --- | | --all | every package in the workspace (also the default when run at the root) | | --ancestors | the current package and what it depends on | | --descendants | the current package and what depends on it | | --bloodline | ancestors, the current package and descendants | | --individual | only the current package, overriding the flags above (the default) | | --type-filter <kind> | edge kinds to follow, repeatable: dependencies, peerDependencies, devDependencies (default all three) | | --prod | resolve folders and entry points from tsconfig.prod.json | | --allow-global | fetch remote versions for the whole scope in one request |

License

Licensed under the @Papit License 1.0 Copyright (c) 2024 Henry Pap (@onkelhoy)

Key points

  • ✅ Free to use in commercial projects
  • ✅ Free to modify and distribute
  • ✅ Attribution required
  • ❌ Cannot resell the component itself as a standalone product

See the LICENSE file for full details.

Related