I created an Interceptor with a related module so that I could manage its imports
without having to import them into the AppModule
.
@Injectable()
export class RequestResponseLoggerInterceptor implements NestInterceptor {
constructor(configService: ConfigService) {
const env = configService.getOrThrow('NECESSARY_ENV');
// do stuff...
}
intercept(context: ExecutionContext, next: CallHandler<any>): Observable<any> | Promise<Observable<any>> {
// do stuff...
}
}
import {Module} from '@nestjs/common';
import {ConfigModule} from '@nestjs/config';
import {
RequestResponseLoggerInterceptor
} from '@app/interceptor-request-response-logger/request-response-logger.interceptor';
import envConfig from '@app/interceptor-request-response-logger/config/env.config';
@Module({
imports: [ConfigModule.forFeature(envConfig)],
providers: [RequestResponseLoggerInterceptor],
exports: [RequestResponseLoggerInterceptor]
})
export class RequestResponseLoggerModule {
}
I also had to add the ConfigModule.forRoot()
imports in AppModule
otherwise the ConfigModule.forFeatures(...)
in the RequestResponseLoggerModule
would not work.
import {Module} from '@nestjs/common';
import {SearchController} from './controllers/search.controller';
import {SearchService} from './services/search.service';
import {RequestResponseLoggerModule} from '@app/interceptor-request-response-logger';
import {ConfigModule} from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
RequestResponseLoggerModule
],
controllers: [SearchController],
providers: [
SearchService
]
})
export class AppModule {
}
Before I get into some abyss trying to get something unintended to work I would like to ask if it makes sense to have such an approach or if Interceptors inherit the module and thus the Module imports into which they are imported.
The project I'm working on will have a lot of these Interceptors that I'll need to reuse on various apps, and that's why I'm trying to figure out how to start with the design of my codebase correctly.
Rather than providing and exporting the interceptor, the module can import and export whatever modules it needs to, as well as provide and export whatever providers the interceptor depends on. Interceptors are a special psuedo-provider referred to as "enhancers", that follow most but not all of the rules that regular providers do. Other enhancers include guards, pipes, and filters, just as an fyi.
Enhancers cannot be provided through the providers
array unless you plan to use the APP_INTERCEPTOR
provider and use the useExisting
custom provider option.
So, in your case, it looks like your RequestResponseLoggerModule
should look like
import {Module} from '@nestjs/common';
import {ConfigModule} from '@nestjs/config';
import envConfig from '@app/interceptor-request-response-logger/config/env.config';
@Module({
imports: [ConfigModule.forFeature(envConfig)],
providers: [],
exports: [ConfigModule]
})
export class RequestResponseLoggerModule {
}
And now, in whatever modules you want to use the RequestResponseLoggerInterceptor
you can import the RequestResponseLoggerModule
and @UseInterceptor(RequestResponseLoggerInterceptor)
with all of its config in place and ready to be made use of.