Getting Started with NestJS
Install the transport and build a first end-to-end NestJS app that sends and handles a KubeMQ command in under 5 minutes.
Implementation steps
Prerequisites
Before you start, make sure you have:
| Requirement | Details |
|---|---|
| Node.js | 20.11.0 or later |
| NestJS app | An existing project, or create one with nest new my-app |
| KubeMQ broker | A running broker reachable on localhost:50000 |
If you do not have a broker yet, start one locally with Docker:
docker run -d \ --name kubemq \ -p 50000:50000 \ -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \ europe-docker.pkg.dev/kubemq/images/kubemq:nextPort 50000 is the gRPC port the transport connects to. The @kubemq/nestjs-transport package is built on the native kubemq-js SDK, so no HTTP connector flag is required.
Install the Transport
Add the transport and its kubemq-js runtime dependency:
npm install @kubemq/nestjs-transport kubemq-jsMost of the peer dependencies already ship with a typical NestJS project. Install any that are missing:
npm install @nestjs/common @nestjs/core @nestjs/microservices rxjs reflect-metadataThe package exposes two optional subpath entry points: @kubemq/nestjs-transport/testing (mocks for unit tests) and @kubemq/nestjs-transport/cqrs (the @nestjs/cqrs bridge). They are only needed for those specific features and pull in their own optional peer dependencies (@nestjs/terminus for health checks, @nestjs/cqrs for the CQRS bridge).
Register the Module
In your root module, register a global connection with forRoot and a named client with register. The global connection is shared across the app; the named client is the proxy you inject to send messages.
import { Module } from '@nestjs/common';
import { KubeMQModule } from '@kubemq/nestjs-transport';
import { OrderHandler } from './order.handler';
import { OrderService } from './order.service';
const address = process.env.KUBEMQ_ADDRESS ?? 'localhost:50000';
@Module({
imports: [
KubeMQModule.forRoot({
address,
clientId: 'orders-app',
isGlobal: true,
}),
KubeMQModule.register({
name: 'KUBEMQ_SERVICE',
address,
clientId: 'orders-client',
}),
],
providers: [OrderHandler, OrderService],
})
export class AppModule {}The name you pass to register (here 'KUBEMQ_SERVICE') is the injection token you will use to inject the client in Step 6.
Add a Command Handler
Create a handler that responds to the orders.create channel. Use @CommandHandler for the channel, @Payload() to bind the message body, and @Ctx() to access the KubeMQCommandContext. Returning a value from the method sends it back as the command response.
import { Injectable, Logger } from '@nestjs/common';
import { CommandHandler, KubeMQCommandContext } from '@kubemq/nestjs-transport';
import { Payload, Ctx } from '@nestjs/microservices';
@Injectable()
export class OrderHandler {
private readonly logger = new Logger(OrderHandler.name);
@CommandHandler('orders.create')
handleCreate(
@Payload() data: { name: string; total: number },
@Ctx() ctx: KubeMQCommandContext,
) {
this.logger.log(`Command from ${ctx.fromClientId} on ${ctx.channel}`);
return { orderId: 'order-123', status: 'created' };
}
}The handler class must be a NestJS-managed provider. If the decorator never fires, the most common cause is a class that is not listed in a module's providers (the class is @Injectable() and the module imports KubeMQModule). A standalone class instantiated outside Nest will not be wired to the transport.
Bootstrap the Hybrid App
A NestJS hybrid app serves both HTTP and the KubeMQ microservice transport. Attach the KubeMQServer strategy with connectMicroservice, start the microservices, then start the HTTP listener.
import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { KubeMQServer } from '@kubemq/nestjs-transport';
import { AppModule } from './app.module';
const address = process.env.KUBEMQ_ADDRESS ?? 'localhost:50000';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.connectMicroservice({
strategy: new KubeMQServer({
address,
clientId: 'orders-server',
group: 'orders-group',
}),
});
await app.startAllMicroservices();
await app.listen(3000);
}
bootstrap();The group option puts the server in a consumer group, so multiple replicas load-balance command delivery instead of each receiving a copy.
Send From a Service
Inject the named client by its token and call send for request-reply. send returns an RxJS Observable, so wrap it in firstValueFrom to await the single response.
import { Injectable, Inject, Logger } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { firstValueFrom } from 'rxjs';
@Injectable()
export class OrderService {
private readonly logger = new Logger(OrderService.name);
constructor(@Inject('KUBEMQ_SERVICE') private readonly client: ClientProxy) {}
async createOrder(data: { name: string; total: number }) {
const response = await firstValueFrom(
this.client.send('orders.create', data),
);
this.logger.log(`Command response: ${JSON.stringify(response)}`);
return response;
}
}By default client.send() sends a Command and client.emit() sends an Event. To send a Query, Events Store message, or Queue message instead, wrap the payload in a KubeMQRecord — see Usage.
Run It
The repository ships a large examples corpus where every folder is a self-contained NestJS mini-app. The fastest way to see a working command round-trip is the rpc/send-command example, which registers a handler and a sender in the same app:
cd examples
npm install
npx tsx examples/rpc/send-command/main.tsExpected output:
[SendCommandExample] KubeMQ microservice started
[CommandService] Sending command...
[CommandHandler] Received command on nestjs-rpc.send-command: {"action":"create-user","name":"Alice"}
[CommandService] Command response: {"executed":true,"action":"create-user"}To see all five handler decorators (@CommandHandler, @QueryHandler, @EventHandler, @EventStoreHandler, @QueueHandler) exercised in one application, run the decorators/all-handlers example:
npx tsx examples/decorators/all-handlers/main.tsEvery example reads the broker address from the KUBEMQ_ADDRESS environment variable and falls back to localhost:50000. To target a remote broker, export the variable before running: KUBEMQ_ADDRESS=my-broker:50000 npx tsx examples/rpc/send-command/main.ts.
Next Steps
Usage
Commands, Queries, Events, Events Store, and Queues with the handler decorators and KubeMQRecord builder.
Module Configuration
forRoot / forRootAsync, register / registerAsync, forTest, and multi-broker setups.
Concepts
How the transport maps NestJS message patterns onto KubeMQ channels and contexts.
Reference
Configuration options, the full decorator/context API, and the error catalog.
Was this page helpful?