'How to inject the path configuration into ServeStaticModule from another service?
The NestJS documentation says to serve static files like this:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
@Module({
imports: [
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'client'),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
But as a DI and SOLID practitioner, I want to make the rootPath configurable. Lets say I have a ConfigModule or my own ConstantsModule. How do I inject rootPath in a way similar to this?
@Module({
imports: [
ServeStaticModule.forRoot({
rootPath: this.configService.get<string>('staticRootPath'),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Solution 1:[1]
The correct answer:
ServeStaticModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => [{
rootPath: join(__dirname, '..', configService.get<string>('STATIC_FOLDER')),
}]
})
Solution 2:[2]
Even if it is not documented, you can use the forRootAsync, it is typical for NestJS modules to have this version which allows you to inject dependencies and/or do async configuration:
@Module({
imports: [
ServeStaticModule.forRootAsync({
imports: [ConfigModule],
injects: [ConfigService],
useFactory: (configService) => ({
rootPath: configService.get<string>('staticRootPath')
})
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
For reference, found it in the GitHub sources
Solution 3:[3]
It must be an array, as declare in code:
useFactory?: (...args: any[])
Solution 4:[4]
I've solved it by implementing ServeStaticModuleOptionsFactory.
serve-static-configuration.module.ts
import { Module } from '@nestjs/common';
import { ConfigurationModule } from '../configuration/configuration.module';
import { ConfigurationService } from '../configuration/configuration.service';
import { ServeStaticConfigurationService } from './serve-static-configuration.service';
@Module({
imports: [ConfigurationModule],
providers: [ServeStaticConfigurationService, ConfigurationService],
exports: [ServeStaticConfigurationService]
})
export class ServeStaticConfigurationModule { }
serve-static-configuration.service.ts
import { Injectable } from '@nestjs/common';
import { ServeStaticModuleOptions, ServeStaticModuleOptionsFactory } from '@nestjs/serve-static';
import { ConfigurationService } from '../configuration/configuration.service';
@Injectable()
export class ServeStaticConfigurationService implements ServeStaticModuleOptionsFactory {
constructor(private configurationService: ConfigurationService) { }
createLoggerOptions(): ServeStaticModuleOptions[] | Promise<ServeStaticModuleOptions[]> {
return [{
rootPath: this.configurationService.wwwRoot,
exclude: [`/api*`]
}];
}
}
app.module.ts
import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { AppController } from './app.controller';
import { ServeStaticConfigurationModule } from './serve-static-configuration/serve-static-configuration.module';
import { ServeStaticConfigurationService } from './serve-static-configuration/serve-static-configuration.service';
@Module({
imports: [
ServeStaticModule.forRootAsync({
imports: [ServeStaticConfigurationModule],
useExisting: ServeStaticConfigurationService
})
],
controllers: [AppController]
})
export class AppModule { }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Aleksa |
| Solution 2 | leonardfactory |
| Solution 3 | Bhargav Rao |
| Solution 4 | Maz T |
