如何创建基于异步配置的 Nestjs 模块?

Mar*_*mba 0 asynchronous config nestjs

我正在尝试创建一个数据库模块,如下所示:

const dbProvider = {
  provide: 'DB',
  useFactory: async (configService:ConfigService) => {
    const dbUrl = configService.get<string>('DB_URL')
    return Knex({
      client: 'pg',
      connection: dbUrl
    })
  },
  inject: [ConfigService]
}

@Module({
  providers: [ConfigService, dbProvider],
  exports: [dbProvider],
})
export class DbModule {}
Run Code Online (Sandbox Code Playgroud)

这是 AppModule 定义:

@Module({
  controllers: [AppController],
  providers: [Logger, AppService, {
    provide: ConfigService,
    useFactory: getConfigFactory(['DB_URL']),
  }],
  exports: [ConfigService]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)

和:

export function getConfigFactory(paramsToLoad: string[]) {
    return async () => {await getConfigService(paramsToLoad)}
}
export async function getConfigService(paramsToLoad: string[]) {

    const paramStoreParams = await loadParamStore(paramsToLoad)
    return new ConfigService(paramStoreParams)
}
Run Code Online (Sandbox Code Playgroud)

loadParamStore使用SSM从SSM中获取参数

问题是,当执行数据库设置(上面)时,ConfigService 仅包含从 .env 获取的环境,DB_URL 仅在稍后阶段加载(已验证),因此在构建 knex 时,DB_URL 尚未加载可用的。

是否有正确的 Nestjs 方法来实现此类功能?

小智 5

所以我遇到了类似的问题。我的问题陈述是 -在 Nest JS 中加载 AWS Secrets。这必须在实例化任何其他模块之前完成。示例 - TypeORM、JWT 模块都需要配置值。

我是如何实现的?通过构建一个辅助函数,从 AWS 获取机密并将这些值保留在 process.env 中

export async function secretLoader(){
  const secretsManager = new SecretsManager({
    region: process.env['AWS_REGION'],
  });
  const secretsIds = [process.env['AWS_SECRET_ID']];

  const commands = secretsIds.map(
    (secretId) =>
      new GetSecretValueCommand({
        SecretId: secretId,
      }),
  );
  const resp = commands.map((command) =>
    secretsManager.send(command),
  );
  const secrets = await Promise.all(resp);
  const response = secrets.reduce((acc, secret) => {
    const sec = JSON.parse(<string>secret.SecretString);
    return {
      ...acc,
      ...sec,
    };
  }, {});
  Object.keys(response).forEach((key) => {
    process.env[key] = response[key];
  });
}
Run Code Online (Sandbox Code Playgroud)

您只需在环境文件中设置 2 个属性 - 'AWS_REGION' 和 'AWS_SECRET_ID'

接下来,在 main.ts 文件中。导入并运行该函数。

import { secretLoader } from './secretLoader';

async function bootstrap() {
  await secretLoader();
  initializeTransactionalContext(); // Initialize cls-hooked
  const app = await NestFactory.create(AppModule);
  const configService: ConfigService = app.get(ConfigService);
  await app.listen(configService.get<number>('PORT') || 3000);
}
bootstrap();
Run Code Online (Sandbox Code Playgroud)

干杯!

PS - 我尝试在“加载”中使用配置工厂方法。但它不起作用,因为某些模块在配置模块之前初始化。