asyncapi/
channel.rs

1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5    ChannelBinding, ExternalDocumentation, Message, OperationBinding, OperationTrait, Parameter,
6    ReferenceOr, Tag,
7};
8
9/// Describes the operations available on a single channel.
10///
11/// # Examples
12/// ```json
13/// {
14///     "description": "This channel is used to exchange messages about users signing up",
15///     "subscribe": {
16///         "summary": "A user signed up.",
17///         "message": {
18///         "description": "A longer description of the message",
19///         "payload": {
20///             "type": "object",
21///             "properties": {
22///             "user": {
23///                 "$ref": "#/components/schemas/user"
24///             },
25///             "signup": {
26///                 "$ref": "#/components/schemas/signup"
27///             }
28///             }
29///         }
30///         }
31///     },
32///     "bindings": {
33///         "amqp": {
34///         "is": "queue",
35///         "queue": {
36///             "exclusive": true
37///         }
38///         }
39///     }
40/// }
41/// ```
42///
43/// ```yaml
44/// description: This channel is used to exchange messages about users signing up
45/// subscribe:
46///   summary: A user signed up.
47///   message:
48///     description: A longer description of the message
49///     payload:
50///       type: object
51///       properties:
52///         user:
53///           $ref: "#/components/schemas/user"
54///         signup:
55/// bindings:
56///   amqp:
57///     is: queue
58///     queue:
59///       exclusive: true
60/// ```
61///
62/// Using `oneOf` to specify multiple messages per operation:
63///
64/// ```json
65/// {
66///     "subscribe": {
67///         "message": {
68///         "oneOf": [
69///             { "$ref": "#/components/messages/signup" },
70///             { "$ref": "#/components/messages/login" }
71///         ]
72///         }
73///     }
74/// }
75/// ```
76///
77/// ```yaml
78/// subscribe:
79///   message:
80///     oneOf:
81///       - $ref: '#/components/messages/signup'
82///       - $ref: '#/components/messages/login'
83/// ```
84#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
85#[serde(rename_all = "camelCase")]
86pub struct Channel {
87    /// Allows for an external definition of this channel item. The referenced structure
88    /// MUST be in the format of a
89    /// [Channel Item Object][crate::Channel].
90    /// If there are conflicts between the referenced definition and this Channel Item's
91    /// definition, the behavior is *undefined*.
92    #[deprecated(note = "The $ref field in Channel Item Object is now deprecated
93        from AsyncAPI 2.3.0. The current plan is that the $ref field will be 
94        removed from Channel Item Object in AsyncAPI 3.0, and replaced with 
95        Reference Object.")]
96    #[serde(rename = "$ref")]
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub reference: Option<String>,
99    /// An optional description of this channel item.
100    /// [CommonMark syntax](https://spec.commonmark.org/) can be used for rich
101    /// text representation.
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub description: Option<String>,
104    /// The servers on which this channel is available, specified as an optional unordered
105    /// list of names (string keys) of [Server Objects][crate::Server] defined in the
106    /// [Servers Object][crate::Server] (a map). If `servers` is absent or empty then this
107    /// channel must be available on all servers defined in the [Servers Object][crate::Server].
108    #[serde(default, skip_serializing_if = "Vec::is_empty")]
109    pub servers: Vec<String>,
110    /// A definition of the SUBSCRIBE operation, which defines the messages produced
111    /// by the application and sent to the channel.
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub subscribe: Option<Operation>,
114    /// A definition of the PUBLISH operation, which defines the messages consumed
115    /// by the application from the channel.
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub publish: Option<Operation>,
118    /// A map of the parameters included in the channel name. It SHOULD be present only
119    /// when using channels with expressions (as defined by
120    /// [RFC 6570 section 2.2](https://tools.ietf.org/html/rfc6570#section-2.2)).
121    ///
122    /// Describes a map of parameters included in a channel name.
123    ///
124    /// This map MUST contain all the parameters used in the parent channel name.
125    ///
126    /// # Examples
127    ///
128    /// ```json
129    /// {
130    ///     "user/{userId}/signup": {
131    ///         "parameters": {
132    ///             "userId": {
133    ///                 "description": "Id of the user.",
134    ///                 "schema": {
135    ///                    "type": "string"
136    ///                 }
137    ///             }
138    ///         },
139    ///         "subscribe": {
140    ///             "$ref": "#/components/messages/userSignedUp"
141    ///         }
142    ///     }
143    /// }
144    /// ```
145    ///
146    /// ```yaml
147    /// user/{userId}/signup:
148    ///   parameters:
149    ///     userId:
150    ///       description: Id of the user.
151    ///       schema:
152    ///         type: string
153    ///   subscribe:
154    ///     $ref: "#/components/messages/userSignedUp"
155    /// ```
156    #[serde(default, skip_serializing_if = "IndexMap::is_empty")]
157    pub parameters: IndexMap<String, ReferenceOr<Parameter>>,
158    /// A map where the keys describe the name of the protocol and the values
159    /// describe protocol-specific definitions for the channel.
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub bindings: Option<ReferenceOr<ChannelBinding>>,
162    /// This object can be extended with
163    /// [Specification Extensions](https://www.asyncapi.com/docs/specifications/v2.3.0#specificationExtensions).
164    #[serde(flatten)]
165    pub extensions: IndexMap<String, serde_json::Value>,
166}
167
168/// Describes a publish or a subscribe operation. This provides a place to document how
169/// and why messages are sent and received.
170///
171/// For example, an operation might describe a chat application use case where a user sends
172/// a text message to a group. A publish operation describes messages that are received by
173/// the chat application, whereas a subscribe operation describes messages that are sent by
174/// the chat application.
175///
176/// # Examples
177/// ```json
178/// {
179///     "operationId": "registerUser",
180///     "summary": "Action to sign a user up.",
181///     "description": "A longer description",
182///     "tags": [
183///         { "name": "user" },
184///         { "name": "signup" },
185///         { "name": "register" }
186///     ],
187///     "message": {
188///         "headers": {
189///         "type": "object",
190///         "properties": {
191///             "applicationInstanceId": {
192///             "description": "Unique identifier for a given instance of the publishing application",
193///             "type": "string"
194///             }
195///         }
196///         },
197///         "payload": {
198///         "type": "object",
199///         "properties": {
200///             "user": {
201///             "$ref": "#/components/schemas/userCreate"
202///             },
203///             "signup": {
204///             "$ref": "#/components/schemas/signup"
205///             }
206///         }
207///         }
208///     },
209///     "bindings": {
210///         "amqp": {
211///         "ack": false
212///         }
213///     },
214///     "traits": [
215///         { "$ref": "#/components/operationTraits/kafka" }
216///     ]
217/// }
218/// ```
219///
220/// ```yaml
221/// operationId: registerUser
222/// summary: Action to sign a user up.
223/// description: A longer description
224/// tags:
225///   - name: user
226///   - name: signup
227///   - name: register
228/// message:
229///   headers:
230///     type: object
231///     properties:
232///       applicationInstanceId:
233///         description: Unique identifier for a given instance of the publishing application
234///         type: string
235///   payload:
236///     type: object
237///     properties:
238///       user:
239///         $ref: "#/components/schemas/userCreate"
240///       signup:
241///         $ref: "#/components/schemas/signup"
242/// bindings:
243///   amqp:
244///     ack: false
245/// traits:
246///   - $ref: "#/components/operationTraits/kafka"
247/// ```
248#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
249#[serde(rename_all = "camelCase")]
250pub struct Operation {
251    /// Unique string used to identify the operation.
252    /// The id MUST be unique among all operations described in the API.
253    /// The operationId value is **case-sensitive**.
254    /// Tools and libraries MAY use the operationId to uniquely identify an
255    /// operation, therefore, it is RECOMMENDED to follow common programming
256    /// naming conventions.
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub operation_id: Option<String>,
259    /// A short summary of what the operation is about.
260    #[serde(skip_serializing_if = "Option::is_none")]
261    pub summary: Option<String>,
262    /// A verbose explanation of the operation.
263    /// [CommonMark syntax](https://spec.commonmark.org/)
264    /// can be used for rich text representation.
265    #[serde(skip_serializing_if = "Option::is_none")]
266    pub description: Option<String>,
267    /// A list of tags for API documentation control.
268    /// Tags can be used for logical grouping of operations.
269    #[serde(default, skip_serializing_if = "Vec::is_empty")]
270    pub tags: Vec<Tag>,
271    /// Additional external documentation for this operation.
272    #[serde(skip_serializing_if = "Option::is_none")]
273    pub external_docs: Option<ExternalDocumentation>,
274    /// A map where the keys describe the name of the protocol and the
275    /// values describe protocol-specific definitions for the operation.
276    #[serde(skip_serializing_if = "Option::is_none")]
277    pub bindings: Option<ReferenceOr<OperationBinding>>,
278    /// A list of traits to apply to the operation object.
279    /// Traits MUST be merged into the operation object using the
280    /// [JSON Merge Patch](https://tools.ietf.org/html/rfc7386)
281    /// algorithm in the same order they are defined here.
282    #[serde(default, skip_serializing_if = "Vec::is_empty")]
283    pub traits: Vec<ReferenceOr<OperationTrait>>,
284    /// A definition of the message that will be published or received on
285    /// this channel. `oneOf` is allowed here to specify multiple messages, however,
286    /// **a message MUST be valid only against one of the referenced message objects.**
287    #[serde(default, skip_serializing_if = "Option::is_none")]
288    pub message: Option<OperationMessageType>,
289    /// This object can be extended with
290    /// [Specification Extensions](https://www.asyncapi.com/docs/specifications/v2.3.0#specificationExtensions).
291    #[serde(flatten)]
292    pub extensions: IndexMap<String, serde_json::Value>,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
296#[serde(untagged)]
297pub enum OperationMessageType {
298    Map(IndexMap<String, ReferenceOr<Message>>),
299    Single(ReferenceOr<Message>),
300}