## Nest.js Dynamic module ### Implementation example ``` . ├── index.ts ├── sender.module.ts ├── sender.service.ts └── types.ts ``` ```ts export { SenderModule } from './sender.module'; export { SenderService } from './sender.service'; export { SenderServiceOptions } from './types'; ``` ```ts import { DynamicModule, Module } from '@nestjs/common'; import { SenderService } from './sender.service'; import { SenderServiceOptions } from './types'; @Module({}) export class SenderModule { static forRoot(options: SenderServiceOptions): DynamicModule { return { module: SenderModule, exports: [SenderService], global: true, providers: [ { provide: SenderService, useFactory: () => { return new SenderService(options); }, }, ], }; } static forRootAsync(options: { imports?: any[]; useFactory: (...args: any[]) => Promise | SenderServiceOptions; inject?: any[]; }): DynamicModule { return { module: SenderModule, imports: options.imports || [], exports: [SenderService], global: true, providers: [ { provide: SenderService, useFactory: async (...args: any[]) => { const config = await options.useFactory(...args); return new SenderService(config); }, inject: options.inject || [], }, ], }; } } ``` ```ts import { SenderServiceOptions } from './types'; export class SenderService { constructor(private options: SenderServiceOptions) {} showOptions(): SenderServiceOptions { return this.options; } } ``` ```ts export interface SenderServiceOptions { apiKey: string; } ``` ### Usage example ```ts @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, load: [appConfig, authConfig, databaseConfig], }), DatabaseModule, AuthModule, UsersModule, // SenderModule.forRoot({ apiKey: 'my-key' }), SenderModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (config: ConfigService) => ({ apiKey: config.getOrThrow('auth.apiKey', { infer: true }), }), }), ], controllers: [AppController], }) export class AppModule {} ```