barbacane_compiler/spec_parser/model.rs
1use serde::{Deserialize, Serialize};
2use std::collections::BTreeMap;
3
4/// A parsed API spec (OpenAPI or AsyncAPI).
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct ApiSpec {
7 /// Original filename (if parsed from file).
8 pub filename: Option<String>,
9 /// The format detected from the root field.
10 pub format: SpecFormat,
11 /// The spec version string (e.g. "3.1.0").
12 pub version: String,
13 /// The `info.title` field.
14 pub title: String,
15 /// The `info.version` field (API version, not spec version).
16 pub api_version: String,
17 /// Parsed path operations.
18 pub operations: Vec<Operation>,
19 /// Global middlewares from root-level `x-barbacane-middlewares`.
20 pub global_middlewares: Vec<MiddlewareConfig>,
21 /// Raw `x-barbacane-*` extensions at root level.
22 pub extensions: BTreeMap<String, serde_json::Value>,
23}
24
25/// Detected spec format.
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
27#[serde(rename_all = "lowercase")]
28pub enum SpecFormat {
29 OpenApi,
30 AsyncApi,
31}
32
33/// A single API operation (path + method for OpenAPI, channel + action for AsyncAPI).
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct Operation {
36 /// The path template (OpenAPI: "/users/{id}", AsyncAPI: channel address).
37 pub path: String,
38 /// The HTTP method (OpenAPI: "GET", AsyncAPI: "SEND"/"RECEIVE").
39 pub method: String,
40 /// The operationId, if present.
41 pub operation_id: Option<String>,
42 /// The operation summary (short description for MCP tool name).
43 #[serde(default)]
44 pub summary: Option<String>,
45 /// The operation description (detailed description for MCP tool).
46 #[serde(default)]
47 pub description: Option<String>,
48 /// Path/channel parameters defined on this operation.
49 pub parameters: Vec<Parameter>,
50 /// Request body definition (OpenAPI: requestBody, AsyncAPI: message payload for SEND).
51 pub request_body: Option<RequestBody>,
52 /// The dispatcher configuration from `x-barbacane-dispatch`.
53 pub dispatch: Option<DispatchConfig>,
54 /// Operation-level middlewares (replaces global chain if present).
55 pub middlewares: Option<Vec<MiddlewareConfig>>,
56 /// Whether this operation is deprecated (OpenAPI `deprecated` field).
57 #[serde(default)]
58 pub deprecated: bool,
59 /// Sunset date for deprecated operations (from `x-sunset` per RFC 8594).
60 /// Format: HTTP-date per RFC 9110 (e.g., "Sat, 31 Dec 2024 23:59:59 GMT").
61 pub sunset: Option<String>,
62 /// Operation-level `x-barbacane-*` extensions.
63 pub extensions: BTreeMap<String, serde_json::Value>,
64 /// AsyncAPI messages (for async operations only).
65 #[serde(default, skip_serializing_if = "Vec::is_empty")]
66 pub messages: Vec<Message>,
67 /// Protocol bindings (AsyncAPI: kafka, nats, mqtt, amqp, ws).
68 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
69 pub bindings: BTreeMap<String, serde_json::Value>,
70 /// Response definitions keyed by status code (e.g., "200", "201").
71 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
72 pub responses: BTreeMap<String, ResponseContent>,
73}
74
75/// Response content for a specific status code.
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct ResponseContent {
78 /// Content types and their schemas (e.g., "application/json" -> schema).
79 pub content: BTreeMap<String, ContentSchema>,
80}
81
82/// A path, query, or header parameter.
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct Parameter {
85 /// Parameter name.
86 pub name: String,
87 /// Location: "path", "query", "header".
88 pub location: String,
89 /// Whether this parameter is required.
90 pub required: bool,
91 /// The parameter's schema (for validation in M2).
92 pub schema: Option<serde_json::Value>,
93}
94
95/// Dispatcher configuration extracted from `x-barbacane-dispatch`.
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct DispatchConfig {
98 /// Plugin name (or name@version).
99 pub name: String,
100 /// Plugin-specific configuration.
101 #[serde(default)]
102 pub config: serde_json::Value,
103}
104
105/// Middleware configuration from `x-barbacane-middlewares`.
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct MiddlewareConfig {
108 /// Plugin name (or name@version).
109 pub name: String,
110 /// Plugin-specific configuration.
111 #[serde(default)]
112 pub config: serde_json::Value,
113}
114
115/// Request body definition from `requestBody`.
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct RequestBody {
118 /// Whether the request body is required.
119 pub required: bool,
120 /// Content types and their schemas (e.g., "application/json" -> schema).
121 pub content: BTreeMap<String, ContentSchema>,
122}
123
124/// Content schema for a specific media type.
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct ContentSchema {
127 /// The JSON Schema for this content type.
128 pub schema: Option<serde_json::Value>,
129}
130
131/// AsyncAPI message definition.
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct Message {
134 /// Message name/ID.
135 pub name: String,
136 /// Message payload schema.
137 pub payload: Option<serde_json::Value>,
138 /// Content type (e.g., "application/json").
139 pub content_type: Option<String>,
140 /// Protocol-specific bindings (kafka, nats, mqtt, amqp, ws, etc.).
141 #[serde(default)]
142 pub bindings: BTreeMap<String, serde_json::Value>,
143}
144
145/// AsyncAPI channel definition.
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct Channel {
148 /// Channel address/topic (e.g., "user/signedup", "orders.{orderId}").
149 pub address: String,
150 /// Messages that can be sent/received on this channel.
151 pub messages: Vec<Message>,
152 /// Channel parameters (for templated addresses like "orders.{orderId}").
153 pub parameters: Vec<Parameter>,
154 /// Protocol-specific bindings.
155 #[serde(default)]
156 pub bindings: BTreeMap<String, serde_json::Value>,
157}
158
159/// AsyncAPI operation action.
160#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
161#[serde(rename_all = "lowercase")]
162pub enum AsyncAction {
163 /// Gateway sends/publishes a message to the channel.
164 Send,
165 /// Gateway receives/subscribes to messages from the channel.
166 Receive,
167}
168
169impl std::fmt::Display for AsyncAction {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 match self {
172 AsyncAction::Send => write!(f, "SEND"),
173 AsyncAction::Receive => write!(f, "RECEIVE"),
174 }
175 }
176}