Repository navigation
API Genie CLI 0.9.0
Highlights
- Translations for all five standards.
apigenie i18n extractandi18n applywork on OpenAPI, Swagger 2.0,
AsyncAPI, Protobuf and GraphQL files: the texts are extracted keyed by JSON pointers, declaration names or schema
coordinates, and translations are put back without touching the rest of the file
(i18n). - Contract testing across OpenAPI, Swagger, AsyncAPI, gRPC and GraphQL, with TLS.
apigenie testruns.http
files (HTTP, gRPC, WebSocket, MQTT and GraphQL requests) and generated requests against a live API, and
apigenie-mock --proxy-tosits between clients and a real server or broker (HTTP, WebSocket, MQTT, gRPC, GraphQL),
checking every request and response against the contract. Both report coverage, JSON and JUnit reports, and fail
CI with--fail-onand--min-coverage. TLS is supported throughout: the mock serves HTTPS, WSS and gRPC over TLS
(--tls-cert,--tls-key), and requests and upstreams can behttps://,wss://andmqtts://, verified against
the system's CA certificates (--ca-cert,--insecure) (test,
mock server). - Code generation for five stacks. Clients and servers for TypeScript (fetch, Express, oRPC, WebSocket, Kafka on
KafkaJS, Zod), Python (httpx, FastAPI, FastStream), Go (net/http, Kafka), Java (Spring clients and servers, Kafka)
and C# (HttpClient, ASP.NET Core, Kafka), from OpenAPI 3.0–3.2 and, for event-driven APIs, AsyncAPI 3.x. Every target
is checked by a conformance suite: snapshots, the target's own compiler and linter, and a run against
apigenie-mock --proxy-to. The generators are a separate executable,apigenie-generator, installed with the CLI
(apigenie-generator). - Web components for every spec type, and
generate docs. Theapg-*custom elements
(@mykulyak/apigenie-web-componentson npm) document OpenAPI, Swagger 2.0, AsyncAPI, Protobuf/gRPC and GraphQL
APIs, with Try it out for HTTP and GraphQL, built on the same engine as the CLI compiled to WebAssembly.
apigenie-generator docscompiles any of these files, several at once, into a docs bundle that the components
render into a static site (npm install && npm run build), with translations, the git changelog and example
files; it replacesgenerate doc html(see Upgrading).
Upgrading
apigenie generateis nowapigenie-generator. The code generators moved out ofapigenieinto a separate
executable,apigenie-generator, installed next to it by every archive and package, the npm package and Homebrew,
and included in themykulyak/apigenieDocker image (docker run --entrypoint apigenie-generator ...). Drop
generatefrom the command line:apigenie generate client fetch spec.yaml -o outbecomes
apigenie-generator client fetch spec.yaml -o out. The options and thecommands.generatesection of the
configuration file are unchanged;apigenie generatefails as an unknown command. The banners of generated files
name the new command. The entries below still call the generatorsgenerate <target>. The design is ADR-123.generate doc htmlis replaced bygenerate docs, with no alias.apigenie-generator docs openapi.yaml -o docs
replacesapigenie generate doc html openapi.yaml --output docs; it takes several inputs of mixed families (OpenAPI,
Swagger 2.0, AsyncAPI, GraphQL, Protobuf) and makes one site, and-c/--config,--i18n LOCALE=FILE,
--package-nameand--package-versionkeep their meaning. The output is no longer an Astro project but a docs
bundle (apigenie-docs.jsonanddocuments/<id>/document.<locale>.json, ADR-122) with apackage.jsonthat
depends on@mykulyak/apigenie-web-componentsinstead of@mykulyak/api-genie-doc-html-template;
npm install && npm run buildstill builds the static site, now intodist/, prerendered from the web components.
--bundle-onlywrites the bundle alone, for a site built by other means. The CLI does not run Node. The
configuration sectioncommands.generate.doc_htmliscommands.generate.docs:html_title_prefixistitle,
i18n.default_localeandi18n.prefix_default_localemove to the top of the section (the locales come from
--i18n),changelogkeeps its name (also--changelog), anddocumentslists the inputs (file,id,
title,proto_paths,examples).pages,operations,resources,search,sidebar,html_meta,
template,openapi_schema,request_code_examples,use_request_body_examples,generate_response_schema,
use_response_examplesandfail_on_generator_errordescribed the Astro layout and have no replacement: the site
has the layout of<apg-api-reference>(navigation with search, one page per operation and schema), themed with
the components' CSS custom properties and::part(). Generated Astro projects keep building with the template they
depend on, but nothing regenerates them: rungenerate docsinto a new directory.- New dependency: Mbed TLS.
apigenieandapigenie-mocklink Mbed TLS 3.6 (Apache-2.0) forhttps://,
wss://andmqtts://connections; release binaries grow by about 0.9 MB. Builds from source get it from vcpkg
(mbedtls >= 3.6.2). Verifying servers needs the system's CA certificates: the Docker images now include them; in
your own minimal images installca-certificates.apigenie creditsandapigenie license --library mbedtlslist
it. - Telemetry is opt-in. The CLI no longer writes
.apigenie.telemetryin the current directory, and sends
nothing. SetAPIGENIE_TELEMETRY_FILEto a path to keep a local telemetry log; old.apigenie.telemetryfiles
can be deleted. i18nhas subcommands.apigenie i18n FILE --output DESTbecomesapigenie i18n extract FILE --output DEST.lintfails on errors.lintexits with status 1 when issues of severityerrorremain (after--fix), so CI
jobs that ran it only for its report fail now; lower the severities in the configuration to keep them passing.apigenie-mock --stubswith a GraphQL schema or an AsyncAPI document exits with status 2 instead of ignoring
the option.
Added
-
generate docsdocuments OpenAPI, Swagger 2.0, AsyncAPI, GraphQL and Protobuf files, several at once, as one static
site: it writes a docs bundle (apigenie-docs.json; per document and locale the resolved document, or the
documentation model of AsyncAPI, GraphQL and Protobuf files; with--changelogthe git changelog, asapigenie changelogcomputes it; the example files next to a GraphQL schema and those listed in the configuration) and the
npm project that renders it with@mykulyak/apigenie-web-components(npm install && npm run build): prerendered
pages with declarative shadow DOM that hydrate in the browser, Try it out, a sitemap, a locale switcher for the
--i18nlocales, a changelog page and the examples.--bundle-onlywrites the bundle alone. Internal: the
docs_bundlelibrary (compileDocsBundle),changelog_helpers(the changelog of any family, shared with the
changelogcommand), andgraphql_describeandprotobuf_describe, which write the documentation models that the
graphqlandprotobufWebAssembly modules used to write themselves, asasyncapi_describedoes for AsyncAPI.
The design is ADR-122. -
generate server spring(OpenAPI) routes QUERY operations andadditionalOperationssuch as COPY: their handlers
carry@ExtensionMethod("QUERY"), which the generatedExtensionMethodConfigurationmatches through a custom
request condition of the request mapping (WebMvcRegistrations, orWebFluxRegistrationswithreactive=true).
pipeDelimitedandspaceDelimitedarray query parameters are split on their separator (@DelimitedParameter),
and query parameters with JSONcontentare read as JSON into their model (@JsonParameter), which is null and
left unvalidated when the parameter is absent; both converters are registered byParameterConversionConfiguration.
Request media types whose bodies have different types get a handler each, named as the methods of
generate client java(updateShipmentforapplication/merge-patch+json,updateShipmentWithJsonPatchfor the
application/json-patch+jsonarray). The newApiExceptionHandleranswers invalid requests with a 400 Problem
(type,title,status,detailand, for constraint violations of the parameters,errorswith thename,
pathandmessageof each), where aConstraintViolationExceptionused to answer 500. Conformance Level 3 of the
target only expects the x-internal operation, which servers leave out, to fail. -
generate server aspnet(OpenAPI) falls back to the default mapping of a discriminator (defaultMapping, or
x-defaultMappingbefore 3.2): unions are read and written by the converters ofgenerate client csharp, written
next to the abstract record and attached with[JsonConverter]instead of[JsonPolymorphic], so a missing or
unmapped discriminator reads as the default type, and the discriminator may be anywhere in the object on .NET 8 too.
Request media types whose bodies have different types get an endpoint and API method each, named as the methods of
the C# client (UpdateShipmentforapplication/merge-patch+json,UpdateShipmentJsonPatchfor the
application/json-patch+jsonarray) and restricted to their media types withAccepts<T>(), so routing picks the
endpoint by Content-Type; the JSON Patch array used to be bound as aShipmentPatchobject (400). Conformance Level 3
of the target passes with only the x-internal operation, which the server leaves out, expected to fail. -
The codegen conformance runner decides that the x-internal operations of the fixture are expected to fail for servers
that leave them out:omitsInternalOperationson a Level 3 entry oftests/conformance/targets.json(set for the
ASP.NET and Spring servers) expects every request of those operations, the request set's and the generated one, to
fail, instead of hand-writtenexpectedentries; a server that starts serving one still fails the level. -
generate client kafkajsandgenerate server kafkajsgenerate TypeScript (Node.js) packages for the Kafka channels
of AsyncAPI 3.x documents, on KafkaJS 2.2.4: the server for the described application (KafkaApp, taking a handler
per received operation, withstart()andstop()), the client for its counterpart (KafkaClient, withconnect(),
listen<Operation>(handler)andclose());perspectiveswaps either. Every sent operation gets a sender with a
send<Message>(message)method per message, which validates the message, writes the constant headers (e.g.
ce_type), the key and the topic, and, for an operation with a reply, sends the request with a new correlation id
unless it has one and resolves with the typed reply, matched by correlation id on one reply consumer per operation
(ReplyTimeoutErrorwhen none arrives in time). Received operations get handler interfaces withon<Message>(message, record)andonUnknown, dispatched byce_typeheader, payload property or deduction; repliers return the reply,
sent with the request's correlation id. Payloads are validated by dependency-free functions generated from the schemas
(MessageValidationError), headers by their constraints. Avro payloads, topics with parameters and replies at
runtime-expression addresses are skipped with a warning. Configured undercommands.generate.client_kafkajsand
commands.generate.server_kafkajs(layout,import_extension,perspective,validation); the design is ADR-120.
The codegen conformance suite checks both commands in both perspectives at Levels 1 and 2 (tscand ESLint) and, at
Level 3, runs the client against the server on the Kafka service container both ways, as for Go and C#. -
generate client wsandgenerate server wsgenerate the replies of operations whosereplyis on the request's
channel: the client gets typedon<Message>handlers for the reply messages and, when the messages have a correlation
id in their payloads,request<Operation>(payload, { timeoutMs })resolving with the reply carrying the request's id;
the server session getssend<Message>methods for them andreplyTo<Operation>(request, reply), which copies the
request's correlation id into the reply. On the AsyncAPI conformance fixture,requestPickup()and
replyToRequestPickup(). Replies on another channel or at a runtime-expression address are still reported as
unsupported. -
apigenie testsends WS regions towss://and MQTT regions tomqtts://(orssl://) URLs, with ports 443 and
8883 by default. Their certificates are checked as forhttps://, with SNI and the URL's host name, so--ca-cert
and--insecureapply. MQTT regions send theirusernameandpasswordsettings in CONNECT (MQTT 3.1.1). A setting
the region doesn't give comes fromAPIGENIE_MQTT_USERNAMEandAPIGENIE_MQTT_PASSWORD. A refusal names the reason
(bad user name or password, not authorized). Credentials show as[redacted]in the console and the JSON and JUnit
reports, as OAuth 2 secrets do, and a URL'suser:password@is shown as***@. These URLs used to fail with "speaks plain WebSocket/MQTT only", and the
credentials were noted as not sent. MQTT 5 is still not supported. The design is the amendment of ADR-110. -
apigenie testwith an AsyncAPI--specchecks HTTP requests against the document's HTTP channels, with the code
and checks of the validating proxy: the channel and operation by path and method (areceiveoperation's HTTP
binding's method, GET for asendone) or by# @operation, areceiveoperation's body, query and header fields
against its messages and a 2XX response against its reply, asendoperation's response against its messages. The
requests count for their operations in the coverage, which used to show them as not tested, and--generatesends
one request per HTTP channel operation (to--base-url, aws://URL taken ashttp://). A path of no HTTP
channel is a note. Bothapigenie testandapigenie-mock --proxy-tonow check thequeryof an operation's HTTP
binding (operation.query.invalid) and the header fields of a message'sheadersand HTTP bindingheaders, its
traits' included (message.headers.invalid); responses other than 2XX are still not checked. The design is
ADR-118, which amends ADR-110 and ADR-112. -
apigenie testruns httpYac's OAuth 2 authorization instead of skipping it:Authorization: oauth2 [GRANT] [PREFIX](andopenid) with theclient_credentials,passwordandrefresh_tokengrants requests a token from
<prefix>_tokenEndpoint(or the OpenID Connect discovery document of<prefix>_issuer) with the<prefix>_clientId,
_clientSecret,_scope,_audience,_username,_passwordand_useAuthorizationHeadervariables, keeps it
for the run, requests it again (with its refresh token) when it expires, and sendsAuthorization: Bearer <token>.
Token endpoints are reached like other requests,https://included (--ca-cert,--insecure); a refused token
request fails its request, which isn't sent. Theauthorization_code,implicitanddevice_codegrants are still
skipped, with a reason naming the grant. With--spec, requests sent with a token are checked by the new
request.authorization.oauth2-schemeandrequest.authorization.oauth2-scopewarnings (the operation has no OAuth 2
scheme, the requested scopes aren't its). Tokens, client secrets, passwords andAuthorizationcredentials show as
[redacted]in the output, the reports and warnings.apigenie test importmaps Postman's client credentials and
password grants to these variables instead of disabling the requests. The design is ADR-117. -
The
asyncapiWebAssembly module (asyncapi.mjs, andasyncapi.web.mjsfor browsers) exports
describe(text, {fileName, files}). It returns the documentation model of an AsyncAPI 3.0 or 3.1 document as plain
JSON ({"apigenieAsyncAPI": 1, …}):- servers, channels, operations and messages with their JSON pointers and source positions;
- references followed and external files given in
filesbundled asapigenie asyncapi bundledoes; - traits applied with JSON Merge Patch, and the defaults of the specification;
- headers and payloads as schemas (other formats, such as Avro, kept with their
schemaFormat), and a position
table; - the problems found as
issues.
AsyncAPI 2.x is an error. It is built on the new
asyncapi_describelibrary; the JSON Merge Patch of traits moved
into theasyncapilibrary (asyncapi/traits.hpp), where the models generators use it too. ADR-119 has the design. -
apigenie-mock, its validating proxy (--proxy-to) andapigenie test --spectake Swagger 2.0 documents: they
convert them to OpenAPI 3.2 in memory, asconvert --to openapi32does, each time the document is read, and write
no file. Locations stay those of the Swagger file: the lines of warnings, the lines and JSON pointers of
x-apigenie-mockproblems, and the newpointerof each operation in the contract reports. What the conversion
can only approximate is told once at startup asinfo:lines with the Swagger file's line and JSON pointer
({"event":"info"}withapigenie test --formatter json). Swagger 2.0 documents used to be refused with exit
status 3. -
apigenie-mock --proxy-to mqtt://host:port(ormqtts://, verified likehttps://upstreams) with an AsyncAPI
document contract-tests a real MQTT broker: the mock's broker relays, each client getting a connection of its own to
the broker with its identifier, version, clean start, keep-alive, will and credentials, and the broker's CONNACK and
SUBACK. Every PUBLISH is checked against the topic's channel: what clients publish against itsreceiveoperations,
with the QoS of their MQTT binding (message.qos.unexpected), what the broker delivers against itssendoperations
(a channel without them: itsreceiveoperations and the replies sent there). In enforce mode invalid messages
aren't forwarded (MQTT 5 clients get reason code 0x99). Wills, refusals and an unreachable broker (server
unavailable) are passed on, clients stay connected across reloads, the log hasmqtt-connectandmqtt-disconnect
events, and coverage,--report,--report-junit,--fail-onand--min-coveragework as for WebSocket.
--proxy-tocan be repeated to proxy a WebSocket server and an MQTT broker at once (proxy.targettakes a list).
The design is ADR-112, which supersedes parts of ADR-097. -
An AsyncAPI document's HTTP channels are proxied to the
http(s)://orws(s)://server of--proxy-tothrough
the OpenAPI proxy's transport and checked against the AsyncAPI document: areceiveoperation's request body against
its messages and a 2XX response's body against its reply, asendoperation's response (GET) against its messages.
In enforce mode invalid requests get 422 and invalid responses are replaced by 502; paths of no channel get 404 or
405. -
The AsyncAPI checks have
channel.parameter.invalid: a value of an address parameter (a topic level, a path segment)
outside the parameter'senum, for WebSocket, MQTT and HTTP channels. -
mqtt::ClientConnection, an MQTT 3.1.1 and 5 client on the event loop (over TLS too), and broker hooks that decide
CONNECT and SUBSCRIBE later and let the owner relay instead of delivering. -
apigenie testruns GraphQL requests instead of skipping them:GRAPHQL URLrequests of httpYac and the JetBrains
HTTP client (the query, then its variables as JSON after a blank line;# @operationis theoperationName) and
POSTrequests whose body is a query are sent as GraphQL over HTTP, and JSON{"query": ...}bodies as they are.
With a GraphQL schema as--spec(.graphql,.graphqls,.gql), each operation is validated against the schema
before it is sent (an invalid one fails its request, not the run, and isn't sent), and each response is checked as
apigenie-mock --proxy-tochecks it: the shape ofdataanderrors, value types,nullin non-null fields that no
error explains,__typenameof abstract types and schema drift. Coverage is per field and per root field
(--min-coverageis the share of fields), and--reportand--report-junitare the GraphQL contract report of
apigenie-mockwith the run'stestsandrequests.--generatesends one request per field ofQueryand
Mutation, with required arguments made up from their types as the mock makes up values;--base-urlis the
endpoint.--severitytakes the GraphQL checks. The design is ADR-111; the GraphQL contract report moved from the
apigenie-mockexecutable into thegraphql_mocklibrary, with the same output. -
apigenie testruns httpYac'sWSandMQTTrequests and checks their messages against an AsyncAPI 3.x--spec.
A region connects to aws://server or anmqtt://broker (MQTT 3.1.1;topic,publish,subscribe,qos,
retainheaders), sends the messages of its body (separated by===,=== wait-for-server) and waits for the
server's until# @expect Ncame or# @timeout(--message-timeout, 5000 ms) passed; the messages received are
the response, a JSON array (?? body $[0].type == pickup.confirmed,?? body $.length == 2,response.messagesin
scripts). The channel comes from the URL's path or the topic (# @channelnames it); messages sent are checked
against the channel's receive operations and messages received against its send operations, with the AsyncAPI
proxy's checks. A message of a request/reply operation is paired with its reply, checked by the new contract checks
message.reply.missing(warn) andmessage.reply.uncorrelated(error, a payloadcorrelationIdthat differs);
correlation ids and reply addresses in message headers are noted as not checkable over MQTT 3.1.1. Coverage per
operation and message and the reports (--report,--report-junit,--formatter json,--min-coverage) are the
AsyncAPI proxy's.--generatesends a region per WebSocket and MQTT channel with the receive operations' example
messages, at--base-url ws://...and the new--mqtt-url. The design is ADR-110, extending ADR-092 and ADR-097. -
apigenie-mock --proxy-tocontract-tests a real gRPC server against its.protofile: the proxy checks the
upstream's messages against their output types (also fields marked[(google.api.field_behavior) = REQUIRED],
under proto3's presence rules, and deprecated fields and enum values), its status (HTTP status, content type,
grpc-status, the percent-encoding ofgrpc-message,grpc-status-details-binas agoogle.rpc.Statuswhose code
isgrpc-status), the number of messages of unary calls and the-binmetadata, with check ids such as
response.message.incompatibleandresponse.status.details-incompatiblethatcontract.severitychanges.
Locations name the field (message[0]/items/2/sku). It counts the calls of each service and method, and writes the
contract reports the OpenAPI, GraphQL and AsyncAPI proxies write (--reportwith"specification": "grpc",
--report-junitwith a test case per method,--fail-on,--min-coverageas the share of methods, exit status
5,GET /__apigenie/contract).--strict(orgrpc.validation.response: enforce) checks each upstream message
before forwarding it and fails the call with INTERNAL. The upstream isHOST:PORT(cleartext HTTP/2) or
https://host[:port](HTTP/2 over TLS). The design is ADR-109. -
apigenie testsendsGRPCrequests of.httpfiles (httpYac'sGRPC host:port/package.Service/Methodwith the
request message as a proto3 JSON body, metadata as headers) with a.protofile as--spec, its imports looked up
in the new--proto-pathdirectories. Unary and server-streaming calls are made over HTTP/2, cleartext or over TLS
forgrpcs://URLs (with--ca-certand--insecure), and checked like the proxy's; a body that isn't a valid message fails the request with the field's path before it is sent.
Assertions and scripts see the status code asstatus(?? status == 0), metadata and trailers as headers and the
message as a JSON body (an array for server streaming). Client- and bidi-streaming requests are reported as skipped
with a warning.--generate --base-url HOST:PORT(orgrpcs://HOST:PORT) sends a request per method with a
generated message. The
reports are the gRPC contract report plus the requests (grpc,grpcStatus). -
apigenie-mock --tls-cert FILE --tls-key FILEserves HTTPS, WSS and gRPC over TLS. Clients that ask forh2by
ALPN, such as browsers and gRPC clients, get HTTP/2. The settings are alsotls.certandtls.keyin the
configuration, andAPIGENIE_MOCK_TLS_CERTandAPIGENIE_MOCK_TLS_KEY. A separate admin port uses the same
certificate, and the MQTT broker stays cleartext. The startup line showshttps://andwss://URLs and
"tls": true. TLS 1.2 and 1.3 come from Mbed TLS; the design is ADR-104. -
apigenie-mock --proxy-toreaches TLS upstreams:https://for the OpenAPI and GraphQL validating proxies,
wss://for the AsyncAPI WebSocket proxy, andhttps://host[:port]for gRPC (HTTP/2 over TLS with ALPNh2,
shown asgrpcs://). Certificates are verified against the system's roots: the macOS keychains, the Windows ROOT
store, the Linux CA bundle, orSSL_CERT_FILEandSSL_CERT_DIR.--ca-cert FILE(repeatable;tls.ca_certs,
APIGENIE_MOCK_CA_CERT) adds authorities, and--insecure(tls.insecure,APIGENIE_MOCK_INSECURE=1) skips
verification. A rejected certificate gets the usual 502 with the reason. -
apigenie testsendshttps://requests, with the same--ca-cert FILEand--insecureoptions. Imported
collections no longer need their HTTPS URLs pointed at a cleartext server. -
generate server goalso takes AsyncAPI 3.x documents and generates a Go module (Go 1.22) for their Kafka channels
on franz-go (github.com/twmb/franz-go/pkg/kgo, pinned at v1.18.1, with a completego.sum): structs, enums and
sealed-interface unions withjsontags andValidatemethods for the payloads, a struct per message (key, typed
headers, payload) validated before it is sent and after it is received, and anAppwith a consumer group and a
handler interface per receive operation (several messages told apart by a constant payload property or header, e.g.
thece_typeof binary-mode CloudEvents; others go toOnUnknown) and a typed sender per send operation. Request/reply
operations with a reply channel return the reply from the sender, matched by its correlation id, and repliers send the
handler's reply with the correlation id copied. Consumer groups and client ids come from the Kafka operation bindings.
cmd/<package>/main.gotakes the brokers from-brokersorKAFKA_BROKERS, wires stub handlers and stops cleanly on
SIGINT and SIGTERM. Channels of other protocols are skipped with an info line, Avro payloads with a warning. Configured
undercommands.generate.server_go.asyncapi; the design is ADR-105. The codegen conformance suite checks both
perspectives at Levels 1 and 2 and, at Level 3, has the application and the counterpart exchange the fixture's Kafka
messages on the conformance workflow's new Kafka service container, including therequestLabelRenderreply, an
unknownce_typeand an invalid payload. -
generate client goalso takes AsyncAPI 3.x documents and generates a Go Kafka client package (a Go 1.22 module on
franz-go v1.18.1, withoutmain.go), by default for the counterpart of the described application and with
perspective: applicationfor the application itself.NewClient(options)creates the producer,Close()closes
every client, andOptionstakes the brokers, a client id and franz-go options passed to every client. A send
operation getsSend<Operation>(ctx, message), which writes the constant headers (e.g.ce_type), the key and the
topic from the bindings; with several messages it takes an interface they implement. A request/reply operation gets
a blockingRequest<Operation>(ctx, message)that sets a fresh correlation id, waits for the reply until the
context's deadline and returns it typed (an interface of the replies when there are several), with one reply
consumer per operation shared by all requests. A receive operation getsListen<Operation>(handler), consuming in the
background with the server's dispatch, validation and repliers. Configured under
commands.generate.client_go.asyncapi; the design is ADR-106. The codegen conformance suite checks both perspectives
at Levels 1 and 2 and, at Level 3, runs the client againstgenerate server goon the Kafka service container both
ways: the server's events and label requests reach the client's listeners and replier, and the client's sends and
requests (concurrent ones and one ending at its context's deadline included) reach the server's handlers. -
Options.ClientIDof the Go Kafka code ofgenerate server goandgenerate client goreplaces the producer's
client id. -
generate server aspnetalso takes AsyncAPI 3.x documents and generates an ASP.NET Core project (.NET 8) for their
Kafka channels on Confluent.Kafka 2.15.1, so a REST API and its events can live in one application: the payload models
ofgenerate client csharp(records, enums, unions read by converters of the System.Text.Json source-generated
context), a record per message (key, typed headers with DataAnnotations, payload) validated before it is sent and
after it is received, and per receive operation a handler interface, registered with dependency injection and resolved
per record, and a consumer hosted as aBackgroundServicein the operation's consumer group (several messages told
apart by a constant payload property or header, e.g. thece_typeof binary-mode CloudEvents; others go to
OnUnknownAsync). Records are committed once their handler returns and handled again when it throws; invalid
records are logged and committed. Each send operation gets a typed sender; request/reply operations with a reply
channel return the reply fromRequest<Message>Async, matched by correlation id, and repliers send the handler's
reply with the correlation id copied. TheAsyncApi:Kafkasection ofappsettings.jsonholds the brokers, topics,
group and client ids (from the Kafka operation bindings) and further librdkafka properties, overridable by
environment variables; stopping the host closes the consumers. Configured under
commands.generate.server_aspnet.asyncapi; the design is ADR-107. The codegen conformance suite checks both
perspectives at Levels 1 and 2 and, at Level 3, runs the application and the counterpart on the conformance
workflow's Kafka service container, as for Go. -
generate client csharpalso takes AsyncAPI 3.x documents and generates a C# Kafka client library (.NET 8 class
library on Confluent.Kafka 2.15.1), by default for the counterpart of the described application and with
perspective: applicationfor the application itself.<Name>KafkaClienthas a producer per channel it sends to,
whoseSend<Message>Asyncwrites the constant headers (e.g.ce_type), the key and the topic from the bindings; a
request/reply operation getsRequest<Message>Async, which sets a fresh correlation id, waits for the reply with a
timeout (ReplyTimeoutor an argument) and aCancellationToken, and returns it typed (an interface of the replies
when there are several), with one reply consumer per client and a pending request per correlation id. Receive
operations get the handler interfaces and hosted consumers ofgenerate server aspnet, with its dispatch,
validation and repliers.Add<Name>KafkaClient(configuration, configure)binds the options to theAsyncApi:Kafka
section and registers the client and its producers, and its builder'sAdd<Operation>Handler<THandler>()registers
a handler with its consumer.--package-nameis the root namespace (default: the title followed by.Client), as
for OpenAPI. Configured undercommands.generate.client_csharp.asyncapi; the design is ADR-108. The codegen
conformance suite checks both perspectives at Levels 1 and 2 and, at Level 3, runs the client against
generate server aspneton the Kafka service container both ways, including concurrent requests, a request timing
out and a cancelled one. -
generate client javaalso takes AsyncAPI 3.x documents and generates a Java Kafka client library (a Maven project
for Java 21 on the Apache Kafka client 4.1.0, Jackson and Hibernate Validator, without Spring), by default for the
counterpart of the described application and withperspective: applicationfor the application itself. It shares
the message records, models, dispatch, validation and repliers ofgenerate server spring.<Name>KafkaClient
(with<Name>KafkaClientOptions: servers, topics, client and group ids, reply timeout, producer and consumer
properties) getssend<Message>(message)per send operation, writing the constant headers (e.g.ce_type), the key
and the topic from the bindings;<operation>(message[, timeout])per request/reply operation, which sets a fresh
correlation id (header, payload pointer orkafka_correlationId) and completes with the typed reply, with one
group-less reply consumer per client; andlisten<Operation>(handler)per receive operation, consuming on a virtual
thread withonUnknownandonErrordefaults.--libraryand-pare errors with AsyncAPI input. Configured under
commands.generate.client_java.asyncapi; the design is ADR-121. The codegen conformance suite checks both
perspectives at Levels 1 and 2 (mvn package,javac -Xlint:all -Werror) and, at Level 3, runs the client against
generate server springon the Kafka service container both ways, including concurrent requests and a timeout. -
generate client pythonalso takes AsyncAPI 3.x documents and generates an asyncio Kafka client package on aiokafka
with the Pydantic models ofgenerate server faststream, by default for the counterpart of the described application
and withperspective: applicationfor the application itself.messages.pyhas a dataclass per message (payload,
headers, key) with headers models and their constant headers;<Name>KafkaClient, an async context manager, gets
send_<message>(),request_<operation>(message, *, timeout=None)(fresh correlation id, typed reply, one
group-less reply consumer per client,TimeoutError) andlisten_<operation>(handler)with abstract handler classes
(on_unknownandon_errordefaults), by the Kafka rules of ADR-102. The package passesmypy --strictand ruff,
and depends onaiokafka[lz4,snappy,zstd], so it reads topics other producers compress.
Configured undercommands.generate.client_python.asyncapi; the design is ADR-121. The codegen conformance suite
checks both perspectives at Levels 1 and 2 and, at Level 3, runs the client's counterpart against the Kafka broker of
generate server faststream's application and the client's application against its counterpart on the Kafka service
container, including concurrent requests and a timeout. -
generate server springalso takes AsyncAPI 3.x documents and generates a Spring Boot application (Maven project)
for their Kafka channels: a record per payload and per message (key, payload, headers) with Jackson and Jakarta Bean
Validation annotations, a@KafkaListenerand a handler interface per receive operation (several messages told apart
by a constant payload property or header, e.g. thece_typeof binary-mode CloudEvents), and a sender over
KafkaTemplateper send operation. Request/reply operations with a reply channel useReplyingKafkaTemplate, and
replies carry the correlation id from thecorrelationIdlocation. Topics, group and client ids (from the Kafka
bindings) and servers go toapplication.yaml; message headers are merged with those of their traits as AsyncAPI
does. Constraints Bean Validation can't express (draft-07dependencies,if/then/else, tuples) become comments.
Channels of other protocols are skipped with an info line, Avro payloads with a warning. Configured under
commands.generate.server_spring.asyncapi; the design is ADR-102. The codegen conformance suite builds both
perspectives at Level 2 and, at Level 3, has the application and the counterpart exchange the fixture's Kafka messages
on an embedded broker (@EmbeddedKafka), including therequestLabelRenderreply. -
generate client gogenerates a Go client for thenet/httppackage of Go 1.22 from an OpenAPI 3.x document, using
the standard library only. OneClientover a configurable*http.Clienttakes functional options (base URL,
request editors, user agent, an option per security scheme such asWithAPIKey), and has a method per operation and
request media type taking acontext.Contextfirst. Each method returns a response struct with one typed field per
documented status and media type (JSON200,ApplicationProblemJSON404 *ProblemDetails) and the raw
*http.Response; statuses of 400 and above also return an*APIErrorwith the RFC 9457 problem details.
text/event-streamandapplication/jsonlresponses are iterators typed fromitemSchema(x-itemSchemain 3.0
and 3.1), binary responses stay open asio.ReadCloser, multipart bodies are structs whose binary parts (from
contentMediaTypeorformat: binary) areFilevalues honouringencoding,contentparameters are sent as
JSON, operation and path servers are honoured (WithOperationServers(false)ignores them), credentials go to the
operations that accept them, andx-internaloperations are left out. Types and validation are shared with
generate server go. Configured undercommands.generate.client_go. -
generate client csharpgenerates a C# client of an OpenAPI 3.0, 3.1 or 3.2 document for .NET 8 (or 9 and 10), built
onHttpClientandSystem.Text.Json: a class library with one client per tag taking theHttpClientin its
constructor (client.Shipments.ListShipmentsAsync()), a client of the whole API, andAdd{Api}Client()registering
them withIHttpClientFactory. Methods areasyncwith aCancellationToken; they return the body of the success
response, or a*Resultby status when statuses have different bodies, and throwApiExceptionwith the RFC 9457
problem details of error responses. Every parameter style is supported, objects andcontentparameters (as JSON)
included; bodies are JSON, text, binary, forms and multipart withFileParts forformat: binaryand
contentMediaTypefields; other media types of bodies and responses are methods of their own
(UpdateShipmentJsonPatchAsync); server-sent events and JSON Lines areIAsyncEnumerable<T>typed byitemSchema
(orx-itemSchema). Operation and path servers are honoured,x-internaloperations left out, and bearer, basic,
OAuth 2.0, OpenID Connect and API key credentials sent byDelegatingHandlers. The models are those of
generate server aspnet, with a source-generatedJsonSerializerContextand converters that read everyoneOf/
anyOfwith a discriminator wherever the discriminator is, falling back todefaultMapping(or
x-defaultMapping). The code builds with-warnaserrorand the .NET analyzers. Configured under
commands.generate.client_csharp. -
The OpenAPI reader reads
itemSchemaof media types anddefaultMappingof discriminators (OpenAPI 3.2), and the
writer keeps them. -
apigenie test import COLLECTION -o DIRimports Collection Format v2.0/v2.1 JSON exports into
folder-based.httptests with environments, bearer/basic/API-key references, upload assets,
inherited scripts and a marker-gated QuickJSpmcompatibility subset. Status-only tests become
??assertions; unsupported script blocks are preserved as comments with source-line warnings,
and OAuth 2 requests are disabled.--specadds operation bindings and saved-response example
overlays without editing the spec.--environmentcan be repeated;--forceopts into replacing
generated files. Authentication secrets are stored only in the generated environment file. -
apigenie testreadsQUERYrequests (the safe method with a body of OpenAPI 3.2) in.httpfiles, and--spec
takes OpenAPI 3.2 documents. -
apigenie testruns the requests of.httpfiles (the httpYac flavour, which the JetBrains HTTP client and VS Code's
REST Client read too) against a live server and validates every request and response against an OpenAPI document
(--spec) with the checks ofapigenie-mock's validating proxy. Files have###regions,{{var}}variables,
@var = valuedefinitions,# @name/# @ref/# @forceRefchaining with{{name.response.body.$.id}}
references,{{ }}scripts and JetBrains> {% %}handlers (QuickJS:request,response,client,exports,
test,assert,console),??assertions, and.envandhttp-client.env.jsonenvironments (--env,
--env-file,--var). Requests are bound to operations by method and path;# @operation <operationId>picks
one,# @operation offskips the checks.--generatesends one request per operation, from the document's
examples or generated values. The run fails with exit status 5 when a request fails or when the contract gate
(--fail-on,errorsby default, and--min-coverage) does;--reportand--report-junitwrite
apigenie-mock's contract report with the requests added. Unknown directives are warnings. GraphQL, gRPC, HTTPS
and OAuth 2 are not supported yet. -
--strip-commentsforformat,overlayandlint --fixdrops the comments of the files they write, which
they keep otherwise (ADR-093): YAML comments of OpenAPI, Swagger and AsyncAPI documents, comments of Protobuf
files and#comments of GraphQL documents, whose descriptions are kept. -
i18n applyapplies translations to Protobuf (.proto) and GraphQL (.graphql,.graphqls,.gql) files, keyed as
i18n extractwrites them: the leading comments of Protobuf declarations and the descriptions of GraphQL definitions
are rewritten in place, in their style (//lines,/* */blocks, block or quoted strings), and every other byte of
the file is kept, comments included, so applying untranslated texts returns the file unchanged. Keys addressing no
comment or description are warnings, or errors with--strict(ADR-103). -
i18n extractextracts the texts of Swagger 2.0 documents, recognized by theirswaggerproperty, as it does for
OpenAPI: titles, summaries and descriptions keyed by JSON pointers, whichi18n applyputs back (ADR-103). -
i18n apply --strip-commentsdrops the YAML comments of a spec or the#comments of a GraphQL file (descriptions are
kept), asformat,overlayandlint --fixdo (ADR-093); it is refused for Protobuf files, whose translated texts
are comments. -
i18n applyapplies translations to OpenAPI and AsyncAPI documents (JSON or YAML): each key of a translation file,
a JSON pointer asi18n extractwrites it, has the string it points to replaced by its value, and everything else
is kept, YAML comments included.--translationscan be repeated (later files override earlier ones), the result
goes to--outputor the standard output in the input format or that of--format, and keys pointing to nothing
are warnings, or errors with--strict. -
apigenie-mock --proxy-to ws://host:portwith an AsyncAPI document is a validating proxy for contract testing of a
WebSocket API: clients of a WebSocket channel are relayed to the real server (handshake headers and subprotocol
passed on, 502 or 504 when it can't be reached), and every message of both sides is checked against the channel's
receive(client messages) andsend(server messages) operations. Violations carry checks such as
message.incompatibleandchannel.send.undeclared, go to the log, and--strictkeeps invalid messages from going
on (the client gets aninvalid-messageorinvalid-upstream-messageproblem instead). Coverage counts each message
of each operation;--report,--report-junit,--fail-on,--min-coverageandGET /__apigenie/contractwork as
for OpenAPI. HTTP channels and the MQTT broker keep being mocked.contract.severityaccepts the new checks. -
apigenie-mock --proxy-to ... --record-dir DIRwith an OpenAPI document writes each exchange the server answered as a
stub file (getPet-1.yaml, orGET_health-1.yamlfor a route of no operation: the request's method, path, query,
headers and body, and the response's status, headers and body), which--stubs DIR(orstubs:in the
configuration) replays without the server: before the document's examples, afterPreferand scenario rules, with
X-Apigenie-Mock-Source: stub:getPet-1.--record-har FILEwrites the whole session through the proxy, the mock's
own answers included, as a HAR 1.2 file when the server stops, withcomment(proxyormock) and_apigenie
(source, operation, upstream status, violations) on each entry. Both hide the values ofAuthorization,Cookie,
Set-Cookie,Proxy-AuthorizationandX-Api-Key;proxy.redactsets the list. Alsoproxy.record_harand
APIGENIE_MOCK_RECORD_HAR. -
apigenie-mock --proxy-mode fallbackwith an OpenAPI document and--proxy-to: every request still goes to the
real server, but when the server can't be reached, doesn't answer in time, or answers 404 or 501 for an operation of
the document, the mock answers as it would without--proxy-to(examples, generated data, scenarios,Prefer).
Such answers carryX-Apigenie-Mock-Upstream-Status, are logged withfallback: trueand aren't
response.status.unknownviolations. The contract report tells the server's answers from the mock's:
summary.sources, each operation'ssourcesandmockedResponses, two JUnit properties and aSources:line in
the summary. Configured underproxy.mode. -
apigenie-mockserves OpenAPI 3.2 documents: thequerymethod and the methods ofadditionalOperations(such as
COPY) are routed, validated and recorded in contract reports like the others. Streams described byitemSchemaare
answered with an empty body. -
A codegen conformance suite runs every OpenAPI generator on one shared, realistic OpenAPI 3.2 fixture, the Carpet
Express Shipping API (data/fixtures/openapi, with its 3.1 and 3.0 variants, Spring and mock overlays and a feature
catalog). Level 1, part of every ctest run, compares each generator's output byte for byte with a checked-in snapshot
and checks a per-target manifest of the features it doesn't support yet. Levels 2 and 3 type-check and lint the output
with the target's own toolchain and run the generated code against the fixture's contract (clients behind
apigenie-mock --proxy-to, servers withapigenie test --generateand a hand-written request set), for the fetch,
C#, Go, Java and Python clients and the FastAPI, Spring, Go, ASP.NET and Express servers, and the zod schemas at Level
2, in a Linux workflow that runs on generator changes and on demand. The results are indocs/codegen_conformance.md;
the design is ADR-098. -
The codegen conformance suite covers the AsyncAPI generators:
generate client wsandgenerate server wsrun on
the Carpet Express Event Platform (data/fixtures/asyncapi), the AsyncAPI 3.0 event side of the same service (Kafka,
WebSocket, MQTT 5, HTTP and AMQP channels, three request/reply styles, traits with a merge trap, bindings for all five
protocols, draft-07 schemas), with a mock overlay and a feature catalog. Level 1 compares their output with
snapshots and checks their manifests (the twelve non-WebSocket channels don't concern them; the reply of a
request/reply operation is not generated yet). Level 2 type-checks and lints the generated packages; Level 3 drives
the generated client and server throughapigenie-mockas a validating WebSocket proxy. The matrix in
docs/codegen_conformance.mdhas an AsyncAPI section; the design is ADR-100. -
apigenie generate server faststreamgenerates a Python FastStream application from the
Kafka, AMQP (RabbitMQ) and MQTT channels of an AsyncAPI 3.x document: a broker per server (URL from an environment
variable), a subscriber per receive operation (topics and patterns, consumer groups, queues, exchanges and routing
keys, QoS from the bindings; several messages dispatched by a constant property) calling a handler you write in
handlers.py, which regenerating keeps, and a publisher with a typed publish function per send operation. Payloads
and headers become Pydantic v2 models, the same asgenerate client python's, with trait headers merged; headers
are typedHeader()parameters. Requests wait for their reply on the document's reply channel by correlation id;
reply addresses in headers becomereply_toarguments. WebSocket and HTTP channels and Avro payloads are skipped
and reported. Configuration iscommands.generate.server_faststream; it is in the codegen conformance suite at
Levels 1 to 3. The design is ADR-101. -
The codegen conformance suite runs
generate server faststreamat Level 3: the conformance workflow has RabbitMQ
(with the fixture's virtual host) and Mosquitto service containers, pinned by digest, next to its Kafka one, and the
generated application runs on the three brokers next to a counterpart. The counterpart publishes the fixture's
examples (MQTT courier positions and sorter scans, AMQP customs decisions) to the application's handlers, receives
what the application publishes (shipment events and label requests on Kafka, job offers on MQTT, customs filings on
thecustomsexchange) and answers the label requests on their reply topic. The MQTT traffic goes through
apigenie-mock's MQTT bridge, whose contract report checks it; the Kafka and AMQP messages and the MQTT 5 user
properties are checked against the fixture in the harness (checkMessages(), ajv). Every item passes. -
apigenie-mock --proxy-to http://host:port/graphqlwith a GraphQL schema is a validating proxy for contract
testing: GraphQL requests are checked against the schema (graphql-js's rules, variables, deprecated usage) and
forwarded to the real server, whose answers are checked field by field against the schema and the request's selection
set (missing and unexpected fields, nulls no error explains, scalar, enum and__typenamevalues, lists, the shape of
errors, statuses and media types). The proxy also introspects the server and reports where its schema differs
(schema.drift,schema.addition). Violations carry checks such asresponse.data.incompatible, go to the log and
X-Apigenie-Mock-Violations-Detail, and--strictanswers bad requests itself and replaces bad answers (502). Field
and root field coverage,--report,--report-junit,--fail-onand--min-coveragework as for OpenAPI.
--proxy-mode fallbacklets examples, scenarios and scripts answer first, and--record-dirwrites the server's
answers as examples the mock replays. -
generate server fastapigenerates a Python FastAPI server from an OpenAPI 3.x document, with the project layout and
options of openapi-generator'spython-fastapigenerator: pydantic 2 models (enums, unions with discriminators,
recursive models, aliases and constraints), a router and a base class to implement per tag, security dependencies for
API keys, HTTP, OAuth2 and OpenID Connect schemes with alternatives and scopes,pyproject.toml, a Dockerfile and
pytest tests. Routes declare their status codes and response classes, parameters and bodies of every kind (forms,
uploads, text, binary) are typed, and the implementation package, the tests and.openapi-generator-ignoreare
never overwritten. Configured undercommands.generate.server_fastapi. -
generate client pythongenerates a Python client of an OpenAPI document, built on httpx (or httpx2) and Pydantic 2:
ClientandAsyncClientclasses with one resource per tag (client.pets.list_pets()), Pydantic models with
Python field names, tagged unions for discriminators andInputvariants forreadOnly/writeOnlyproperties,
all parameter styles, JSON, form, multipart, text and binary bodies, typed errors parsed with the documented schemas,
retries with backoff honoringRetry-After, per-request options, raw and streaming responses, server-sent events,
server variables, and authentication by security scheme, including the OAuth 2.0 client credentials flow. The code
passesmypy --strict. Configured undercommands.generate.client_python. -
generate client javagenerates a Java client of an OpenAPI document as a Maven project (Java 17, Spring Framework
and Jackson versions from the Spring Boot BOM, without Spring Boot): anApiClienton Spring'sRestClient
(--library restclient, the default) orRestTemplate(resttemplate) with one class per tag, whose operations have
op(...),opWithHttpInfo(...),opStream(...)(a lazyStreamoftext/event-streamand JSON Lines items) and
opWith<MediaType>(...)methods for further request media types (updateShipmentWithJsonPatch); every parameter
style, JSON-encodedcontentparameters, JSON, JSON Lines, form, multipart (Resourceparts) and binary bodies,
QUERY and other methods, operation and path servers, credentials per security scheme (bearer, basic, API keys in
headers, queries and cookies) applied to the operations requiring them, andApiException/ProblemDetailsException
(RFC 9457) for errors;x-internaloperations are left out.--library feignand--library http-interface
generate Spring Cloud OpenFeign and Spring HTTP interface clients. Configured undercommands.generate.client_java. -
generate server expressgenerates an Express 5 server stub in TypeScript from OpenAPI 3.x documents: typed handler
interfaces per tag, implemented in files of your own, andcreateRouter(handlers, options), a router which checks
security requirements with security handlers per scheme, decodes parameters in all OpenAPI styles and converts them
to the types of their schemas, parses bodies, validates requests (and optionally responses) with Ajv or with
generated validators without dependencies (validation), answers errors with RFC 9457 problem details and
operations without handlers with 501. It can include the document and an example server. Configured under
commands.generate.server_express. -
generate server orpcgenerates a TypeScript server based on oRPC (https://orpc.dev) from an OpenAPI document: Zod
schemas, a procedure contract per operation with its route, input, output and type-safe errors (one per 4xx/5xx
response, sent with the response body of the document), handler stubs, and a Node.js server serving the procedures
with oRPC'sOpenAPIHandlerand their OpenAPI reference. Inputs use oRPC's compact structure unless the request
needs the detailed one, parameters are converted from strings, and operations with several success responses or
response headers return status, headers and body. Handlers and the server files are written once, so regenerating
keeps them. Targets oRPC 1, or oRPC 2 (beta) withorpc_version: 2. Configured under
commands.generate.server_orpc. -
generate server aspnetgenerates an ASP.NET Core server in C# built on Minimal APIs, for .NET 8 to 10 and
without NuGet packages: records and enums of the schemas, one interface per group of operations whose methods return
Results<...>unions of typed results (generated result types cover statusesTypedResultslacks), endpoints
binding path, query, header and cookie parameters (array styles included) and JSON, text, binary, form and multipart
bodies, and a project withProgram.csand stub implementations written only when missing.oneOfwith a
discriminator becomes[JsonPolymorphic]records, enums keep the values of the document, an endpoint filter
validates requests against the constraints of their schemas (400 validation problems), and operations with security
requirements callRequireAuthorization().layout: sourceswrites only the sources, for existing projects.
Configured undercommands.generate.server_aspnet. -
apigenie-mock --proxy-to http://host:portwith an OpenAPI document is a validating proxy for contract testing: it
forwards every request to the real server and checks the request and the server's response against the document
(parameters, bodies, security, statuses, media types, headers). Violations carry stable checks such as
response.body.incompatibleand show up in the log, inX-Apigenie-Mock-Violations-Detailand at
GET /__apigenie/contract;--strictrejects bad requests (422) and replaces bad responses (502). The mock counts
the operations, request bodies and responses the traffic covered, and writes--report(JSON) and--report-junit
when it stops;--fail-onand--min-coveragemake it exit with 5. Configured underproxyandcontract. -
overlaycommand applies OpenAPI Overlays (versions 1.0, 1.1 and 1.2 of the specification) to an OpenAPI document,
or to any JSON or YAML document:apigenie overlay INPUT --overlay OVERLAY, with--overlayrepeated to apply
several overlays in order. Updates, copies and removals follow the merge rules of the specification, reusable actions
are supported, YAML comments are kept, and actions that select nothing are reported as warnings.--validateonly
checks the overlays, with the line and column of each issue. Targets are RFC 9535 JSONPath queries, functions
(length(),count(),match(),search(),value()) included. Theopenapi_overlayWebAssembly module exports
the sameapplyandvalidate. -
generate server gogenerates a Go server for thenet/http.ServeMuxof Go 1.22 from an OpenAPI 3.x document, using
the standard library only. Names and layering follow oapi-codegen:ServerInterfacereceives bound parameters,
StrictServerInterfacerequest and response objects (typed headers, statuses, JSON, form, multipart, text and binary
bodies). Types carryValidate()methods, and parameters and bodies are validated before the handlers run, with RFC
9457 problem details for failures;oneOf/anyOfbecome structs with one field per variant, optional nullable
propertiesNullable[T]. Patterns end with{$}where needed, and the patternshttp.ServeMuxcan't register together
share one that dispatches to the most specific operation. ASecurityHandlerand middlewares run before parameters
are bound. Configured undercommands.generate.server_go. -
generate schema zodgenerates Zod (v4) schemas, with their inferred TypeScript types, from the root schema and the
$defsof a JSON Schema document (drafts 4 to 2020-12), or from the component schemas of an OpenAPI 3.x, Swagger 2.0
or AsyncAPI document. Objects follow JSON Schema and keep unknown properties unlessadditionalPropertiessays
otherwise; formats, numeric and string constraints, tuples,patternProperties,not,if/then/elseand
dependencies are validated, discriminated unions are detected, and recursive schemas become getters. Configured under
commands.generate.schema_zod. -
generate client wsandgenerate server wsgenerate TypeScript code from the WebSocket channels of AsyncAPI 3.x
documents: a client with one class per channel (browsers and Node.js, no dependencies) and a Node.js server built on
thewspackage, with session classes and handler interfaces. Payloads, address parameters and the query of the
WebSocket binding are typed; received messages get handlers of their own when a property with a constant value tells
them apart. The server implements the described application and the client its counterpart, unless the
perspectiveoption says otherwise. Configured undercommands.generate.client_wsandcommands.generate.server_ws. -
format --checkreports the files that formatting would change, one path per line, and exits with 1 when
there are any, without writing anything. -
GitHub Action (
src/github_action, not published yet) that installs the CLI on Linux, macOS and Windows
runners and runslint,format --checkordiff(against the pull request's base), with annotations on the
files and a job summary. Withsarif: true, lint issues are also uploaded to GitHub code scanning; on pull
requests, thediffreport is posted as a comment that later runs update in place. -
sarifformatter oflint: SARIF 2.1.0 for GitHub code scanning and other dashboards, with paths relative to the
current directory and fingerprints based on JSON pointers, so that issues are tracked across runs. -
apigenie-mock, a mock server for OpenAPI 3.0 and 3.1 documents, installed withapigenieby every package and
published as themykulyak/apigenie-mockDocker image. It answers with the document's examples or with data
generated from its schemas, validates requests (422 with problem details) and its own responses, checks security
requirements, followsPreferheaders (code,example,dynamic,delay,drop,scenario), simulates
latency, jitter, dropped connections and bandwidth limits, and logs every exchange as text or JSON lines. Scenarios
force error states from a configuration file (apigenie-mock.yamlorcommands.mock),x-apigenie-mockdocument
extensions or an admin API under/__apigenie, which also reloads, reseeds and stops the server.--watchreloads
the document and the configuration when they change. Schemas can pick faker functions withx-faker. -
apigenie-mockserves AsyncAPI 3.x documents: WebSocket clients of a channel get its send operations' messages on a
schedule and their messages are checked against its receive operations and answered with their replies; HTTP
channels take and answer messages; an in-house MQTT 3.1.1 and 5 broker serves the channels of mqtt servers. -
apigenie-mockserves the gRPC services of.protofiles over cleartext HTTP/2, on the same port as HTTP:
unary and streaming methods answered from YAML or JSON stub files (--stubs,grpc.stubs) with request and
metadata matchers, templates, delays and error statuses withgoogle.rpcdetails, or with messages generated from
the response types. It honours deadlines and message limits, followsx-apigenie-mock-*metadata, applies
scenarios (grpc_status,grpc_message) and scripts, serves server reflection (v1 and v1alpha) and health checks,
proxies unanswered calls to an upstream server (--proxy-to) and records them as stub files (--record-dir). The
admin API manages stubs and has the call history and averifyendpoint under/__apigenie/grpc. Imports are
looked up in--proto-pathdirectories and among the embedded well-known,google/apiandgoogle/rpcfiles. -
apigenie-mockalso answers OpenAPI documents over cleartext HTTP/2 (prior knowledge). -
apigenie-mockserves GraphQL schemas (.graphql,.graphqls,.gql) at/graphql: GET, POST and batched
requests per GraphQL over HTTP, validated against the schema with the rules and messages of graphql-js, executed
with generated data (by type, field name and custom scalar name, or as graphql-faker's@fake,@examplesand
@listLengthand the mock's@mockdirectives say), full introspection, GraphiQL and the SDL. Entities (types
with anid) keep their values across requests, anduser(id:),users,usersConnection(Relay) and
createUser,updateUser,deleteUser-like fields read and change them. Examples (graphql.examples, example
files,<schema>_examples/) answer operations or fields, cut to the selection set and completed with generated
values; scenario rules match operations and root fields and inject errors at field paths. Subscriptions are served
over WebSocket (graphql-transport-wsand the legacygraphql-ws) and server-sent events. Configured under
graphql. -
apigenie-mockruns JavaScript hooks (--script,scripts):onRequestanswers requests,onResponsechanges
responses and their simulated delays or drops,onMessagechanges or drops AsyncAPI messages,onGraphQL
answers GraphQL operations, with state kept
between requests, logging, seeded random numbers, faker functions and scenarios. -
Linter validates documents against the OpenAPI schema, and more rules support autofixing, including the new
schema-no-optional-nullable-propertiesrule. -
diffcommand (openapi-diff) and the HTML documentation generator are available again. -
diffseverities are configurable per context:requestandresponserule overlays (callbacks and webhooks
swap them),overridesfor single locations, conditions such asif: required, andadd_first_item/
remove_last_itemrules. Schema properties are compared, respectingreadOnlyandwriteOnly. -
diffdetailed reports describe each change in all formats. -
diffcommand compares AsyncAPI 3.x documents: servers, channels, operations, messages and their payloads and
headers, security schemes, bindings (property by property for HTTP, WebSockets, Kafka, AMQP and MQTT) and
components, with the same reports, formatters, exit status and--update-versionas OpenAPI documents. The
severity of a message change depends on whether the application sends or receives the message (sendand
receiverule overlays). Configured undercommands.diff.asyncapi. -
diffcommand compares Protobuf (proto3.proto) files: package, imports, options, messages, fields (matched by
their numbers), oneofs, enums, services, methods, extend blocks, reserved numbers and names, and comments, with the
same reports, formatters and exit status as OpenAPI documents. Type names are resolved before they are compared,
and removing a field whose number the new file reserves is not breaking. Severities can depend onreserved,
deprecatedandwire_compatibleconditions, and options are configured by their names. Configured under
commands.diff.protobuf. -
diffcommand compares Swagger 2.0 documents: host, base path, schemes, media types, paths, operations,
parameters (matched by location and name, the body parameter by location), responses, headers, schemas
(following references to definitions), security definitions and requirements, and tags, with the same reports,
formatters, exit status and--update-versionas OpenAPI documents. Body parameters and consumed media types get
therequestrules, responses and produced media types theresponseones, and definitions the stricter of the
two. Configured undercommands.diff.swagger. -
diffcommand compares GraphQL schemas (.graphql,.graphqlsand.gqlfiles): root operation types, types of
every kind, fields, arguments, input fields, default values, interfaces, union members, enum values, directive
definitions, applied directives and descriptions, with the same reports, formatters and exit status as OpenAPI
documents. Type extensions are merged into their types, and operations are ignored. Severities follow graphql-js's
breaking changes and can depend onrequired,compatible,deprecatedand boolean conditions; directives are
configured by their names. Configured undercommands.diff.graphql. -
changelogcommand builds the changelog of an OpenAPI file from its git history: one entry per commit or per
release tag, or the history of each operation (--by operation, filtered with--operation), as stylish text,
Markdown, HTML or JSON. Files the specification references are followed in each version. -
changelogcommand builds the changelog of AsyncAPI 3.x files too: added, removed and changed operations, channels
and servers, with the changes of a channel's messages shown under the operations using it, rated with the
commands.diff.asyncapirules.--operationselects AsyncAPI operations by id, bysend/receiveand channel
address, or by channel address. -
changelogcommand builds the changelog of Protobuf (.proto) files too: added, removed and changed methods
(namedService.Method), messages, enums, services and extensions, package changes shown like version changes,
rated with thecommands.diff.protobufrules. The file is compared on its own, without the files it imports.
--by operationgroups the changes by method, and--operationselects methods by full name, method name or
service name. -
Swagger 2.0 input support.
-
changelogcommand builds the changelog of Swagger 2.0 documents too: added, removed, deprecated and changed
operations, with the changes of a path item shown under its operations, and the host, base path, schemes, media
types and security of the API as metadata, rated with thecommands.diff.swaggerrules. Files the specification
references are followed in each version. -
changelogcommand builds the changelog of GraphQL (.graphql,.graphqls,.gql) schema files too: added,
removed and changed operations (the fields of the root operation types, named likeQuery.books), scalars, object
types, interfaces, unions, enums, input objects and directive definitions, with changes of the root operation
types, the schema description and the schema directives as metadata, rated with thecommands.diff.graphqlrules.
The file is compared on its own.--by operationgroups the changes by operation, and--operationselects
operations by full name, field name, root type name or operation type (query,mutation,subscription). -
bundlecommand bundles Swagger 2.0 documents and the local files they reference into a single file: referenced
schemas, parameters and responses become entries ofdefinitions,parametersandresponses, and referenced
path items take the content of their files. -
bundlecommand bundles AsyncAPI 3.x documents and the local files they reference into a single file. Root
servers, channels and operations kept in other files take the content of those files, so that operations still
refer to their channels and channel messages; other referenced objects become components. Schemas in other formats,
such as Avro, are copied as they are, and references by URL are kept. -
bundlecommand bundles Protobuf (.proto) files: the input file and the messages, enums and extensions it uses
from the files it imports (searched in the-I/--proto-pathdirectories) are combined into one proto3 file.
Declarations from other packages are renamed with a prefix made from their package, and well-known type imports
are kept. -
formatcommand formats AsyncAPI 3.x documents, configured undercommands.format.asyncapi. -
i18ncommand extracts the texts of AsyncAPI 3.x documents for translation: the titles, summaries and
descriptions of servers, channels, operations, messages, schemas and the other objects, keyed by their JSON
pointers. -
i18ncommand extracts the leading comments of Protobuf (.proto) files for translation, keyed by the fully
qualified name of the message, field, oneof, enum, enum value, service or method they document; enum values are
keyed under their enum, and the comment of the file (that of itssyntaxstatement) under the package name. -
i18ncommand extracts the descriptions of GraphQL (.graphql,.graphqls,.gql) files for translation, keyed
by full name: the schema (schema), types, fields, arguments, input fields, enum values and directives by their
schema coordinates (e.g.Query.search(text:),Genre.POETRY,@key), operations and their variables (e.g.
query FindBooks,query FindBooks($text:)) and fragments (e.g.fragment BookSummary). -
formatcommand formats Swagger 2.0 documents, configured undercommands.format.swagger. -
formatcommand formats GraphQL schemas and operations (.graphql,.graphqls,.gql) in the layout of Prettier,
keeping all comments, and optionally sorts definitions and the members of types. Configured under
commands.format.graphql. -
lintcommand lints AsyncAPI 3.x documents with 31 rules (ported from the OpenAPI ones where they apply, plus
channel-parameters-defined,channel-addresses-uniqueandserver-hosts), rulesets, custom rules and autofixes,
configured undercommands.lint.asyncapi. -
lintcommand lints Swagger 2.0 documents with 46 rules (ported from the OpenAPI ones where they apply, plus
host-defined,schemes-secure,media-types-definedandswagger-validation, which reports the specification
violations found by the Swagger validator), rulesets, custom rules and autofixes, configured under
commands.lint.swagger. -
lintcommand lints Protobuf (proto3.proto) files with 39 rules modelled on buf's: naming conventions, packages
(versions, directories, consistent language options, import cycles between packages), imports (unresolved,
unused, public, weak, cycles, order), enums, services and RPCs, comments and spell checking. Imports are looked up
in--proto-pathdirectories, theimport_pathsof the configuration and the directories above the file, with
the well-knowngoogle/protobuffiles built in.--fixremoves unused imports and sorts imports; an
// apigenie-lint-disable <rules>comment disables rules for a declaration. Configured under
commands.lint.protobufwith therecommended(default),strictandallrulesets. -
lintcommand lints GraphQL schemas and operations (.graphql,.graphqls,.gql) with 87 rules modelled on
graphql-eslint, graphql-schema-linter and Apollo's schema linter: the type system and operation rules of the
specification, naming conventions, descriptions, deprecations (reasons, deletion dates), schema design (root types,
mutations and payloads, unreachable types, identifiers,@oneOf, circular input types), the Relay connection
conventions, ordering, spelling, and operations checked against the schema (unknown fields, types and arguments,
required arguments, deprecated fields, selection depth, identifier selections). Operations are checked against the
files named by--graphql-schemaor by theschemaoption, or against the type system of their own document. A# apigenie-lint-disable <rules>
comment disables rules for a definition. Configured undercommands.lint.graphqlwith therecommended(default),
strict,allandrelayrulesets;--fixdoesn't apply to GraphQL files. -
Minimal telemetry.
-
Linter rules reasoning about schemas:
schema-no-contradictions(constraints rejecting every value, and
properties forbidden by anallOfmember withadditionalProperties: false),schema-oneof-no-overlap(oneOf
branches a single value matches, shown in the report),schema-required-properties-definedand
schema-conditional-effective(if/then/elsewithout effect), all in therecommendedruleset, and
patch-request-body-partial(required properties inPATCHbodies) in thestrictruleset. -
Official release binaries for macOS (arm64), Linux (x64, static, runs on any distribution) and Windows (x64),
plus.deband.rpmpackages, a Homebrew formula, per-platform npm packages and a versioned Docker image. -
generate server expressandgenerate client fetchfollowdiscriminator.defaultMapping(OpenAPI 3.2;
x-defaultMappingin 3.0 and 3.1). Express validates such aoneOfby the discriminating property: with Ajv as an
if/then/elsechain that ends with the default schema, withvalidation: generatedby a dispatch reporting the
same issues. A value whose property matches no mapping, or lacks it, is validated against the default schema instead
of failingoneOf. The types of both targets get a type guard per member (isParcelShipment(value: Shipment)), the
default member's taking the values no mapping matches. The fetch client's conformance snapshots cover OpenAPI 3.1 and
3.0 too.
Changed
-
The documentation smoke run of the codegen conformance suite is
generate docs(test_docs_bundle) instead of
generate doc html, and thee2e/generate_doc_htmlbenchmark cases aree2e/generate_docs. -
apigenie test importwrites the credentials it finds (bearer tokens, basic credentials, API keys, OAuth 2 client
secrets and passwords) to a generatedhttp-client.private.env.jsoninstead ofhttp-client.env.json, which keeps
the other variables and no secret;apigenie testreads both. Thesensitive-environmentwarning names the private
file. -
The web components read AsyncAPI documents with the
asyncapiWebAssembly module, as they read GraphQL and
Protobuf: setasyncapi-wasm-urlon<apg-spec>or<apg-api-reference>, or callconfigureAsyncApiEngine(url).
npm run prerendertakes--asyncapi-wasm. There is no JavaScript reader for AsyncAPI any more; without the module,
AsyncAPI documents fail to load with a message saying what to set. The views are unchanged.
@mykulyak/apigenie-asyncapi-viewreads the module's documentation model; itsparseandtraitsmodules are
gone. Server-rendered pages embed the model, so hydration needs no module. -
The JSON contract reports of
apigenie-mock --report,GET /__apigenie/contractandapigenie test --reportgive
each OpenAPI operation the JSONpointerof the operation in the document (e.g./paths/~1pets/get). -
Internal:
swagger_convertreturns a source map with each conversion, from the JSON pointers of the result to those
of the Swagger 2.0 document. -
apigenie-mock --proxy-towith a.protofile logs request violations instead of failing the call with
INVALID_ARGUMENT, as the OpenAPI, GraphQL and AsyncAPI proxies do;--strictorgrpc.validation.request: enforce
restores it, and a request is then checked before it reaches the upstream (an always-mode proxy forwarded it first).
A mock without--proxy-tokeeps enforcing requests, and now also rejects a request that misses a field marked
[(google.api.field_behavior) = REQUIRED]. A non-200 HTTP answer of the upstream ends the call with the
status gRPC clients make of it (UNAVAILABLE for 503) instead of always UNAVAILABLE, and an upstream answer without
grpc-statusends as UNKNOWN instead of OK. -
--reportand--report-junitofapigenie-mockare accepted for.protofiles, and/__apigenie/contract
answers for them. -
The requester of
generate server aspnet's Kafka code (AsyncAPI) waits for replies on the runtime's new
KafkaReplies, whichgenerate client csharpshares; its behaviour is unchanged. The OpenAPI configurations of
generate client csharpandgenerate server aspnetignore theirasyncapisection instead of rejecting it as an
unknown option. -
generate server aspnet(OpenAPI) writes the recursive DataAnnotations validation ofValidationFilteras
Infrastructure/ModelValidator.cs, which the AsyncAPI Kafka application uses for its messages too; the behavior
is unchanged. -
apigenieandapigenie-mocklink Mbed TLS 3.6 (Apache-2.0), the first runtime library from vcpkg;creditsand
license --library mbedtlslist it. The release binaries grow by about 0.9 MB (macOS arm64:apigenie+3.5%,
apigenie-mock+8.2%). The Docker images now include Alpine's CA certificates. -
apigenie-mock --proxy-tono longer refuseshttps://andwss://targets with exit status 2, and the 426 answer
to gRPC over HTTP/1.1 on a TLS port says to ask forh2by ALPN instead of offeringUpgrade: h2c. -
generate server springis built onopenapi_generator_java, the Java layer it shares withgenerate client java,
whose Feign and HTTP interface writers now generate itsspring-cloudandspring-http-interfacelibraries; their
output is unchanged. Models getdefaultImplfromdiscriminator.defaultMapping(x-defaultMappingbefore 3.2),
name implicit discriminator mappings after theconstvalue of the members (personinstead ofPerson), no
longer require the properties ofanyOf/oneOfalternatives (Person and Company required bothemailandphone
of ContactChannels), and treat anallOfwith only a reference to aoneOfinterface as that interface (3.0
documents produced a class extending an interface). -
generate server go: ananyOforoneOfwhose members only list required properties no longer makes a union of
untyped values, soallOfschemas holding one are merged into structs (instead ofany) andValidate()checks
the alternatives; a discriminator'sdefaultMapping(x-defaultMappingin 3.0 and 3.1) decodes unknown values as
its fallback variant, and an implicit mapping also accepts theconstthe variant gives the property. The runtime's
request binders moved fromruntime_params.gen.goto a newruntime_bind.gen.go. -
The OpenAPI library reads a media type's
itemSchemaand a discriminator'sdefaultMapping(3.2), and their
x-itemSchemaandx-defaultMappingforms in 3.0 and 3.1 documents. -
generate server aspnetandgenerate client csharpshare their C# models (src/openapi_generator_csharp). The
server's output changes in two ways: the implicit discriminator value of aoneOfvariant is theconstof its
discriminator property when it has one (e.g."person"instead of the schema name"Person"), and aoneOfor
anyOfwhose members map to one C# type has that type (e.g.List<string>for strings of theipv4andipv6
formats, instead ofList<object>). -
The contract report of
apigenie-mock(gate, JSON and JUnit) moved into themockandopenapi_mocklibraries,
shared withapigenie test; its output is unchanged. -
formatkeeps the YAML comments of OpenAPI, Swagger and AsyncAPI documents (at the top and the end of the file,
above keys, at the end of lines, inside sequences and between entries); comments move with their keys when
properties are sorted. Before, every comment was dropped, andformat --checkreported commented files that were
formatted. -
lint --fixkeeps the YAML comments of the OpenAPI, Swagger and AsyncAPI documents it rewrites, including those of
the properties a fix replaces, instead of dropping them all. -
formatwrites a Protobuf comment that follows a declaration on the next line (and that protoc attaches to it)
on its own line again, instead of moving it to the end of the declaration's line. -
i18nhas two subcommands:i18n extractextracts texts, asi18ndid, andi18n applyapplies translations.
apigenie i18n FILE --output DESTbecomesapigenie i18n extract FILE --output DEST, which also accepts-o. -
apigenie-mock --stubswith a GraphQL schema or an AsyncAPI document exits with status 2 instead of being ignored;
stubs answer the calls of a.protofile and, now, the operations of an OpenAPI document. -
lintexits with status 1 when it reports issues of severityerror(those remaining after--fix), so CI
jobs fail on them; warnings keep the exit status at 0. -
The CLI binary is about 2.8 MB (14%) smaller: the test-data generator's string tables (names, addresses, words and
the like) are stored compressed and decoded when first used, instead of as pointer tables. -
The built-in English spelling dictionary is stored compressed (about 290 KB less in the binary) and decoded
only when the first spell-check rule runs; the decoded bytes are released once the dictionary is parsed. -
The third-party license texts shown by
license --libraryare stored compressed and decoded only when one is
printed. -
formatreports files that are neither OpenAPI nor AsyncAPI documents and leaves them untouched,
instead of writing empty output. -
Parse errors in JSON and YAML input now report why and where the input cannot be parsed.
-
lintwith several input files writes a single report for thejson,checkstyle,junit,html,sarifand
tapformatters, instead of one document per file. -
diffexit status and--update-versionconsider all changes, whatever the report shows, and a fixed severity
of a node caps the severities of changes inside it (e.g. adding an optional parameter is non-breaking). -
diff --update-versionchanges only the version in the file, keeping its formatting. -
diffconfiguration is validated: unknown node types, properties and severities are reported. -
generate server springbuilds Java sources with a syntax tree instead of text templates. The generated code
is the same, but imports are sorted and blank lines and indentation are consistent. -
unused-shared-componentis enabled again in therecommended(warning),strictandallrulesets, and skips
documents without operations, which are libraries of components for other documents. -
schema-no-optional-nullable-propertiesrecognizes OpenAPI 3.0nullable: true, referenced nullable schemas and
anyOf/oneOfnull branches, findsrequiredinallOfmembers, and skipsPATCHand merge-patch bodies, where
nullclears a value (optionignorePatchBodies). -
spell-check(OpenAPI and AsyncAPI) now checks spelling: it reports each misspelled word of titles, summaries
and descriptions with suggested corrections, using a built-in English dictionary, and skips code, URLs,
identifiers and acronyms. Optionswords(extra words),suggestionsanddictionary/affix(any Hunspell
dictionary) are optional. The rule moved from therecommendedruleset tostrictandall. -
Internal: the Swagger 2.0 to OpenAPI 3.2 conversion behind
convert --to openapi32moved from the CLI into its own
library,swagger_convert, which also reports what each conversion approximates or drops (not shown by the CLI
yet). The output ofconvertis unchanged. -
Internal: a release gate (
release_gate.yaml) runs every test on Linux, Windows and macOS, the tests that build
generated code with Java, Go, .NET and Python, the RealWorld demo, codegen conformance Levels 2 and 3 and the
WebAssembly build; acli-*tag only gets its draft release once the gate passed on the tagged commit.
Removed
generate doc html, the Astro documentation project it generated and the@mykulyak/api-genie-doc-html-template
package it depended on, with thecommands.generate.doc_htmlconfiguration section (see Upgrading). Internal:
openapi_generator_doc_htmlandcode_morph_astro.
Fixed
apigenie-mock --licensewithout a library name prints API Genie's license instead of the usage: an option whose
value is optional counted as given only with a value.generate server springreads request bodies typed by a oneOf without discriminator (JSON Patch operations, Carpet
Express's recursiveSearchFilter): such interfaces had no type information, so Jackson couldn't instantiate them
and the request answered 500. The interface now names aDeserializerbuilt on the generatedOneOfDeserializer,
which reads the one member the value matches: a member that declares all its properties (or takes additional
properties), reads it and, with Bean Validation, is valid. A value matching no member, or several, is a 400.
useDeductionForOneOfInterfaces=truekeeps Jackson's deduction. Strings withformat: uri(java.net.URI) no
longer get@Patternor@Sizeingenerate server springandgenerate client java: Bean Validation can't check
them on a URI and threwUnexpectedTypeException(the server'screateWebhookSubscriptionanswered 500); their
pattern isn't checked.- The Pydantic models of
generate client python,generate server faststreamand the Python Kafka client check
pattern:Annotated[str, matching(r"...")], a validator of_models.pycompiling the pattern with Python'sre
when a value is first checked (Pydantic's default engine rejects look-arounds, back-references and large\w
repetitions, which would break the model). Named string schemas keep their constraints in their aliases, e.g.
ShipmentId: TypeAlias = Annotated[str, matching(r"^shp_[0-9A-Za-z]{24}$")]; a patternrecan't compile, such as
one using\p{L}, isn't checked. generate server faststream: published messages and replies no longer carrynullfor optional fields that weren't
set, which their schemas don't allow. The publish functions and the subscribers' replies send payloads through the
runtime's newencode_message()(the fields that were set), instead of letting FastStream serialize the models with
every field. Subscribers of operations with a static reply channel now return aKafkaResponse,RabbitResponseor
MQTTResponse, and their reply publisher states the reply's schema (schema=).- The code of
generate client wsandgenerate server wspasses typescript-eslint's recommended type-checked rules:
options and handler interfaces that would be empty are type aliases, the client runtime's
WebSocketLike.addEventListenerhas one overload per event instead of ananylistener, and the shared AsyncAPI type
mapper no longer writesunknowninto unions ([key: string]: unknown) or intersections (ananyOfofrequired
lists). - The validators of
generate server express(validation: functions) importpointerTokenonly when a generated
function uses it, so object schemas withadditionalProperties: trueno longer leave an unused import. - Generated values (
apigenie-mockresponses and messages, examples) satisfy an object schema'soneOf/anyOfnext
to itsproperties, such asanyOf: [{required: [phone]}, {required: [email]}]: one alternative is picked and
what it requires is generated. The alternatives used to be ignored, so such objects could lack every property they
ask for. apigenie-mock: the problems of anx-apigenie-mockextension name it by a well-formed JSON pointer
(/paths/~1pets/get/x-apigenie-mock, not/paths//pets/get/...), and by its line when the value has no position
of its own.apigenie-mockgenerates AsyncAPI messages whose schemas use AsyncAPI's stringdiscriminatoror anexternalDocs
given by$ref: such documents made every message without an example fail with "the payload has no schema values
can be generated from". A reply whose message has itscorrelationIdin the payload now carries the request's value
(Carpet Express'srequestPickupgets apickupConfirmedwith itsrequestId).apigenie-mock --proxy-to ws://checks the server's reply to a client message of a request/reply operation against
the reply's messages and itscorrelationId(message.reply.uncorrelated), instead of reporting it as
channel.send.undeclaredon a channel withoutsendoperations (ADR-110).generate server faststreamno longer fails with "The message schemas can't be mapped to Python types" when a payload
schema'sexternalDocsis a$ref, as the AsyncAPI fixture'sCloudEventhas: the reference is followed.- The AsyncAPI contract report counts the requests of HTTP channels, mocked or proxied, as messages of their
operations. generate client csharp: the generated project compiles again: the client of the API is registered with
AddHttpClient<TClient, TClient>(factory), asAddHttpClient<TClient>has no factory overload and bound the lambda to
its configuration callback (CS1503). Unions read by the generated discriminator converters no longer carry
[JsonPolymorphic]/[JsonDerivedType], which System.Text.Json rejects next to a custom converter ("does not support
metadata writes or reads") when sending or reading aoneOfwith a discriminator.generate client csharpandgenerate server aspnet: properties with a default value are settable instead of
init-only, because the System.Text.Json source generator of .NET 8 assigns every init-only property and replaced the
default of an absent one with0/false/null; decimals described as strings (type: string, format: decimal) are
written as JSON strings.generate client python: form body fields whoseencodingsetsstyleorexplodeare written like query parameters
of that style (deepObject:hints[building]=rear) instead of as JSON text. The package passes ruff's default rules:
__all__lists are sorted as RUF022 expects, and the runtime usesX | Yunions andSelf.generate server expresswithvalidation: generated: objects without declared properties (maps), or with only
patternProperties, no longer get validators with constant conditions (if (!(false)),false || ...), which
failed ESLint'sno-constant-condition. The codegen conformance suite's Level 2 now also type-checks and lints a
validation: generatedbuild.generate client fetch: properties ofapplication/x-www-form-urlencodedbodies whoseencodingsetsstyleor
explodeare written like query parameters of that style (deepObject:hints%5Bbuilding%5D=rear, also
pipeDelimited,spaceDelimitedand unexplodedform) instead of as JSON text; the other object properties stay
JSON. The runtime no longer callsString()on values of unknown type, so it passes typescript-eslint's
no-base-to-string.generate server expressroutesQUERYandCOPYoperations (OpenAPI 3.2): their routes were typed with a method
the runtime'sHttpMethodtype lacked, so the generated package didn't compile. An empty form field of a nullable
property (location=foroneOf: [GeoPoint, {type: null}]) is read as null instead of failing validation, and the
runtime passes typescript-eslint's recommended type-checked rules.generate client fetch,generate server expressandgenerate server orpc:anyOf/oneOfalternatives that only
add constraints (anyOf: [{required: [email]}, {required: [phone]}]) no longer add& unknownto the type.generate server aspnet: an empty form field for an object (location=, how form style writes an empty or null
value) is read as null instead of failing to parse as JSON with 400.generate server spring: a@lombok.*annotation in a model'sx-class-extra-annotationdrops the members Lombok
generates for that model and adds Lombok to the pom, asadditionalModelTypeAnnotationsdoes; before, the model kept
its ownequals/hashCodenext to@lombok.EqualsAndHashCodeand the project didn't build without Lombok. Deprecated
parameters no longer get@Deprecated, which has no effect on parameters (javac -Xlintwarns since JDK 21); the
deprecation stays in@Parameter(deprecated = true).generate client pythonandgenerate server faststream:allOfparts withoneOf/anyOfalternatives that only
add constraints, such as Carpet Express'sContactChannels(an email or a phone), are merged like other object
parts, soPersonandCompanyare models instead ofAny. Discriminated unions dispatch on the mapping, on the
schema names of the members it leaves out (the implicit mapping) and on the value each of those members fixes the
property to withconstor a singleenumvalue (partyType: personof a schema namedPerson). Values whose tag
is missing or unknown are read as thediscriminator.defaultMappingschema (x-defaultMappingin OpenAPI 3.0 and
3.1), which joins the union if it isn't a member; before, they matched no model. The unions keep their callable
pydantic.Discriminator, asField(discriminator=...)can neither fall back nor take several tags per model. The
codegen conformance suite checksgenerate client pythonagainst the OpenAPI 3.1 and 3.0 fixtures too.generate server fastapipasses the codegen conformance suite's mypy, ruff and runtime checks without known
failures, on the OpenAPI 3.2, 3.1 and 3.0 fixtures:- Discriminator tags follow the Python models: a member that fixes the property with
constor a singleenum
value gets that value (party_type: Literal["person"]for a schema namedPerson), where the implicit mapping
made itLiteral["Person"]and rejected valid parties. A union with adiscriminator.defaultMapping
(x-defaultMappingin OpenAPI 3.0 and 3.1) dispatches with a callableDiscriminator()that reads values with a
missing or unknown tag as the default schema, which joins the union if it isn't a member. RootModelsubclasses have their type argument (RootModel[int | str]; a forward reference in a cycle), which
mypy --strictasked for.- A request body with several JSON media types, such as
application/merge-patch+jsonand
application/json-patch+json, is validated against the schema of the request'sContent-Type(415 for another
one); the route took only the first media type's schema. The body parameter is the union of the schemas and the
served OpenAPI document lists every media type. - Integer enums in parameters and form fields convert the request's text (
dpi=300);Literal[203, 300, 600]
rejected every value. - Multipart file parts described with
contentMediaTypeorcontentEncoding: binary(OpenAPI 3.1 and 3.2), not
onlyformat: binary, areUploadFiles, and arrays of themlist[UploadFile]. - Imports are sorted the way Ruff's isort rules expect (case-insensitive, numbers by value, long single-name imports
wrapped), and the imports at the end of modules of a cycle no longer carry a# noqa: E402that Ruff reports as
unused.
- Discriminator tags follow the Python models: a member that fixes the property with
apigenie test --generatesends multipart file parts (format: binary,contentMediaTypeor
contentEncoding: binary) with a file name and the Content-Type of their encoding, and an array as a part per item;
servers that only take parts with a file name as files, such as FastAPI's and ASP.NET Core's, rejected the generated
requests.generate client pythonandgenerate server faststream: an object schema with properties of its own andoneOf
oranyOfalternatives that are objects (each narrowing a property or requiring others) becomes a union of one
model per alternative with the object's properties merged in. The properties were lost (a union of classes holding
only the alternatives' properties), andanyOfofrequiredlists, such as "an email or a phone", wasAny.- The CLI no longer writes
.apigenie.telemetryin the current directory; set
APIGENIE_TELEMETRY_FILEto keep a local telemetry log. apigenie-mockandapigenie testtype the fields of form and multipart bodies (and deepObject and delimited
parameters) whose properties come fromallOfmembers, references included:residential=falseof a body
allOf: [$ref Address, {...}]is the booleanfalse, not the string. They were validated as strings, so valid
requests were reported or rejected with 422.- YAML output quotes strings that YAML 1.1 parsers (PyYAML, SnakeYAML, go-yaml v2) read as booleans, numbers or
merge keys:yes,No,ON,off,y,N,0b101,1_000,1:30,<<and the like. Before,bundle,
overlay,lint --fix,convertandformatwith thebest-fitstyle wrote them plain, so other tools read
enum: [yes, no]as booleans and1:30as 90. apigenie-mockvalidates requests and responses whose schemas refer to themselves (trees, nested filters, recursive
oneOfs). They were accepted without any check, in OpenAPI and AsyncAPI documents alike. The lint rules
schema-no-contradictionsandschema-oneof-no-overlapnow analyze such schemas too.- OpenAPI 3.2 documents: examples written with
dataValueand media types that refer tocomponents/mediaTypesare
read. Generators no longer drop them (Spring rendered such examples asnull, Go typed such problem responses as
any), andapigenie-mockanswers with those examples. generate server fastapiroutes the OpenAPI 3.2querymethod and the methods ofadditionalOperations(such as
COPY) with@router.api_route(..., methods=[...]). They were emitted as@router.query/@router.copy, which
APIRouterdoesn't have, so a server generated from a document with such an operation failed to import.convert --to openapi32converts the structure of Swagger 2.0 documents, not only their references: body and
formDataparameters become request bodies with the media types ofconsumes(files asmultipart/form-data),
collectionFormatbecomesstyleandexplode, response schemas, headers and examples move intocontentper media
type ofproduces, global body parameters becomecomponents.requestBodies, and references to parameters and
responses point intocomponents. Schemas gettype: fileas binary strings, object discriminators, numeric
exclusive bounds andx-nullableas anulltype. Before, most converted documents could not be read (2163 of the
2168 Swagger documents of the openapi-directory corpus convert into readable documents now, the others are invalid).- Many memory-safety and robustness issues in the parsers, bundler, reader and linter.
diffchangelog reports rate added, removed and modified operations by their own changes rather than their
path's, report request body changes as such instead of as response codes, and no longer list a removed
deprecated operation as deprecated.generate server springnumbers enum constants whose names collide (e.g. the values+1and-1, both named
_1), like openapi-generator, so the generated models compile.testreports a rejected certificate as such forwss://,mqtts://andgrpcs://URLs whose host name has
several addresses: it stops at the first address that answers instead of trying the others and reporting the
last one's "Connection refused" (on macOS,localhostis 127.0.0.1 and ::1, and a server often listens on one).- The YAML and JSON writers report an alias of a collection that contains it as soon as they meet it again,
instead of after expanding it to the depth limit, which overflowed the JavaScript stack of the WebAssembly
build. generate server springwithuseSpringBoot4no longer declaresspring-boot-starter-restclient(or
-webclient) twice, which Maven rejects as a duplicate dependency.