1use serde::{Deserialize, Serialize};
6
7pub trait ExtensionContext: Send + Sync {
9 fn extension_id(&self) -> &str;
11
12 fn version(&self) -> &str;
14
15 fn publisher(&self) -> &str;
17
18 fn display_name(&self) -> &str;
20
21 fn description(&self) -> &str;
23
24 fn is_development(&self) -> bool;
26}
27
28pub trait ExtensionMetadata: Send + Sync {
30 fn name(&self) -> &str;
32
33 fn publisher(&self) -> &str;
35
36 fn version(&self) -> &str;
38
39 fn description(&self) -> &str;
41
42 fn main(&self) -> &str;
44
45 fn activation_events(&self) -> &[String];
47
48 fn capabilities(&self) -> &[String];
50
51 fn dependencies(&self) -> &[String];
53
54 fn engine(&self) -> &str;
56}
57
58pub type GroveResult<T> = Result<T, GroveError>;
60
61#[derive(Debug, thiserror::Error)]
63pub enum GroveError {
64 #[error("Extension not found: {0}")]
66 ExtensionNotFound(String),
67
68 #[error("Extension activation failed: {0}")]
70 ActivationFailed(String),
71
72 #[error("Extension deactivation failed: {0}")]
74 DeactivationFailed(String),
75
76 #[error("Transport error: {0}")]
78 TransportError(String),
79
80 #[error("WASM runtime error: {0}")]
82 WASMError(String),
83
84 #[error("API error: {0}")]
86 APIError(String),
87
88 #[error("Configuration error: {0}")]
90 ConfigurationError(String),
91
92 #[error("I/O error: {0}")]
94 IoError(#[from] std::io::Error),
95
96 #[error("Serialization error: {0}")]
98 SerializationError(String),
99
100 #[error("Deserialization error: {0}")]
102 DeserializationError(String),
103
104 #[error("Operation timed out")]
106 Timeout,
107
108 #[error("Invalid argument: {0}")]
110 InvalidArgument(String),
111
112 #[error("Not implemented: {0}")]
114 NotImplemented(String),
115
116 #[error("{0}")]
118 Other(String),
119}
120
121pub trait Identifiable {
123 fn id(&self) -> &str;
125}
126
127pub trait Named {
129 fn name(&self) -> &str;
131}
132
133pub trait Configurable {
135 type Config;
137
138 fn configure(&mut self, config:Self::Config) -> anyhow::Result<()>;
140
141 fn config(&self) -> &Self::Config;
143}
144
145pub trait Resettable {
147 fn reset(&mut self) -> anyhow::Result<()>;
149}
150
151pub trait Disposable {
153 fn dispose(&mut self) -> anyhow::Result<()>;
155}
156
157pub trait ContextClone {
159 fn clone_with_context(&self, context:&serde_json::Value) -> anyhow::Result<Self>
161 where
162 Self: Sized;
163}
164
165pub trait Stateful {
167 type State: Clone;
169
170 fn state(&self) -> Self::State;
172
173 fn set_state(&mut self, state:Self::State) -> anyhow::Result<()>;
175
176 fn restore_state(&mut self, state:Self::State) -> anyhow::Result<()>;
178}
179
180pub trait Observable {
182 type Event;
184
185 fn subscribe(&self, callback:fn(Self::Event)) -> anyhow::Result<()>;
187
188 fn unsubscribe(&self) -> anyhow::Result<()>;
190}
191
192pub trait Validatable {
194 fn validate(&self) -> anyhow::Result<()>;
196}
197
198pub trait Serializable: Serialize + for<'de> Deserialize<'de> {
200 fn to_json(&self) -> anyhow::Result<String> {
202 serde_json::to_string(self).map_err(|e| anyhow::anyhow!("Serialization failed: {}", e))
203 }
204
205 fn to_json_pretty(&self) -> anyhow::Result<String> {
207 serde_json::to_string_pretty(self).map_err(|e| anyhow::anyhow!("Serialization failed: {}", e))
208 }
209
210 fn from_json(json:&str) -> anyhow::Result<Self>
212 where
213 Self: Sized, {
214 serde_json::from_str(json).map_err(|e| anyhow::anyhow!("Deserialization failed: {}", e))
215 }
216}
217
218impl<T> Serializable for T where T: Serialize + for<'de> Deserialize<'de> {}
220
221pub trait Versioned {
223 fn version(&self) -> &str;
225
226 fn is_compatible_with(&self, other_version:&str) -> bool;
228}
229
230pub trait Retryable {
232 fn execute_with_retry<F, T, E>(&self, mut operation:F, max_retries:u32, delay_ms:u64) -> anyhow::Result<T>
234 where
235 F: FnMut() -> Result<T, E> + Send,
236 E: std::fmt::Display + Send + 'static,
237 T: Send, {
238 let mut last_error = None;
239
240 for attempt in 0..=max_retries {
241 match operation() {
242 Ok(result) => return Ok(result),
243 Err(e) => {
244 last_error = Some(e.to_string());
245 if attempt < max_retries {
246 std::thread::sleep(std::time::Duration::from_millis(delay_ms));
247 }
248 },
249 }
250 }
251
252 Err(anyhow::anyhow!(
253 "Operation failed after {} attempts: {}",
254 max_retries + 1,
255 last_error.unwrap_or_else(|| "Unknown error".to_string())
256 ))
257 }
258}
259
260#[cfg(test)]
261mod tests {
262 use super::*;
263
264 #[test]
265 fn test_grove_error_display() {
266 let err = GroveError::ExtensionNotFound("test.ext".to_string());
267 assert_eq!(err.to_string(), "Extension not found: test.ext");
268
269 let err = GroveError::Timeout;
270 assert_eq!(err.to_string(), "Operation timed out");
271 }
272
273 #[test]
274 fn test_serializable_trait() {
275 #[derive(Serialize, Deserialize, PartialEq, Debug)]
276 struct TestStruct {
277 value:i32,
278 }
279
280 let test = TestStruct { value:42 };
281 let json = test.to_json().unwrap();
282 let deserialized:TestStruct = TestStruct::from_json(&json).unwrap();
283 assert_eq!(test, deserialized);
284 }
285
286 #[test]
287 fn test_retryable_execute_with_retry() {
288 let retryable = RetryableTrait;
289
290 let mut attempt_count = 0;
291 let result = retryable.execute_with_retry(
292 || {
293 attempt_count += 1;
294 if attempt_count < 3 { Err("Not ready") } else { Ok("Success") }
295 },
296 5,
297 100,
298 );
299
300 assert!(result.is_ok());
301 assert_eq!(result.unwrap(), "Success");
302 assert_eq!(attempt_count, 3);
303 }
304}
305
306#[allow(dead_code)]
308struct RetryableTrait;
309
310impl Retryable for RetryableTrait {}