Nestjs - connect bull-board in a normal controller

Viewed 3993

I created an app using nest.js and bull. I added bull-board package to monitor my queues, but in documentation, only one way to add it to the app is mount as middleware:

In main.ts:

app.use('/admin/queues', bullUI);

Is there any way to add bullUI in a normal nest controller, after jwt auth? Like:

    @UseGuards(JwtAuthGuard)
    @Get("queues")
    activate() {
        return UI
    }
3 Answers

You can use any express middleware like this inside controllers, but maybe some cases cause errors like serving static files with Guard exception and etc.

@UseGuards(JwtAuthGuard)
@Get("queues/*")
activate(@Req() req, @Res() res) {
  bullUI(req, res)
}

I've got this working via a middleware consumer, so something like this:

import { router } from 'bull-board';

@Module({
  imports: [
    NestBullModule.forRoot({ redis }),
  ],
  providers: [],
})
export class BullModule {
  configure(consumer: MiddlewareConsumer): void {
    consumer
      .apply(router)
      .forRoutes('/admin/queues');
  }
}

I'd like to extend the original answer of @JCF, mainly, because it's working and much easier to understand.

I am using not default bull, with @nestjs/queue, but an improved version of BullMQ from anchan828 repo, with NestJS decorators, but I guess in both cases, the result will be the same.

The queue.module file:

@Module({
  imports: [
    BullModule.forRoot({
      options: {
        connection: {
          host: redisConfig.host,
          port: redisConfig.port,
        },
      },
    }),
    /** DI all your queues and Redis connection */
    BullModule.registerQueue('yourQueueName'),
  ],
  controllers: [],
  providers: [],
})
export class QueueModule {

  constructor (
    @BullQueueInject('yourQueueName')
    private readonly queueOne: Queue,
  ) {
    /** Add queues with adapter, one-by-one */
    setQueues([new BullMQAdapter(this.queueOne, { readOnlyMode: false })]) 
  }
  
  configure(consumer: MiddlewareConsumer): void {
    consumer
      .apply(router)
      .forRoutes('/admin/queues');
  }
}

Then just add it, to parent AppModule, via import, like that:

I am not sure, that Redis connection is needed here, for parent AppModule

@Module({
  imports: [
    BullModule.forRoot({
      options: {
        connection: {
          host: redisConfig.host,
          port: redisConfig.port,
        },
      },
    }),
    QueueModule
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

run the main.js, and visit, localhost:8000/admin/queues

Related