Skip to content

Instantly share code, notes, and snippets.

@zmts
Last active January 14, 2025 15:50
Show Gist options
  • Save zmts/cd709aab2e05cfc392a4683da1e8979c to your computer and use it in GitHub Desktop.
Save zmts/cd709aab2e05cfc392a4683da1e8979c to your computer and use it in GitHub Desktop.
Nest.js Dynamic module

Nest.js Dynamic module

Implementation example

.
├── index.ts
├── sender.module.ts
├── sender.service.ts
└── types.ts
export { SenderModule } from './sender.module';
export { SenderService } from './sender.service';
export { SenderServiceOptions } from './types';
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> | 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 || [],
        },
      ],
    };
  }
}
import { SenderServiceOptions } from './types';

export class SenderService {
  constructor(private options: SenderServiceOptions) {}

  showOptions(): SenderServiceOptions {
    return this.options;
  }
}
export interface SenderServiceOptions {
  apiKey: string;
}

Usage example

@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<AllConfig>) => ({
        apiKey: config.getOrThrow('auth.apiKey', { infer: true }),
      }),
    }),
  ],
  controllers: [AppController],
})
export class AppModule {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment