Asyncapi

AsyncAPI 3.0 emitter for pubsub / WebSocket / SSE channels; complements b.openapi. Operators describe their pubsub / websocket / kafka / mqtt surfaces as a single document the framework serves at /asyncapi.json (or .yaml) for downstream tooling.

The builder is FRAMEWORK-FACING: it produces a valid AsyncAPI 3.0 document, but the operator's hand-written contract is the source of truth — it does NOT auto-walk b.pubsub topics or b.websocketChannels subscriptions (operators frequently want a smaller / different surface published than what is in-process).

Builder fluent surface: channel(id, opts) registers a channel, operation(id, opts) registers a send/receive operation that $refs an already-registered channel (operations referencing undeclared channels throw asyncapi/dangling-channel), schema() / message() / parameter() / correlationId() / security.add() / security.require() / tag() / server() register components. Terminal calls are toJson() / toJsonString(indent) / toYaml(). Typed binding builders for websockets / kafka / amqp / mqtt / http live on b.asyncapi.bindings; reusable trait builders on b.asyncapi.traits.

b.asyncapi.create(opts) #

0.6.30
{
  info:               { title, version, description?, contact?, license? },   // REQUIRED — title + version are non-empty strings
  servers:            { serverId: { host, protocol, description?, ... } },    // map keyed by id; each entry needs host + protocol
  defaultContentType: string,                  // defaults to "application/json"
  security:           array,                   // doc-level security requirements [{ schemeName: ["scope"] }, ...]
  externalDocs:       { url, description? },
  tags:               array,                   // [{ name, description? }, ...] — seed; builder.tag() appends more
  id:                 string,                  // optional document identifier (e.g. "urn:com:acme:events")
}

Build a fluent AsyncAPI 3.0 document builder. opts.info is required (title + version). opts.servers is a map keyed by server id, each entry carrying host + protocol. Returns a chainable builder; terminal calls are toJson(), toJsonString(indent), and toYaml(). toJson() cross-checks every doc-level and per-operation security requirement against components.securitySchemes and throws AsyncApiError("asyncapi/dangling-security") on a missing scheme.

var aapi = b.asyncapi.create({
  info:    { title: "Acme Events", version: "1.0.0" },
  servers: { production: { host: "broker.acme.example.com:9092", protocol: "kafka" } },
});
aapi.channel("orders.created", {
  address:  "orders.created",
  messages: { OrderCreated: { payload: { type: "object", properties: { id: { type: "string" } }, required: ["id"] }, contentType: "application/json" } },
  bindings: { kafka: b.asyncapi.bindings.kafka({ topic: "orders.created", partitions: 4 }) },
});
aapi.operation("publishOrderCreated", {
  action:  "send",
  channel: "orders.created",
  summary: "Publish an order-created event",
});
var doc = aapi.toJson();
doc.asyncapi;                                    // → "3.0.0"
doc.operations.publishOrderCreated.action;       // → "send"
doc.operations.publishOrderCreated.channel.$ref; // → "#/channels/orders.created"

b.asyncapi.parse(jsonStringOrObject) #

0.6.30

Parse + validate an external AsyncAPI 3.0 document. Throws on invalid JSON or non-object input; otherwise returns { doc, errors, valid }. errors is an array of strings — empty on a valid document. Operations must declare action: "send" | "receive" and a channel.$ref resolving to a declared channel; server entries need both host and protocol; doc-level security must reference declared schemes.

var result = b.asyncapi.parse('{"asyncapi":"3.0.0","info":{"title":"x","version":"1.0.0"}}');
result.valid;       // → true
result.errors;      // → []

var bad = b.asyncapi.parse({
  asyncapi: "3.0.0",
  info:     { title: "x", version: "1.0.0" },
  channels: {},
  operations: { pub: { action: "send", channel: { $ref: "#/channels/missing" } } },
});
bad.valid;          // → false
bad.errors[0];      // → 'operations.pub.channel: $ref "#/channels/missing" does not resolve to a declared channel'

Last updated 2026-08-08T16:39:49.652Z by seeder.