Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you import a NestJS module on condition

I'am creating a microservice in NestJS. Now I want to use RabbitMQ to send messages to another service.

My question is: is it possible to import the RabbitmqModule based on a .env variable? Such as: USE_BROKER=false. If this variable is false, than don't import the module?

RabbitMQ is imported in the GraphQLModule below.

@Module({
  imports: [
    GraphQLFederationModule.forRoot({
      autoSchemaFile: true,
      context: ({ req }) => ({ req }),
    }),
    DatabaseModule,
    AuthModule,
    RabbitmqModule,
  ],
  providers: [UserResolver, FamilyResolver, AuthResolver],
})
export class GraphQLModule {}

RabbitmqModule:

import { Global, Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
import { UserProducer } from './producers/user.producer';

@Global()
@Module({
  imports: [
    RabbitMQModule.forRootAsync(RabbitMQModule, {
      useFactory: async (config: ConfigService) => ({
        exchanges: [
          {
            name: config.get('rabbitMQ.exchange'),
            type: config.get('rabbitMQ.exchangeType'),
          },
        ],
        uri: config.get('rabbitMQ.url'),
        connectionInitOptions: { wait: false },
      }),
      inject: [ConfigService],
    }),
  ],
  providers: [UserProducer],
  exports: [UserProducer],
})
export class RabbitmqModule {}
like image 480
joey Avatar asked Dec 18 '20 11:12

joey


People also ask

What is dynamic modules in NestJS?

In other words, dynamic modules provide an API for importing one module into another, and customizing the properties and behavior of that module when it is imported, as opposed to using the static bindings we've seen so far.

What does forRoot do in NestJS?

The forRoot sets up the loading of the . env file and the forChild uses it in another module. The problem is that forChild is called before forRoot . The ConfigService would be injected with missing config because forRoot hasn't executed first.

How does dependency injection work in NestJS?

Dependency injection is an inversion of control (IoC) technique wherein you delegate instantiation of dependencies to the IoC container (in our case, the NestJS runtime system), instead of doing it in your own code imperatively.


2 Answers

I think the recommended way to do so is to use the DynamicModule feature from NestJS.

It is explained here: https://docs.nestjs.com/fundamentals/dynamic-modules

Simply check your environment variable in the register function and return your Module object. Something like:

@Module({})
export class GraphQLModule {
  static register(): DynamicModule {
    const imports = [
      GraphQLFederationModule.forRoot({
        autoSchemaFile: true,
        context: ({ req }) => ({ req }),
      }),
      DatabaseModule,
      AuthModule]
    if (process.env.USE_BROKER) {
      modules.push(RabbitmqModule)
    }
    return {
      imports,
      providers: [UserResolver, FamilyResolver, AuthResolver],
    };
  }
}
like image 122
nero408 Avatar answered Nov 02 '22 14:11

nero408


Well I tried a simple workaround, in a small nest project, and it worked just fine. Check it out:

const mymodules = [TypeOrmModule.forRoot(typeOrmConfig), UsersModule];
if (config.get('importModule')) {
    mymodules.push(PoopModule);
}
@Module({
    imports: mymodules,
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {}

I created an "importModule" in my env/config, and tested it with true and false. If true my Poop module gets deployed, else it doesn't deploy, only the other modules.

Can you try the same in your project?

like image 40
Bruno Lamps Avatar answered Nov 02 '22 14:11

Bruno Lamps