# `AsyncApiSpex.Channel`
[🔗](https://github.com/jamescarr/ankusa/blob/async_api_spex-v0.2.0/packages/async_api_spex/lib/async_api_spex/channel.ex#L1)

A channel: a topic, exchange and routing key, subject, or any other address a
message is sent to or received from.

`address` is `nil` when the address is computed at runtime and cannot be
described statically; in that case `parameters` must be empty. `messages` maps
a channel-local key to a message, which may be a `%AsyncApiSpex.Message{}`, a
`%AsyncApiSpex.Reference{}`, or a module that exports `__async_api_message__/0`
(moved into `components.messages` by `AsyncApiSpex.resolve/1`).

## Declaring a channel on the module that uses it

`use AsyncApiSpex.Channel` decorates the module that publishes to (or consumes
from) a channel. It declares the channel, the broker it lives on, and the
operation, so `use AsyncApiSpex.Spec` can assemble a document from the modules
your application already has:

    defmodule Shop.Kafka.OrderProducer do
      use AsyncApiSpex.Channel,
        address: "shop.orders",
        server: [id: "kafka", host: "kafka:9092", protocol: "kafka"],
        messages: [Shop.Events.OrderCreated, Shop.Events.OrderShipped],
        bindings: %{"kafka" => %{"partitions" => 12}}

      def publish(event), do: # ... produce to "shop.orders"
    end

Options:

  * `:address` (required) — a string literal, or the literal `nil` when the
    address is computed at runtime.
  * `:id` — the channel id in the document; a string literal matching
    `~r/\A[A-Za-z0-9_-]+\z/`. Defaults to `:address` with every
    other character replaced by `_` (`"shop.orders"` becomes `"shop_orders"`).
    Required when `:address` is `nil`.
  * `:server` (required) — a keyword list literal with `:host` and `:protocol`
    and optionally `:id` (default: the protocol), `:protocol_version`,
    `:pathname`, `:title`, `:summary`, `:description`, `:tags`, `:bindings`.
    Values are evaluated when the document is built, so
    `System.get_env/2` and `Application.get_env/2` work.
  * `:messages` (required) — a non-empty list of modules, each using either
    `AsyncApiSpex.Message` or `AsyncApiSpex.Schema`. A schema module becomes a
    message in `components.messages`, named after the schema, with `:content_type`.
  * `:action` — `:send` (default) when this module publishes, `:receive` when
    it consumes.
  * `:content_type` — the content type of messages derived from schema
    modules. Defaults to `"application/json"`.
  * `:title`, `:summary`, `:description`, `:parameters`, `:tags`, `:bindings`,
    `:extensions` — the same fields of the channel struct.
  * `:operation` — a keyword list literal of `:title`, `:summary`,
    `:description`, `:tags`, `:bindings`, `:extensions` for the operation.

Unknown options and invalid literals raise `ArgumentError` at compile time.

The module gets `channel/0`, returning the `t:t/0`, and
`__async_api_channel__/0`, returning a map with the channel `:id`, the
`:server` as `{id, server}`, the `:channel`, the `:operation` as
`{id, operation}` (its id is `"<action>-<channel id>"`), and `:messages`, the
`components.messages` entries derived from schema modules. Message keys on the
channel are the message names with every character outside
`A-Za-z0-9_-` replaced by `_`.

`channel/0` alone is not a complete document fragment: a message derived from
a schema module is a reference to `#/components/messages/<name>`, and that
message is only in `__async_api_channel__/0`'s `:messages`. Use
`AsyncApiSpex.Spec`, which assembles all of it; if you build a
`%AsyncApiSpex.Document{}` from `channel/0` yourself, add `:messages` to
`components.messages`, the server, and the operation too, or
`AsyncApiSpex.validate/1` reports the unresolved reference.

# `t`

```elixir
@type t() :: %AsyncApiSpex.Channel{
  address: String.t() | nil,
  bindings: map() | nil,
  description: String.t() | nil,
  extensions: map(),
  messages: %{
    optional(String.t()) =&gt;
      AsyncApiSpex.Message.t() | AsyncApiSpex.Reference.t() | module()
  },
  parameters: %{optional(String.t()) =&gt; AsyncApiSpex.Parameter.t()},
  servers: [AsyncApiSpex.Reference.t()] | nil,
  summary: String.t() | nil,
  tags: [AsyncApiSpex.Tag.t()] | nil,
  title: String.t() | nil
}
```

# `__using__`
*macro* 

Declares the channel, its server, and its operation on the calling module.

See the module documentation for the options.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
