NestJS 93 termes

93 termes affichés

TypeConcept Method Pattern Principle Security Tool
Niveau 🟢 Junior 🟡 Mid 🔴 Senior

Mis à jour ces 90 derniers jours 10 nouvelles · 50 révisées

@Body

NestJS 🟢 Junior? entretien

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.

#core#interview#nest12

@Get/@Post/@Put/@Delete/@Patch

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Utiliser @Post pour des opérations de lecture ou @Get avec un body de requête.
#core#interview

@Headers

NestJS 🟢 Junior

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.

#core

@Inject

NestJS 🟡 Mid

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.

#core

@Injectable

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Oublier @Injectable sur un service qui injecte d'autres dépendances, causant une erreur runtime.
#core#interview

@Param

NestJS 🟢 Junior

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.

#core

@Query

NestJS 🟢 Junior

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.

#core

@SetMetadata

NestJS 🟡 Mid

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.

#core#security

@UseFilters

NestJS 🟡 Mid

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.

#core

@UseGuards

NestJS 🟡 Mid

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.

#core#security

@UseInterceptors

NestJS 🟡 Mid

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.

#core

@UsePipes

NestJS 🟡 Mid

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.

#core

ABAC

NestJS 🔴 Senior

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'.

#security

BullModule

NestJS 🟡 Mid

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.

Anti-pattern : Traiter des taches longues de façon synchrone dans le request handler, bloquant la réponse.
#core

CacheModule

NestJS 🟡 Mid

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.

Anti-pattern : Cacher des données sensibles ou mutables sans stratégie d'invalidation.
#core#keyv

CASL

NestJS 🔴 Senior

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/false

Cas d'usage : Gérer des permissions granulaires avec des conditions sur les champs des entités.

#security

Circular Dependency

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Accepter les dépendances circulaires comme normales au lieu de repenser l'architecture.
#core#interview

ClientProxy

NestJS 🔴 Senior

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é.

#architecture

ConfigModule

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Accéder directement a process.env partout au lieu d'utiliser ConfigService.
#core#interview

Connection Pooling

NestJS 🔴 Senior? entretien

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.

Anti-pattern : Créer une nouvelle connexion a chaque requête sans pool, saturant la base de données.
#database#interview

Controller

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Mettre de la logique métier dans le controller au lieu de la déléguer au service.
#core#interview

Cookies natifs (adapter-agnostic)

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Garder cookie-parser installe en double alors que le support natif suffit, source de conflits de headers.
#core#nest12#interview

CORS

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Configurer origin: '*' avec credentials: true, ce qui est interdit par les navigateurs et insecurise.
#security#interview

CQRS Module

NestJS 🔴 Senior? entretien

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).

Anti-pattern : Appliquer CQRS et des sagas a un CRUD simple, ajoutant de la complexité sans bénéfice réel.
#architecture#interview

createTestingModule

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Tester les services sans TestingModule, instanciant manuellement avec new et perdant la DI.
#testing#interview

CSRF

NestJS 🟡 Mid

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 mutation

Cas d'usage : Protéger les applications avec sessions/cookies contre les requêtes forgées.

Anti-pattern : Désactiver la protection CSRF sur les endpoints de mutation par facilite.
#security

Custom Decorator

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Accéder a request.user directement partout au lieu de créer un décorateur réutilisable.
#core#interview

Custom Providers

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Accéder directement a process.env dans les services au lieu d'injecter la configuration.
#core#interview

DataLoader

NestJS 🔴 Senior? entretien

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.

Anti-pattern : Charger les relations une par une dans chaque resolver sans DataLoader.
#communication#interview

Dependency Injection

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Instancier les dépendances avec new directement dans la classe au lieu de les injecter.
#core#interview#architecture

Drizzle ORM (integration officielle)

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Répliquer le pattern forFeature() de TypeORM avec Drizzle, qui n'en a pas besoin.
#core#interview

Dynamic Module

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Hardcoder la configuration directement dans le module au lieu de la rendre injectable.
#core#architecture#interview

E2E supertest

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Ne tester que les services unitairement sans jamais vérifier le pipeline HTTP complet.
#testing#interview

EventEmitterModule

NestJS 🟡 Mid

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.

Anti-pattern : Utiliser des appels directs entre services pour des side-effects au lieu d'evenements.
#core#architecture

Exception Filter

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Entourer chaque handler de try/catch au lieu d'utiliser un filtre d'exception global.
#core#interview

FastifyAdapter

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Migrer vers Fastify en gardant des recettes ou middlewares spécifiques a Express sans vérifier leur compatibilité.
#core#interview

forwardRef

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Utiliser forwardRef comme solution par défaut au lieu de repenser l'architecture pour éliminer les cycles.
#core#interview

Global Module

NestJS 🟢 Junior

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.

Anti-pattern : Rendre tous les modules globaux, ce qui détruit l'encapsulation et rend les dépendances implicites.
#core#architecture

GraphQL @Subscription

NestJS 🔴 Senior

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.

#communication

GraphQL Resolver

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Mettre de la logique métier dans le resolver au lieu de la déléguer au service.
#communication#interview

gRPC

NestJS 🔴 Senior

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.

Anti-pattern : Utiliser gRPC pour une API publique consommée par des navigateurs au lieu de REST/GraphQL.
#communication#architecture

Guard

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Vérifier l'authentification dans chaque controller au lieu d'utiliser un guard réutilisable.
#core#security#interview

Helmet

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Déployer en production sans Helmet, laissant les headers de sécurité absents.
#security#interview

Hybrid Application

NestJS 🔴 Senior

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.

#architecture

Injection Scopes

NestJS 🔴 Senior? entretien

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.

Anti-pattern : Utiliser REQUEST scope partout, ce qui désactive le singleton et dégrade les performances.
#core#interview

Interceptor

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Utiliser un interceptor pour de la validation de données au lieu d'un pipe.
#core#interview

IntrinsicException

NestJS 🔴 Senior? entretien

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 critique

Cas d'usage : Éviter de polluer les logs d'erreurs avec des exceptions métier attendues (stock épuisé, validation refusée).

Anti-pattern : Étendre Error directement pour une exception métier attendue, qui sera alors loguee comme une vraie erreur.
#core#interview

IoC Container

NestJS 🟡 Mid? entretien

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.

#core#architecture#interview

JSON Logger

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Garder le format texte colore en production, ce qui oblige les agregateurs a parser des chaînés non structurées.
#core#nest12#interview

JWT Strategy

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Stocker des données sensibles (mot de passe, carte) dans le payload JWT.
#security#interview

Kafka Transporter

NestJS 🔴 Senior? entretien

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.

Anti-pattern : Utiliser @MessagePattern (request-reply) pour de gros volumes d'evenements fire-and-forget au lieu de @EventPattern.
#architecture#interview

Lifecycle Hooks

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Initialiser des ressources dans le constructeur au lieu de onModuleInit, bloquant la DI.
#core#interview

Local Strategy

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Comparer les mots de passe en clair au lieu d'utiliser bcrypt.
#security#interview

MessagePattern vs EventPattern

NestJS 🔴 Senior? entretien

@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.

Anti-pattern : Utiliser MessagePattern pour des events qui ne nécessitent pas de réponse, bloquant inutilement.
#architecture#interview

Middleware

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Utiliser un middleware pour de la logique métier spécifique a une route au lieu d'un interceptor ou guard.
#core#interview

Module

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Mettre tous les providers dans AppModule au lieu de les repartir en modules fonctionnels.
#core#architecture#interview

Mongoose Model

NestJS 🟡 Mid

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.

#database

Mongoose Population

NestJS 🟡 Mid

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.

Anti-pattern : Populer toutes les références par défaut, causant des requêtes excessives sur les grandes collections.
#database

Mongoose Schema

NestJS 🟡 Mid

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.

Anti-pattern : Stocker des documents sans schema défini, rendant les données incohérentes.
#database

NATS Transporter

NestJS 🔴 Senior? entretien

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.

Anti-pattern : Oublier gracefulShutdown/gracePeriod, coupant des messages en cours lors d'un redéploiement.
#architecture#interview

Nest Devtools

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Laisser DevtoolsModule actif avec http: true en production, exposant la structure interne de l'application.
#core#interview

OAuth2 Strategy

NestJS 🔴 Senior

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.

#security

Optional Dependencies

NestJS 🟡 Mid

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.

#core

overrideGuard

NestJS 🟡 Mid

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.

#testing

overrideProvider

NestJS 🟡 Mid

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.

#testing

Pagination

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Retourner tous les enregistrements sans pagination, causant des timeouts avec les grosses tables.
#core#interview

Passport

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Reimplementer la logique d'authentification from scratch au lieu d'utiliser Passport.
#security#interview

Pipe

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Valider manuellement les données dans le controller au lieu d'utiliser ValidationPipe avec des DTOs.
#core#interview

Prisma $transaction

NestJS 🔴 Senior

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.

#database

Prisma Client

NestJS 🟡 Mid

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.

Anti-pattern : Instancier PrismaClient dans chaque service au lieu de le wrapper dans un PrismaService singleton.
#database

Prisma Migration

NestJS 🟡 Mid

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.

Anti-pattern : Utiliser prisma db push en production au lieu de prisma migrate deploy.
#database

Prisma Schema

NestJS 🟡 Mid

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.

Anti-pattern : Modifier manuellement les fichiers générés par Prisma au lieu du schema.
#database

Provider

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Créer des providers sans @Injectable ou oublier de les déclarer dans le tableau providers du module.
#core#interview

Rate Limiting

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Ne pas limiter les endpoints sensibles comme /login, permettant les attaques par force brute.
#security#interview

RBAC

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Hardcoder les vérifications de role dans chaque handler au lieu d'utiliser un guard + metadata.
#security#interview

REST/DTO

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Utiliser le type any ou l'entité base de données directement comme DTO d'entrée.
#core#interview

ScheduleModule

NestJS 🟡 Mid

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.

Anti-pattern : Utiliser setInterval natif au lieu de @nestjs/schedule, perdant le contexte DI.
#core

Seeding

NestJS 🟡 Mid

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.

Anti-pattern : Seeder en production sans vérifier si les données existent déjà, causant des doublons.
#database

Serialization

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Retourner les entités brutes de la base de données sans filtrer les champs sensibles.
#core#security#interview

Service

NestJS 🟢 Junior? entretien

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.

Anti-pattern : Accéder directement au repository depuis le controller en bypassant le service.
#core#interview

SSE

NestJS 🟡 Mid

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.

Anti-pattern : Utiliser WebSocket quand un flux unidirectionnel SSE suffit.
#communication

Standard Schema Validation

NestJS 🔴 Senior? entretien

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.

Anti-pattern : Mélanger schema Standard Schema et class-validator sur le même DTO sans convention claire dans l'équipe.
#core#nest12#interview

Swagger/OpenAPI

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Maintenir une documentation API manuelle qui se desynchronise du code.
#core#interview#nest12

TerminusModule

NestJS 🟡 Mid

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.

Anti-pattern : Retourner toujours 200 sur /health sans vérifier réellement l'état des dépendances.
#core

Transport Layer

NestJS 🔴 Senior

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.

Anti-pattern : Coupler les services directement via HTTP au lieu d'utiliser un transport asynchrone.
#architecture

TypeORM Entity

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Ajouter de la logique métier dans l'entité au lieu de la garder comme simple mapping.
#database#interview

TypeORM Migration

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Utiliser synchronize: true en production au lieu de migrations versionees.
#database#interview

TypeORM QueryBuilder

NestJS 🔴 Senior? entretien

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.

Anti-pattern : Concaténer du SQL brut au lieu d'utiliser les paramètrès bindables, ouvrant la porte aux injections SQL.
#database#interview

TypeORM Relations

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Charger les relations en eager par défaut, causant des requêtes N+1 massives.
#database#interview

TypeORM Repository

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Utiliser le repository directement dans le controller au lieu de passer par un service.
#database#interview

TypeORM Transactions

NestJS 🔴 Senior? entretien

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.

Anti-pattern : Effectuer des opérations liées sans transaction, risquant un état incohérent en cas d'erreur.
#database#interview

Versioning

NestJS 🟡 Mid

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.

Anti-pattern : Modifier les endpoints existants sans versioning, cassant les clients en production.
#core

WebSocket Gateway

NestJS 🟡 Mid? entretien

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.

Anti-pattern : Utiliser du polling HTTP pour des fonctionnalités temps réel au lieu de WebSocket.
#communication#interview