Nest js将模块从forRoot转换为forRootAsync


@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,
};
}
}

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

我想好了如何实现这一点,不幸的是,它只适用于nest.js版本9(当前最新版本)。首先,您需要创建一个新文件。例如CCD_ 1。现在,在这个文件中,我们需要创建ConfigurableModuleBuilder

import { ConfigurableModuleBuilder } from '@nestjs/common';
import { AuthModuleConfig } from './config.interface';
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
new ConfigurableModuleBuilder<AuthModuleConfig>()
.setClassMethodName('forRoot')
.build();

我们需要设置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('*');
}
}
实际上就是这样,所以从现在起我们有了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 {
}

这里我使用的是auth.module-definition.ts0,但你不需要,所以你可以随心所欲地使用它。我知道我的英语不是最好的,所以如果你仍然不懂,你可以查一下这些资料https://docs.nestjs.com/fundamentals/dynamic-modules#configurable-模块生成器https://trilon.io/blog/nestjs-9-is-now-available#Configurable-模块生成器

如果您也想与v6+和9+兼容,您可以创建一个新的提供程序。

import { MySql2Database } from 'drizzle-orm/mysql2';
import { DRIZZLE_ORM } from './constants';
import { NestDrizzleService } from './nest-drizzle.service';
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
export const connectionFactory = {
provide: DRIZZLE_ORM,
useFactory: async (nestDrizzleService: {
getDrizzle: () => Promise<
MySql2Database | PostgresJsDatabase | BetterSQLite3Database
>;
}) => {
return nestDrizzleService.getDrizzle();
},
inject: [NestDrizzleService],
};
提供使用令牌(最佳实践):

@Inject(DRIZZLE_ORM) private readonly db: PostgresJsDb

并像一样使用它

public static forRootAsync(options: NestDrizzleAsyncOptions): DynamicModule {
return {
module: NestDrizzleModule,
providers: [...this.createProviders(options)],
exports: [...this.createProviders(options)],
};
}
private static createProviders(options: NestDrizzleAsyncOptions): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createOptionsProvider(options)];
}
return [
this.createOptionsProvider(options),
{
provide: options.useClass,
useClass: options.useClass,
},
];
}

最新更新