Structure NestJS GraphQL
Où chaque fichier se trouve dans une application NestJS GraphQL (code-first), et comment chaque fichier fonctionne. Cette compétence est un guide de placement et d'anatomie : elle répond à « dans quel dossier ce fichier va-t-il ? », « de quoi ce fichier est-il responsable ? » et « comment les modules se connectent-ils pour résoudre les champs et les relations ? ». Elle couvre la carte structurelle de base ainsi que les règles par fichier pour les modules, services, résolveurs (requête, mutation, abonnement et champ), entrées et arguments, pagination, entités (bonnes pratiques de schéma Mongoose pour les types partagés), injection de modèles réservée aux repositories, modèles/mappeurs, repositories, discriminateurs Mongoose, champs dérivés, fournisseurs, chargeurs, événements, tâches planifiées, authentification, exceptions, scalaires personnalisés, configuration, blocs communs, infrastructure, et les conventions de nommage, test et lint.
Elle est délibérément séparée de la compétence nestjs-best-practices. Cette compétence couvre le comportement du framework (profondeur d'injection de dépendances, sécurité, performances, gestion des erreurs, microservices, DevOps) ; celle-ci couvre la structure et la composition des modules. Là où elles se chevauchent (modules fonctionnels, dépendances circulaires), cette compétence l'examine sous un angle de placement et renvoie à l'autre compétence pour la profondeur comportementale.
Cette compétence couvre à la fois les règles de structure (où vit un fichier) et les règles de résolution de modules (comment les modules se connectent à l'exécution — par ex. résolution des dépendances circulaires). Les règles de résolution de modules se trouvent dans les sections 2 et 3.
Quand appliquer
Consultez ces directives lorsque :
- Vous décidez où placer un nouveau fichier dans une base de code NestJS GraphQL
- Vous concevez ou révisez une structure de répertoires orientée fonctionnalité
- Vous créez un nouveau module fonctionnel et ses fichiers
- Vous décidez comment modéliser des documents polymorphes (discriminateurs Mongoose) et publier automatiquement leur type GraphQL
- Vous décidez où un modèle Mongoose peut être injecté — et maintenez l'accès à la base de données derrière un repository
- Vous décidez si une valeur doit être en base de données ou dérivée à la lecture
- Vous déterminez comment un module résout un champ ou une relation qui se trouve dans un autre module
- Vous résolvez des problèmes de connexion entre modules (dépendances circulaires, exports manquants)
Catégories de règles par priorité
| Priorité | Catégorie | Impact | Préfixe |
|---|---|---|---|
| 1 | Structure de l'application | CRITIQUE | struct- |
| 2 | Modules & Bootstrap | CRITIQUE | module- |
| 3 | Relations & Cross-Module | CRITIQUE | relations- |
| 4 | Services | ÉLEVÉ | service- |
| 5 | Résolveurs GraphQL | ÉLEVÉ | resolver- |
| 6 | Types & Entrées GraphQL | ÉLEVÉ | type- |
| 7 | Accès aux données | MOYEN-ÉLEVÉ | data- |
| 8 | Configuration, Commun & Infra | MOYEN | infra- |
| 9 | Conventions & Tests | MOYEN | conventions- |
Référence rapide
1. Structure de l'application (CRITIQUE)
struct-auth-feature- Garder l'authentification dans son propre module fonctionnelstruct-canonical-layout- Structure d'application canoniquestruct-feature-decomposition- Diviser une fonctionnalité en sous-modules quand elle granditstruct-file-placement-table- Tableau de placement des fichiersstruct-module-kinds- Distinguer les fonctionnalités métier des modules au niveau de l'applicationstruct-schema-artifact- Localiser et définir la politique de l'artefact de schéma généré
2. Modules & Bootstrap (CRITIQUE)
module-bootstrap- Garder main.ts et app.module.ts légersmodule-export-policy- N'exporter que l'API publique de la fonctionnalité (ses services)module-feature-module- Le fichier du module fonctionnel
3. Relations & Cross-Module (CRITIQUE)
relations-avoid-circular- Résoudre les dépendances circulaires entre modulesrelations-dataloader- Regrouper les relations avec un DataLoader par requêterelations-events- Découpler les modules avec des événementsrelations-field-resolvers- Résoudre les relations avec @ResolveFieldrelations-owning-module- Placer un champ de relation dans le module propriétaire de ses données
4. Services (ÉLEVÉ)
service-background-jobs- Garder les processeurs de files d'attente et les tâches planifiées avec la fonctionnalitéservice-external-providers- Garder les clients tiers dans providers/service-interfaces-tokens- Déclarer les contrats de service et les jetons d'injection dans interfaces/service-single-responsibility- Plusieurs services ciblés par moduleservice-small-focused-methods- Garder les méthodes des services petites et ciblées
5. Résolveurs GraphQL (ÉLEVÉ)
resolver-computed-fields- Déclarer les champs sur le type ; résoudre les champs calculés dans le résolveurresolver-organization- Répartir les résolveurs par rôle dans resolvers/resolver-per-type- Un fichier de résolveur par type ayant des résolveurs de champresolver-subscriptions- Placer les résolveurs d'abonnement dans resolvers/ avec PubSub dans infra/
6. Types & Entrées GraphQL (ÉLEVÉ)
type-args- Définir les classes @Args dans dto/type-inputs- Définir les entrées GraphQL dans dto/type-pagination- Paginer les requêtes de liste avec un type Page partagétype-polymorphic-discriminators- Publier les documents discriminés sous forme d'interface ou d'uniontype-unions-interfaces- Placer les types union et interface avec les types du module
7. Accès aux données (MOYEN-ÉLEVÉ)
data-derived-fields- Calculer les champs dérivés ; ne pas les stockerdata-discriminators- Modéliser les sous-types polymorphes avec des discriminateursdata-entity-mongodb- Placer les entités MongoDB dans entities/data-model-injection- N'injecter un modèle que dans le repositorydata-models-mappers- Séparer models/ et mappers/ quand l'API diffère du stockagedata-mongoose-schema- Bonnes pratiques de schéma Mongoose pour les types partagésdata-repository- Garder l'accès aux données dans repositories/
8. Configuration, Commun & Infra (MOYEN)
infra-common-types- Placer les types partagés dans common/types/infra-common- Placer les blocs communs dans common/infra-config- Placer la configuration typée dans config/infra-custom-scalars- Implémenter les scalaires personnalisés dans common/scalars/infra-database- Placer la configuration de base de données et les migrations dans infra/database/infra-directives- Placer les directives de schéma dans common/directives/infra-exceptions- Placer les exceptions dans exceptions/infra-graphql- Placer la configuration GraphQL dans infra/graphql/infra-seeds- Placer les scripts d'initialisation dans infra/database/seeds/infra-shared-module- Utiliser un SharedModule pour les services transversaux
9. Conventions & Tests (MOYEN)
conventions-barrels-aliases- Utiliser les barils et les alias de chemin délibérémentconventions-cli-generator- Utiliser le générateur CLI Nest, puis ajusterconventions-constants-enums- Garder les constantes et les énumérations en dehors des fichiers de classeconventions-module-boundaries- Appliquer les limites de module avec le lintconventions-naming- Conventions de nommage des fichiers et des classesconventions-test-fixtures- Placer les fixtures, fabriques et assistants de test dans test/conventions-testing- Placement des fichiers de test
Comment utiliser
Commencez par la règle de structure de base, puis lisez la règle pour le type de fichier spécifique sur lequel vous travaillez. Les fichiers de règles se trouvent sous rules/ :
rules/struct-canonical-layout.md
rules/_sections.md
Chaque fichier de règle contient :
- Objectif et placement (où vit le fichier et comment il est nommé)
- Responsabilités et anti-responsabilités
- Un exemple incorrect avec une explication
- Un exemple correct avec une explication
Document compilé complet
Pour le guide complet avec toutes les règles développées dans un seul document, voir AGENTS.md.