3

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 {}
JBCP
  • 13,109
  • 9
  • 73
  • 111

4 Answers4

4

The correct answer:

ServeStaticModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => [{
          rootPath: join(__dirname, '..', configService.get<string>('STATIC_FOLDER')),
      }]
})
Aleksa
  • 98
  • 9
1

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

leonardfactory
  • 3,353
  • 1
  • 18
  • 25
0

It must be an array, as declare in code:

useFactory?: (...args: any[])
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
0

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 { }
Maz T
  • 1,184
  • 13
  • 18
  • Hi there..looks like a good solution. May I please know how does your ConfigurationModule and ConfigurationService looks like? I am a bit confused about what these files are doing? Would be a great help..Thanks in advance – Saif Islam Feb 15 '23 at 09:41