1use std::collections::HashMap;
7use std::sync::Arc;
8
9use parking_lot::RwLock;
10
11#[derive(Debug, Clone)]
13pub struct PluginMetadata {
14 pub name: String,
16 pub version: String,
18 pub description: String,
20 pub author: String,
22}
23
24impl PluginMetadata {
25 pub fn new(
27 name: impl Into<String>,
28 version: impl Into<String>,
29 description: impl Into<String>,
30 ) -> Self {
31 Self {
32 name: name.into(),
33 version: version.into(),
34 description: description.into(),
35 author: String::new(),
36 }
37 }
38
39 pub fn with_author(mut self, author: impl Into<String>) -> Self {
41 self.author = author.into();
42 self
43 }
44}
45
46pub trait AiExtension: Send + Sync {
48 fn name(&self) -> &str;
50
51 fn execute(&self, input: &str) -> Result<String, PluginError>;
53}
54
55pub trait DialectExtension: Send + Sync {
57 fn dialect_name(&self) -> &str;
59
60 fn translate(&self, sql: &str) -> Result<String, PluginError>;
62}
63
64pub trait MiddlewareExtension: Send + Sync {
66 fn name(&self) -> &str;
68
69 fn before_query(&self, sql: &str) -> Result<String, PluginError>;
71
72 fn after_query(&self, sql: &str, result: &str) -> Result<String, PluginError>;
74}
75
76#[derive(Debug, Clone)]
78pub enum PluginError {
79 NotFound(String),
81 ExecutionFailed(String),
83 RegistrationFailed(String),
85}
86
87impl std::fmt::Display for PluginError {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 match self {
90 PluginError::NotFound(msg) => write!(f, "Plugin not found: {}", msg),
91 PluginError::ExecutionFailed(msg) => write!(f, "Execution failed: {}", msg),
92 PluginError::RegistrationFailed(msg) => write!(f, "Registration failed: {}", msg),
93 }
94 }
95}
96
97impl std::error::Error for PluginError {}
98
99pub trait SzOrmPlugin: Send + Sync {
103 fn metadata(&self) -> &PluginMetadata;
105
106 fn init(&self) -> Result<(), PluginError> {
108 Ok(())
109 }
110
111 fn ai_extension(&self) -> Option<&dyn AiExtension> {
113 None
114 }
115
116 fn dialect_extension(&self) -> Option<&dyn DialectExtension> {
118 None
119 }
120
121 fn middleware_extension(&self) -> Option<&dyn MiddlewareExtension> {
123 None
124 }
125}
126
127pub struct PluginRegistry {
131 plugins: RwLock<HashMap<String, Arc<dyn SzOrmPlugin>>>,
132}
133
134impl Default for PluginRegistry {
135 fn default() -> Self {
136 Self::new()
137 }
138}
139
140impl PluginRegistry {
141 pub fn new() -> Self {
143 Self {
144 plugins: RwLock::new(HashMap::new()),
145 }
146 }
147
148 pub fn register(&self, plugin: Arc<dyn SzOrmPlugin>) -> Result<(), PluginError> {
150 let metadata = plugin.metadata();
151 let name = metadata.name.clone();
152
153 plugin.init()?;
154
155 let mut plugins = self.plugins.write();
156 if plugins.contains_key(&name) {
157 return Err(PluginError::RegistrationFailed(format!(
158 "插件 {} 已存在",
159 name
160 )));
161 }
162 plugins.insert(name, plugin);
163 Ok(())
164 }
165
166 pub fn unregister(&self, name: &str) -> Result<(), PluginError> {
168 let mut plugins = self.plugins.write();
169 plugins
170 .remove(name)
171 .ok_or_else(|| PluginError::NotFound(name.to_string()))?;
172 Ok(())
173 }
174
175 pub fn get(&self, name: &str) -> Option<Arc<dyn SzOrmPlugin>> {
177 self.plugins.read().get(name).cloned()
178 }
179
180 pub fn list(&self) -> Vec<String> {
182 self.plugins.read().keys().cloned().collect()
183 }
184
185 pub fn len(&self) -> usize {
187 self.plugins.read().len()
188 }
189
190 pub fn is_empty(&self) -> bool {
192 self.plugins.read().is_empty()
193 }
194
195 pub fn execute_ai(&self, plugin_name: &str, input: &str) -> Result<String, PluginError> {
197 let plugin = self
198 .get(plugin_name)
199 .ok_or_else(|| PluginError::NotFound(plugin_name.to_string()))?;
200 let ext = plugin
201 .ai_extension()
202 .ok_or_else(|| PluginError::ExecutionFailed("插件无 AI 扩展".to_string()))?;
203 ext.execute(input)
204 }
205
206 pub fn translate_dialect(&self, plugin_name: &str, sql: &str) -> Result<String, PluginError> {
208 let plugin = self
209 .get(plugin_name)
210 .ok_or_else(|| PluginError::NotFound(plugin_name.to_string()))?;
211 let ext = plugin
212 .dialect_extension()
213 .ok_or_else(|| PluginError::ExecutionFailed("插件无方言扩展".to_string()))?;
214 ext.translate(sql)
215 }
216
217 pub fn before_query(&self, plugin_name: &str, sql: &str) -> Result<String, PluginError> {
219 let plugin = self
220 .get(plugin_name)
221 .ok_or_else(|| PluginError::NotFound(plugin_name.to_string()))?;
222 let ext = plugin
223 .middleware_extension()
224 .ok_or_else(|| PluginError::ExecutionFailed("插件无中间件扩展".to_string()))?;
225 ext.before_query(sql)
226 }
227
228 pub fn after_query(
230 &self,
231 plugin_name: &str,
232 sql: &str,
233 result: &str,
234 ) -> Result<String, PluginError> {
235 let plugin = self
236 .get(plugin_name)
237 .ok_or_else(|| PluginError::NotFound(plugin_name.to_string()))?;
238 let ext = plugin
239 .middleware_extension()
240 .ok_or_else(|| PluginError::ExecutionFailed("插件无中间件扩展".to_string()))?;
241 ext.after_query(sql, result)
242 }
243}