📖 Scenario: You are building a NestJS application that needs a configurable logging module. This module should allow different parts of the app to use it with custom settings.
🎯 Goal: Create a dynamic module called LoggerModule that accepts a configuration object with a logLevel property. This module should provide a LoggerService that uses the configured logLevel.
📋 What You'll Learn
Create a LoggerModule class with a static forRoot method that accepts a config object with logLevel string property.
Inside forRoot, return a dynamic module with module, providers, and exports properties.
Create a LoggerService class that uses the injected logLevel to control logging.
Use NestJS dependency injection to provide the logLevel value to LoggerService.
💡 Why This Matters
🌍 Real World
Dynamic modules let you build reusable NestJS modules that can be configured differently in various parts of your app, like database connections or logging.
💼 Career
Understanding dynamic modules is essential for building scalable and maintainable NestJS applications in professional backend development.
Progress0 / 4 steps
1
Create the LoggerModule class with forRoot method
Create a class called LoggerModule with a static method forRoot that accepts a parameter options of type { logLevel: string }. The method should return an object with a module property set to LoggerModule.
NestJS
Hint
Define a class and a static method that returns an object with a module property.
2
Add provider for logLevel token
Inside the forRoot method of LoggerModule, add a providers array to the returned object. This array should contain an object with provide set to 'LOG_LEVEL' and useValue set to options.logLevel. Also add exports array with 'LOG_LEVEL'.
NestJS
Hint
Add providers and exports arrays to the returned object in forRoot.
3
Create LoggerService using injected logLevel
Create a class called LoggerService with a constructor that injects logLevel using @Inject('LOG_LEVEL'). Store it in a private readonly property called logLevel. Add a method log that accepts a message string and logs it only if logLevel is not 'none'.
NestJS
Hint
Use @Inject('LOG_LEVEL') in the constructor to get the log level value.
4
Add LoggerService provider and export to LoggerModule
In the forRoot method of LoggerModule, add LoggerService to the providers array and also add it to the exports array.
NestJS
Hint
Add LoggerService to both providers and exports arrays in forRoot.
Practice
(1/5)
1. What is the main purpose of a dynamic module in NestJS?
easy
A. To automatically generate database schemas
B. To create modules without any providers or exports
C. To replace the need for controllers in an application
D. To allow configuration of modules with custom options at runtime
Solution
Step 1: Understand dynamic module concept
Dynamic modules let you pass custom options to configure the module when importing it.
Step 2: Identify the main purpose
This flexibility helps reuse modules with different settings instead of hardcoding them.
Final Answer:
To allow configuration of modules with custom options at runtime -> Option D
Quick Check:
Dynamic modules = configurable modules [OK]
Hint: Dynamic modules customize modules with options [OK]
Common Mistakes:
Thinking dynamic modules remove controllers
Believing dynamic modules auto-generate schemas
Assuming dynamic modules have no providers
2. Which of the following is the correct way to define a dynamic module method in NestJS?
easy
A. constructor(options: ModuleOptions): void { ... }
B. static forRoot(options: ModuleOptions): DynamicModule { ... }
C. export function createModule(options: ModuleOptions) { ... }
D. async initialize(options: ModuleOptions): Promise<void> { ... }
Solution
Step 1: Recall dynamic module pattern
Dynamic modules use a static method, commonly named forRoot, returning a DynamicModule object.
Step 2: Match method signature
Only a static method can be called without creating an instance, fitting the dynamic module pattern.
Final Answer:
static forRoot(options: ModuleOptions): DynamicModule { ... } -> Option B
Quick Check:
Dynamic module method = static forRoot [OK]
Hint: Dynamic modules use static forRoot method [OK]
Common Mistakes:
Using constructor instead of static method
Defining dynamic module as a normal function
Making dynamic module method async without returning DynamicModule
3. Given this dynamic module code, what will be the value of the exported provider's token?
5. You want to create a dynamic module that accepts a configuration object and provides two services using that config. Which approach correctly implements this pattern?
hard
A. Use a static forRoot method returning a DynamicModule with providers using useValue for config and export both services
B. Create a constructor in the module class that sets config and exports services directly
C. Define services inside the module without any configuration and import them normally
D. Use a global module without any providers and configure services externally
Solution
Step 1: Understand dynamic module pattern for config
Dynamic modules use a static method (like forRoot) to accept config and return a DynamicModule object with providers.
Step 2: Provide config and services properly
Use useValue or useFactory to inject config into providers, and export services to make them available outside.
Final Answer:
Use a static forRoot method returning a DynamicModule with providers using useValue for config and export both services -> Option A
Quick Check:
Dynamic module with static forRoot and providers = Use a static forRoot method returning a DynamicModule with providers using useValue for config and export both services [OK]
Hint: Use static forRoot with providers and exports [OK]
Common Mistakes:
Trying to configure modules via constructor
Not exporting services after providing them
Using global module without providers for config
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.