Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional Registration using the ConfigModule #1407

Closed
1 task done
jmcdo29 opened this issue Aug 7, 2023 · 9 comments
Closed
1 task done

Optional Registration using the ConfigModule #1407

jmcdo29 opened this issue Aug 7, 2023 · 9 comments

Comments

@jmcdo29
Copy link
Member

jmcdo29 commented Aug 7, 2023

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe it

There arises occasions where we might want to allow for registering a module optionally, I see this come up on the Discord server every now and again. Like running the CronModule in only one running instance based on the env variables, or setting up the serve static in a single instance.

Describe the solution you'd like

I'd like to propose a new static method on the ConfigModule, something like optionallyRegisterModule that takes in the module to optionally register, and the environment variable that should be checked against if the module should be registered, or a method that returns a boolean for the same reason. If the valueof the key is falsy, or the method returns false, the new method should return a new NoopModule which has no imports, exports, providers, or controllers.

This method would be an async method that await ConfigModule.envVariablesLoaded and then check against process.env[key] to ensure that we can properly wait for the environment variables to be loaded and then react accordingly.

Teachability, documentation, adoption, migration strategy

We mention it in the docs and possibly make a blog article on it

What is the motivation / use case for changing the behavior?

Optionally registering modules, as described above :)

I'm happy to work on this as well if we like the idea of it.

@micalevisk
Copy link
Member

micalevisk commented Aug 7, 2023

can you show some code snippet on how it would looks like from consumer side?

@jmcdo29
Copy link
Member Author

jmcdo29 commented Aug 7, 2023

@Module({
  imports: [
    ConfigModule.forRoot(),
    ConfifgModule.optionallyRegisterModule(
      ScheduleModule.forRoot(),
      'USE_CRON'
    )
  ],
  ...
})
export class AppModule {}

OR

@Module({
  imports: [
    ConfigModule.forRoot(),
    ConfifgModule.optionallyRegisterModule(
      ScheduleModule.forRoot(),
      () => JSON.parse(process.env.USE_ENV)
    )
  ],
  ...
})
export class AppModule {}

@micalevisk
Copy link
Member

micalevisk commented Aug 7, 2023

I wonder if it couldn't be something that works on top of ConfigService:

@Module({
  imports: [
    ConfigModule.forRoot(),
    ConfigModule.registerModule({
      module: ScheduleModule.forRoot(),
      when: (configService: ConfigService) =>
        configService.get('USE_ENV') == true
    })
  ],
  ...
})
export class AppModule {}

@jmcdo29
Copy link
Member Author

jmcdo29 commented Aug 7, 2023

Hmmm, I'm not quite sure how feasible that would be, as injecting a provider is usually for module configuration, not module registration, y'know? But as imports can have async values, we can make use of the existing method for waiting for process.env to be loaded and return the correct module. I do like the registerModule with the object rather than the two parameters though

@kamilmysliwiec
Copy link
Member

So basically you're suggesting that we could expose this helper type out of the box, as part of the @nestjs/config package:

export class ConditionalModule {
  static async registerWhen(moduleToRegister, condition) {
    await ConfigModule.envVariablesLoaded();
    return condition(process.env) 
         ? { module: ConditionalModule, imports: [moduleToRegister] 
         : { module: ConditionalModule, imports: [] }
  }
}

Example

imports: [ConditionalModule.registerWhen(ScheduleModule.forRoot(), ({ USE_CRON }) => ...)]

@jmcdo29
Copy link
Member Author

jmcdo29 commented Aug 7, 2023

@kamilmysliwiec yep, that's generally it. Figured we'd make it a part of this package as it's very closely tied to the module

@kamilmysliwiec
Copy link
Member

This would make a lot of sense indeed. Would you like to create a PR for this?

@jmcdo29
Copy link
Member Author

jmcdo29 commented Aug 7, 2023

Absolutely. I'll work on it this week

@jmcdo29
Copy link
Member Author

jmcdo29 commented Aug 8, 2023

Let's track this here

@jmcdo29 jmcdo29 closed this as completed Aug 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants