1
votes

I have NestJS application with couple microservices stored in single repository (monorepo approach).

AccessControl module stores in libs, it should be shared across multiple microservices. It has AccessControlModule.ts file

@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();
  }
}

This file responsible for module description, it creates connection for another microservice and provide it to ACGuard service. 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 
  }
}

This part by itself compiles well and logically works fine. Problem begins when I try to inject it into one of microservices. I do it as usual by adding AccessControlModule into import part of some module. For example KioskModule:

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

Since AccessControlModule marked as Global and exports ACGuard I expect it to be injectable into my providers.

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

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

   ... 
}

But this code falls on the compilation step with error:

[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.

On the other hand, if i inject it in KiosksResolver's constructor, application builds successfully.

I will appreciate any help and ideas, thanks!

1

1 Answers

1
votes

The way how i solved this issue was exporting CONNECTION1 provider in AccessControlModule.ts.

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

With this export KioskModule creates it's own ACGuard but provides here connection exported from AccessControlModule. It's not clear for me why KioskModule doesn't get built instance of ACGuard exported from AccessControlModule but try build it once more.