Mis à jour ces 90 derniers jours 10 nouvelles · 50 révisées
Décorateur de paramètre qui extrait le corps de la requête HTTP et le mappe sur un DTO. Peut cibler une propriété spécifique avec @Body('key'). Depuis NestJS 12.0.0, @Body() accepte aussi une option schema compatible Standard Schema (Zod, Valibot, ArkType), validée par StandardSchemaValidationPipe, en complément du flux class-validator historique.
Comme ouvrir un colis et en extraire le contenu pour le traiter.
@Post()
create(@Body() dto: CreateUserDto) {
return this.userService.create(dto);
}
@Post('login')
login(@Body('email') email: string) {
return this.authService.login(email);
}Cas d'usage : Recevoir les données envoyées par le client dans les requêtes POST, PUT ou PATCH.
Décorateurs de méthode qui mappent les méthodes HTTP aux handlers du controller. Chacun définit le verbe HTTP et le chemin optionnel de la route.
Comme les panneaux directionnels dans un aéroport : chacun oriente vers la bonne porte d'embarquement.
@Controller('items')
export class ItemController {
@Get() findAll() { /* ... */ }
@Post() create(@Body() dto: CreateItemDto) { /* ... */ }
@Put(':id') update(@Param('id') id: string) { /* ... */ }
@Delete(':id') remove(@Param('id') id: string) { /* ... */ }
}Cas d'usage : Définir les opérations CRUD standard sur une ressource REST.
Décorateur de paramètre qui extrait les headers HTTP de la requête. Peut cibler un header spécifique par nom ou récupérer tous les headers.
Comme lire l'étiquette sur un colis pour connaître l'expéditeur et le contenu.
@Get()
getData(@Headers('authorization') auth: string) {
return this.service.getData(auth);
}Cas d'usage : Extraire les tokens d'authentification, API keys ou headers custom des requêtes.
Décorateur qui spécifie le token d'injection pour un paramètre de constructeur. Nécessaire pour les providers enregistres avec un token string ou symbol.
Comme préciser le nom exact du fournisseur quand il y a plusieurs pour le même type de service.
@Injectable()
export class AppService {
constructor(
@Inject('DATABASE_CONNECTION')
private db: Connection,
) {}
}Cas d'usage : Injecter des providers enregistres avec useValue/useFactory qui utilisent des tokens string.
Décorateur qui marque une classe comme injectable par le conteneur DI de NestJS. Obligatoire pour tout provider qui participe a l'injection de dépendances.
Comme un badge professionnel : sans lui, le système ne te reconnaît pas comme employé.
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}Cas d'usage : Annoter chaque service, guard, interceptor, pipe et tout provider custom.
Décorateur de paramètre qui extrait les paramètrès de route de l'URL (ex: /users/:id). Peut cibler un paramètre spécifique ou récupérer tous les params.
Comme lire le numéro de chambre sur la clé d'hôtel pour savoir ou aller.
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.userService.findOne(id);
}Cas d'usage : Extraire les identifiants de ressources ou slugs depuis les URLs REST.
Décorateur de paramètre qui extrait les query parameters de l'URL (ex: ?page=1&limit=10). Supporte la transformation via pipes.
Comme les filtres de recherche sur un site e-commerce : ils affinent les résultats sans changer la page.
@Get()
findAll(
@Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
@Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number,
) { return this.service.paginate(page, limit); }Cas d'usage : Implémenter la pagination, le tri et le filtrage sur les endpoints de liste.
Décorateur qui attache des metadonnees personnalisées a un handler ou controller, lisibles via Reflector dans les guards ou interceptors.
Comme coller une étiquette 'VIP' ou 'Public' sur une porte pour que le vigile sache qui laisser entrer.
export const Roles = (...roles: string[]) =>
SetMetadata('roles', roles);
@Post()
@Roles('admin')
create() { /* ... */ }Cas d'usage : Définir les roles requis sur un endpoint pour les vérifier dans un RolesGuard.
Décorateur qui attache un ou plusieurs filtres d'exception a un controller ou handler pour intercepter et formater les erreurs spécifiques.
Comme un traducteur qui reformule les erreurs techniques en messages compréhensibles pour le client.
@Controller('users')
@UseFilters(new HttpExceptionFilter())
export class UserController {
@Post()
create(@Body() dto: CreateUserDto) {
return this.service.create(dto);
}
}Cas d'usage : Appliquer un format d'erreur personnalise pour un domaine spécifique de l'API.
Décorateur qui attache un ou plusieurs guards a un controller ou un handler. Les guards s'exécutent avant le handler pour autoriser ou refuser l'accès.
Comme placer un vigile devant une porte spécifique ou a l'entrée de tout le bâtiment.
@Controller('admin')
@UseGuards(AuthGuard, RolesGuard)
export class AdminController {
@Get('dashboard')
getDashboard() { return 'admin data'; }
}Cas d'usage : Protéger un controller entier ou des routes spécifiques avec authentification et autorisation.
Décorateur qui attache un ou plusieurs interceptors a un controller ou handler pour transformer les requêtes/réponses ou ajouter des comportements transversaux.
Comme ajouter un filtre Instagram a une photo : le contenu est le même mais la présentation change.
@Controller('users')
@UseInterceptors(CacheInterceptor)
export class UserController {
@Get()
@UseInterceptors(ClassSerializerInterceptor)
findAll() { return this.service.findAll(); }
}Cas d'usage : Appliquer la sérialisation, le cache ou le logging sur des routes spécifiques.
Décorateur qui attache un ou plusieurs pipes a un controller ou handler pour valider ou transformer les données entrantes automatiquement.
Comme un détecteur de métaux a l'entrée : il filtre automatiquement tout ce qui n'est pas conforme.
@Post()
@UsePipes(new ValidationPipe({ whitelist: true }))
create(@Body() dto: CreateUserDto) {
return this.service.create(dto);
}Cas d'usage : Activer la validation automatique des DTOs avec class-validator sur des routes spécifiques.
Attribute-Based Access Control : système d'autorisation base sur les attributs du sujet, de la ressource et du contexte. Plus flexible que RBAC.
Comme une boite de nuit avec des règles complexes : âge + tenue + liste VIP + heure déterminant l'accès.
// Regle ABAC: l'auteur peut modifier son propre article
canActivate(ctx: ExecutionContext) {
const user = ctx.switchToHttp().getRequest().user;
const articleId = ctx.switchToHttp().getRequest().params.id;
const article = await this.articleService.findOne(articleId);
return article.authorId === user.id;
}Cas d'usage : Implémenter des règles d'autorisation fines comme 'un auteur ne peut modifier que ses propres articles'.
Module pour gérer des queues de jobs asynchrones via Redis et Bull/BullMQ. Permet le traitement en arrière-plan avec retries et scheduling.
Comme une file d'attente au guichet : les taches arrivent, sont traitées dans l'ordre et reessayees si besoin.
@Processor('email')
export class EmailProcessor {
@Process()
async sendEmail(job: Job<EmailData>) {
await this.mailer.send(job.data);
}
}
// Ajout en queue
await this.emailQueue.add({ to: '[email protected]', subject: 'Hello' });Cas d'usage : Traiter l'envoi d'emails, le redimensionnement d'images ou les exports CSV en arrière-plan.
Module de cache intégré (@nestjs/cache-manager) qui supporte le cache en mémoire ou via des stores externes (Redis, via @keyv/redis). Utilise des interceptors pour cacher les réponses automatiquement. Le store repose désormais sur Keyv : get() renvoie undefined si l'entrée est absente, alors que cache-manager v6 renvoyait null pour le même cas.
Comme un post-it avec les réponses fréquentes : plus rapide que de recalculer a chaque fois.
@Module({
imports: [CacheModule.register({
store: redisStore,
host: 'localhost',
ttl: 60,
})],
})
export class AppModule {}
@UseInterceptors(CacheInterceptor)
@Get()
findAll() { return this.service.findAll(); }Cas d'usage : Cacher les réponses de endpoints lourds comme les listes avec pagination pour réduire la charge DB.
Librairie d'autorisation isomorphe qui définit les abilities (permissions) de façon déclarative. S'intègré avec NestJS via un guard custom.
Comme un règlement intérieur détaillé : chaque personne sait exactement ce qu'elle peut et ne peut pas faire.
const ability = defineAbility((can, cannot) => {
can('read', 'Article');
can('update', 'Article', { authorId: user.id });
cannot('delete', 'Article');
});
// ability.can('update', article) -> true/falseCas d'usage : Gérer des permissions granulaires avec des conditions sur les champs des entités.
Situation ou deux providers ou modules dépendent mutuellement l'un de l'autre, causant une erreur de résolution. Se résout avec forwardRef.
Comme deux personnes bloquées a une porte, chacune attendant que l'autre passe en premier.
// Module A importe B, B importe A
@Module({
imports: [forwardRef(() => ModuleB)],
})
export class ModuleA {}Cas d'usage : Résoudre temporairement une dépendance circulaire tout en planifiant un refactoring pour l'éliminer.
Abstraction pour communiquer avec d'autres microservices via send() (request-reply) ou émit() (event-based). Injectée via ClientsModule. Pour les cas avances, unwrap() donne un accès direct a l'instance du driver sous-jacent (par exemple kafkajs.Producer ou ioredis) quand l'API standard de NestJS ne suffit pas.
Comme un téléphone interne d'entreprise : tu appelles un autre service et attends (send) ou laisses un message (émit).
@Injectable()
export class OrderService {
constructor(@Inject('PAYMENT_SERVICE') private client: ClientProxy) {}
processPayment(order: Order) {
return this.client.send('process_payment', order);
}
notifyShipping(order: Order) {
this.client.emit('order_shipped', order);
}
}Cas d'usage : Appeler des microservices distants depuis un service NestJS de façon découplé.
Module officiel @nestjs/config pour gérer les variables d'environnement. Charge les fichiers .env et fournit ConfigService pour l'injection.
Comme un coffre-fort d'entreprise : centralise tous les secrets et paramètrès, accessible uniquement aux autorises.
@Module({
imports: [ConfigModule.forRoot({
isGlobal: true,
validationSchema: Joi.object({
DB_HOST: Joi.string().required(),
DB_PORT: Joi.number().default(5432),
}),
})],
})
export class AppModule {}Cas d'usage : Centraliser et valider toutes les variables d'environnement au démarrage de l'application.
Technique de réutilisation de connexions base de données via un pool precharge. Évite le coût de création/destruction de connexions a chaque requête.
Comme un parc de voitures partagées : au lieu que chacun acheté sa voiture, on partage un pool.
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
extra: {
max: 20,
idleTimeoutMillis: 30000,
},
})Cas d'usage : Optimiser les performances en production en configurant le pool selon la charge attendue.
Classe décorée @Controller qui gère les requêtes HTTP entrantes et retourne les réponses. Chaque méthode est mappee a une route via des décorateurs HTTP.
Comme un réceptionniste d'hôtel : il reçoit les demandes des clients et les redirigé vers le bon service.
@Controller('users')
export class UserController {
constructor(private userService: UserService) {}
@Get(':id')
findOne(@Param('id') id: string) {
return this.userService.findOne(id);
}
}Cas d'usage : Définir les endpoints REST de l'API et déléguer la logique métier aux services.
NestJS 12.1.0 (23 septembre 2026) introduit un support de cookies intégré et indépendant de l'adaptateur HTTP (Express ou Fastify), auparavant délégué a des middlewares tiers comme cookie-parser. Il expose une API commune pour lire et écrire des cookies quel que soit le serveur HTTP sous-jacent.
Comme une prise électrique universelle : le même cookie fonctionne, qu'on soit branche sur Express ou sur Fastify.
// Nest 12.1 : plus besoin de cookie-parser, quel que soit l'adaptateur
@Get()
getData(@Res({ passthrough: true }) res: Response) {
res.cookie('session', 'abc123', { httpOnly: true });
return { ok: true };
}Cas d'usage : Lire/écrire des cookies de session sans dépendre d'un middleware spécifique a Express ou Fastify.
Cross-Origin Resource Sharing : mécanisme HTTP qui permet a un frontend sur un domaine différent d'accéder a l'API. Configure via app.enableCors().
Comme un visa d'entrée : il autorise les visiteurs de certains pays (origines) a accéder au territoire (API).
app.enableCors({
origin: ['https://monsite.com', 'https://admin.monsite.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true,
});Cas d'usage : Permettre au frontend SPA sur un autre domaine de communiquer avec l'API backend.
Module @nestjs/cqrs qui sépare les écritures (CommandBus + @CommandHandler) des lectures (QueryBus + @QueryHandler) et notifie les changements d'état via EventBus + @EventsHandler. Les Sagas écoûtent les evenements via RxJS pour déclencher de nouvelles commandes dans des workflows complexes.
Comme séparer le guichet des dépôts (commands) de celui des renseignements (queries) dans une banque, avec un tableau d'affichage (events) pour prévenir les autres services.
@CommandHandler(CreateOrderCommand)
export class CreateOrderHandler
implements ICommandHandler<CreateOrderCommand> {
constructor(private eventBus: EventBus, private repo: OrderRepo) {}
async execute(cmd: CreateOrderCommand) {
const order = await this.repo.create(cmd.dto);
this.eventBus.publish(new OrderCreatedEvent(order.id));
return order;
}
}Cas d'usage : Découpler la logique d'écriture, de lecture et de notification dans un domaine métier complexe (e-commerce, facturation).
Méthode de Test.createTestingModule qui crée un module NestJS isole pour les tests. Permet de mocker les dépendances via overrideProvider.
Comme un simulateur de vol : tu recrees l'environnement complet mais en mode test.
const module = await Test.createTestingModule({
providers: [UserService,
{ provide: UserRepository, useValue: mockRepo }],
}).compile();
const service = module.get<UserService>(UserService);
expect(await service.findAll()).toEqual([]);Cas d'usage : Écrire des tests unitaires et d'intégration pour les services NestJS avec des mocks.
Cross-Site Request Forgery : attaque ou un site malveillant force le navigateur a envoyer des requêtes authentifiées. Protège via des tokens anti-CSRF.
Comme quelqu'un qui forge ta signature pour signer un chèque a ta place sans que tu le saches.
import csurf from 'csurf';
app.use(csurf({ cookie: true }));
// Le token CSRF est envoye au client et verifie a chaque mutationCas d'usage : Protéger les applications avec sessions/cookies contre les requêtes forgées.
Décorateur personalise créé avec createParamDecorator ou applyDecorators pour extraire des données ou combiner des décorateurs existants.
Comme créer un raccourci clavier personnalise qui combine plusieurs actions en un seul geste.
export const CurrentUser = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.user;
},
);Cas d'usage : Extraire l'utilisateur courant du token JWT dans chaque handler sans dupliquer le code.
Providers définis avec useClass, useValue, useFactory ou useExisting pour un contrôle total sur ce qui est injecte. Permet l'injection de valeurs non-classes.
Comme choisir entre acheter un meuble en kit, le faire sur mesure ou recycler un ancien meuble.
providers: [
{ provide: 'API_KEY', useValue: process.env.API_KEY },
{ provide: Logger, useClass: ProdLogger },
{ provide: 'DB', useFactory: (cfg: ConfigService) =>
createConnection(cfg.get('DB_URL')),
inject: [ConfigService],
},
]Cas d'usage : Injecter des variables d'environnement, des connexions dynamiques ou des implémentations alternatives.
Utilitaire qui regroupe et met en cache les requêtes de base de données dans une exécution GraphQL. Résout le problème classique N+1.
Comme un livreur qui regroupe toutes les commandes d'un quartier en une seule tournée au lieu de faire un aller-retour par colis.
@Injectable({ scope: Scope.REQUEST })
export class UserLoader {
private loader = new DataLoader<number, User>(async (ids) => {
const users = await this.userService.findByIds([...ids]);
return ids.map(id => users.find(u => u.id === id));
});
load(id: number) { return this.loader.load(id); }
}Cas d'usage : Optimiser les resolvers GraphQL en batchant les requêtes par entité pour éviter le N+1.
Pattern ou les dépendances sont fournies a une classe par le framework plutôt que créées par la classe elle-même. NestJS utilise l'injection par constructeur.
Comme un restaurant ou les ingrédients sont livres par les fournisseurs plutôt que cultives par le chef.
@Injectable()
export class OrderService {
constructor(
private userService: UserService,
private paymentService: PaymentService,
) {}
}Cas d'usage : Découplé les classes pour faciliter les tests unitaires et permettre le remplacement des implémentations.
Intégration officielle @nestjs/drizzle documentée sur docs.nestjs.com. Contrairement a TypeORM, Drizzle n'a pas d'étape forFeature() par table : DrizzleModule.forRootAsync() enregistre la base globalement et l'instance s'injecte partout via @InjectDrizzle().
Comme une arrivée d'eau commune a tout un immeuble plutôt qu'un compteur par appartement : un seul enregistrement global, injectable partout.
DrizzleModule.forRootAsync({
useFactory: (config: ConfigService) => ({
drizzle,
connection: config.getOrThrow<string>('DATABASE_URL'),
}),
inject: [ConfigService],
});
constructor(@InjectDrizzle() private db: NodePgDatabase) {}Cas d'usage : Adopter un ORM TypeScript-first, sans décorateurs ni génération de code, avec un typage inféré du schema.
Module configurable via une méthode statique (forRoot/forRootAsync) qui retourne un DynamicModule. Permet de passer des options de configuration a l'import.
Comme un abonnement téléphonique : le même opérateur mais tu choisis ton forfait (options) a la souscription.
@Module({})
export class MailModule {
static forRoot(config: MailConfig): DynamicModule {
return {
module: MailModule,
providers: [{ provide: 'MAIL_CONFIG', useValue: config }, MailService],
exports: [MailService],
};
}
}Cas d'usage : Créer des modules réutilisables comme les modules de config, cache ou mail avec des paramètrès variables.
Tests end-to-end qui simulent de vraies requêtes HTTP via la librairie supertest. Testent le pipeline complet du request au response.
Comme un client mystère qui teste le restaurant de A a Z : de la réservation au dessert.
const app = moduleFixture.createNestApplication();
await app.init();
await request(app.getHttpServer())
.post('/users')
.send({ email: '[email protected]', password: '12345678' })
.expect(201)
.expect(res => expect(res.body.email).toBe('[email protected]'));Cas d'usage : Valider que les endpoints, la validation, les guards et la sérialisation fonctionnent ensemble.
Module pour la communication asynchrone intra-application via evenements. Les services émettent des evenements et les listeners les traitent de façon découplé.
Comme un système de haut-parleurs dans un bâtiment : un message est diffuse et ceux concernes réagissent.
// Emission
this.eventEmitter.emit('order.created', new OrderCreatedEvent(order));
// Listener
@OnEvent('order.created')
async handleOrderCreated(event: OrderCreatedEvent) {
await this.emailService.sendConfirmation(event.order);
}Cas d'usage : Découpler les effets de bord (email, notifications) de la logique métier principale.
Classe décorée @Catch qui intercepte les exceptions non gérées et les transforme en réponses HTTP structurées. Centralise la gestion d'erreurs.
Comme un filet de sécurité sous un trapéziste : il attrape les chutes et les transforme en atterrissage contrôle.
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
response.status(exception.getStatus()).json({
message: exception.message,
});
}
}Cas d'usage : Formater toutes les erreurs API de manière cohérente avec des codes d'erreur et messages standardises.
Adaptateur @nestjs/platform-fastify qui remplace Express comme serveur HTTP sous-jacent de NestJS. Fastify affiche des performances proches du double d'Express sur les benchmarks officiels, au prix de quelques incompatibilités avec les middlewares et recettes écrits spécifiquement pour Express.
Comme changer le moteur d'une voiture en gardant la carrosserie : même API NestJS en surface, machinerie HTTP bien plus rapide dessous.
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
// Fastify n'ecoute que localhost par defaut
await app.listen(3000, '0.0.0.0');Cas d'usage : Maximiser le throughput HTTP d'une API NestJS a forte charge sans changer le code métier.
Fonction utilitaire qui résout les dépendances circulaires en retardant la résolution de la référence. Utilise un wrapper de fonction pour différer l'évaluation.
Comme dire 'je te présenterai mon collègué quand il arrivera' plutôt que d'exiger sa présence immédiate.
@Injectable()
export class CatService {
constructor(
@Inject(forwardRef(() => DogService))
private dogService: DogService,
) {}
}Cas d'usage : Résoudre les dépendances circulaires entre deux services ou modules qui se réfèrent mutuellement.
Module décoré avec @Global() dont les providers sont accessibles dans toute l'application sans import explicite. A utiliser avec parcimonie.
Comme le WiFi dans un hôtel : disponible partout sans avoir a le demander a chaque étage.
@Global()
@Module({
providers: [ConfigService],
exports: [ConfigService],
})
export class ConfigModule {}Cas d'usage : Exposer des services transversaux comme la configuration ou le logging sans imports répétitifs.
Décorateur pour définir des abonnements temps réel via WebSocket dans GraphQL. Permet au client de recevoir des mises a jour en push.
Comme un flux d'actualités en direct : tu t'abonnes une fois et les nouvelles arrivent automatiquement.
@Subscription(() => Comment, {
filter: (payload, variables) =>
payload.commentAdded.postId === variables.postId,
})
commentAdded(@Args('postId') postId: string) {
return this.pubSub.asyncIterator('commentAdded');
}Cas d'usage : Implémenter des notifications temps réel comme les nouveaux commentaires ou messages.
Classe décorée @Resolver qui définit les opérations GraphQL (queries, mutations, subscriptions) en approche code-first avec des décorateurs TypeScript.
Comme un serveur de restaurant avec un menu a la carte : le client choisit exactement ce qu'il veut recevoir.
@Resolver(() => User)
export class UserResolver {
constructor(private userService: UserService) {}
@Query(() => [User])
users() { return this.userService.findAll(); }
@Mutation(() => User)
createUser(@Args('input') input: CreateUserInput) {
return this.userService.create(input);
}
}Cas d'usage : Exposer une API GraphQL code-first avec typage automatique du schema depuis TypeScript.
Framework RPC haute performance utilisant Protocol Buffers et HTTP/2. NestJS supporte gRPC comme transport pour les microservices.
Comme un langage signe standardise entre machines : ultra-rapide et compact, mais moins lisible pour les humains.
@GrpcMethod('UserService', 'FindOne')
findOne(data: { id: number }): User {
return this.userService.findOne(data.id);
}
// .proto: service UserService {
// rpc FindOne (UserById) returns (User);
// }Cas d'usage : Communiquer entre microservices avec des performances supérieures a REST et un contrat strict.
Classe @Injectable implémentant CanActivate qui décide si une requête peut continuer. Idéal pour l'authentification et l'autorisation.
Comme un videur de boite de nuit : il vérifie si tu as le droit d'entrer avant de te laisser passer.
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return !!request.headers.authorization;
}
}Cas d'usage : Protéger des routes avec authentification JWT, vérifier les roles RBAC ou valider des permissions.
Middleware qui sécurise les headers HTTP (X-Frame-Options, CSP, HSTS, etc.). Protège contre les attaques web courantes comme le clickjacking.
Comme un casque de moto : protection basique mais indispensable contre les dangers les plus courants.
// main.ts
import helmet from 'helmet';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(helmet());
await app.listen(3000);
}Cas d'usage : Ajouter les headers de sécurité HTTP standard a toute API NestJS en production.
Application NestJS qui combine un serveur HTTP et un ou plusieurs microservices dans le même processus. Écoûte sur plusieurs transports simultanément.
Comme un restaurant avec salle et livraison : le même service cuisine mais répond a deux canaux différents.
const app = await NestFactory.create(AppModule);
app.connectMicroservice({ transport: Transport.REDIS,
options: { host: 'localhost', port: 6379 } });
await app.startAllMicroservices();
await app.listen(3000);Cas d'usage : Migrer progressivement vers une architecture microservices en gardant l'API HTTP existante.
Définit le cycle de vie d'un provider : DEFAULT (singleton), REQUEST (par requête) ou TRANSIENT (nouvelle instance a chaque injection).
Comme un bureau : partage (singleton), un par client (request) ou jetable après chaque usage (transient).
@Injectable({ scope: Scope.REQUEST })
export class RequestLogger {
private requestId = randomUUID();
log(msg: string) {
console.log(`[${this.requestId}] ${msg}`);
}
}Cas d'usage : Utiliser REQUEST scope pour des services qui doivent stocker des données spécifiques a chaque requête.
Classe implémentant NestInterceptor qui enveloppe l'exécution du handler via RxJS. Peut transformer la réponse, ajouter du logging ou gérer le cache.
Comme un emballeur cadeau : le produit (réponse) passe par lui avant et après pour être transforme.
@Injectable()
export class TransformInterceptor implements NestInterceptor {
intercept(ctx: ExecutionContext, next: CallHandler) {
return next.handle().pipe(
map(data => ({ data, timestamp: Date.now() })),
);
}
}Cas d'usage : Wrapper toutes les réponses dans un format standard, mesurer le temps de réponse ou implémenter du cache.
Classe de base exportée par @nestjs/common dont hérité HttpException. Les filtres d'exception integres de NestJS ne loguent jamais une instance d'IntrinsicException, ce qui permet de distinguer les erreurs attendues (partie du flux normal) des erreurs inattendues qui méritent d'être remontées.
Comme un videur qui laisse entrer sans alerte les habitues sur liste (exceptions normales) mais déclenche l'alarme pour un inconnu (erreur réelle).
export class OutOfStockException extends HttpException {
constructor() {
super('Produit epuise', HttpStatus.CONFLICT);
}
}
// Herite d'IntrinsicException via HttpException :
// jamais loguee comme une erreur critiqueCas d'usage : Éviter de polluer les logs d'erreurs avec des exceptions métier attendues (stock épuisé, validation refusée).
Le conteneur d'Inversion de Contrôle de NestJS qui gère la création, la résolution et le cycle de vie de tous les providers enregistres.
Comme un annuaire professionnel : tu demandes un plombier et l'annuaire te fournit le bon contact.
// NestJS resout automatiquement le graphe de dependances
// UserController -> UserService -> UserRepository
// Il suffit de declarer les types dans le constructeur
@Injectable()
export class UserService {
constructor(private repo: UserRepository) {}
}Cas d'usage : Laisser le framework gérer la création et l'injection de toutes les instances de l'application.
Le ConsoleLogger de NestJS peut émettre des logs structures en JSON via l'option json: true passée a son constructeur ou a NestFactory.create(). Chaque ligne devient un objet JSON exploitable par des agregateurs comme Datadog ou Elasticsearch, la colorisation étant désactivée automatiquement pour garder un JSON valide.
Comme remplacer un rapport manuscrit par un formulaire a cases : chaque champ (niveau, message, contexte) est identifiable sans relecture humaine.
const app = await NestFactory.create(AppModule, {
logger: new ConsoleLogger({ json: true }),
});
// Sortie :
// {"level":"log","pid":123,"timestamp":169...,
// "message":"Starting Nest application...","context":"NestFactory"}Cas d'usage : Envoyer les logs applicatifs vers un système d'observabilite (CloudWatch, Datadog, ELK) sans parser du texte libre.
Stratégie Passport qui valide les tokens JWT extraits du header Authorization. Décodé le payload et l'attache a request.user.
Comme un scanner de badge électronique : il lit le badge (token), vérifié sa validité et identifie la personne.
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(config: ConfigService) {
super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: config.get('JWT_SECRET') });
}
validate(payload: any) { return { id: payload.sub, email: payload.email }; }
}Cas d'usage : Protéger les endpoints API avec authentification stateless par token JWT.
Transporteur de microservices NestJS base sur kafkajs, configure via Transport.KAFKA. Il expose ClientKafkaProxy pour producteur/consommateur, gère automatiquement les topics de réponse (suffixe .reply) et, depuis NestJS v12, accepte des expressions régulières dans @MessagePattern/@EventPattern pour matcher plusieurs topics.
Comme un central téléphonique qui route les appels (messages) vers le bon service selon le numéro compose (topic), avec la possibilité d'écoûter tout un groupe de numéros a la fois (regex).
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.KAFKA,
options: { client: { brokers: ['localhost:9092'] } },
});
@MessagePattern('orders.created')
handleOrder(@Payload() data: any, @Ctx() ctx: KafkaContext) {
const { topic, partition } = ctx.getMessage();
}Cas d'usage : Faire communiquer des microservices via un bus Kafka haute-throughput avec garanties de partitionnement.
Interfaces (OnModuleInit, OnModuleDestroy, OnApplicationBootstrap, OnApplicationShutdown) qui permettent d'exécuter du code a des moments clés du cycle de vie.
Comme les étapes d'ouverture et fermeture d'un magasin : mise en place le matin, rangement le soir.
@Injectable()
export class DbService implements OnModuleInit, OnModuleDestroy {
async onModuleInit() {
await this.connect();
}
async onModuleDestroy() {
await this.disconnect();
}
}Cas d'usage : Initialiser des connexions base de données au démarrage et les fermer proprement a l'arrêt.
Stratégie Passport qui authentifie via email/mot de passe. Valide les credentials contre la base de données et retourne l'utilisateur.
Comme présenter sa carte d'identité et son mot de passe a un guichet pour prouver son identité.
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) { super(); }
async validate(username: string, password: string) {
const user = await this.authService.validateUser(username, password);
if (!user) throw new UnauthorizedException();
return user;
}
}Cas d'usage : Implémenter le login classique par email et mot de passe avant d'émettre un JWT.
@MessagePattern attend une réponse (request-reply) tandis que @EventPattern est fire-and-forget (event-based). Deux paradigmes de communication inter-services.
Comme envoyer un recommande avec accuse de réception (message) vs jeter une bouteille a la mer (event).
// Request-reply: l'appelant attend une reponse
@MessagePattern('get_user')
getUser(data: { id: number }) {
return this.userService.findOne(data.id);
}
// Fire-and-forget: pas de reponse attendue
@EventPattern('user_created')
handleUserCreated(data: UserCreatedEvent) {
this.emailService.sendWelcome(data.email);
}Cas d'usage : Utiliser MessagePattern pour les queries et EventPattern pour les notifications asynchrones.
Fonction ou classe exécutée avant le route handler, avec accès a request, response et next(). Compatible avec les middlewares Express/Fastify.
Comme un agent de sécurité a l'entrée d'un immeuble : il vérifie ton badge avant de te laisser monter.
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`${req.method} ${req.url}`);
next();
}
}Cas d'usage : Logger les requêtes, parser des headers custom ou modifier la requête avant qu'elle atteigne le controller.
Classe annotée @Module qui organise l'application en blocs fonctionnels cohesifs. Chaque module déclaré ses controllers, providers, imports et exports.
Comme un département dans une entreprise : chaque département a ses employés, ses outils et ses responsabilités bien définies.
@Module({
imports: [DatabaseModule],
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}Cas d'usage : Structurer chaque domaine métier en module dédié pour maintenir la séparation des responsabilités.
Interface pour interagir avec une collection MongoDB, injectée via @InjectModel. Fournit les méthodes CRUD (find, create, updateOne, deleteMany).
Comme un guichet dédié a une collection : il sait lire, écrire et supprimer les documents de sa collection.
@Injectable()
export class CatService {
constructor(
@InjectModel(Cat.name) private catModel: Model<Cat>,
) {}
create(dto: CreateCatDto) {
return new this.catModel(dto).save();
}
}Cas d'usage : Effectuer les opérations CRUD sur les collections MongoDB dans un service NestJS.
Mécanisme pour charger automatiquement les documents références depuis d'autres collections. Équivalent des jointures SQL pour MongoDB.
Comme des liens hypertexte dans un document : cliquer dessus charge le contenu référence.
async findWithOwner(id: string) {
return this.catModel
.findById(id)
.populate('owner')
.exec();
}Cas d'usage : Charger les documents lies sans faire plusieurs requêtes manuelles.
Définition de la structure d'un document MongoDB via @Schema et @Prop de @nestjs/mongoose. Génère le schema Mongoose a partir des décorateurs TypeScript.
Comme un formulaire avec des champs obligatoires et optionnels : il définit ce qu'un document doit contenir.
@Schema({ timestamps: true })
export class Cat {
@Prop({ required: true })
name: string;
@Prop()
age: number;
@Prop({ type: Types.ObjectId, ref: 'Owner' })
owner: Owner;
}Cas d'usage : Définir la structure des documents MongoDB avec validation et typage TypeScript.
Transporteur de microservices NestJS pour NATS, migre depuis NestJS v12 vers le driver @nats-io/transport-node (NATS v3). Il supporte les queue groups pour repartir la charge entre instances et les wildcards de sujets (par exemple time.us.*) pour matcher des patterns dynamiques.
Comme une bande FM : plusieurs récepteurs (queue group) peuvent écoûter la même fréquence (sujet) et se partager les messages sans double réception.
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.NATS,
options: { servers: ['nats://localhost:4222'], queue: 'orders_queue' },
});
@MessagePattern('time.us.*')
handleTime(@Payload() data: any) { /* wildcard */ }Cas d'usage : Repartir la charge entre plusieurs instances d'un même microservice via un queue group NATS.
Outil officiel (@nestjs/devtools-intégration) qui visualise en temps réel le graphe de dépendances d'une application NestJS : modules, providers, controllers et routes HTTP/WebSocket/gRPC/GraphQL. Il expose aussi une analyse du temps de bootstrap et un playground pour exécuter du code contre l'application.
Comme un plan de métro interactif de ton application : chaque station (module) et chaque ligne (dépendance) entre elles est visible.
// main.ts
const app = await NestFactory.create(AppModule, { snapshot: true });
// app.module.ts
@Module({
imports: [DevtoolsModule.register({
http: process.env.NODE_ENV !== 'production',
})],
})
export class AppModule {}Cas d'usage : Diagnostiquer un cycle de dépendances ou un bootstrap lent en visualisant le graphe réel de l'application.
Stratégie Passport pour l'authentification via providers tiers (Google, GitHub, Facebook). Gère le flow d'autorisation OAuth2 avec callback.
Comme se connecter a un hôtel avec sa carte de membre d'une chaîne : un tiers de confiance confirme ton identité.
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor(cfg: ConfigService) {
super({ clientID: cfg.get('GOOGLE_ID'),
clientSecret: cfg.get('GOOGLE_SECRET'),
callbackURL: '/auth/google/callback',
scope: ['email', 'profile'] });
}
validate(token, refresh, profile) { return profile; }
}Cas d'usage : Proposer le 'Login with Google/GitHub' pour simplifier l'onboarding utilisateur.
Dépendances marquées @Optional() qui ne causent pas d'erreur si elles ne sont pas enregistrées. Le provider reçoit undefined si absent.
Comme commander un burger avec 'fromage en option' : si y'en a pas, tu reçois quand même ton burger.
@Injectable()
export class NotificationService {
constructor(
@Optional() @Inject('SMS_SERVICE')
private sms?: SmsService,
) {}
}Cas d'usage : Implémenter des fonctionnalités optionnelles comme les notifications SMS qui ne sont pas toujours configurées.
Méthode du TestingModule pour remplacer un guard par une implémentation permissive dans les tests. Permet de tester les handlers sans authentification.
Comme désactiver le badge d'accès pendant les tests incendie pour que tout le monde puisse circuler.
const module = await Test.createTestingModule({
imports: [AppModule],
}).overrideGuard(AuthGuard)
.useValue({ canActivate: () => true })
.compile();Cas d'usage : Tester les endpoints proteges sans avoir a générer de vrais tokens JWT.
Méthode du TestingModule pour remplacer un provider par un mock ou une implémentation alternative dans les tests.
Comme remplacer un acteur par sa doublure pour une scène dangereuse : le role est le même, l'implémentation change.
const module = await Test.createTestingModule({
imports: [UserModule],
}).overrideProvider(UserService)
.useValue({ findAll: jest.fn().mockResolvedValue([]) })
.compile();Cas d'usage : Mocker les services de base de données ou les APIs externes dans les tests d'intégration.
Pattern pour retourner les résultats par pages via offset/limit ou cursor-based. Évite de charger des milliers d'enregistrements en une seule requête.
Comme un livre avec des pages : tu lis page par page au lieu de tout le livre d'un coup.
async findAll(page = 1, limit = 10) {
const [items, total] = await this.repo.findAndCount({
skip: (page - 1) * limit,
take: limit,
});
return { items, total, page, lastPage: Math.ceil(total / limit) };
}Cas d'usage : Toute API de liste doit être paginée pour éviter les réponses massives et les timeouts.
Librairie d'authentification intégrée via @nestjs/passport. Fournit un système de stratégies (JWT, Local, OAuth2) avec des guards dedies.
Comme un système de vérification d'identité multi-documents : passeport, carte d'identité ou badge selon le contexte.
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
@Controller('profile')
export class ProfileController {
@UseGuards(JwtAuthGuard)
@Get()
getProfile(@Request() req) { return req.user; }
}Cas d'usage : Implémenter l'authentification avec support multi-stratégies dans une API NestJS.
Classe implémentant PipeTransform qui valide ou transforme les données entrantes avant qu'elles atteignent le handler. Fonctionne avec class-validator.
Comme un filtre a eau : l'eau (données) passe a travers et seule l'eau propre (valide) continue.
@Injectable()
export class ParseIntPipe implements PipeTransform {
transform(value: string): number {
const val = parseInt(value, 10);
if (isNaN(val)) throw new BadRequestException('Not a number');
return val;
}
}Cas d'usage : Valider les DTOs entrants avec class-validator ou transformer les paramètrès de route.
Méthode de Prisma Client pour exécuter plusieurs opérations en transaction atomique. Supporte le mode batch (tableau) et le mode interactif (callback).
Comme un contrat notarié : toutes les clauses s'appliquent ensemble ou le contrat est annule.
await this.prisma.$transaction(async (tx) => {
const user = await tx.user.create({ data: userData });
await tx.account.create({
data: { userId: user.id, balance: 0 },
});
});Cas d'usage : Garantir l'atomicité lors de la création d'entités liées comme user + compte.
Client auto-génère et type-safe pour interagir avec la base de données. Fournit une API fluide avec autocompletion complète en TypeScript.
Comme un assistant personnel qui connaît parfaitement ta base de données et te corrige en temps réel.
@Injectable()
export class UserService {
constructor(private prisma: PrismaService) {}
findAll() {
return this.prisma.user.findMany({
include: { posts: true },
});
}
}Cas d'usage : Effectuer des requêtes type-safe avec autocompletion et validation au compile-time.
Système de migration génère automatiquement a partir des changements du schema Prisma. Créé des fichiers SQL versiones pour chaque modification.
Comme un photographe qui capture chaque modification de la maison pour pouvoir les rejouer ou annuler.
// Terminal
// npx prisma migrate dev --name add-user-role
// Genere: migrations/20240101_add_user_role/migration.sql
// ALTER TABLE "User" ADD COLUMN "role" TEXT DEFAULT 'user';Cas d'usage : Versionner et déployer les changements de schema en production avec Prisma.
Fichier schema.prisma qui définit les modèles, relations et source de données en SDL (Schema Définition Language). Génère le client type-safe.
Comme un plan de construction : tu dessines la structure et Prisma génère toute la plomberie automatiquement.
// schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorId], references: [id])
authorId Int
}Cas d'usage : Définir le schema de données de façon déclarative et générer un client ORM type-safe.
Toute classe injectable dans le système DI de NestJS via @Injectable. Les services, repositories, factories et helpers sont tous des providers.
Comme un artisan dans une coopérative : il offre ses compétences et peut être appelé par quiconque en a besoin.
@Injectable()
export class LoggerService {
log(message: string) {
console.log(`[LOG] ${message}`);
}
}Cas d'usage : Encapsuler la logique métier, l'accès aux données ou tout service réutilisable dans l'application.
Mécanisme qui limite le nombre de requêtes par client dans une fenêtre de temps. Implémentable via @nestjs/throttler pour protéger contre les abus.
Comme un portillon de métro : il ne laisse passer qu'un certain nombre de personnes par minute.
@Module({
imports: [ThrottlerModule.forRoot([{
ttl: 60000,
limit: 10,
}])],
})
export class AppModule {}
@UseGuards(ThrottlerGuard)
@Controller('auth')
export class AuthController {}Cas d'usage : Protéger les endpoints de login ou d'API publique contre le brute force et les abus.
Role-Based Access Control : système d'autorisation ou les permissions sont attribuées a des roles (admin, user, editor) plutôt qu'a des individus.
Comme les clés d'un immeuble : le gardien a le passe-partout, les résidents ont la clé de leur étage.
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(ctx: ExecutionContext) {
const roles = this.reflector.get<string[]>('roles', ctx.getHandler());
if (!roles) return true;
const user = ctx.switchToHttp().getRequest().user;
return roles.includes(user.role);
}
}Cas d'usage : Restreindre l'accès aux endpoints admin ou modérateur selon le role de l'utilisateur.
Data Transfer Object : classe qui définit la structure des données entrantes/sortantes. Utilisée avec class-validator pour la validation automatique.
Comme un formulaire officiel : il définit les champs attendus et rejette les soumissions invalides.
export class CreateUserDto {
@IsEmail()
email: string;
@IsString()
@MinLength(8)
password: string;
@IsOptional()
@IsString()
name?: string;
}Cas d'usage : Valider et typer les données entrantes de l'API avant qu'elles atteignent la logique métier.
Module pour planifier des taches périodiques via des décorateurs cron (@Cron), interval (@Interval) ou timeout (@Timeout).
Comme un réveil programme : il exécute automatiquement des actions a des heures définies.
@Injectable()
export class TaskService {
@Cron('0 0 * * *') // Chaque jour a minuit
async dailyCleanup() {
await this.sessionService.deleteExpired();
}
@Interval(30000) // Toutes les 30 secondes
checkHealth() { this.logger.log('Health check'); }
}Cas d'usage : Exécuter des taches de maintenance comme le nettoyage de sessions expirées ou l'envoi de rapports.
Processus de remplissage de la base de données avec des données initiales ou de test. Exécuté via des scripts ou des modules dedies au démarrage.
Comme meubler un appartement témoin : tu prepares des données de demo pour que tout soit fonctionnel.
@Injectable()
export class SeedService implements OnModuleInit {
constructor(private userService: UserService) {}
async onModuleInit() {
const count = await this.userService.count();
if (count === 0) {
await this.userService.create({ email: '[email protected]', role: 'admin' });
}
}
}Cas d'usage : Initialiser les roles, permissions ou comptes admin lors du premier déploiement.
Transformation des objets en réponse JSON via ClassSerializerInterceptor et class-transformer. Permet d'exclure des champs sensibles avec @Exclude.
Comme un filtre photo qui masque les informations sensibles avant de publier.
export class UserEntity {
id: number;
email: string;
@Exclude()
password: string;
constructor(partial: Partial<UserEntity>) {
Object.assign(this, partial);
}
}Cas d'usage : Masquer les mots de passe, tokens internes et données sensibles des réponses API.
Provider dédié a la logique métier, annote @Injectable. Il encapsulé les opérations de domaine et est injecte dans les controllers ou autres services.
Comme le chef cuisinier d'un restaurant : le serveur (controller) prend la commande mais c'est le chef qui cuisine.
@Injectable()
export class UserService {
constructor(private repo: UserRepository) {}
async findAll(): Promise<User[]> {
return this.repo.find();
}
}Cas d'usage : Centraliser la logique métier pour qu'elle soit testable indépendamment des controllers.
Server-Sent Events : protocole HTTP unidirectionnel du serveur vers le client. Plus simple que WebSocket quand le flux est unidirectionnel.
Comme une radio : le serveur diffuse et les clients écoûtent, sans possibilité de répondre via le même canal.
@Controller('events')
export class EventController {
@Sse('stream')
stream(): Observable<MessageEvent> {
return interval(1000).pipe(
map(i => ({ data: { count: i } } as MessageEvent)),
);
}
}Cas d'usage : Streamer des mises a jour de progression, logs temps réel ou notifications sans WebSocket.
Depuis NestJS 12.0.0 (27 août 2026), les décorateurs @Body(), @Query(), @Param() et @RawBody() acceptent une option schema compatible avec la spécification Standard Schema (Zod, Valibot, ArkType). Le StandardSchemaValidationPipe valide la charge utile contre ce schema, en parallèle du flux historique class-validator qui reste entièrement supporte.
Comme accepter un badge d'accès différent (RFID, QR code) au même portique : plusieurs formats de validation cohabitent sans casser l'existant.
@Post()
create(@Body({ schema: createUserSchema }) body: CreateUserDto) {
return this.usersService.create(body);
}
// Activation globale du pipe
app.useGlobalPipes(new StandardSchemaValidationPipe());Cas d'usage : Valider les requêtes avec des schémas Zod/Valibot déjà utilises cote frontend, sans réécrire des DTO class-validator.
Module @nestjs/swagger qui génère automatiquement la documentation API OpenAPI a partir des décorateurs, DTOs et controllers. Depuis la version 12.0.0 (27 août 2026, alignée sur NestJS 12), le module est publie en ESM natif et peut refléter des schémas Standard Schema (Zod, Valibot) dans le document OpenAPI via l'option standardSchemaConverter, en plus du flux class-validator historique qui reste entièrement supporte.
Comme un menu de restaurant génère automatiquement a partir des plats disponibles en cuisine.
const config = new DocumentBuilder()
.setTitle('My API')
.setVersion('1.0')
.addBearerAuth()
.build();
const doc = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, doc);Cas d'usage : Fournir une documentation API interactive et toujours a jour pour les développeurs frontend.
Module de health checks via @nestjs/terminus. Expose un endpoint /health qui vérifie la base de données, Redis, disque et services externes. HealthCheckService peut renvoyer un statut dégrade (degraded) en plus de ok/error ; chaque indicateur peut être borne dans le temps avec withTimeout() ou mis en cache avec cacheFor(), et gracefulShutdownTimeoutMs pilote l'arrêt propre sous un orchestrateur comme Kubernetes.
Comme un bilan de santé : le médecin vérifié chaque organe et donne un bulletin de santé global.
@Controller('health')
export class HealthController {
constructor(private health: HealthCheckService,
private db: TypeOrmHealthIndicator) {}
@Get()
check() {
return this.health.check([
() => this.db.pingCheck('database'),
]);
}
}Cas d'usage : Fournir un endpoint de santé pour les load balancers et orchestrateurs comme Kubernetes.
Couche d'abstraction de NestJS pour la communication entre microservices. Supporte TCP, Redis, NATS, MQTT, RabbitMQ, Kafka et gRPC. Depuis NestJS v12, le transporteur Kafka accepte des expressions régulières dans @MessagePattern/@EventPattern pour matcher plusieurs topics d'un coup, et le transporteur NATS a migre vers le driver @nats-io/transport-node cible sur NATS v3.
Comme choisir entre la poste, le coursier ou le mail : le message est le même, seul le moyen de transport change.
// main.ts
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.REDIS,
options: { host: 'localhost', port: 6379 },
});
await app.listen();Cas d'usage : Connecter des microservices NestJS via différents brokers de messages selon les besoins.
Classe décorée @Entity qui représente une table de base de données. Chaque propriété décorée (@Column, @PrimaryGeneratedColumn) correspond a une colonne.
Comme un plan d'architecte : il décrit la structure exacte de la table a construire.
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column({ default: true })
isActive: boolean;
}Cas d'usage : Définir le schema de la base de données directement dans le code TypeScript avec TypeORM.
Fichier versionne qui décrit les modifications de schema de base de données (up/down). Permet de gérer l'évolution du schema de façon reproductible.
Comme un historique Git mais pour la structure de ta base de données.
export class AddUserAge1234567890 implements MigrationInterface {
async up(qr: QueryRunner) {
await qr.addColumn('user',
new TableColumn({ name: 'age', type: 'int', isNullable: true }));
}
async down(qr: QueryRunner) {
await qr.dropColumn('user', 'age');
}
}Cas d'usage : Déployer des changements de schema en production de manière sécurisée et réversible.
API fluide pour construire des requêtes SQL complexes avec TypeORM. Supporte les jointures, sous-requêtes, groupements et requêtes paginée.
Comme assembler une requête en Lego : tu ajoutes chaque pièce (clause) une par une pour construire la requête finale.
const users = await this.repo
.createQueryBuilder('user')
.leftJoinAndSelect('user.orders', 'order')
.where('user.isActive = :active', { active: true })
.orderBy('user.createdAt', 'DESC')
.take(10)
.getMany();Cas d'usage : Construire des requêtes complexes avec jointures, filtres dynamiques et pagination.
Décorateurs (@OneToMany, @ManyToOne, @ManyToMany, @OneToOne) qui définissent les relations entre entités. Permettent le chargement eager ou lazy.
Comme les liens de parente dans un arbre généalogique : chaque relation a un type et une direction.
@Entity()
export class User {
@OneToMany(() => Order, order => order.user)
orders: Order[];
}
@Entity()
export class Order {
@ManyToOne(() => User, user => user.orders)
user: User;
}Cas d'usage : Modéliser les associations entre tables et naviguer le graphe d'objets en TypeScript.
Pattern d'accès aux données qui fournit des méthodes CRUD (find, save, delete) pour une entité. Injecte via @InjectRepository dans les services.
Comme un bibliothécaire spécialisé : il sait exactement comment chercher, ranger et prêter les livres de sa section.
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private repo: Repository<User>,
) {}
findAll() { return this.repo.find(); }
}Cas d'usage : Effectuer les opérations CRUD sur les entités sans écrire de SQL brut.
Mécanisme pour exécuter plusieurs opérations de base de données de façon atomique. Soit toutes réussissent, soit toutes sont annulées.
Comme un virement bancaire : le débit ET le crédit doivent passer ensemble, sinon rien ne bouge.
async transfer(from: string, to: string, amount: number) {
await this.dataSource.transaction(async (manager) => {
await manager.decrement(Account, { id: from }, 'balance', amount);
await manager.increment(Account, { id: to }, 'balance', amount);
});
}Cas d'usage : Garantir la cohérence des données lors d'opérations multi-tables comme les paiements.
Système de versioning d'API intégré supportant URI (/v1/), header, média type et custom. Permet d'évoluer l'API sans casser les clients existants.
Comme les éditions d'un livre : la v2 existe mais la v1 reste disponible pour ceux qui l'utilisent.
app.enableVersioning({ type: VersioningType.URI });
@Controller({ path: 'users', version: '1' })
export class UserV1Controller {}
@Controller({ path: 'users', version: '2' })
export class UserV2Controller {}Cas d'usage : Maintenir la retrocompatibilite tout en déployant de nouvelles versions d'endpoints.
Classe décorée @WebSocketGateway qui gère les connexions WebSocket bidirectionnelles. Utilise Socket.IO ou ws pour la communication temps réel.
Comme un talkie-walkie : la communication est instantanée dans les deux sens, sans besoin de 'rappeler'.
@WebSocketGateway({ cors: true })
export class ChatGateway {
@WebSocketServer() server: Server;
@SubscribeMessage('message')
handleMessage(@MessageBody() data: string) {
this.server.emit('message', data);
}
}Cas d'usage : Implémenter un chat en temps réel, des notifications push ou un tableau de bord live.