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/orm-lint

v0.1.0

Published

SQL DDL/migration linter for @mostajs/orm — generates annotated DDL from EntitySchema, lints via Atlas + house rules, remaps findings back to EntitySchema coordinates

Readme

@mostajs/orm-lint

Auteur : Dr Hamid MADANI [email protected] · Licence : AGPL-3.0-or-later Statut : ✅ 0.1.0 — implémenté, 26 tests verts (via @mostajs/mjs-unit).

Linter SQL pour @mostajs/orm. Là où @mostajs/orm/validator analyse l'EntitySchema (règles conceptuelles), ce module passe par le SQL généré pour attraper les anti-patterns invisibles au niveau abstrait (mots réservés, FK sans index, ADD COLUMN NOT NULL sans DEFAULT, identifiants trop longs…), via des règles maison et Atlas (optionnel), puis remappe chaque finding sur les coordonnées (schema, field).


Principe : réutilisation, pas réinvention

Le module ne réimplémente pas le SQL. Il réutilise l'instance de dialecte de l'ORM (@mostajs/orm/dialects, sous-export né en ORM 2.11.0) et ses méthodes publiques generateCreateTable / generateIndexes — le DDL linté est exactement celui que l'ORM produit, pour les 17 dialectes SQL. La plus-value ajoutée ici : annotations, règles maison, Atlas, remapping. Sélection du dialecte par registre piloté .env (pas de switch).

EntitySchema[]
   │  (réutilise @mostajs/orm/dialects → createDialect(type), sans connexion)
   ▼
DDL/Migration exact de l'ORM  ──annoté──►  -- @mostajs-orm:schema=…,field=…
   │
   ├─► règles maison (6)        ─┐
   ├─► Atlas schema lint (opt.) ─┤► findings bruts ──remap (ligne→schema/field)──► Finding[]
   └─────────────────────────────┘

Installation

npm i -D @mostajs/orm-lint @mostajs/orm   # @mostajs/orm >= 2.11.0
brew install ariga/tap/atlas                  # optionnel (sinon fallback règles maison)

Démarrage rapide

import { validateSqlGenerated } from "@mostajs/orm-lint";

const schemas = [
  { name: "Project", collection: "projects",
    fields: { title: { type: "string", required: true } },
    relations: {}, indexes: [], timestamps: true },
  { name: "Registration", collection: "registrations",
    fields: { code: { type: "string", required: true } },
    relations: { project: { target: "Project", type: "many-to-one", required: true } },
    indexes: [], timestamps: true },
];

const report = await validateSqlGenerated(schemas, { dialect: "postgres", tools: ["house"] });
for (const f of report.findings) {
  console.log(`[${f.severity}] ${f.ruleId} ${f.location.schema}.${f.location.field} — ${f.message}`);
}
// [warning] SQL-HOUSE-FK-WITHOUT-INDEX Registration.project — colonne FK "project" sans index

API

| Export | Rôle | |---|---| | validateSqlGenerated(schemas, options?) | pipeline complet → Promise<SqlLintReport> | | generateDdlForLint(schemas, ld, {annotate}) | DDL annoté (réutilise l'ORM) | | generateMigrationForLint(old, new, ld, {annotate}) | ALTER annotés (champs ajoutés) | | getLintDialect(config) | dialecte de lint (instance ORM + métadonnées) | | supportedDialects() | liste des dialectes SQL | | runHouseRules(sql, ld, fkByTable, enabled?) | règles maison sur du SQL arbitraire | | parseAnnotations(sql) / remapToFinding(raw, map) | annotations & remapping | | isAtlasAvailable(bin?) / runAtlasLint(...) / parseAtlasOutput(json) | Atlas | | loadConfig(dialectOverride?) | config résolue depuis .env |

SqlLintOptions

{ dialect?, scope?: "ddl"|"migration"|"both", oldSchemas?, tools?: ("house"|"atlas")[],
  atlasBinary?, atlasMissingBehavior?: "graceful"|"strict", houseRules?, ignore? }

Tout champ absent est résolu depuis l'environnement (.env).

SqlLintReport

{ schemaCount, findings: Finding[], toolsRun, atlasAvailable, durationMs,
  generatedDdl?, generatedMigration? }

Finding = { ruleId, severity, message, location:{line?,schema?,field?}, suggestion, fixable } (structurellement compatible avec Finding de @mostajs/orm/validator).

Règles maison

| Code (SQL-HOUSE-…) | Sévérité | Détecte | Exemple TP | |---|---|---|---| | RESERVED-WORDS | warning | identifiant non quoté réservé | CREATE TABLE t (user TEXT…) | | MISSING-PK | error | table sans PRIMARY KEY | CREATE TABLE t (a TEXT) | | FK-WITHOUT-INDEX | warning | colonne FK sans index | relation project non indexée | | COMPOSITE-INDEX-PK-FIRST | info | index composite préfixé par la PK seule | INDEX(id, code) avec PK id | | NOT-NULL-WITHOUT-DEFAULT-IN-ALTER | error | ADD COLUMN … NOT NULL sans DEFAULT | lock ACCESS EXCLUSIVE en prod | | IDENTIFIER-TOO-LONG | warning | identifiant > limite du dialecte | colonne de 70 car. en Postgres (63) |

Atlas (si installé) : ses diagnostics AR* sont remappés sous SQL-ATLAS-AR* ; sinon fallback graceful. atlasMissingBehavior: "strict" lève si Atlas est absent.

Configuration .env (via @mostajs/config — jamais en dur)

| Clé | Rôle | |---|---| | ORM_LINT_DIALECT | dialecte (sinon DB_DIALECT, sinon postgres) | | ORM_LINT_TOOLS | house,atlas | | ORM_LINT_ATLAS_BINARY / _ATLAS_MISSING | binaire Atlas / graceful|strict | | ORM_LINT_IGNORE / _HOUSE_RULES | règles ignorées / restreintes | | ORM_LINT_RESERVED[_<DIALECT>] | mots réservés supplémentaires | | ORM_LINT_LIMIT_<DIALECT> | limite d'identifiant |

Cascade ${MOSTA_ENV}_${KEY}${KEY} → défaut. Charger le .env en amont (node --env-file=.env ou dotenv de l'app). Priorité : options de code > .env > défauts SQL.

CLI

orm-lint examples/schemas.mjs --dialect postgres --scope both --tools house,atlas
orm-lint examples/schemas.mjs --ignore SQL-HOUSE-FK-WITHOUT-INDEX --json
orm-lint examples/schemas.mjs --ddl    # imprime aussi le DDL généré

Le fichier exporte schemas (ESM) ou est un tableau (.json). Sortie 1 si finding error.

Exemples & démo

node examples/demo.mjs              # lint DDL : DDL annoté + findings console
node examples/migration-demo.mjs    # scope migration : ADD COLUMN NOT NULL sans DEFAULT
node examples/multi-dialect-demo.mjs# même schéma sur Postgres/MySQL/Oracle (limites d'identifiant)
node examples/annotations-demo.mjs  # les annotations : DDL annoté → carte → remapping
orm-lint examples/schemas.mjs   # même chose en CLI

Tous décrits dans examples/README.md.

Tests

Suite exécutée par le CLI @mostajs/mjs-unit :

npm test    # typecheck → build → node node_modules/.bin/mjs-unit test-scripts/*.test.mjs

26 tests : règles maison (TP/TN), générateur, annotations/remapping, Atlas, E2E multi-dialecte + .env.

Limites

  • DDL généré sans exécution (l'ORM couple DDL+exécution dans initSchema).
  • Dialectes non-SQL (mongodb/firestore/redis) → exception explicite.
  • --fix non implémenté (findings fixable: false en 0.1.0).