Skip to content

Reusable components

A component in components can be referenced from many places with $ref. The emitter decides on its own what goes there to be shared.

components

SectionWhat goes there
schemasEvery named model, enum, union, and user-declared scalar. A schema written in another language, on its second use
serverVariablesEvery server address variable
messagesEvery @message model
securitySchemesEvery @securityScheme
parametersEvery channel address parameter
correlationIdsA @correlationId two or more messages state alike
serverBindingsA Bindings Object two or more servers carry alike
channelBindingsA Bindings Object two or more channels carry alike
operationBindingsA Bindings Object two or more operations carry alike
tagsEvery tag
externalDocsAn @externalDocs two or more places carry alike

messageBindings follows the same rule as the other three binding sections.

How a component is named

The key of a component is the name in the source.

ComponentKey
TagThe name of the @asyncTag
Channel parameter, server variableThe name of the parameter or variable
Model, enum, union, scalarThe declaration name
Bindings ObjectThe name of the namespace, interface or model the binding decorator is applied to
External Documentation ObjectThe name of the first object that carries it

A name with a character a components key does not allow is rewritten by the schema key rules.

When a property writes a scalar in place

A user-declared scalar goes into components, and a property that uses it writes a $ref.

If the property carries @doc, @summary, @example, @format or @encode of its own, it writes the scalar in place instead, with the property's own settings on top. A $ref cannot override the description or format the scalar already has.

typespec
@doc("An RFC 5321 mailbox address.")
scalar Email extends string;

@message
model Signup {
  contact: Email;

  /** Where the receipt goes. */
  receipt: Email;
}
yaml
components:
  schemas:
    Email:
      type: string
      description: An RFC 5321 mailbox address.
    Signup:
      type: object
      properties:
        contact:
          $ref: "#/components/schemas/Email"
        receipt:
          type: string
          description: Where the receipt goes.

A property that only constrains the value further still writes a $ref. Two constraints on one value both hold, and that is what allOf means.

typespec
@maxLength(254)
scalar Email extends string;

@message
model Signup {
  @maxLength(64)
  short: Email;
}
yaml
short:
  allOf:
    - $ref: "#/components/schemas/Email"
  maxLength: 64

A named union follows the same rule for @encode. Its component describes the union as declared, so a property whose encoding describes one of the variants writes the whole union in place. An encoding that describes no variant is reported as encoding-describes-no-variant, and every variant keeps the shape its own type states.

What the emitter does not extract

SectionWhy not
serversAsyncAPI states that a channel's servers must point at the root servers map. A server in components has no reader.
channelsAn operation addresses the root channels map. Only a channel that no operation points at could go here.
operationsNothing in one document refers to an operation, so an entry here is text no tool resolves.
replies, replyAddressesTwo identical Operation Reply Objects mean two operations share a channel and a set of messages. That is a fact worth reporting to the author, not one to deduplicate.