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

@memnox/code-graph

v0.2.0

Published

Deterministic file-level import graph and blast-radius analysis — what a code change can actually reach.

Downloads

279

Readme

@memnox/code-graph

Answers one question, deterministically: if an agent changes this file, what else does that touch?

Policies match the path an action names. That is not enough — an agent editing src/utils/money.ts is editing payment code if payment/checkout.ts imports it. This package builds the import graph that makes that reachability visible, and ships an advisor that escalates on it.

Zero runtime dependencies beyond @memnox/core and @memnox/policy-engine, no filesystem access, no network, no clock. Same repository in, same graph out.

Using it

import { CodeGraph, computeBlastRadius, BlastRadiusAdvisor } from '@memnox/code-graph';

const graph = CodeGraph.build([
  { path: 'src/utils/money.ts', content: 'export const round = …' },
  { path: 'src/payment/checkout.ts', content: "import { round } from '../utils/money';" },
]);

computeBlastRadius(graph, 'src/utils/money.ts');
// { resolvedPath: 'src/utils/money.ts', reached: ['src/payment/checkout.ts'], depth: 1, … }

As an advisor on the decision path:

new BlastRadiusAdvisor(graph, {
  protectedPaths: ['*/payment/*', '*/auth/*'],
  approvers: ['security-team'],
});

A code.modify on any file that payment/ transitively imports now needs a human.

How it is put together

| File | Responsibility | |---|---| | language.ts | path → language, by extension only | | imports.ts | source text → import specifiers, per language | | module-resolver.ts | specifier → a path in the graph (or null if external) | | code-graph.ts | forward/reverse adjacency, snapshot load/save | | blast-radius.ts | bounded reverse-reachability walk | | blast-radius-advisor.ts | turns a radius into an escalation |

Each stage is a pure function over the stage before it, so a contributor adding a language touches exactly two files: a pattern set in imports.ts and, if its module system is unusual, a branch in module-resolver.ts.

Deliberate limits

  • File-level, not symbol-level. The legacy implementation also derived call edges from regex (this.dep.method()). Those edges are too imprecise to escalate a security decision on, so they are not here. Import edges are checkable and explainable; call edges were guesses.
  • Regex parsing, not real parsers. A parser per language is a dependency tree the trust-critical path cannot carry. The cost is that exotic syntax is missed — which under-reports reach. Since the advisor only ever escalates, a missed edge means a missed escalation, never a wrongful block.
  • Bounded traversal. MAX_BLAST_RADIUS_DEPTH and MAX_BLAST_RADIUS_NODES cap the walk; results past a ceiling report truncated: true rather than silently shortening.
  • Ambiguity resolves to nothing. If an action target matches two graph paths by suffix, resolvePath returns null and the advisor stays silent. Attributing a blast radius to the wrong file is worse than attributing none.

Adding a language

  1. Map its extensions in EXTENSION_LANGUAGES (code-graph.constants.ts).
  2. Add its import patterns and a case in extractImports (imports.ts).
  3. If specifiers are not plain relative paths, add a base-path helper in module-resolver.ts (see pythonBase / rustBase).
  4. Add a case to test/imports.test.ts and a resolution case to test/module-resolver.test.ts.