Injection d’un service Nest.js à partir d’un autre module



L’intégration d’un service depuis un autre module dans Nest.js requiert de suivre certaines étapes clés pour assurer une injection de dépendance efficace et une structure modulaire appropriée. En explorant deux modules distincts, nous allons détailler comment fonctionne l’exportation et l’importation de services.

Création d’un projet Nest.js

Pour initialiser un nouveau projet Nest.js, la CLI (interface de ligne de commande) doit être installée sur votre système. Si ce n’est pas le cas, la commande suivante permet son installation :

npm install -g @nestjs/cli

Une fois la CLI Nest.js installée, utilisez cette commande pour générer un nouveau projet :

nest new <nom-du-projet>

Remplacez « <nom-du-projet> » par le nom souhaité pour votre projet. L’exécution de cette commande va créer un nouveau projet Nest.js avec le nom spécifié.

La structure de votre projet devrait ressembler à l’image ci-dessous :

Pour vous exercer à l’injection de service entre modules, nous allons créer deux modules : ‘module-a’ et ‘module-b’, ainsi que leurs fichiers de service et de contrôleur respectifs.

Exécutez cette commande pour générer le module-a :

nest generate module module-a

Puis, la commande équivalente pour module-b :

nest generate module module-b

Ensuite, créez les fichiers de service et de contrôleur pour module-a avec :

nest generate service module-a && nest generate controller module-a

Et de même pour module-b :

nest generate service module-b && nest generate controller module-b

Votre répertoire de projet devrait désormais afficher les dossiers ‘src/module-a’ et ‘src/module-b’ :

Exportation d’un service depuis le module A

Pour rendre accessible le service de module-a, vous devez l’inclure dans le tableau des exportations du fichier de module de module-a (‘module-a.module.ts’). Par défaut, la CLI Nest.js ne génère pas ce tableau. Le fichier module ressemblera donc initialement à ceci :

import { Module } from '@nestjs/common';
import { ModuleAService } from './module-a.service';
import { ModuleAController } from './module-a.controller';

@Module({
  providers: [ModuleAService],
  controllers: [ModuleAController],
})

export class ModuleAModule {}

Pour permettre l’accès au service-a (module-a.service.ts) par les modules qui importent le module-a, il faut créer un tableau ‘exports’ dans le décorateur ‘@Module’ et y ajouter ‘ModuleAService’.

Ce qui donne :

import { Module } from '@nestjs/common';
import { ModuleAService } from './module-a.service';
import { ModuleAController } from './module-a.controller';

@Module({
  providers: [ModuleAService],
  controllers: [ModuleAController],
  exports: [ModuleAService],
})

export class ModuleAModule {}

Pour tester, ajoutez une fonction simple à votre fichier de service ‘module-a’ (‘module-a.service.ts’) :

import { Injectable } from '@nestjs/common';

@Injectable()
export class ModuleAService {
  getHello(): string {
    return 'Bonjour depuis le Module A!';
  }
}

Cette fonction retourne un message de test. Après avoir injecté le service-a dans le module-b, nous appellerons cette fonction pour valider que l’importation est effective.

Importation d’un service dans le module B

Pour importer un module dans un autre, il faut le mentionner dans le tableau ‘imports’ du module de destination. Dans ce cas, vous devez ajouter ‘module-a’ au tableau ‘imports’ du décorateur ‘@Module’ de ‘module-b’.

Comme précédemment, la CLI Nest.js n’inclut pas automatiquement ce tableau. Il est donc nécessaire de l’ajouter manuellement.

Commencez par importer le module parent (‘module-a.module.ts’) dans le module récepteur (‘module-b.module.ts’), puis créez le tableau ‘imports’ et ajoutez-y ‘ModuleAModule’ :

import { Module } from '@nestjs/common';
import { ModuleBController } from './module-b.controller';
import { ModuleBService } from './module-b.service';
import { ModuleAModule } from '../module-a/module-a.module';

@Module({
  imports: [ModuleAModule],
  controllers: [ModuleBController],
  providers: [ModuleBService],
})

export class ModuleBModule {}

Ensuite, ouvrez votre fichier ‘module-b.service.ts’ et importez les décorateurs ‘Inject’ et ‘ModuleAServerice’ depuis ‘@nests/common’ et ‘../module-a/module-a.service’, respectivement :

import { Injectable, Inject } from '@nestjs/common';
import { ModuleAService } from '../module-a/module-a.service';

Le décorateur ‘Inject’ marque son paramètre comme cible pour l’injection de dépendance.

Dans votre classe ‘ModuleBService’, insérez le code suivant :

@Inject(ModuleAService)
private readonly moduleAService: ModuleAService;

Ce code permet à votre ‘ModuleBService’ d’accéder aux méthodes de votre ‘ModuleAService’.

Vous pouvez tester ce service en appelant la méthode ‘getHello’ de ‘ModuleAService’.

import { Injectable, Inject } from '@nestjs/common';
import { ModuleAService } from 'src/module-a/module-a.service';

@Injectable()
export class ModuleBService {
  @Inject(ModuleAService)
  private readonly moduleAService: ModuleAService;

  getHello(): string {
    return this.moduleAService.getHello();
  }
}

Maintenant, ouvrez ‘module-b.controller.ts’ et remplacez le code existant par :

import { Controller, Get } from '@nestjs/common';
import { ModuleBService } from './module-b.service';

@Controller('module-b')
export class ModuleBController {
  constructor(private readonly moduleBService: ModuleBService) {}

  @Get('/hello')
  getHello(): string {
    return this.moduleBService.getHello();
  }
}

Ce code configure un gestionnaire de route GET pour la fonction ‘getHello’.

Enfin, effectuez une requête GET avec curl à l’adresse ‘localhost:3000/module-b/hello’. La console devrait afficher « Bonjour depuis le Module A ! ».

Vous avez réussi à injecter un service dans un autre module. Cette méthode est particulièrement utile pour les API Nest.js comportant plusieurs modules qui ont besoin d’interagir.

Avantages de l’injection inter-modules

Bien qu’appeler directement un service depuis un autre module puisse sembler plus simple au départ, cela peut aboutir à un système plus complexe, difficile à maintenir et moins évolutif à long terme.

L’injection inter-modules, en revanche, favorise la modularité, la réutilisation du code et simplifie la maintenance. Elle centralise les dépendances, améliore la testabilité et supporte une architecture découplée et évolutive.