brind-apiwalker
v0.2.0
Published
Vérifie une API depuis son contrat OpenAPI : exerce chaque route sur un environnement jetable et engendre un rapport par module.
Maintainers
Readme
brind-apiwalker
Exerce chaque route d'une API depuis son contrat OpenAPI, sur un environnement monté pour l'occasion, et écrit un rapport par module : la route, ce qu'elle fait, le rôle exigé, le payload envoyé, la réponse obtenue.
npx brind-apiwalker # tous les modules
npx brind-apiwalker care-links lab # ceux-là seulementRien à installer : npx récupère le paquet, lit verifier.config.ts à la
racine du projet, et travaille.
Ce que ça produit
docs/verification/README.md est le document qui résume tout : le compte
par module, puis, module par module, ce que chacun propose — une ligne par
route, groupées par sujet, avec ce qu'elle a réellement répondu — et enfin les
routes en erreur serveur et celles restées hors de portée.
Un fichier par module à côté porte la pièce à conviction : pour chaque route, l'appel exact et la réponse reçue.
Le code de sortie vaut 1 dès qu'une route répond en 5xx, 0 sinon. Une route
hors de portée n'est pas un défaut de l'API : elle ne fait pas échouer la
vérification, elle est signalée.
Ce qu'il faut lui dire
Une seule chose est vraiment obligatoire : où joindre l'API. Le reste a un défaut raisonnable.
// verifier.config.ts
import type { Configuration } from 'brind-apiwalker';
const config: Configuration = {
base: 'http://localhost:3000',
contrat: '/api/docs-json',
};
export default config;Cela suffit à exercer les routes ouvertes. Les autres exigent un jeton, donc un contexte.
Le contexte : qui est connecté, et quoi désigner
OpenAPI décrit des formes, jamais des données. GET /patients/{patientId}
demande un identifiant qui existe — le contrat ne peut pas l'inventer.
contexte: async (base) => ({
jetons: { PATIENT: '…', DOCTOR: '…', '*': '…' },
valeurs: { patientId: 'cmt8…', appointmentId: 'cmt9…' },
journal: ['patient connecté', 'rendez-vous créé'],
}),La clé * sert de repli quand aucun rôle ne correspond. journal est repris
tel quel dans les rapports : ce qui a été préparé, et ce qui a échoué.
Une route dont un paramètre manque au contexte est déclarée hors de portée plutôt qu'exercée à vide — un 404 sur un identifiant inventé n'apprend rien.
Les rôles
OpenAPI dit qu'un jeton est attendu, jamais lequel. Un projet qui déclare ses rôles par décorateur peut les faire lire :
import { rolesDepuisLesSources } from 'brind-apiwalker/adaptateurs/nestjs';
roles: rolesDepuisLesSources({ racine: 'src/modules', defaut: '*' }),Sans cela, toutes les routes protégées sont servies avec le jeton de repli.
Les noms de paramètres
/pharmacy/{id} désigne une officine, /users/{id} un compte : le nom seul ne
le dit pas. Par défaut la clé se dérive du segment qui précède
(/pharmacies/{id} → pharmacyId). parametre corrige les exceptions.
L'environnement jetable
Rejouer les mêmes appels sur une base qui garde ses traces donne des réponses différentes d'une fois sur l'autre : un identifiant déjà pris répond 409, un créneau déjà réservé aussi. Le rapport ne vaudrait alors que pour l'état de la base au moment où il a été écrit.
import { baseJetable } from 'brind-apiwalker/adaptateurs/base-jetable';
environnement: baseJetable({
url: process.env.DATABASE_URL!, // seul le nom de la base change
migrer: ['npx', 'prisma', 'migrate', 'deploy'],
semer: ['npx', 'prisma', 'db', 'seed'],
batir: ['npx', 'nest', 'build'],
demarrer: [process.execPath, 'dist/src/main.js'],
sonde: '/api/docs-json',
port: 3977,
}),Base créée, migrée, semée, serveur démarré, routes exercées, tout détruit — y compris si la vérification échoue en route.
Cet adaptateur suppose PostgreSQL et un serveur Node. Un projet bâti autrement
fournit son propre Environnement : le noyau n'en demande que demarrer et
arreter.
.envn'est pas lu tout seul. Un projet qui y range sonDATABASE_URLappelledotenv.config()en tête de sa configuration.
Ce qui précède l'exercice
avant reçoit un nom de module et rend ce qu'on veut voir en tête du rapport —
une couverture unitaire, une analyse statique, un numéro de version :
avant: async (module) => couvertureDuModule(module),Elles sont prises après que toutes les routes ont été exercées : une analyse un peu longue laisserait sinon le serveur patienter, et rien n'y gagnerait en justesse.
Rendre le résumé lisible
Le document de synthèse groupe les routes par sujet, d'après l'URL —
establishments, users. Un projet peut leur donner un titre français, et
décrire le parcours que ses routes dessinent : cela ne se déduit d'aucun
contrat, seul quelqu'un qui connaît le métier le sait.
const PRESENTATIONS = {
admin: {
groupes: { establishments: '🏥 Établissements', users: '👥 Utilisateurs' },
schema: `
SUPER_ADMIN → Établissements → Admins établissement → Rôles
`,
},
};
resume: (module) => PRESENTATIONS[module],Le schéma est repris tel quel, dans un bloc préformaté. Un dessin en caractères tient dans un fichier versionné, se lit dans un terminal, et se compare d'une version à l'autre — ce qu'aucune image ne fait.
Un module sans entrée n'est pas moins vérifié : son résumé porte les noms que l'URL lui donne, et pas de schéma.
Portée
Le noyau ne suppose ni framework, ni base de données, ni langage côté serveur : il lit un contrat, exerce des routes, écrit des rapports. Toute API qui publie un OpenAPI 3 est vérifiable — ce qui lui est propre passe par sa configuration.
Les adaptateurs (nestjs, base-jetable) sont des commodités, pas des
dépendances : un projet peut n'en utiliser aucun.
Ce que ça ne fait pas
Ce n'est pas une suite de tests : rien n'est comparé à un résultat attendu, il n'y a pas d'assertion. C'est un relevé — ce que l'API répond aujourd'hui, route par route, sur des données connues. Il sert à voir ce qui casse, à documenter le comportement réel, et à faire échouer une intégration continue sur une erreur serveur.
En bibliothèque
import { verifier } from 'brind-apiwalker';
const { bilans, code } = await verifier(config, ['care-links']);Licence
MIT.
