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

@gomani/boundaries

v0.14.0

Published

A build-time module-boundary gate: enforce that modules talk only through their public interface, so a modular monolith stays carve-able into services later.

Readme

@gomani/boundaries

A build-time module-boundary gate. A modular monolith gives you most of the independent-evolution benefit of microservices with none of the network tax — and it stays carve-able into separate services along its seams, if and when one genuinely needs independent scaling. But only if the seams are real. This enforces them the way @gomani/budget enforces size: a violation fails the build.

The convention

Modules live under app/modules/<name>/. Each has a public entry (index.ts) — the only legal way in. Everything else in the module is private. Then:

  • deep-import — importing another module's internals (anything but its public entry) fails.
  • forbidden-dependency — a module depending on another that isn't in its allow-list fails (when you declare one in gomani.boundaries.json).
  • cycle — a dependency cycle between modules fails.

Imports within a module, imports of a module's public entry, and package imports are all fine.

gomani boundaries check          # standalone (CI); exits non-zero on any violation

The gate also runs inside gomani build (like the budget + a11y gates). A project with no app/modules/ trivially passes — boundaries only bind once you declare modules.

Config (optional)

gomani.boundaries.json declares an allow-list per module; without it, any public cross-module import is allowed (only deep imports and cycles are rejected):

{
  "modules": {
    "checkout": { "mayUse": ["catalog", "shared"] },
    "catalog": { "mayUse": ["shared"] },
    "shared": { "mayUse": [] },
  },
  "forbidCycles": true,
}

Programmatic API

Zero dependencies; usable on any TS/JS project. The analyzer is pure (feed it files) so it is exhaustively testable; checkBoundaries is the thin filesystem wrapper.

import { checkBoundaries, analyzeBoundaries, formatBoundaryReport } from '@gomani/boundaries';

const report = checkBoundaries(projectRoot); // scans app/**, loads gomani.boundaries.json
if (!report.ok) console.error(formatBoundaryReport(report)); // located, one line per violation

// Or purely, from in-memory files (no disk):
analyzeBoundaries({ files: [{ path: 'app/modules/a/index.ts', source }], config });

Imports are extracted with a comment- and string-safe scanner (a commented-out or string-embedded import '…' is never mistaken for a real one), and each violation is located to file:line:column.