À propos de ce cours
Objectifs de la leçon
- Identifier le rôle de chaque fichier d'un projet NestJS.
- Suivre le parcours d'une requête dans le code.
- Lire les décorateurs @Module, @Controller, @Get et @Injectable.
- Organiser un projet par fonctionnalités.
Vue d'ensemble
api-formation/
├── dist/ ← code JavaScript compilé (généré, non versionné)
├── node_modules/ ← dépendances (générées, non versionnées)
├── src/ ← VOTRE CODE
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test/ ← tests end-to-end
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── .gitignore
├── .prettierrc
├── nest-cli.json
├── package.json
├── package-lock.json
├── README.md
├── tsconfig.build.json
└── tsconfig.json
On travaille presque exclusivement dans src/. Les autres fichiers configurent le projet (leçon 3.4).
main.ts : le point d'entrée
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();
C'est le premier fichier exécuté : il crée l'application à partir du module racine et démarre le serveur. Il est détaillé à la leçon 3.3.
app.module.ts : le module racine
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [], // autres modules utilisés
controllers: [AppController], // contrôleurs de ce module
providers: [AppService], // services injectables
})
export class AppModule {}
Le décorateur @Module décrit l'organisation : NestJS lit ces métadonnées pour savoir quelles classes créer et comment les relier. Chaque nouvelle fonctionnalité (stagiaires, groupes…) aura son propre module, ajouté dans imports.
app.controller.ts : les routes
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller() // préfixe de route : aucun → '/'
export class AppController {
constructor(private readonly appService: AppService) {} // injection
@Get() // GET /
getHello(): string {
return this.appService.getHello();
}
}
Le contrôleur reçoit les requêtes HTTP. Il ne contient pas de logique : il délègue au service, qu'il reçoit par son constructeur.
app.service.ts : la logique
import { Injectable } from '@nestjs/common';
@Injectable() // peut être injecté ailleurs
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
La requête GET / arrive au contrôleur, qui appelle le service ; la valeur renvoyée devient la réponse HTTP.
Les fichiers de test
*.spec.ts(danssrc/) : tests unitaires, placés à côté du fichier testé.app.controller.spec.tsvérifie quegetHello()renvoie « Hello World! ».test/app.e2e-spec.ts: test end-to-end, qui démarre l'application et envoie une vraie requêteGET /.
Les tests sont étudiés au chapitre 17 ; en attendant, ne supprimez pas ces fichiers et lancez npm test de temps en temps.
Les dépendances principales
| Paquet | Rôle |
|---|---|
@nestjs/core | Cœur du framework : NestFactory, injection de dépendances |
@nestjs/common | Décorateurs et outils : @Module, @Controller, @Get, exceptions… |
@nestjs/platform-express | Adaptateur qui fait tourner NestJS sur Express |
reflect-metadata | Permet de lire les métadonnées des décorateurs |
rxjs | Programmation réactive (utilisée par les intercepteurs, chapitre 09) |
@nestjs/cli, @nestjs/testing, typescript, jest… (dev) | Outils de développement et de test |
Organiser un vrai projet : par fonctionnalités
On ne range pas tous les contrôleurs dans un dossier et tous les services dans un autre. On crée un dossier par fonctionnalité, qui contient tout ce qui la concerne :
src/
├── app.module.ts
├── main.ts
├── stagiaires/
│ ├── dto/
│ ├── entities/
│ ├── stagiaires.controller.ts
│ ├── stagiaires.module.ts
│ └── stagiaires.service.ts
├── groupes/
│ └── …
└── common/ ← éléments partagés (filtres, guards, décorateurs…)
Activités
Activité 1 Suivre une requête
Sans exécuter le code, répondez : (a) quel fichier est exécuté en premier ? (b) quelle méthode répond à GET /? (c) d'où vient le texte renvoyé ? (d) que se passe-t-il pour GET /bonjour?
Voir le corrigé
(a) main.ts; (b) AppController.getHello(); (c) AppService.getHello(); (d) aucune route ne correspond : NestJS renvoie 404 avec "Cannot GET /bonjour".
Activité 2 Ajouter une route
Ajoutez la route GET /version qui renvoie { "application": "api-formation", "version": "0.0.1" }. La logique doit être dans le service, le contrôleur se contente de l'appeler.
Voir le corrigé
// app.service.ts
getVersion() {
return { application: 'api-formation', version: '0.0.1' };
}
// app.controller.ts
@Get('version')
getVersion() {
return this.appService.getVersion();
}
Un objet renvoyé par une méthode de contrôleur est automatiquement converti en JSON, avec l'en-tête Content-Type: application/json.
Activité 3 Casser pour comprendre
Retirez AppService de la liste providers de app.module.ts et enregistrez. Lisez le message d'erreur dans le terminal, puis rétablissez la ligne.
Voir le corrigé
NestJS ne peut plus créer le contrôleur : « Nest can't resolve dependencies of the AppController (?). Please make sure that the argument AppService at index [0] is available in the AppModule module. » Un service doit être déclaré dans les providers d'un module pour être injecté.
À retenir
- Tout votre code est dans src/ ; dist/ et node_modules/ sont générés.
- main.ts démarre l'application à partir du module racine AppModule.
- @Module déclare contrôleurs (routes) et providers (services).
- Le contrôleur reçoit la requête et délègue la logique au service injecté.
- Un vrai projet s'organise en un dossier (et un module) par fonctionnalité.