apigenie-generatorAsyncAPI serversserver kafkajs
server kafkajs
Generate a TypeScript (Node.js) Kafka application of an AsyncAPI document, on KafkaJS.
Usage
apigenie-generator server kafkajs [...OPTIONS] INPUT_FILE
Description
The input must be an AsyncAPI 3.x document. Documents referencing other files are bundled first.
The generator handles the Kafka channels: channels of a server whose protocol is kafka or
kafka-secure, or with a kafka binding when the document has no servers. Other channels are
skipped with an info message. The generated code runs on Node.js with
KafkaJS 2.2.4, its only dependency.
The application is the one the document describes: it sends the messages of send operations and
receives those of receive operations. Set the perspective option to counterpart to generate
the other side.
import { KafkaApp } from "order-service-kafka-app";
const app = new KafkaApp({ brokers: ["localhost:9092"] }, {
handleOrderCommands: {
onPlaceOrderMessage: (message) => ({ payload: { requestId: message.payload.requestId, orderId: "o-1" } }),
onCancelOrderMessage: () => undefined,
},
});
await app.start();
await app.publishStockLevels.sendStockLevelMessage({ key: "ABC-0001", payload: { sku: "ABC-0001", quantity: 3 } });
await app.stop();
KafkaApp takes the handlers of all received operations. start() connects the producer and the
consumers and resolves once every consumer joined its group; stop() commits, leaves the groups
and disconnects. Each sent operation has a sender property.
Every sent operation gets a sender property with a send<Message>(message) method per message.
It validates the message, sets the constant headers (e.g. ce_type) and resolves once the brokers
have it. A message is { key?, headers, payload }, with the headers under their names on the wire
(ce_id). The method of an operation with a reply sends the request with a new correlation id
unless it has one, and resolves with the reply: the reply message, or { name, message } when
there are several. It rejects with ReplyTimeoutError when no reply arrives in time
({ timeoutMs }, KafkaOptions.replyTimeoutMs, 30 seconds by default).
Every received operation gets a handler interface: on<Message>(message, record) for each of its
messages and an optional onUnknown(record). Records are matched to messages by their ce_type
(or other constant) header, by a constant payload property, or, failing both, by the first message
whose payload is valid. The handlers of an operation with a reply return the reply (or
undefined for none), which is sent with the request’s correlation id. Invalid records are
reported to KafkaOptions.onError and skipped. A handler that throws is reported too and the
record is retried (KafkaJS doesn’t commit it).
Payloads and headers are validated against their schemas by generated functions without
dependencies; invalid messages throw MessageValidationError, whose issues point into
/headers or /payload. KafkaOptions takes the brokers, the producer’s clientId, config
(KafkaJS options for every client: ssl, sasl, retry, logLevel, …), groupIds replacing
the generated consumer groups, fromBeginning (true by default) and onError. The generated code
creates no topics.
The package contains src/types.ts (payload types), src/messages.ts (message and header
interfaces), src/kafka.ts (servers, topics, ids, senders, handlers and the KafkaApp),
src/codecs.ts (validators and the descriptions of the messages the runtime works with),
src/runtime.ts, src/validation_runtime.ts and src/index.ts, with package.json and
tsconfig.json.
Not supported, and reported as warnings: Avro payloads, topics with parameters, replies at
runtime-expression addresses, and replies without correlation ids. No security code is generated
(pass KafkaJS’s ssl and sasl in KafkaOptions.config).
apigenie-generator client kafkajs generates the other
side on the same runtime. The design is ADR-120.
Extensions
| Extension | Effect |
|---|---|
x-apigenie.codegen.name |
name of the type of a component schema |
x-apigenie.codegen.disabled |
true on a channel or an operation leaves it out (with the operations of a channel left out) |
The extensions can live in an overlay for this target instead of in the document, e.g.
kafkajs.overlay.yaml:
overlay: 1.0.0
info:
title: TypeScript names
version: 1.0.0
actions:
- target: $.components.schemas.Order
update:
x-apigenie:
codegen:
name: PurchaseOrder
- target: $.operations.publishAudit
update:
x-apigenie:
codegen:
disabled: true
apigenie-generator server kafkajs asyncapi.yaml --overlay kafkajs.overlay.yaml -o out
Options
-c, –config
Path to the configuration file to use. See the “Configuration” section for more information.
–overlay OVERLAY
Path to an OpenAPI Overlay (1.0 to 1.2) applied to the input before generating, e.g. one setting the
extensions of the “Extensions” section. Can be repeated: the overlays apply in order, after those
listed under commands.generate.server_kafkajs.overlay in the configuration file (with paths
relative to it). Warnings and errors about a value an overlay set point to the overlay. The overlays
apply to the AsyncAPI document bundled with the files it references.
–strict
Makes an overlay action whose target selects nothing an error (exit status 2, nothing is generated)
instead of a warning (OVERLAY:LINE:COL: action #N (TARGET) selects no nodes.).
-o, –output
Directory where the package is generated.
–package-name
Name of the generated package. Defaults to the title of the API followed by -kafka-app.
It is also the base of the generated consumer group and client ids.
–package-version
Version of the generated package. Defaults to the version of the API.
Configuration
version: '1.0'
commands:
generate:
server_kafkajs:
layout: package
import_extension: .js
perspective: application
validation: true
| Option | Description |
|---|---|
layout |
package (default): an npm package with sources in src/; sources: the sources only |
import_extension |
Extension of relative imports: .js (default, Node.js) or an empty string (bundlers) |
perspective |
application (default): the described application; counterpart: its counterpart |
validation |
true (default): validate payloads against their schemas; false: check the headers only |
Unknown options are errors.