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

@nest-native/asyncapi

v0.2.0

Published

Decorator-first AsyncAPI 3.0 documentation generator for NestJS event-driven services — the AsyncAPI counterpart to @nestjs/swagger

Readme

@nest-native/asyncapi

[!NOTE] Status: 0.1.1 (0.x). Functional and fully tested (100% coverage), and usable today — but the public API may still change before 1.0. The public API covers: the module (AsyncApiModule.forRoot() / forRootAsync()), the channel and operation decorators (@AsyncApiChannel, @AsyncApiPub, @AsyncApiSub), message and header payloads (@AsyncApiMessage, @AsyncApiHeaders) with DTO ↔ JSON Schema generation, document generation (getAsyncApiDocument), typed transport bindings for Kafka, NATS, MQTT, and AMQP (@AsyncApiServer, @AsyncApiChannelBindings, @AsyncApiOperationBindings, @AsyncApiMessageBindings), and the hosted docs route with viewer (AsyncApiModule.setup). Every generated document passes the official @asyncapi/parser. Per semver, 0.x minor releases can include breaking changes, so pin a version — see the support policy and the CHANGELOG.

What This Is

@nest-native/asyncapi is a community NestJS integration that makes AsyncAPI 3.0 documentation feel like a first-class Nest primitive — the event/message counterpart to @nestjs/swagger. You decorate your @nestjs/microservices handlers and message DTOs, and the package generates a spec-compliant asyncapi.json / asyncapi.yaml served alongside an AsyncAPI viewer.

It mirrors the mental model any Nest user already has from documenting an HTTP API with @nestjs/swagger, while staying faithful to AsyncAPI 3.0's channels/operations/messages separation. It is documentation only — not a runtime transport.

Compatibility

| Runtime | Supported line | | --- | --- | | Node.js | >=20 | | NestJS | 11.x | | AsyncAPI spec target | 3.0 (2.x: best-effort conversion only) | | Transports | Kafka, NATS, MQTT, AMQP (typed bindings) |

The published package has no runtime dependencies. The NestJS packages are declared as peerDependencies, and the AsyncAPI parser and viewer are optional peers installed only when you need them.

Installation

npm i @nest-native/asyncapi

Required peers:

npm i @nestjs/common @nestjs/core reflect-metadata rxjs

Usage

Register the module, then declare channels and operations with decorators. @AsyncApiChannel is the class-level counterpart to @Controller('path'), and @AsyncApiPub / @AsyncApiSub are the method-level counterparts to the HTTP verb decorators. @AsyncApiPub produces an AsyncAPI 3.0 send operation and @AsyncApiSub produces a receive operation.

import { Module } from '@nestjs/common';
import {
  AsyncApiModule,
  AsyncApiChannel,
  AsyncApiPub,
  AsyncApiSub,
} from '@nest-native/asyncapi';

@AsyncApiChannel('orders', { address: 'orders.v1', title: 'Orders' })
class OrdersHandler {
  @AsyncApiPub({ operationId: 'orderPlaced' })
  publishOrderPlaced(): void {}

  @AsyncApiSub({ operationId: 'onOrderShipped' })
  handleOrderShipped(): void {}
}

@Module({
  imports: [
    AsyncApiModule.forRoot({
      defaultInfo: { title: 'Orders Service', version: '1.0.0' },
    }),
  ],
  controllers: [OrdersHandler],
})
export class AppModule {}

Generate the document from a running application — the AsyncAPI counterpart to SwaggerModule.createDocument:

import { getAsyncApiDocument } from '@nest-native/asyncapi';

const document = getAsyncApiDocument(app, {
  title: 'Orders Service',
  version: '1.0.0',
});

Channel ids are explicit by design — they are never derived from the class name. A channel's address defaults to its id; pass address: null to mark an address that is unknown at design time, and operation ids default to the decorated method name.

Message payloads

Attach a payload (and optional headers) to an operation with @AsyncApiMessage and @AsyncApiHeaders. The generated message lands in components.messages, its schemas in components.schemas, and the operation references the channel's message — exactly as AsyncAPI 3.0 prescribes. Every generated document passes the official @asyncapi/parser.

Two validation worlds are supported, mirroring @nestjs/swagger's dual posture:

class-validator DTOs (default). Pass a DTO class. The package reuses the @nestjs/swagger chain to turn it into JSON Schema — no parallel reflector — so install @nestjs/swagger as a peer when you use this path.

import { ApiProperty } from '@nestjs/swagger';
import { IsUUID } from 'class-validator';
import {
  AsyncApiChannel,
  AsyncApiHeaders,
  AsyncApiMessage,
  AsyncApiPub,
} from '@nest-native/asyncapi';

class OrderHeadersDto {
  @ApiProperty()
  @IsUUID()
  traceId!: string;
}

class OrderPlacedDto {
  @ApiProperty()
  @IsUUID()
  id!: string;
}

@AsyncApiChannel('orders', { address: 'orders.v1' })
class OrdersHandler {
  @AsyncApiPub({ operationId: 'orderPlaced' })
  @AsyncApiMessage(OrderPlacedDto, { name: 'OrderPlaced' })
  @AsyncApiHeaders(OrderHeadersDto)
  publishOrderPlaced(): void {}
}

Zod (optional). Pass a Zod schema directly as a { name, schema } source. The generator detects it and converts it with Zod 4's native z.toJSONSchema() in the draft-07 dialect AsyncAPI 3.0 documents default to. zod (^4) is an optional peer, required lazily only when a Zod source is registered — never at module load.

import { z } from 'zod';
import { AsyncApiMessage } from '@nest-native/asyncapi';

const OrderShipped = z.object({ orderId: z.uuid() });

class ShipmentsHandler {
  @AsyncApiSub({ operationId: 'onOrderShipped' })
  @AsyncApiMessage({ name: 'OrderShipped', schema: OrderShipped })
  handleOrderShipped(): void {}
}

Need custom conversion options? Convert yourself and pass the result ({ name, schema: z.toJSONSchema(OrderShipped, options) }) — pre-computed JSON Schema is registered verbatim, so any Zod-to-JSON-Schema converter works.

The message name defaults to the DTO class name (or the schema source name), the content type defaults to application/json, and a payload DTO shared across messages is emitted once under its class name.

Transport bindings

AsyncAPI 3.0 carries protocol-specific detail in bindings. @nest-native/asyncapi ships typed bindings for Kafka, NATS, MQTT, and AMQP across all four binding scopes:

  • @AsyncApiServer(name, host, protocol, options) — declare a broker (class level, repeatable). The protocol and server bindings carry the transport identity and connection metadata.
  • @AsyncApiChannelBindings({ kafka, amqp }) — channel topic/exchange details.
  • @AsyncApiOperationBindings({ kafka, nats, mqtt, amqp }) — consumer groups, queue groups, QoS, delivery mode.
  • @AsyncApiMessageBindings({ kafka, mqtt, amqp }) — message wire-format detail.
import {
  AsyncApiChannel,
  AsyncApiChannelBindings,
  AsyncApiOperationBindings,
  AsyncApiPub,
  AsyncApiServer,
} from '@nest-native/asyncapi';

@AsyncApiServer('kafka', 'kafka.example.com:9092', 'kafka', {
  bindings: { kafka: { schemaRegistryVendor: 'confluent', bindingVersion: '0.5.0' } },
})
@AsyncApiChannel('orders', { address: 'orders.v1' })
@AsyncApiChannelBindings({
  kafka: { topic: 'orders.v1', partitions: 3, bindingVersion: '0.5.0' },
})
class OrdersHandler {
  @AsyncApiPub({ operationId: 'orderPlaced' })
  @AsyncApiOperationBindings({
    kafka: { groupId: { type: 'string' }, bindingVersion: '0.5.0' },
  })
  publishOrderPlaced(): void {}
}

The binding maps are typed for the four v1 protocols but stay open, so any other protocol's spec-compliant binding can be attached verbatim. Bindings are emitted unchanged, so the official @asyncapi/parser remains the source of truth for what is valid.

Docs route with viewer

AsyncApiModule.setup is the AsyncAPI counterpart to SwaggerModule.setup: it serves the generated document and a live viewer over your application's existing HTTP server. It mounts three GET routes — the viewer page at path, the raw JSON at ${path}-json, and the raw YAML at ${path}-yaml (YAML is the canonical AsyncAPI interchange format; JSON is offered alongside it).

import { NestFactory } from '@nestjs/core';
import { AsyncApiModule, getAsyncApiDocument } from '@nest-native/asyncapi';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const document = getAsyncApiDocument(app, {
    title: 'Orders Service',
    version: '1.0.0',
  });
  AsyncApiModule.setup('async-docs', app, document);

  await app.listen(3000);
  // Viewer: http://localhost:3000/async-docs
  // JSON:   http://localhost:3000/async-docs-json
  // YAML:   http://localhost:3000/async-docs-yaml
}

Call setup before app.listen() (the same ordering SwaggerModule.setup requires) so the routes attach before the HTTP server finalizes its routing. It is adapter-agnostic — it works on @nestjs/platform-express and @nestjs/platform-fastify alike.

The viewer page renders with the official @asyncapi/react-component standalone bundle, loaded from a CDN by default so the package ships no viewer runtime dependency. The spec is embedded inline in the page, so it renders without a second request. For air-gapped deployments, self-host the assets and point scriptUrl / stylesUrl at them; customize the page heading with title, and the spec routes with jsonDocumentUrl / yamlDocumentUrl.

AsyncApiModule.setup('async-docs', app, document, {
  title: 'Orders Service — AsyncAPI',
  scriptUrl: '/assets/asyncapi/standalone.js',
  stylesUrl: '/assets/asyncapi/styles.css',
});

Security. The generated spec is served unauthenticated by default and may reveal channel, schema, and server detail you do not want public. Put the docs routes behind your application's existing auth (a guard or a reverse proxy) when the document is sensitive, and never place secrets in example payloads.

Migrating from nestjs-asyncapi

Coming from the abandoned 2.x nestjs-asyncapi? The migration guide maps every 2.x decorator and the AsyncApiDocumentBuilder flow onto this package's 3.0 model, and is validated by porting the nestjs-asyncapi sample app in sample/05-migration-nestjs-asyncapi.

Links