Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
NestJS

La structure et l'architecture d'un projet NestJS (main.ts, app.module.ts…)

Cette leçon explique la structure d'un projet NestJS fichier par fichier : le dossier src avec main.ts, app.module.ts, app.controller.ts et app.service.ts, les fichiers de tests unitaires et end-to-en...

0 chapitres 0 QCM Accès gratuit
La structure et l'architecture d'un projet NestJS (main.ts, app.module.ts…)

À propos de ce cours

Cette leçon explique la structure d'un projet NestJS fichier par fichier : le dossier src avec main.ts, app.module.ts, app.controller.ts et app.service.ts, les fichiers de tests unitaires et end-to-end, les fichiers de configuration et les dépendances principales. Elle suit le parcours d'une requête GET / à travers ces fichiers et présente l'organisation d'un projet réel par fonctionnalités, avec des activités de lecture et de modification du code.

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!';
  }
}

Parcours d'une requête dans un projet NestJS

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 (dans src/) : tests unitaires, placés à côté du fichier testé. app.controller.spec.ts vérifie que getHello() renvoie « Hello World! ».
  • test/app.e2e-spec.ts: test end-to-end, qui démarre l'application et envoie une vraie requête GET /.

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
PaquetRôle
@nestjs/coreCœur du framework : NestFactory, injection de dépendances
@nestjs/commonDécorateurs et outils : @Module, @Controller, @Get, exceptions…
@nestjs/platform-expressAdaptateur qui fait tourner NestJS sur Express
reflect-metadataPermet de lire les métadonnées des décorateurs
rxjsProgrammation 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é.