Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to use config service in NestJS Module

I want to use environment variables to configure the HttpModule per module, from the docs I can use the configuration like this:

@Module({
  imports: [HttpModule.register({
    timeout: 5000,
    maxRedirects: 5,
  })],
})

But I don't know what is the best practice to inclue a baseURL from environment vairable (or a config service), for example like this:

@Module({
imports: [HttpModule.register({
    baseURL:  this.config.get('API_BASE_URL'),
    timeout: 5000,
    maxRedirects: 5,
})],

The this.config is undefined here cause it's out of class.

What is the best practice to set baseURL from environment variables (or config service)?

like image 327
Siavash Ahmadpour Avatar asked Nov 22 '18 08:11

Siavash Ahmadpour


People also ask

Can I use NestJS Config service outside a module?

Yep, you can get anything from Nest.

How do I see environment variables in NestJS?

To access the configuration values start by importing ConfigService from @nestjs/config. Inject it into the class's constructor by declaring a private variable and assigning ConfigService as its type. To access a variable, call the get method on the ConfigService on your private variable.

What is dynamic modules in NestJS?

In fact, what our register() method will return is a DynamicModule . A dynamic module is nothing more than a module created at run-time, with the same exact properties as a static module, plus one additional property called module .

What is forRoot 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. > AppModule > ConfigModule.


2 Answers

Update Jan 19

HttpModule.registerAsync() was added in version 5.5.0 with this pull request.

HttpModule.registerAsync({
  imports:[ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    baseURL:  configService.get('API_BASE_URL'),
    timeout: 5000,
    maxRedirects: 5,
  }),
  inject: [ConfigService]
}),

Original Post

This problem was discussed in this issue. For the nestjs modules like the TypeOrmModule or the MongooseModule the following pattern was implemented.

The useFactory method returns the configuration object.

TypeOrmModule.forRootAsync({
  imports:[ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    type: configService.getDatabase()
  }),
  inject: [ConfigService]
}),

Although Kamil wrote

Above convention is now applied in all nest modules and will be treated as a best practice (+recommendation for 3rd party modules). More in the docs

it does not seem to be implemented for the HttpModule yet, but maybe you can open an issue about it. There are also some other suggestions in the issue I mentioned above.

Also have a look at the official docs with best practices on how to implement a ConfigService.

like image 114
Kim Kern Avatar answered Oct 12 '22 22:10

Kim Kern


I also encountered several issues with implementing a ConfigService as described in the NestJS documentation (no type-safety, no modularity of configuration values, ...), I wrote down our company's final NestJS configuration management strategy in great detail here: NestJS Configuration Management

The basic idea is to have a central config module that loads all configuration values from the processes' environment. However, instead of providing a single service to all modules, each module can inject a dedicated subset of the configuration values! So each module contains a class that specifies all configuration values that this module needs to be provided at runtime. This simultaneously gives the developer type-safe access to configuration values (instead of using string literals throughout the codebase)

Hope this pattern also works for your use-case :)

like image 28
derbenoo Avatar answered Oct 12 '22 22:10

derbenoo