Reputation: 13485
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 {}
Upvotes: 4
Views: 1883
Reputation: 1244
I've solved it by implementing ServeStaticModuleOptionsFactory
.
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 { }
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*`]
}];
}
}
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 { }
Upvotes: 0
Reputation: 1
It must be an array, as declare in code:
useFactory?: (...args: any[])
Upvotes: 0
Reputation: 148
The correct answer:
ServeStaticModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => [{
rootPath: join(__dirname, '..', configService.get<string>('STATIC_FOLDER')),
}]
})
Upvotes: 6
Reputation: 3501
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
Upvotes: 1