NestJs monorepo共享库注入

NestJs monorepo shared lib injection

我有 NestJS 应用程序,其中几个微服务存储在单个存储库中(monorepo 方法)。

AccessControl 模块存储在 libs 中,它应该在多个微服务之间共享。它有 AccessControlModule.ts 个文件

@Global()
@Module({
  providers: [
    {
      provide: 'CONNECTION1',
      useFactory: (configService: ConfigService) => {
        return ClientProxyFactory.create(
          configService.getRMQConnection(),
        );
      },
      inject: [ConfigService],
    },
    ACGuard,
  ],
  exports: [ACGuard],
  imports: [ConfigModule],
})
export class AccessControlModule implements OnModuleDestroy {
  constructor(
    @Inject('CONNECTION1')
    protected readonly orgConnection: ClientProxy,
  ) {}

  onModuleDestroy(): any {
    this.orgConnection.close();
  }
}

这个文件负责模块描述,它为另一个微服务创建连接并提供给ACGuard服务。 ACGuard.ts:

@Injectable()
export class ACGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private config: ConfigService,
    @Inject('CONNECTION1')
    private readonly userConnection: ClientProxy;
  ) {}

  public async canActivate(context: ExecutionContext): Promise<boolean> {
   // do some stuff 
  }
}

这部分本身编译得很好并且逻辑上工作正常。当我尝试将其注入其中一个微服务时,问题就出现了。我像往常一样通过将 AccessControlModule 添加到某些模块的 import 部分来做到这一点。例如 KioskModule:

@Module({
  imports: [
    ...
    AccessControlModule
  ],
  providers: [
    ...
    KiosksResolver
  ]
})
export class KiosksModule {}

自从 AccessControlModule 标记为 Global 并导出 ACGuard 我希望它可以注入我的供应商。

@Resolver('Kiosk')
export class KiosksResolver {
  ...

  @UseGuards(ACGuard)
  @Query()
  kiosks() {
    // ...
  }

   ... 
}

但是这段代码落在编译步骤出错了:

[Nest] 9964 - 05/07/2020, 9:33:02 PM [ExceptionHandler] Nest can't resolve dependencies of the ACGuard (Reflector, ConfigService, ?). Please make sure that the argument CONNECTION1 at index [2] is available in the KiosksModule context.

另一方面,如果我将它注入 KiosksResolver 的构造函数,应用程序将成功构建。

我将不胜感激任何帮助和想法,谢谢!

我解决这个问题的方法是在 AccessControlModule.ts 中导出 CONNECTION1 提供商。

@Module({
  providers: [
    {
      provide: 'CONNECTION1',
      useFactory: (configService: ConfigService) => {
        return ClientProxyFactory.create(
          configService.getRMQConnection(),
        );
      },
      inject: [ConfigService],
    },
    ACGuard,
  ],
  exports: [ACGuard, 'CONNECTION1'],
  imports: [ConfigModule],
})
export class AccessControlModule ...

使用此导出 KioskModule 创建它自己的 ACGuard 但此处提供从 AccessControlModule 导出的连接。 我不清楚为什么 KioskModule 没有从 AccessControlModule 导出 ACGuard 的构建实例,但尝试再次构建它。