1use serde_json::{json, Value};
2
3use crate::types::ApiParam;
4
5pub fn inject_description(schema: &mut Value, description: &str) {
7 if let Value::Object(map) = schema {
8 map.insert(
9 "description".to_string(),
10 Value::String(description.to_string()),
11 );
12 }
13}
14
15pub fn build_input_schema(params: &[ApiParam], request_body_schema: Option<&Value>) -> Value {
23 let mut properties = serde_json::Map::new();
24 let mut required: Vec<Value> = Vec::new();
25
26 for param in params {
27 let mut schema = param.schema.clone();
28 if let Some(desc) = ¶m.description {
29 inject_description(&mut schema, desc);
30 }
31 properties.insert(param.name.clone(), schema);
32 if param.required {
33 required.push(Value::String(param.name.clone()));
34 }
35 }
36
37 if let Some(body_schema) = request_body_schema {
38 let mut body_prop = body_schema.clone();
39 inject_description(&mut body_prop, "Request body (JSON)");
40 properties.insert("body".to_string(), body_prop);
41 }
42
43 json!({
44 "type": "object",
45 "properties": properties,
46 "required": required,
47 })
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use crate::types::ParamLocation;
54
55 #[test]
56 fn build_input_schema_path_params_only() {
57 let params = vec![ApiParam {
58 name: "id".to_string(),
59 location: ParamLocation::Path,
60 required: true,
61 schema: json!({"type": "string"}),
62 description: None,
63 }];
64
65 let schema = build_input_schema(¶ms, None);
66
67 assert_eq!(schema["type"], "object");
68 assert_eq!(schema["properties"]["id"]["type"], "string");
69 assert_eq!(schema["required"], json!(["id"]));
70 }
71
72 #[test]
73 fn build_input_schema_query_params() {
74 let params = vec![ApiParam {
75 name: "page".to_string(),
76 location: ParamLocation::Query,
77 required: false,
78 schema: json!({"type": "integer"}),
79 description: Some("Page number".to_string()),
80 }];
81
82 let schema = build_input_schema(¶ms, None);
83
84 assert_eq!(schema["properties"]["page"]["type"], "integer");
85 assert_eq!(schema["properties"]["page"]["description"], "Page number");
86 assert_eq!(schema["required"], json!([]));
87 }
88
89 #[test]
90 fn build_input_schema_with_body() {
91 let body_schema = json!({
92 "type": "object",
93 "properties": {
94 "name": {"type": "string"},
95 "email": {"type": "string"}
96 },
97 "required": ["name", "email"]
98 });
99
100 let schema = build_input_schema(&[], Some(&body_schema));
101
102 assert!(schema["properties"]["body"].is_object());
103 assert_eq!(
104 schema["properties"]["body"]["description"],
105 "Request body (JSON)"
106 );
107 assert_eq!(
108 schema["properties"]["body"]["properties"]["name"]["type"],
109 "string"
110 );
111 }
112
113 #[test]
114 fn build_input_schema_no_params() {
115 let schema = build_input_schema(&[], None);
116
117 assert_eq!(schema["type"], "object");
118 assert_eq!(schema["properties"], json!({}));
119 assert_eq!(schema["required"], json!([]));
120 }
121
122 #[test]
123 fn build_input_schema_mixed_params_and_body() {
124 let params = vec![
125 ApiParam {
126 name: "user_id".to_string(),
127 location: ParamLocation::Path,
128 required: true,
129 schema: json!({"type": "integer"}),
130 description: Some("User identifier".to_string()),
131 },
132 ApiParam {
133 name: "page".to_string(),
134 location: ParamLocation::Query,
135 required: false,
136 schema: json!({"type": "integer"}),
137 description: None,
138 },
139 ];
140
141 let body_schema = json!({
142 "type": "object",
143 "properties": {
144 "name": {"type": "string"}
145 }
146 });
147
148 let schema = build_input_schema(¶ms, Some(&body_schema));
149
150 assert!(schema["properties"]["user_id"].is_object());
152 assert!(schema["properties"]["page"].is_object());
153 assert!(schema["properties"]["body"].is_object());
154
155 assert_eq!(schema["required"], json!(["user_id"]));
157
158 assert_eq!(
160 schema["properties"]["user_id"]["description"],
161 "User identifier"
162 );
163 assert_eq!(
164 schema["properties"]["body"]["description"],
165 "Request body (JSON)"
166 );
167 }
168
169 #[test]
170 fn inject_description_adds_to_object() {
171 let mut schema = json!({"type": "string"});
172 inject_description(&mut schema, "A test field");
173 assert_eq!(schema["description"], "A test field");
174 }
175
176 #[test]
177 fn inject_description_ignores_non_object() {
178 let mut schema = json!("not an object");
179 inject_description(&mut schema, "ignored");
180 assert_eq!(schema, json!("not an object"));
181 }
182}