@angularkit/atlas
v0.2.0
Published
Evidence-backed static inventory of Angular routes for audits and AI agents.
Maintainers
Readme
AngularKit Atlas
Français · English
Cartographie et audit de la navigation Angular : routes, écrans et preuves dans le code, pour développeurs et agents IA.
La carte HTML interactive sert à explorer les routes ; le JSON détaillé ou compact alimente les outils et agents IA. Un rapport Markdown est également disponible. Atlas ne mesure pas les parcours réellement empruntés et ne constitue pas un audit de sécurité.
Installation et utilisation
Prérequis : Node.js 22 minimum (CI sur 22 et 24), les sources du projet Angular et ses dépendances installées. Aucune modification de l’application, aucun serveur Angular et aucun navigateur automatisé ne sont nécessaires.
Depuis le dossier de votre application, générer une première carte :
npx --package=@angularkit/atlas@latest angular-atlas . --html carte.htmlOuvrir ensuite carte.html dans un navigateur. Pour analyser un autre dossier :
npx --package=@angularkit/atlas@latest angular-atlas /chemin/vers/application --html carte.htmlPour appeler l'API depuis un outil Node.js en ESM :
npm install --save-dev @angularkit/atlas@latestAvec pnpm :
pnpm add -D @angularkit/atlas
pnpm exec angular-atlas . --html carte.htmlimport { scan, toHtml } from '@angularkit/atlas';
import { writeFileSync } from 'node:fs';
writeFileSync('carte.html', toHtml(scan('/chemin/vers/application')));Atlas s’exécute sous Node.js ; aucune intégration au runtime Angular n’est nécessaire. Les types TypeScript sont inclus. La distribution est ESM, sans entrée CommonJS dédiée.
Poids et partage de TypeScript
La version npm 0.1.0 dépend de TypeScript ^6.0.3. Si votre projet utilise TypeScript 5, elle peut installer un second compilateur (environ 20 à 25 Mo sur disque). Cela concerne l’outil de développement, sans ajout au bundle Angular.
À partir de 0.1.1 : TypeScript est une dépendance partagée (peerDependency) compatible avec >=5.4.2 <6.1. Une installation locale d’Atlas utilise le compilateur compatible déjà présent dans le projet, sans installer une copie privée. Les versions vérifiées en CI sont 5.4.2, 5.4.5, 5.5.4, 5.6.3, 5.7.3, 5.8.3, 5.9.3 et 6.0.3.
Avec 0.1.1 ou plus récent, privilégier l’installation dans le projet pour partager son compilateur :
npm install --save-dev @angularkit/atlas
npx angular-atlas . --html carte.htmlLe partage dépend de l’emplacement d’installation d’Atlas, pas simplement du dossier analysé. Une exécution ponctuelle via npx --package=… depuis un projet où Atlas n’est pas installé peut créer un environnement dans le cache npm et y télécharger TypeScript. Avec npm moderne et ses réglages standards, une dépendance partagée absente est installée automatiquement ; une version incompatible doit être résolue selon les contraintes du projet Angular, sans forcer sa mise à niveau pour Atlas. Fonctionnement des dépendances partagées npm.
tool.typescriptVersion dans le rapport indique le compilateur effectivement utilisé. Le contrat JSON reste le même ; les différences de compilateur peuvent modifier les diagnostics et l’empreinte du projet. La compatibilité TypeScript ne constitue pas une certification de toutes les versions Angular.
Les exemples utilisent latest. Pour un audit reproductible, verrouiller une version dans le lockfile du projet ou remplacer @latest par la version souhaitée. Consulter les releases pour connaître les versions disponibles.
Choisir l’application à analyser
Pour un monorepo ou une sélection explicite :
npx --package=@angularkit/atlas@latest angular-atlas /chemin/vers/workspace --tsconfig apps/shop/tsconfig.app.jsonAtlas utilise les options tsConfig des projets de build dans angular.json, puis tsconfig.app.json, puis tsconfig.json. Plusieurs applications détectées demandent un --tsconfig explicite. Les configurations solution à références de projets demandent de sélectionner le tsconfig d'une application. Pour Nx et les configurations non standard, préciser ce chemin.
--entry src/app/app.config.ts limite la découverte des appels d'enregistrement à ce fichier. Le contexte de compilation reste celui du projet ; les avertissements sur les modifications runtime restent visibles.
Sans --json, --md ni --html, le JSON est écrit sur stdout ; le résumé va sur stderr. Les chemins de sortie sont relatifs au répertoire courant, leurs dossiers doivent exister. Les fichiers existants ne sont pas écrasés.
Référence CLI
angular-atlas [racine-du-projet] [options] utilise le dossier courant si la racine est omise. --tsconfig et --entry sont relatifs à cette racine ; les chemins de sortie sont relatifs au dossier depuis lequel la commande est lancée.
| Option | Usage |
|---|---|
| --tsconfig <fichier> | Choisir le tsconfig de l’application, notamment pour Nx et les monorepos. |
| --entry <fichier> | Limiter la découverte des enregistrements du routeur à un fichier. |
| --html <fichier> | Générer une carte HTML autonome. |
| --json <fichier> | Enregistrer l’inventaire JSON. |
| --md <fichier> | Enregistrer le rapport Markdown. |
| --compact | Alléger les sorties JSON et Markdown ; la carte reste détaillée. |
| --fail-on-partial | Retourner le code 2 si les routes ou la navigation sont partiellement analysées, après écriture des rapports. |
| --help | Afficher l’aide. |
Pour intégrer un inventaire à votre propre CI :
npx --package=@angularkit/atlas@latest angular-atlas . --compact --fail-on-partial --json routes.jsonCette commande échoue aussi lorsqu’une limite connue, par exemple le SSG, rend le rapport partiel. Utiliser --fail-on-partial seulement si ce comportement est souhaité.
La documentation est disponible en français et en anglais. Dans la version actuelle, l’aide CLI, la carte et les rapports Markdown sont principalement en français ; il n’y a pas encore d’option de langue. Les clés JSON restent identiques dans les deux guides.
Carte interactive
npx --package=@angularkit/atlas@latest angular-atlas /chemin/vers/application --html carte.htmlOuvrir carte.html dans un navigateur. Le fichier fonctionne hors ligne, sans serveur ni dépendance distante. Il contient l'inventaire complet et ses références source : le partager revient à partager ces informations.
- Les routes racines sont visibles au départ ; les boutons + / − déplient et replient les branches, avec leur nombre de descendants.
- La recherche porte sur les chemins et noms de composants. Elle révèle les ancêtres des résultats ; sélectionner un résultat conserve le filtre. « Vue d’ensemble » remet la carte à son état initial.
- Un clic sur un chemin ouvre les composants, guards, resolvers, redirections et sources. Les guards restent associés à leur route de déclaration.
- Les traits pleins représentent la relation parent–enfant. « Liens de la sélection » affiche en pointillés les destinations candidates de la route sélectionnée. Le panneau présente les références entrantes/sortantes et permet d’ouvrir une destination, même repliée. Les permissions ne sont pas déduites.
- La carte propose le zoom et le déplacement ; sur mobile les branches se lisent verticalement. Les contrôles sont utilisables au clavier.
- Les diagnostics restent visibles, y compris les limites du SSG. Les doublons de chemins conservent leurs identités distinctes.
--html, --json et --md peuvent être combinés avec des fichiers distincts. --compact s'applique au JSON et au Markdown ; la carte conserve les détails disponibles au clic. --fail-on-partial garde le même comportement pour tous les formats.
import { scan, toHtml } from '@angularkit/atlas';
import { writeFileSync } from 'node:fs';
writeFileSync('carte.html', toHtml(scan('/chemin/vers/application')));Liens de navigation (0.2+)
La carte et les exports incluent désormais les références routerLink des templates Angular (inline ou templateUrl) et les appels TypeScript Router.navigate() / Router.navigateByUrl(). Aucune option supplémentaire n’est nécessaire. Dans la carte, ouvrir Références de navigation pour le relevé global ; sélectionner une route pour ses liens entrants et sortants, puis activer Liens de la sélection pour les connexions en pointillés. Les candidats masqués par une recherche restent accessibles depuis le panneau.
<a routerLink="/catalogue">Catalogue</a>
<a [routerLink]="['/produit', 42]">Produit</a>router.navigate(['/catalogue']);
router.navigate(['../liste'], { relativeTo: this.route });
router.navigateByUrl('/catalogue?tri=date#resultats');Atlas conserve la référence source, l’expression, la classe propriétaire et, quand elle est connue, la route d’origine. Les liens d’un composant partagé ou d’un service restent visibles avec une origine non attribuée. Un composant utilisé par plusieurs routes produit une référence par contexte ; les liens de ses composants imbriqués ne sont pas propagés automatiquement vers ces routes.
- Destination candidate (
matched) : le chemin correspond à un ou plusieurs motifs explicites. Les doublons et paramètres restent des candidats distincts ; ni l’ordre effectif de sélection, ni les guards, ni les redirections ne sont exécutés. - Sans correspondance explicite (
unmatched) : aucun motif explicite trouvé. Une wildcard ou une route non résolue peut prendre le relais ; ce n’est pas un verdict « lien cassé ». - Non résolu (
unresolved) : destination dynamique ou syntaxe/contexte non pris en charge. L’expression et sa source restent disponibles. - Lien désactivé (
disabled) :routerLinkvaut littéralementnullouundefined.
Les chaînes et tableaux littéraux de chaînes/nombres sont lus sans exécuter le projet. Un routerLink relatif utilise le contexte du composant directement routé ; navigate() part de la racine par défaut. Le relativeTo TypeScript est reconnu pour l’ActivatedRoute directement injectée dans ce composant (champ inject ou paramètre constructeur). Ses parents, une option dynamique, un contexte inconnu ou les paramètres runtime conservés dans un chemin relatif restent non résolus. Les liens absolus d’un composant partagé peuvent toujours avoir une destination candidate.
Le parseur de templates Angular 22.0.7 est embarqué (~496 ko de JavaScript, avant compression). Aucun compilateur Angular supplémentaire n’est installé chez le consommateur ; TypeScript reste partagé. Les templates externes lus entrent dans project.files et l’empreinte du projet. Les syntaxes Angular plus récentes non reconnues produisent un diagnostic. La présence de RouterLink/RouterModule dans les imports standalone confirme le périmètre de la directive ; les scopes NgModule et directives homonymes non confirmés restent non résolus.
Limites de ce jalon : expressions de champs/signaux dans les templates, UrlTree, outlets et paramètres matriciels, segments encodés, relativeTo explicite dans un template, appels de navigation dans les expressions d’événements des templates, host bindings, héritage et composition des composants non analysés. Les templates inline avec échappements JavaScript restent diagnostiqués pour éviter des positions source approximatives. Les références sont plafonnées à 10 000 ; un template externe dépassant 2 millions de caractères ou sortant du projet est diagnostiqué.
Le contrat JSON passe à 1.1, avec navigation: { status, references, diagnostics }. scope.status décrit toujours les routes ; navigation.status décrit cette analyse supplémentaire. --fail-on-partial retourne désormais 2 si l’un ou l’autre est partiel, après écriture des rapports. Les schémas acceptent encore les inventaires 1.0, et les rendus restent compatibles avec leur absence de champ navigation. Le format compact conserve ces références et leurs incertitudes.
Rapport compact
Pour une première lecture ou pour transmettre moins de contexte à un agent IA, créer d’abord le dossier de sortie :
mkdir -p reports
npx --package=@angularkit/atlas@latest angular-atlas /chemin/vers/application --compact --json reports/resume.json --md reports/resume.mdLe Markdown compact commence par les points à vérifier, puis présente une section par parent avec de petits tableaux de chemins relatifs, composants et repères. Les composants communs sont indiqués une fois au-dessus du tableau ; chargements différés, guards et clés de resolvers sont regroupés sous les routes concernées. Deux déclarations avec le même chemin restent distinctes. Les listes de fichiers et les preuves détaillées sont omises. Le JSON compact conserve les occurrences, parents, ordre, points d'entrée, chemins, références source des routes et noms ou expressions des guards/resolvers ; il retire les preuves détaillées de chaque référence, les champs vides et les valeurs par défaut (outlet: primary, pathMatch: prefix, lazyChildren: false). Les valeurs inconnues restent null.
Les diagnostics, le statut partiel et les limites restent présents dans les deux formats. Aucune route n'est regroupée ou supprimée. Sans --compact, la sortie détaillée reste inchangée. --fail-on-partial fonctionne aussi avec ce format.
Le JSON compact est identifié par format: "compact", avec son schéma dédié. Il ne remplace pas le contrat complet retourné par scan().
import { scan, toCompactInventory, toMarkdown } from '@angularkit/atlas';
const inventory = scan('/chemin/vers/application');
const summary = toCompactInventory(inventory);
const markdown = toMarkdown(inventory, { compact: true });Informations produites
- Enregistrements
provideRouteretRouterModule.forRoot, y compris les imports renommés. - Ordre des routes détectées, parents, motifs complets, paramètres, chemins vides, wildcards et redirections textuelles.
- Composants directs, imports différés statiques et tableaux enfants différés, exports par défaut ou nommés.
- Guards par type et par route de déclaration, resolvers et références vers leurs déclarations lorsqu'elles sont résolues.
- Fichier, ligne et colonne pour les preuves ; diagnostics localisés pour les expressions non prises en charge.
- Fichiers analysés, exclusions rencontrées et empreinte SHA-256 des configurations et entrées du compilateur, y compris les déclarations utilisées.
L'évaluateur suit les constantes, imports, alias du tsconfig, satisfies, assertions de type et spreads statiques. Il n'exécute pas le code applicatif et ne modifie pas le projet analysé. Les fixtures utilisent le véritable compilateur TypeScript, des fichiers et des graphes de routes réels ; aucun analyseur interne n'est simulé.
Lire le résultat sans surinterpréter
schemaVersion: "1.1" est décrit par le schéma JSON. Les IDs identifient les occurrences dans un rapport ; ils ne sont pas des identifiants pérennes entre commits. Deux routes qui partagent un composant ou un chemin restent distinctes.
scope.status: "static": aucune limite détectée parmi les formes statiques analysées. Ce n'est pas une garantie d'exhaustivité à l'exécution.scope.status: "partial": des éléments n'ont pas été résolus, ou aucun point d'entrée pris en charge n'a été trouvé. Les diagnostics indiquent où poursuivre la revue.fullPath: null: Atlas ne peut pas déduire un motif linéaire fiable./users/:idreste un motif, pas une URL visitable sans données.guardscontient les guards déclarés sur cette route.parentIdpermet de remonter le contexte ; Atlas ne prétend pas reconstituer leurs conditions d'exécution ou permissions.redirect.targetgarde le texte déclaré, relatif ou absolu. Les redirections fonctionnelles restent des expressions non évaluées.ordersuit les éléments frères détectés. Un spread non résolu peut contenir d'autres routes dont le nombre et la position effective sont inconnus.- Les appels d'enregistrement sont trouvés dans les sources du projet ; Atlas ne démontre pas qu'ils sont exécutés au démarrage. Les tableaux sans enregistrement pris en charge ne sont pas présentés comme des routes actives.
Une erreur de lecture, de syntaxe ou de configuration est fatale : aucun rapport de succès n'est produit. Les erreurs de types Angular ne sont pas vérifiées ; ce prototype ne remplace pas le build du projet.
| Code CLI | Signification |
|---|---|
| 0 | Rapport produit ; vérifier scope.status et les diagnostics. |
| 1 | Erreur fatale ou problème de sortie. |
| 2 | Rapport partiel avec --fail-on-partial. |
Limites explicites du prototype
Matchers personnalisés, outlets nommés, modules différés, assemblage RouterModule.forChild/ROUTES, resetConfig et fabriques arbitraires donnent des diagnostics. Les fonctions de chargement acceptées retournent directement import('...'), import('...').then(m => m.Export) ou une sélection déstructurée simple comme .then(({ routes: selected }) => selected). Les réexports de namespaces avec export par défaut sont déballés comme par Angular. Les sélections à valeur par défaut ou rest et les fonctions à plusieurs instructions ne sont pas évaluées.
Les tableaux de primitives statiques peuvent être développés avec .map((value, index) => …). Array.from({ length: N }, (_, index) => …) est pris en charge pour une longueur entière de 0 à 10 000, avec le véritable Array global. Les callbacks doivent être synchrones, sans paramètre déstructuré, valeur par défaut, rest ou troisième paramètre, et contenir une expression ou un unique return. Les concaténations, templates et additions de primitives sont lus statiquement ; les appels métier ne sont jamais exécutés. Les tableaux creux, sources dynamiques, tableaux d'objets et autres fabriques restent diagnostiqués.
Chaque occurrence générée possède son propre ID, chemin, parent et ordre. Sa référence source désigne le modèle dans le callback : plusieurs occurrences peuvent donc partager fichier, ligne et colonne. Les expressions de guards et resolvers restent le texte source original, sans évaluation de leur résultat. Les deux applications de validation atteignent désormais 31/31 et 105/105 entrées client ; cela ne compte pas les URLs produites par le SSG.
Un appel withRoutes ou provideServerRouting de @angular/ssr produit SERVER_RENDERING_NOT_ANALYZED. Le rapport ne reconstitue ni les règles RenderMode, ni getPrerenderParams, ni les URLs générées par le build. Un chemin /blog/:slug ne représente pas la liste des pages SSG. Les modifications d'objets/tableaux après initialisation et les parcours conditionnels ne sont pas interprétés.
Tests, stories, déclarations et dossiers générés connus sont exclus des cibles d'analyse. excludedFiles liste les exclusions rencontrées par le compilateur et le tsconfig ; il ne recense pas tous les fichiers ignorés sur disque. Les imports hors de la racine sélectionnée ne sont pas développés comme routes applicatives.
Les captures de l’application analysée et un éventuel MCP viendront dans des jalons ultérieurs. Aucun score de sécurité ni verdict « route inutilisée » n'est calculé.
Dépannage
| Situation | Action |
|---|---|
| Several applications found ou Solution tsconfig | Passer --tsconfig avec la configuration d’une application, plutôt qu’une configuration de solution. |
| Aucune route ou rapport partial | Lire diagnostics, vérifier la sélection du projet, ses dépendances et l’enregistrement provideRouter ou RouterModule.forRoot. Un tableau isolé ne suffit pas. |
| Output already exists | Choisir un nouveau nom ou supprimer explicitement l’ancien rapport. Il n’existe pas d’option --force. |
| TypeScript absent après installation (0.1.1+) | Vérifier legacy-peer-deps et --omit=peer, qui peuvent empêcher l’installation des peers. Installer explicitement une version TypeScript compatible avec votre projet, puis relancer Atlas. |
| Conflit de peer TypeScript (0.1.1+) | La plage prise en charge est >=5.4.2 <6.1. Conserver les contraintes Angular du projet ; ne pas utiliser --force pour masquer le conflit. |
| Dossier de sortie introuvable | Créer le dossier avant de lancer la commande. |
| SERVER_RENDERING_NOT_ANALYZED | Les routes client restent dans le rapport ; Atlas n’énumère pas les pages prérendues. |
| Erreur de lecture ou de syntaxe | Corriger le fichier ou le tsconfig indiqué ; Atlas ne retourne pas de rapport valide après une erreur fatale. |
Les noms de composants affichés proviennent des déclarations ou expressions de votre code. Atlas n’invente pas de noms d’écrans. Pour signaler un problème, ouvrir une issue avec la version Node/Atlas, la commande, le diagnostic et un petit exemple de routes reproductible, en retirant les sources privées.
API et développement
L’API est synchrone. scan(root, { tsconfig, entry }) retourne l’inventaire complet et lève une erreur pour les échecs fatals. Les fonctions de rendu prennent cet inventaire ; elles n’écrivent pas les fichiers elles-mêmes.
| Export | Résultat |
|---|---|
| scan(root, options?) | Inventory complet avec routes, diagnostics et preuves. |
| toHtml(inventory) | Chaîne HTML autonome. |
| toMarkdown(inventory, { compact: true }?) | Chaîne Markdown, détaillée par défaut. |
| toCompactInventory(inventory) | Objet JSON compact distinct du contrat complet. |
import { scan, toMarkdown } from '@angularkit/atlas';
const inventory = scan('/chemin/vers/application', { tsconfig: 'tsconfig.app.json' });
console.log(toMarkdown(inventory));Pour contribuer depuis les sources :
git clone https://github.com/AngularKit/atlas.git
cd atlas
pnpm install --frozen-lockfile
pnpm run quality
pnpm run test:package:pnpm
pnpm exec playwright install chromium
pnpm run test:browserLes installations de consommateurs npm et pnpm sont testées séparément ; pnpm doit lui aussi réutiliser le compilateur TypeScript du projet. Les deux gestionnaires restent utilisables pour installer Atlas.
La vérification comprend le typage, les tests de fixtures et de CLI, la validation du schéma JSON, puis l'installation hors ligne d'une archive npm dans un répertoire consommateur séparé. Le package installé est testé via sa CLI et son API. La CI exécute ces vérifications sous Node.js 22 et 24, puis les tests Chromium de la carte sous Node.js 24 : branches, recherche, détails, mobile, diagnostics et contenu source hostile. Playwright est une dépendance de développement ; les utilisateurs du package n’ont aucun navigateur à installer pour générer les rapports.
Le développement d’Atlas utilise TypeScript 6.0.3 ; la CI vérifie aussi les compilateurs partagés listés ci-dessus. Son premier essai réel est documenté dans la validation ; cela ne constitue pas une matrice de compatibilité avec toutes les versions Angular.
Voir l'architecture, les notes de version, la procédure de publication et le premier chantier.
