Nest js 将模块从 forRoot 转换为 forRootAsync

Eiv*_*kus 6 authentication node.js node-modules nestjs nest-dynamic-modules

@Module({
  imports: [],
  providers: [SupertokensService, AuthService],
  exports: [],
  controllers: [AuthController],
})
export class AuthModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(AuthMiddleware).forRoutes('*');
  }
  static forRoot({
    connectionURI,
    apiKey,
    appInfo,
  }: AuthModuleConfig): DynamicModule {
    return {
      providers: [
        {
          useValue: {
            appInfo,
            connectionURI,
            apiKey,
          },
          provide: ConfigInjectionToken,
        },
      ],
      exports: [],
      imports: [],
      module: AuthModule,
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

这个实现的问题是我不能使用环境变量,所以我需要useFactory来传递 ConfigService。有人可以这样做吗,并给出一些解释。

Eiv*_*kus 4

我弄清楚了如何做到这一点,不幸的是它只适用于 Nest.js 版本 9(当前最新版本)。首先您需要创建一个新文件。例如auth.module-definition.ts。现在在这个文件中我们需要创建ConfigurableModuleBuilder.

import { ConfigurableModuleBuilder } from '@nestjs/common';
import { AuthModuleConfig } from './config.interface';

export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
  new ConfigurableModuleBuilder<AuthModuleConfig>()
    .setClassMethodName('forRoot')
    .build();
Run Code Online (Sandbox Code Playgroud)

我们需要设置setClassMethodName('forRoot'),当我们设置时forRoot它会创建两个方法,forRootforRootAsync。下一步是扩展我们创建的ConfigurableModuleClass. 它应该看起来像这样

import { MiddlewareConsumer, Module } from '@nestjs/common';

import { AuthMiddleware } from './auth.middleware';
import { SupertokensService } from './supertokens/supertokens.service';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { ConfigurableModuleClass } from './auth.module-definition';;

@Module({
  imports: [],
  providers: [SupertokensService, AuthService],
  controllers: [AuthController],
  exports: [AuthService],
})
export class AuthModule extends ConfigurableModuleClass {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(AuthMiddleware).forRoutes('*');
  }
}
Run Code Online (Sandbox Code Playgroud)
事实上就是这样,所以从现在开始forRootAsync我们就可以在app.module.ts

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AuthModule } from './auth/auth.module';
import { ConfigModule, ConfigType } from '@nestjs/config';
import authConfig from './auth/auth.config';

@Module({
  imports: [
    AuthModule.forRootAsync({
      inject: [authConfig.KEY],
      imports: [ConfigModule.forFeature(authConfig)],
      useFactory: (config: ConfigType<typeof authConfig>) => {
        return {
          connectionURI: config.CONNECTION_URI,
          appInfo: {
            appName: config.appInfo.APP_NAME,
            apiDomain: config.appInfo.API_DOMAIN,
            websiteDomain: config.appInfo.WEBSITE_DOMAIN,
            apiBasePath: config.appInfo.API_BASE_PATH,
            websiteBasePath: config.appInfo.WEBSITE_BASE_PATH,
          },
        };
      },
    })
  ],
  controllers: [],
  providers: [
  ],
})
export class AppModule implements NestModule {
}
Run Code Online (Sandbox Code Playgroud)

这里我使用的是Nest.js Config,但你不需要,所以你想怎么用就怎么用吧。我知道我的英语不是最好的,所以如果你仍然不明白,你可以检查这些来源https://docs.nestjs.com/fundamentals/dynamic-modules#configurable-module-builder https://trilon.io /博客/nestjs-9-is-now-available#Configurable-module-builder