auth_framework/sdks/
mod.rs1#[cfg(feature = "enhanced-rbac")]
7pub mod javascript;
8
9#[cfg(feature = "enhanced-rbac")]
10pub mod python;
11
12#[cfg(feature = "enhanced-rbac")]
13pub use javascript::{EnhancedSdkConfig as JsConfig, JsSdkGenerator};
14
15#[cfg(feature = "enhanced-rbac")]
16pub use python::{PythonSdkConfig, PythonSdkGenerator};
17
18use serde::{Deserialize, Serialize};
19use std::collections::HashMap;
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct SdkGenerationConfig {
24 pub base_url: String,
26 pub version: String,
28 pub languages: Vec<SdkLanguage>,
30 pub include_rbac: bool,
32 pub include_conditional_permissions: bool,
34 pub include_audit: bool,
36 pub client_names: HashMap<SdkLanguage, String>,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
42pub enum SdkLanguage {
43 JavaScript,
44 TypeScript,
45 Python,
46 Rust,
47 Go,
48 Java,
49 CSharp,
50}
51
52impl Default for SdkGenerationConfig {
53 fn default() -> Self {
54 let mut client_names = HashMap::new();
55 client_names.insert(SdkLanguage::JavaScript, "AuthFrameworkClient".to_string());
56 client_names.insert(SdkLanguage::TypeScript, "AuthFrameworkClient".to_string());
57 client_names.insert(SdkLanguage::Python, "AuthFrameworkClient".to_string());
58
59 Self {
60 base_url: "https://api.example.com".to_string(),
61 version: "v1".to_string(),
62 languages: vec![SdkLanguage::TypeScript, SdkLanguage::Python],
63 include_rbac: true,
64 include_conditional_permissions: true,
65 include_audit: true,
66 client_names,
67 }
68 }
69}
70
71#[derive(Debug)]
73pub struct SdkGenerationResult {
74 pub files: HashMap<SdkLanguage, HashMap<String, String>>,
76 pub errors: Vec<SdkGenerationError>,
78}
79
80#[derive(Debug, thiserror::Error)]
82pub enum SdkGenerationError {
83 #[error("Language {0:?} not supported")]
84 UnsupportedLanguage(SdkLanguage),
85 #[error("Generation failed for {language:?}: {error}")]
86 GenerationFailed {
87 language: SdkLanguage,
88 error: String,
89 },
90 #[error("Configuration error: {0}")]
91 ConfigurationError(String),
92}
93
94pub struct SdkGenerator {
96 config: SdkGenerationConfig,
97}
98
99impl SdkGenerator {
100 pub fn new(config: SdkGenerationConfig) -> Self {
102 Self { config }
103 }
104
105 pub fn generate_all(&self) -> Result<SdkGenerationResult, Box<dyn std::error::Error>> {
107 let mut result = SdkGenerationResult {
108 files: HashMap::new(),
109 errors: Vec::new(),
110 };
111
112 for &language in &self.config.languages {
113 match self.generate_for_language(language) {
114 Ok(files) => {
115 result.files.insert(language, files);
116 }
117 Err(error) => {
118 result.errors.push(SdkGenerationError::GenerationFailed {
119 language,
120 error: error.to_string(),
121 });
122 }
123 }
124 }
125
126 Ok(result)
127 }
128
129 pub fn generate_for_language(
131 &self,
132 language: SdkLanguage,
133 ) -> Result<HashMap<String, String>, Box<dyn std::error::Error>> {
134 match language {
135 #[cfg(feature = "enhanced-rbac")]
136 SdkLanguage::JavaScript | SdkLanguage::TypeScript => {
137 let js_config = javascript::EnhancedSdkConfig {
138 base_url: self.config.base_url.clone(),
139 version: self.config.version.clone(),
140 typescript: language == SdkLanguage::TypeScript,
141 include_rbac: self.config.include_rbac,
142 include_conditional_permissions: self.config.include_conditional_permissions,
143 include_audit: self.config.include_audit,
144 client_name: self
145 .config
146 .client_names
147 .get(&language)
148 .cloned()
149 .unwrap_or_else(|| "AuthFrameworkClient".to_string()),
150 };
151
152 let generator = javascript::JsSdkGenerator::new(js_config);
153 generator.generate_sdk()
154 }
155
156 #[cfg(feature = "enhanced-rbac")]
157 SdkLanguage::Python => {
158 let python_config = python::PythonSdkConfig {
159 base_url: self.config.base_url.clone(),
160 version: self.config.version.clone(),
161 include_rbac: self.config.include_rbac,
162 include_conditional_permissions: self.config.include_conditional_permissions,
163 include_audit: self.config.include_audit,
164 client_name: self
165 .config
166 .client_names
167 .get(&language)
168 .cloned()
169 .unwrap_or_else(|| "AuthFrameworkClient".to_string()),
170 async_support: true,
171 type_hints: true,
172 };
173
174 let generator = python::PythonSdkGenerator::new(python_config);
175 generator.generate_sdk()
176 }
177
178 _ => Err(Box::new(SdkGenerationError::UnsupportedLanguage(language))),
179 }
180 }
181
182 pub fn supported_languages() -> Vec<SdkLanguage> {
184 vec![
185 #[cfg(feature = "enhanced-rbac")]
186 SdkLanguage::JavaScript,
187 #[cfg(feature = "enhanced-rbac")]
188 SdkLanguage::TypeScript,
189 #[cfg(feature = "enhanced-rbac")]
190 SdkLanguage::Python,
191 ]
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 #[test]
200 fn test_sdk_generation_config() {
201 let config = SdkGenerationConfig::default();
202 assert_eq!(config.version, "v1");
203 assert!(config.include_rbac);
204 assert!(config.include_conditional_permissions);
205 assert!(config.include_audit);
206 }
207
208 #[test]
209 fn test_supported_languages() {
210 let languages = SdkGenerator::supported_languages();
211 assert!(!languages.is_empty());
212 }
213
214 #[cfg(feature = "enhanced-rbac")]
215 #[test]
216 fn test_multi_language_generation() {
217 let config = SdkGenerationConfig {
218 languages: vec![SdkLanguage::TypeScript, SdkLanguage::Python],
219 ..Default::default()
220 };
221
222 let generator = SdkGenerator::new(config);
223 let result = generator.generate_all();
224
225 assert!(result.is_ok());
226 let sdk_result = result.unwrap();
227
228 assert!(sdk_result.files.contains_key(&SdkLanguage::TypeScript));
230 assert!(sdk_result.files.contains_key(&SdkLanguage::Python));
231 }
232}
233
234