A incorporação de um serviço de um módulo Nest.js em outro envolve um processo que assegura a correta injeção de dependências e a organização modular. Através da análise de dois módulos exemplificativos, exploraremos como ocorre a exportação e importação de serviços.
Criação de um Projeto Nest.js
Para iniciar um projeto Nest.js, a CLI (Interface de Linha de Comando) deve estar instalada em seu sistema. Caso ainda não esteja, use o seguinte comando:
npm install -g @nestjs/cli
Com a CLI do Nest.js instalada, execute o seguinte comando para gerar um novo projeto:
nest new <nome-do-projeto>
Substitua “<nome-do-projeto>” pelo nome desejado para o seu projeto. Este comando irá criar um novo projeto Nest.js com o nome especificado.
A estrutura do seu projeto será similar à imagem abaixo:
Para demonstrar a injeção de um serviço entre módulos, criaremos dois módulos, denominados módulo-a e módulo-b, juntamente com seus respectivos arquivos de serviço e controlador.
Use este comando para gerar o módulo-a:
nest generate module module-a
E este para o módulo-b:
nest generate module module-b
Em seguida, gere os arquivos de serviço e controlador para o módulo-a com:
nest generate service module-a && nest generate controller module-a
E faça o mesmo para o módulo-b:
nest generate service module-b && nest generate controller module-b
A estrutura de diretórios do seu projeto deverá agora incluir src/module-a e src/module-b, conforme abaixo:
Exportando um Serviço do Módulo A
Para permitir que o serviço do módulo-a seja usado por outros módulos, ele deve ser listado nas exportações do arquivo do módulo-a (module-a.module.ts). A CLI do Nest.js não inclui uma matriz de exportações por padrão no decorador @Module; portanto, o arquivo gerado terá a seguinte estrutura:
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 {}
Para disponibilizar o serviço-a (module-a.service.ts) para outros módulos que importam o módulo-a, adicione uma matriz de exportações ao decorador @Module e inclua ModuleAService nela.
Assim:
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 {}
Para testes, adicione uma função simples ao arquivo de serviço do módulo (module-a.service.ts):
import { Injectable } from '@nestjs/common';@Injectable()
export class ModuleAService {
getHello(): string {
return 'Olá do Módulo A!';
}
}
Essa função retorna uma string como exemplo. Para confirmar que a importação do serviço está correta, chamaremos esta função no módulo-b após a injeção do serviço-a.
Importando um Serviço para o Módulo B
Para importar um módulo em outro, ele deve ser listado no array imports do módulo receptor. Neste caso, o módulo-a deve ser adicionado ao array imports do decorador @Module no módulo-b.
Assim como antes, a CLI do Nest.js não gera automaticamente uma matriz de importações; portanto, ela deve ser adicionada manualmente.
Primeiramente, importe o módulo pai (module-a.module.ts) no módulo receptor (module-b.module.ts), crie o array imports e adicione ModuleAModule a ele:
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 {}
Em seguida, abra o arquivo module-b.service.ts e importe os decoradores Inject e ModuleAServerice de @nests/common e ../module-a/module-a.service, respectivamente:
import { Injectable, Inject } from '@nestjs/common';
import { ModuleAService } from '../module-a/module-a.service';
O decorador Inject indica que o parâmetro será usado para a injeção de dependência.
A seguir, na classe ModuleBService, adicione o seguinte bloco de código:
@Inject(ModuleAService)
private readonly moduleAService: ModuleAService;
Esse bloco de código permite que o ModuleBService acesse os métodos disponíveis no ModuleAService.
Você pode testar o serviço chamando o método getHello do 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();
}
}
Agora, abra o arquivo module-b.controller.ts e substitua o código existente pelo seguinte:
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();
}
}
Este código configura um manipulador de rota GET para a função getHello.
Finalmente, faça uma solicitação GET com curl para localhost:3000/module-b/hello. O comando deve exibir “Olá do Módulo A!” no seu console.
Você concluiu a injeção de um serviço em outro módulo. Isso é útil quando você desenvolve APIs com Nest.js, que possuem múltiplos módulos que necessitam acessar os métodos uns dos outros.
Vantagens da Injeção Entre Módulos
Embora chamar diretamente um serviço de outro módulo possa parecer mais simples inicialmente, isso pode levar a um sistema mais complexo, difícil de manter e menos escalável a longo prazo.
A injeção entre módulos promove a modularidade e a reutilização de código, tornando a manutenção mais simples. Além disso, centraliza as dependências, melhora a testabilidade e oferece suporte a uma arquitetura desacoplada e escalável.