Aller au contenu
NestJS OpenPartie 4, section d
Changer de langue : lire en anglais

d · Gérer la configuration

  • Projet : Loup-Garou
  • Environ 35 minutes
  • 3 exercices

Depuis la partie 3, main.ts lit process.env.PORT directement. Ça fonctionne, mais rien ne dit ce que ton application attend comme variables d’environnement, ni ne prévient si l’une d’elles manque. @nestjs/config structure ça.

Fenêtre de terminal
npm install @nestjs/config
.env
PORT=3000
NOMBRE_MAX_VILLAGES=50

ConfigModule.forRoot({ isGlobal: true }) lit ce fichier au démarrage, et rend ConfigService injectable partout dans l’application :

src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [ConfigModule.forRoot({ isGlobal: true }), /* … */],
})
export class AppModule {}
src/main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AppModule } from './app.module.js';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
const config = app.get(ConfigService);
await app.listen(config.get('PORT') ?? 3000);
}
await bootstrap();

ConfigService s’injecte aussi dans un service, exactement comme n’importe quel autre provider — plus besoin de toucher à process.env où que ce soit dans ton code :

src/villages/villages.service.ts
@Injectable()
export class VillagesService {
constructor(private readonly config: ConfigService) {}
creer(dto: CreerVillageDto) {
const maximum = this.config.get<number>('NOMBRE_MAX_VILLAGES');
// …
}
}

Un .env incomplet plante silencieusement plus tard, au premier undefined inattendu — bien après le démarrage. L’option validate de ConfigModule.forRoot vérifie tout avant, avec les décorateurs de la section b :

src/config/variables-environnement.ts
import { IsNumber, Min } from 'class-validator';
import { plainToInstance } from 'class-transformer';
import { validateSync } from 'class-validator';
class VariablesEnvironnement {
@IsNumber()
PORT: number = 3000;
@IsNumber()
@Min(1)
NOMBRE_MAX_VILLAGES: number;
}
export function validerEnvironnement(config: Record<string, unknown>) {
const validees = plainToInstance(VariablesEnvironnement, config, { enableImplicitConversion: true });
const erreurs = validateSync(validees, { skipMissingProperties: false });
if (erreurs.length > 0) throw new Error(erreurs.toString());
return validees;
}
src/app.module.ts
ConfigModule.forRoot({ isGlobal: true, validate: validerEnvironnement }),

Retire NOMBRE_MAX_VILLAGES du .env, et le serveur refuse de démarrer — au lieu de démarrer normalement et d’échouer beaucoup plus tard, en pleine requête.

Exercices 4.11 à 4.13

Projet : marketplace

Installe @nestjs/config, ajoute ConfigModule.forRoot({ isGlobal: true }) à AppModule. Crée un .env avec PORT et NOMBRE_MAX_PRODUITS. Fais lire PORT par main.ts via ConfigService, à la place de process.env.PORT direct.

Injecte ConfigService dans ProduitsService. Dans la méthode qui crée un produit, refuse-la (avec BadRequestException) si le nombre de produits existants a atteint NOMBRE_MAX_PRODUITS. Vérifie avec une petite valeur (par exemple 1) que la création échoue dès que la limite est atteinte : comme ta marketplace contient déjà quelques produits, c’est la toute prochaine création qui échoue, pas la deuxième.

Ajoute validerEnvironnement (ci-dessus, avec NOMBRE_MAX_PRODUITS à la place de NOMBRE_MAX_VILLAGES) à ConfigModule.forRoot. Retire temporairement NOMBRE_MAX_PRODUITS de ton .env, et relance le serveur : note le message d’erreur exact au démarrage. Remets la variable pour que l’application redémarre normalement.

Pour vérifier ton travail : npm run test:partie-4 (dépôt d'exercices)