L'architecture NestJS
Modules, controllers, services : votre vanilla automatisée.
Objectifs
À la fin de cette leçon, vous saurez :
- situer modules, controllers, services et providers ;
- reconnaître votre architecture vanilla dans NestJS ;
- poser les quatre questions à chaque abstraction.
🔗 Pour vous rafraîchir la mémoire : décorateurs et metadata
Votre serveur, réécrit par Nest
Tout ce que vous avez construit à la main existe dans Nest :
VOTRE VANILLA NESTJS
routeur regex → @Controller + @Get/@Post
lireCorps + JSON.parse → @Body() + ValidationPipe
db.js repository → @Injectable() Repository
assemblage main.js → conteneur DI automatique
try/catch global → Exception Filters
Les trois pièces de base
// task.service.ts : LA logique métier
@Injectable()
export class TasksService {
constructor(private readonly repo: TasksRepository) {}
lister() { return this.repo.findAll(); }
}
// tasks.controller.ts : LE pont HTTP
@Controller('tasks')
export class TasksController {
constructor(private readonly service: TasksService) {}
@Get()
lister() { return this.service.lister(); }
@Post()
creer(@Body() dto: CreateTaskDto) {
return this.service.creer(dto);
}
}
// tasks.module.ts : LE câblage déclaré
@Module({
controllers: [TasksController],
providers: [TasksService, TasksRepository],
})
export class TasksModule {}
Le flux d'une requête est celui que vous connaissez déjà :
Request → Guard → Pipe(DTO) → Controller → Service → Repository → PostgreSQL
Les quatre questions systématiques
Pour chaque abstraction rencontrée, le cursus impose :
- Quel problème résout-elle ?
- Comment faisait-on avant ? (vous savez : vous l'avez écrit !)
- Que fait Nest à notre place ?
- Peut-on reproduire une version simple manuellement ?
Exemple avec le DI : problème = assembler les graphes sans verbosité ; avant = votre main.js ; Nest lit les décorateurs et instancie ; version manuelle = chapitre 31.
Provider et middleware : les deux mots restants
Provider : tout ce que vous enregistrez dans providers: [...] d'un module. Un service en est le cas courant, mais factory, helper ou classe utilitaire peuvent aussi être des providers. Ce qui définit un provider : Nest l'instancie une fois, le range dans le conteneur DI et peut l'injecter partout où on le demande. « Provider » décrit donc un rôle vis-à-vis du conteneur (« fourni par lui »), pas un type de code.
Middleware : le maillon le plus ancien de la chaîne, hérité d'Express. Il s'exécute avant guards, interceptors et pipes — typiquement pour le logging global, la configuration CORS, ou le parsing des cookies. Contrairement à un guard, il ne décide rien sur l'accès ; contrairement à un interceptor, il ne voit pas le résultat de la réponse sous forme de flux RxJS.
La chaîne complète dans l'ordre : middleware → guard → interceptor (avant) → pipe → handler → interceptor (après) → exception filter si erreur. Retenir cet ordre suffit à choisir le bon outil au bon étage.
Exercice
- Listez les modules de Devmind lui-même (catalog, admin, auth...) et leurs responsabilités.
- Pour chaque couche du flux, nommez son équivalent dans votre vanilla.
- Pourquoi le contrôleur reste-t-il mince ?
Résumé
- Modules déclarent, contrôleurs routent, services décident, repositories accèdent.
- Rien de nouveau conceptuellement : tout est automatisation de ce que vous maîtrisez.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 3. Le contrôleur ne fait que traduire HTTP ↔ appels de service : parsing des paramètres, statuts. Toute règle métier descend au service — testable sans HTTP, réutilisable depuis un cron ou une CLI. C'est le SRP appliqué aux couches.