NestJS - 如何使用不同的配置多次注册动态模块提供程序?

Fel*_*rim 4 node.js typescript nestjs

我有一个 knex 模块,其实现如下:

import { DynamicModule, Module } from '@nestjs/common';
import { Knex, knex } from 'knex';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';

export const KNEX_MODULE = 'KNEX_MODULE';

@Module({})
export class KnexModule {
  static register(options: Knex.Config): DynamicModule {
    return {
      module: KnexModule,
      providers: [
        {
          inject: [WINSTON_MODULE_PROVIDER],
          provide: KNEX_MODULE,
          useFactory: (logger: Logger) => {
            logger.info('Creating new knex instance', {
              context: KnexModule.name,
              tags: ['instance', 'knex', 'create'],
            });
            return knex(options);
          },
        },
      ],
      exports: [KNEX_MODULE],
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序需要访问多个数据库,我知道我可以通过创建多个 knex 实例来做到这一点。所以我尝试注册该模块两次,传递不同的配置。然而,该模块只注册一次。第二个寄存器调用似乎是重用现有对象,而不是创建新的 knex 实例。

根据传递的配置生成多个提供程序的正确方法是什么?我发现的最接近的是 typeORM 和 Sequelize 中的 forFeature 函数

Fel*_*rim 8

我刚刚找到了解决方案。我想错了。我需要向我的模块注册两个提供商。不创建我的模块的两个实例。我通过向模块添加一个参数(即提供者令牌)解决了这个问题。现在它正确地创建了两个提供者。

import { DynamicModule, Module } from '@nestjs/common';
import { Knex, knex } from 'knex';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';

export const KNEX_MODULE = 'KNEX_MODULE';

@Module({})
export class KnexModule {
  static register(token: string, options: Knex.Config): DynamicModule {
    return {
      module: KnexModule,
      providers: [
        {
          inject: [WINSTON_MODULE_PROVIDER],
          provide: token,
          useFactory: (logger: Logger) => {
            logger.info('Creating new knex instance', {
              context: KnexModule.name,
              tags: ['instance', 'knex', 'create'],
            });
            return knex(options);
          },
        },
      ],
      exports: [token],
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

每当我想使用它时,我都会像这样注册它:

@Module({
  imports: [KnexModule.register(CatRepository.KNEX_TOKEN, knexConfigs)],
  providers: [CatRepository, CatService],
  controllers: [CatController],
  exports: [CatService],
})
export class CatModule {}
Run Code Online (Sandbox Code Playgroud)

然后在存储库中我可以注入 cats 数据库的 knex 实例。

@Injectable()
export class CatRepository implements Repository<Cat> {
  // eslint-disable-next-line no-useless-constructor
  public static KNEX_TOKEN = 'KNEX_CATS_TOKEN';

  // eslint-disable-next-line no-useless-constructor
  constructor(
    @Inject(CatRepository.KNEX_TOKEN)
    protected knex: Knex,
  ) {}

  ...
}
Run Code Online (Sandbox Code Playgroud)