npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@worker-manager/nestjs

v2.5.0

Published

A NestJS module for the Worker Manager dashboard.

Readme

@worker-manager/nestjs

NestJS module for Worker Manager.

Overview UI

Installation

Install both @worker-manager/api and this module.

$ npm install --save @worker-manager/nestjs @worker-manager/api

Install the Express or Fastify adapter depending on what you use in NestJS (default is Express)

$ npm install --save @worker-manager/express
//or 
$ npm install --save @worker-manager/fastify

Register the root module

Once the installation is completed, we can import the WorkerManagerModule into your rootmodule e.g. AppModule.

import { Module } from '@nestjs/common';
import { WorkerManagerModule } from "@worker-manager/nestjs";

@Module({
  imports: [
    BullModule.forRoot({
      // your bull module config here.
    }),

    // Served at /queues, with the adapter matching your Nest platform (Express or Fastify).
    WorkerManagerModule.forRoot(),
  ],
})
export class AppModule {
}

The forRoot() method registers the Worker Manager instance and allows you to pass several options to both the instance and module. The following options are available, all optional.

| Option | Default | | |---|---|---| | route | '/queues' | Base route of the board, relative to the Nest global prefix. | | adapter | auto-detected | ExpressAdapter (@worker-manager/express) or FastifyAdapter (@worker-manager/fastify). When omitted, the module reads the platform from HttpAdapterHost and loads the matching package. | | auth | none | Built-in authentication, see Authentication. | | enabled | true | false registers nothing: no routes, no middleware, forFeature becomes a no-op and the injected instance is null. | | readOnly | false | Read-only mode for every queue registered through queues or forFeature, unless the queue sets options.readOnlyMode itself. | | queues | [] | Queues to register at the root, same shape as forFeature entries. | | uiConfig | | Merged into boardOptions.uiConfig. | | title / logo / theme | | Shortcuts for uiConfig.boardTitle, uiConfig.boardLogo, uiConfig.theme. | | boardOptions | | Options as provided by the Worker Manager package, such as uiBasePath and uiConfig. | | middleware | | Nest middleware applied to the board route, after auth on Express. |

WorkerManagerModule.forRoot({
  route: '/ops/queues',
  title: 'Ops queues',
  readOnly: process.env.NODE_ENV === 'production',
  enabled: process.env.QUEUE_BOARD !== 'off',
  queues: [{ name: 'emails', adapter: BullMQAdapter }],
}),

Async configuration

forRootAsync() accepts useFactory + inject, useClass or useExisting, with imports:

WorkerManagerModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    route: '/queues',
    enabled: config.get('QUEUE_BOARD_ENABLED') !== 'false',
    auth: {
      strategy: 'keycloak',
      url: config.getOrThrow('KEYCLOAK_URL'),
      realm: config.getOrThrow('KEYCLOAK_REALM'),
      clientId: config.getOrThrow('KEYCLOAK_CLIENT_ID'),
      clientSecret: config.get('KEYCLOAK_CLIENT_SECRET'),
      requiredRoles: ['wm-admin'],
      cookie: { secret: config.getOrThrow('SESSION_SECRET') },
    },
  }),
}),
@Injectable()
class BoardConfig implements WorkerManagerOptionsFactory {
  constructor(private readonly config: ConfigService) {}

  createWorkerManagerOptions(): WorkerManagerModuleOptions {
    return { auth: { strategy: 'basic', users: [{ username: 'admin', password: this.config.getOrThrow('BOARD_PASSWORD') }] } };
  }
}

WorkerManagerModule.forRootAsync({ imports: [ConfigModule], useClass: BoardConfig }),

Authentication

The auth option protects every board route (page, API, assets) with @worker-manager/auth, on Express and Fastify alike, and honours the Nest global prefix.

Basic

WorkerManagerModule.forRoot({
  auth: {
    strategy: 'basic',
    users: [{ username: 'admin', password: process.env.BOARD_PASSWORD, roles: ['admin'] }],
  },
}),

Keycloak

WorkerManagerModule.forRoot({
  auth: {
    strategy: 'keycloak',
    url: 'https://sso.example.com',
    realm: 'ops',
    clientId: 'worker-manager',
    clientSecret: process.env.KEYCLOAK_CLIENT_SECRET,
    publicUrl: 'https://api.example.com/queues', // the board's external URL, base path included
    requiredRoles: ['wm-admin'],
    cookie: { secret: process.env.SESSION_SECRET },
  },
}),

Browsers are sent through the OIDC authorization code flow (PKCE), API clients may send an Authorization: Bearer access token. Register https://api.example.com/queues/auth/callback as a redirect URI on the Keycloak client. The board serves GET /queues/auth/me (the signed-in user) and GET /queues/auth/logout.

Token

WorkerManagerModule.forRoot({
  route: '/admin/queues',
  auth: {
    strategy: 'token',
    tokens: [process.env.BOARD_TOKEN],
    header: 'X-Board-Token', // Authorization: Bearer <token> works too
    cookie: { secret: process.env.BOARD_SESSION_SECRET }, // enables the browser login form
  },
}),

API calls without the token get 401 JSON. A browser is sent to /admin/queues/auth/login, types the token once and gets an encrypted SameSite=Strict session cookie.

Custom

WorkerManagerModule.forRoot({
  auth: {
    strategy: 'custom',
    authenticate: async (req) => verifyMyApiKey(req.headers['x-api-key']), // AuthUser or null
  },
}),

Testing

Test.createTestingModule({ imports: [AppModule] }).compile() works without an explicit adapter: the platform is detected when createNestApplication() provides it, during app.init().

Custom middleware

middleware still takes any Nest middleware, e.g. express-basic-auth. On Express it runs after auth. On Fastify it is applied as Nest middleware to the exact route, before the board's own hooks.

import basicAuth from "express-basic-auth";

WorkerManagerModule.forRoot({
  route: "/queues",
  middleware: basicAuth({
    challenge: true,
    users: { admin: "passwordhere" },
  }),
}),

Register your queues

To register a new queue, you need to register WorkerManagerModule.forFeature in the same module as where your queues are registered.

import { Module } from '@nestjs/common';
import { WorkerManagerModule } from "@worker-manager/nestjs";
import { BullMQAdapter } from "@worker-manager/api/bullMQAdapter";
import { BullModule } from "@nestjs/bullmq";

@Module({
  imports: [
    BullModule.registerQueue(
      {
        name: 'my_awesome_queue'
      }
    ),
    
    WorkerManagerModule.forFeature({
      name: 'my_awesome_queue',
      adapter: BullMQAdapter, //or use BullAdapter if you're using bull instead of bullMQ
    }),
  ],
})
export class FeatureModule {}

The forFeature method registers the given queues to the Worker Manager instance. The following options are available.

  • name the queue name to resolve from the Nest DI container.
  • queue a queue instance to register directly, instead of resolving it by name.
  • adapter either BullAdapter or BullMQAdapter depending on which package you use.
  • options queue adapter options as found in the Worker Manager package, such as readOnlyMode, description etc.

Provide either name or queue.

PostgreSQL-backed queues (BullMQ v6)

A BullMQ v6 queue stored in PostgreSQL has no Redis connection and is usually not in the Nest container, so hand the instance over directly:

import { Queue, createPostgresBackend } from 'bullmq'; // bullmq@6, plus `pg`

const invoices = new Queue(
  'invoices',
  // BullMQ 6.3+: `migrate: true` creates its schema on first connect.
  { connection: { connectionString: process.env.POSTGRES_URL, migrate: true } },
  createPostgresBackend
);

WorkerManagerModule.forRoot({
  queues: [{ queue: invoices, adapter: BullMQAdapter }],
}),

Redis and PostgreSQL queues can share one board.

Registering queue instances directly

@nestjs/bullmq generates the DI token for a queue from its name only, ignoring the prefix. Two queues that share a name but use different prefixes therefore collapse onto a single DI token, and a name-based lookup cannot tell them apart. Pass the queue instances directly via queue to register them as distinct board entries:

@Module({
  imports: [
    WorkerManagerModule.forFeature(
      { queue: emailsTenantA, adapter: BullMQAdapter, options: { prefix: 'tenant-a:' } },
      { queue: emailsTenantB, adapter: BullMQAdapter, options: { prefix: 'tenant-b:' } },
    ),
  ],
})
export class FeatureModule {}

Using the Worker Manager instance in your controllers and/or services.

The created Worker Manager instance is available via the @InjectWorkerManager() decorator. For example in a controller:

import { Controller, Get } from "@nestjs/common";
import { WorkerManagerBoard, InjectWorkerManager } from "@worker-manager/nestjs";

@Controller('my-feature')
export class FeatureController {

  constructor(
    @InjectWorkerManager() private readonly boardInstance: WorkerManagerBoard
  ) {
  }
  
  //controller methods
}

Usage examples

  1. Redis with @nestjs/bullmq and basic auth
  2. PostgreSQL-backed BullMQ v6 queues
  3. Keycloak auth from ConfigService
  4. Fastify platform with a custom auth hook
  5. The pg-boss board over the app's own pg-boss instance

Set it up with an AI agent

The Worker Manager agent skill teaches a coding agent this module (forRoot/forRootAsync/forFeature, named boards, engine: 'pg-boss', auth). In Claude Code: /plugin marketplace add naldomadeira/worker-manager, then /plugin install worker-manager@worker-manager; other agents can unzip worker-manager-skill.zip into their skills folder.

For more info visit the main README