Protobuf Schemas
On this page
apiuikit renders AsyncAPI messages and components whose payload (or headers) use a Protobuf schemaFormat. Support works in both with-parser and no-parser entry points, and no extra install is required (the .proto text parser, protobufjs, ships as a regular dependency of apiuikit).
What you need in the document#
AsyncAPI 3.0 wraps non-default-format schemas in a multi-format object. Protobuf conversion runs only when schemaFormat is a Protobuf MIME type (application/vnd.google.protobuf*) and the schema body is a string of .proto source (in YAML, use a block scalar).
Accepted formats include versioned and unversioned variants, for example:
application/vnd.google.protobuf;version=2application/vnd.google.protobuf;version=3application/vnd.google.protobuf(and any other;version=value)
Example#
channels:
lightingMeasured:
messages:
sensorReading:
payload:
schemaFormat: application/vnd.google.protobuf;version=3
schema: |
syntax = "proto3";
message SensorReading {
string streetlight_id = 1;
int32 lumens = 2;
}The same shape works as JSON, with the source as an escaped string:
{
"payload": {
"schemaFormat": "application/vnd.google.protobuf;version=3",
"schema": "syntax = \"proto3\";\nmessage SensorReading { string streetlight_id = 1; int32 lumens = 2; }"
}
}Root message selection#
The converter renders one root message per schema. When the source defines several messages, the root is the one not referenced by any other message; if several qualify, mark one with a // @RootNode comment or the conversion fails with a "Found more than one root proto messages" error (shown fail-soft in the UI).
Comment annotations#
Comments on messages and fields become descriptions. @-annotations inside comments become JSON Schema constraints, mirroring @asyncapi/protobuf-schema-parser:
| Annotation | Effect |
|---|---|
@RootNode |
Marks the root message when several candidates exist |
@Example <value> |
Adds to examples (repeatable) |
@Default <value> |
Sets default |
@Required |
Marks an optional field as required |
@Min / @Max / @Minimum / @Maximum |
minimum / maximum |
@ExclusiveMinimum / @ExclusiveMaximum / @MultipleOf |
Matching JSON Schema keywords |
@Pattern <regex> / @MinLength / @MaxLength |
String constraints |
@MinItems / @MaxItems |
Array constraints on repeated fields |
@Option primitiveTypesWithLimits false |
Drops numeric wire-type ranges from scalars |
protovalidate ((buf.validate.field)) and protoc-gen-validate ((validate.rules)) field options are also translated into constraints.
Limitations#
- Imports resolve only against bundled definitions:
google/protobuf/*(well-known types, via protobufjs),google/type/*(googleapis common types, bundled in aui), and thevalidate/buf.validateoption protos. Any otherimportfails with "Imports are currently not implemented" (rendered fail-soft: raw source plus a warning). map<k, v>fields render as their value type (upstream parity), not as an object withadditionalProperties.
Dependencies#
- With parser: apiuikit registers its own Protobuf schema parser on
@asyncapi/parser. You do not need@asyncapi/protobuf-schema-parser. - Without parser: conversion happens at render time in the component, with no parser needed.
Implementation notes (for contributors)#
This section is for contributors and anyone debugging Protobuf rendering. Application users can skip it.
Pipeline#
| Entry | When conversion runs | Where |
|---|---|---|
With parser (parseAndRender / AsyncAPIRenderer) |
During parse | ProtobufSchemaParser registered on @asyncapi/parser |
Without parser (AsyncAPI) |
At render time | resolveSchemaInput in schemaFormat.ts |
Both paths share the pure converter in helpers/protobuf (protoToJsonSchema, validateProtobufStructure). The converter is ported from @asyncapi/protobuf-schema-parser so behavior stays aligned; only protobufjs (browser-safe) is pulled into the bundle.
Multi-format wrapper and originals#
@asyncapi/parser converts the inner schema in place but leaves the { schemaFormat, schema } wrapper intact, storing the source under x-parser-original-payload. The renderer always unwraps via resolveSchemaInput:
- Detect multi-format wrapper (
schemaFormat+schema). - If the format is Protobuf and the inner value is a string, convert. (The string check is the whole raw-vs-converted discriminator, since
.protosource can only arrive as a string.) - Surface
originalSchema(the raw source, shown verbatim on the JSON tab) and anyconversionErrorfor fail-soft UI.
The with-parser fail-soft path may set x-aui-conversion-error when conversion throws during parse; the renderer picks that marker up the same way.
Why not @asyncapi/protobuf-schema-parser?#
That package declares @asyncapi/parser as a hard runtime dependency (apiuikit keeps it an optional peer) and does not export its bare converter, which the without-parser render path needs. apiuikit's ProtobufSchemaParser mirrors the upstream plugin factory (parser.registerSchemaParser(ProtobufSchemaParser())) with the same MIME types, but uses the in-tree converter and returns a fail-soft error marker instead of throwing.
Key source files#
| File | Role |
|---|---|
helpers/protobuf/protoToJsonSchema.ts |
.proto source → JSON Schema conversion (via protobufjs) |
helpers/protobuf/primitiveTypes.ts |
Scalar type map (int32, bytes, … + x-primitive) |
helpers/protobuf/googleTypes.ts |
Bundled google/type/* definitions for offline imports |
helpers/protobuf/protovalidate.ts / protocGenValidate.ts |
buf.validate / validate.rules option translation |
helpers/protobuf/validateProtobufStructure.ts |
Compile-based validation before convert |
helpers/protobuf/protobufSchemaParser.ts |
@asyncapi/parser schema-parser plugin |
helpers/schemaFormat.ts |
Unwrap, detect Protobuf MIME, resolve for the UI |
helpers/parser.tsx |
Registers ProtobufSchemaParser when parsing |