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

@mostajs/layer-lint

v0.2.0

Published

Porte d'architecture DEVRULES §5.bis : vérifie la règle de dépendance descendante (un module N(k) ne dépend que de niveaux ≤ k), détecte les cycles et les niveaux incohérents. Sait aussi INFÉRER le plancher de niveau imposé par le graphe.

Readme

@mostajs/layer-lint

Auteur : Dr Hamid MADANI [email protected] · AGPL-3.0-or-later · zéro dépendance

La porte d'architecture de DEVRULES §5.bis : un module de niveau N(k) ne dépend que de modules de niveau ≤ k. Toute inversion de couche ou tout cycle est une faute → refus de publication.

§5.bis est normative depuis le 2026-06-30 et annonçait une vérification « en CI via mostajs-layer-lint ». L'outil n'existait pas, et aucun package.json ne déclarait son niveau : la règle était inapplicable, donc invérifiable, donc morte. Ce module la rend exécutable.

Les cinq couches

| | Nature | Exemples | |---|---|---| | N0 | primitif | config, orm, url, palette | | N1 | générique transverse | auth, rbac, audit, storage | | N2 | composé / UI | app-shell-ui, crud-ui, *-ui | | N3 | métier | incubator, school, marketplace | | N4 | vertical | packs, solutions, assemblages |

Usage

npx mostajs-layer-lint                 # vérifie (0 = conforme · 1 = faute d'architecture)
npx mostajs-layer-lint --strict        # un niveau non déclaré devient une ERREUR (Definition of Done 1.0)
npx mostajs-layer-lint --infer         # PROPOSE un niveau pour chaque module
npx mostajs-layer-lint --infer --write # …et l'écrit dans les package.json

Le manifeste porte alors :

"mostajs": { "niveau": "N1", "nature": "generique", "reutilisabilite": "transverse",
             "depend_de": ["@mostajs/config", "@mostajs/url"] }

Démo

node examples/demo.mjs

Elle monte un écosystème jouet contenant la faute la plus courante — un module transverse (notifications, N1) qui dépend d'un module métier (incubator, N3) — puis lance le lint sur le vrai écosystème.

Ce que la démo montre, et qui est tout l'intérêt de l'outil : la correction n'est pas une évidence technique. Soit notifications n'a rien à faire de l'incubateur (on retire la dépendance), soit il en porte vraiment la logique — et alors ce n'est pas un module transverse : le déclarer N3, c'est accepter de ne plus pouvoir le réutiliser ailleurs. Le lint ne choisit pas : il rend le coût visible avant qu'il soit payé.

Deux distinctions qui font tout

Arêtes dures vs optionnelles. dependencies et les peers requis sont un vrai couplage. Un peer optionnel (peerDependenciesMeta.optional) dit « si tu as X, je m'intègre avec » — un cycle qui n'emprunte que des arêtes optionnelles n'est pas une faute. Sans cette distinction, le lint criait sur auth ↔ net (intégration facultative parfaitement saine) ; avec elle, il ne reste qu'une vraie faute dans 238 modules.

Contrainte vs proposition. Le plancher (max(niveau(deps))) est la contrainte normative : un N2 peut dépendre d'un autre N2. La classification (--infer) est une proposition adossée aux exemples de §5.bis, relevée au plancher par point fixe. Une inférence par simple profondeur de graphe classait auth en N4 — alors que §5.bis le cite comme exemple de N1 : composer trois primitives ne fait pas de vous un vertical. Un niveau dit une nature ; une nature ne se lit pas dans un graphe.

API

readEcosystem(root) · lint(mods, {strict}){errors, warnings, stats} · infer(mods) · write(mods, props) · findCycles · computeFloors · classify · LEVELS / NATURES / BASE / NEUTRAL.

12 tests verts (@mostajs/mjs-unit).