rustisan_core/
traits.rs

1//! Common traits for the Rustisan framework
2//!
3//! This module provides common traits used throughout the framework.
4
5use async_trait::async_trait;
6use axum::response::IntoResponse;
7use serde::{Deserialize, Serialize};
8use std::any::Any;
9use std::collections::HashMap;
10use std::fmt::Debug;
11use crate::errors::Result;
12
13/// Trait for services that can be registered in the container
14pub trait Service: Send + Sync + Any {
15    /// Returns the service name
16    fn name(&self) -> &'static str;
17
18    /// Returns service metadata
19    fn metadata(&self) -> HashMap<String, String> {
20        HashMap::new()
21    }
22}
23
24/// Trait for HTTP controllers
25#[async_trait]
26pub trait Controller: Send + Sync {
27    /// Controller name for identification
28    fn name(&self) -> &'static str;
29
30    /// Initialize the controller
31    async fn init(&mut self) -> Result<()> {
32        Ok(())
33    }
34
35    /// Cleanup when controller is destroyed
36    async fn cleanup(&mut self) -> Result<()> {
37        Ok(())
38    }
39}
40
41/// Trait for data models
42pub trait Model: Send + Sync + Clone + Debug {
43    /// Primary key type
44    type PrimaryKey: Send + Sync + Clone + Debug;
45
46    /// Returns the table name
47    fn table_name() -> &'static str;
48
49    /// Returns the primary key field name
50    fn primary_key() -> &'static str {
51        "id"
52    }
53
54    /// Gets the primary key value
55    fn get_key(&self) -> Option<Self::PrimaryKey>;
56
57    /// Sets the primary key value
58    fn set_key(&mut self, key: Self::PrimaryKey);
59
60    /// Returns fillable fields
61    fn fillable() -> Vec<&'static str> {
62        Vec::new()
63    }
64
65    /// Returns guarded fields
66    fn guarded() -> Vec<&'static str> {
67        Vec::new()
68    }
69
70    /// Returns hidden fields (won't be serialized)
71    fn hidden() -> Vec<&'static str> {
72        Vec::new()
73    }
74
75    /// Returns visible fields (will be serialized)
76    fn visible() -> Vec<&'static str> {
77        Vec::new()
78    }
79
80    /// Validates the model
81    fn validate(&self) -> Result<()> {
82        Ok(())
83    }
84}
85
86/// Trait for database repositories
87#[async_trait]
88pub trait Repository<T: Model + 'static>: Send + Sync {
89    /// Finds a record by primary key
90    async fn find(&self, id: T::PrimaryKey) -> Result<Option<T>>;
91
92    /// Finds all records
93    async fn all(&self) -> Result<Vec<T>>;
94
95    /// Creates a new record
96    async fn create(&self, model: &T) -> Result<T>;
97
98    /// Updates an existing record
99    async fn update(&self, id: T::PrimaryKey, model: &T) -> Result<T>;
100
101    /// Deletes a record
102    async fn delete(&self, id: T::PrimaryKey) -> Result<bool>;
103
104    /// Finds records by criteria
105    async fn find_by(&self, criteria: HashMap<String, serde_json::Value>) -> Result<Vec<T>>;
106
107    /// Counts total records
108    async fn count(&self) -> Result<u64>;
109
110    /// Checks if a record exists
111    async fn exists(&self, id: T::PrimaryKey) -> Result<bool> {
112        Ok(self.find(id).await?.is_some())
113    }
114}
115
116/// Trait for HTTP middleware
117#[async_trait]
118pub trait HttpMiddleware: Send + Sync {
119    /// Processes the request before it reaches the handler
120    async fn before(&self, request: &mut axum::extract::Request) -> Result<()> {
121        Ok(())
122    }
123
124    /// Processes the response after the handler
125    async fn after(&self, response: &mut axum::response::Response) -> Result<()> {
126        Ok(())
127    }
128
129    /// Middleware name
130    fn name(&self) -> &'static str;
131
132    /// Middleware priority (lower runs first)
133    fn priority(&self) -> i32 {
134        100
135    }
136}
137
138/// Trait for validation rules
139pub trait ValidationRule: Send + Sync {
140    /// Validates the given value
141    fn validate(&self, value: &serde_json::Value) -> Result<()>;
142
143    /// Returns the error message for validation failure
144    fn message(&self) -> String;
145
146    /// Rule name
147    fn name(&self) -> &'static str;
148}
149
150/// Trait for cache stores
151#[async_trait]
152pub trait CacheStore: Send + Sync {
153    /// Gets a value from cache
154    async fn get(&self, key: &str) -> Result<Option<String>>;
155
156    /// Sets a value in cache
157    async fn set(&self, key: &str, value: &str, ttl: Option<u64>) -> Result<()>;
158
159    /// Deletes a value from cache
160    async fn delete(&self, key: &str) -> Result<bool>;
161
162    /// Checks if a key exists
163    async fn exists(&self, key: &str) -> Result<bool>;
164
165    /// Clears all cache
166    async fn clear(&self) -> Result<()>;
167
168    /// Gets multiple values
169    async fn get_many(&self, keys: &[&str]) -> Result<HashMap<String, String>>;
170
171    /// Sets multiple values
172    async fn set_many(&self, items: HashMap<String, String>, ttl: Option<u64>) -> Result<()>;
173
174    /// Increments a numeric value
175    async fn increment(&self, key: &str, value: i64) -> Result<i64>;
176
177    /// Decrements a numeric value
178    async fn decrement(&self, key: &str, value: i64) -> Result<i64>;
179}
180
181/// Trait for session stores
182#[async_trait]
183pub trait SessionStore: Send + Sync {
184    /// Gets session data
185    async fn get(&self, session_id: &str) -> Result<Option<HashMap<String, serde_json::Value>>>;
186
187    /// Sets session data
188    async fn set(&self, session_id: &str, data: HashMap<String, serde_json::Value>) -> Result<()>;
189
190    /// Deletes a session
191    async fn delete(&self, session_id: &str) -> Result<bool>;
192
193    /// Updates session timestamp
194    async fn touch(&self, session_id: &str) -> Result<()>;
195
196    /// Garbage collection for expired sessions
197    async fn gc(&self, max_lifetime: u64) -> Result<()>;
198}
199
200/// Trait for queue drivers
201#[async_trait]
202pub trait QueueDriver: Send + Sync {
203    /// Job data type
204    type Job: Send + Sync + Serialize + for<'de> Deserialize<'de>;
205
206    /// Pushes a job to the queue
207    async fn push(&self, queue: &str, job: Self::Job) -> Result<String>;
208
209    /// Pops a job from the queue
210    async fn pop(&self, queue: &str) -> Result<Option<(String, Self::Job)>>;
211
212    /// Acknowledges job completion
213    async fn ack(&self, job_id: &str) -> Result<()>;
214
215    /// Rejects a job (puts it back in queue or dead letter)
216    async fn reject(&self, job_id: &str, requeue: bool) -> Result<()>;
217
218    /// Gets queue size
219    async fn size(&self, queue: &str) -> Result<u64>;
220
221    /// Purges a queue
222    async fn purge(&self, queue: &str) -> Result<()>;
223}
224
225/// Trait for event listeners
226#[async_trait]
227pub trait EventListener: Send + Sync {
228    /// Event type this listener handles
229    type Event: Send + Sync;
230
231    /// Handles the event
232    async fn handle(&self, event: Self::Event) -> Result<()>;
233
234    /// Listener name
235    fn name(&self) -> &'static str;
236
237    /// Whether this listener should run synchronously
238    fn is_sync(&self) -> bool {
239        false
240    }
241}
242
243/// Trait for resource transformers (for API responses)
244pub trait Transformer<T>: Send + Sync {
245    /// Output type after transformation
246    type Output: Serialize;
247
248    /// Transforms the resource
249    fn transform(&self, resource: T) -> Self::Output;
250
251    /// Transformer name
252    fn name(&self) -> &'static str;
253}
254
255/// Trait for form requests (validation and authorization)
256#[async_trait]
257pub trait FormRequest: Send + Sync {
258    /// Request data type
259    type Data: for<'de> Deserialize<'de>;
260
261    /// Authorizes the request
262    async fn authorize(&self) -> Result<bool> {
263        Ok(true)
264    }
265
266    /// Validation rules
267    fn rules(&self) -> HashMap<String, Vec<Box<dyn ValidationRule>>>;
268
269    /// Custom error messages
270    fn messages(&self) -> HashMap<String, String> {
271        HashMap::new()
272    }
273
274    /// Validates the request data
275    async fn validate(&self, data: &Self::Data) -> Result<()>;
276}
277
278/// Trait for resource collections
279pub trait ResourceCollection<T>: Send + Sync {
280    /// Collection data type
281    type Item: Serialize;
282
283    /// Transforms collection items
284    fn collect(&self, items: Vec<T>) -> Vec<Self::Item>;
285
286    /// Additional data to include with collection
287    fn with(&self) -> HashMap<String, serde_json::Value> {
288        HashMap::new()
289    }
290
291    /// Meta information
292    fn meta(&self) -> HashMap<String, serde_json::Value> {
293        HashMap::new()
294    }
295}
296
297/// Trait for authentication guards
298#[async_trait]
299pub trait AuthGuard: Send + Sync {
300    /// User type
301    type User: Send + Sync;
302
303    /// Authenticates the request
304    async fn authenticate(&self, request: &axum::extract::Request) -> Result<Option<Self::User>>;
305
306    /// Guard name
307    fn name(&self) -> &'static str;
308}
309
310/// Trait for authorization policies
311#[async_trait]
312pub trait Policy<T>: Send + Sync {
313    /// User type
314    type User: Send + Sync;
315
316    /// Checks if user can view the resource
317    async fn view(&self, user: &Self::User, resource: &T) -> Result<bool> {
318        Ok(false)
319    }
320
321    /// Checks if user can create the resource
322    async fn create(&self, user: &Self::User) -> Result<bool> {
323        Ok(false)
324    }
325
326    /// Checks if user can update the resource
327    async fn update(&self, user: &Self::User, resource: &T) -> Result<bool> {
328        Ok(false)
329    }
330
331    /// Checks if user can delete the resource
332    async fn delete(&self, user: &Self::User, resource: &T) -> Result<bool> {
333        Ok(false)
334    }
335
336    /// Policy name
337    fn name(&self) -> &'static str;
338}
339
340/// Trait for command handlers
341#[async_trait]
342pub trait CommandHandler: Send + Sync {
343    /// Command arguments type
344    type Args: Send + Sync;
345
346    /// Executes the command
347    async fn handle(&self, args: Self::Args) -> Result<()>;
348
349    /// Command name
350    fn name(&self) -> &'static str;
351
352    /// Command description
353    fn description(&self) -> &'static str {
354        ""
355    }
356
357    /// Command signature (for help)
358    fn signature(&self) -> &'static str {
359        ""
360    }
361}
362
363/// Trait for HTTP response factories
364pub trait ResponseFactory: Send + Sync {
365    /// Creates a success response
366    fn success<T: Serialize>(&self, data: T) -> impl IntoResponse;
367
368    /// Creates an error response
369    fn error(&self, message: &str, status: axum::http::StatusCode) -> impl IntoResponse;
370
371    /// Creates a paginated response
372    fn paginated<T: Serialize>(&self, data: Vec<T>, total: u64, page: u64, per_page: u64) -> impl IntoResponse;
373}
374
375/// Macro to implement the Service trait for a type
376#[macro_export]
377macro_rules! impl_service {
378    ($type:ty, $name:expr) => {
379        impl $crate::traits::Service for $type {
380            fn name(&self) -> &'static str {
381                $name
382            }
383        }
384    };
385}
386
387/// Macro to implement the Model trait with basic functionality
388#[macro_export]
389macro_rules! impl_model {
390    ($type:ty, $pk_type:ty, $table:expr) => {
391        impl $crate::traits::Model for $type {
392            type PrimaryKey = $pk_type;
393
394            fn table_name() -> &'static str {
395                $table
396            }
397
398            fn get_key(&self) -> Option<Self::PrimaryKey> {
399                self.id.clone()
400            }
401
402            fn set_key(&mut self, key: Self::PrimaryKey) {
403                self.id = Some(key);
404            }
405        }
406    };
407}