use crate::Row;
use crate::DbResult;
use async_trait::async_trait;
#[async_trait]
pub trait Hook: Send + Sync {
async fn before_insert(&self, row: &mut Row) -> DbResult<()> { let _ = row; Ok(()) }
async fn after_insert(&self, row: &Row) -> DbResult<()> { let _ = row; Ok(()) }
async fn before_update(&self, row: &mut Row) -> DbResult<()> { let _ = row; Ok(()) }
async fn after_update(&self, row: &Row) -> DbResult<()> { let _ = row; Ok(()) }
async fn before_delete(&self, table: &str, id: &str) -> DbResult<()> {
let _ = (table, id); Ok(())
}
async fn after_delete(&self, table: &str, id: &str) -> DbResult<()> {
let _ = (table, id); Ok(())
}
}
pub struct NullHook;
#[async_trait]
impl Hook for NullHook {}
pub struct HookChain {
hooks: Vec<Box<dyn Hook>>,
}
impl HookChain {
pub fn new() -> Self {
Self { hooks: Vec::new() }
}
pub fn add<H: Hook + 'static>(&mut self, hook: H) -> &mut Self {
self.hooks.push(Box::new(hook));
self
}
}
#[async_trait]
impl Hook for HookChain {
async fn before_insert(&self, row: &mut Row) -> DbResult<()> {
for hook in &self.hooks {
hook.before_insert(row).await?;
}
Ok(())
}
async fn after_insert(&self, row: &Row) -> DbResult<()> {
for hook in &self.hooks {
hook.after_insert(row).await?;
}
Ok(())
}
async fn before_update(&self, row: &mut Row) -> DbResult<()> {
for hook in &self.hooks {
hook.before_update(row).await?;
}
Ok(())
}
async fn after_update(&self, row: &Row) -> DbResult<()> {
for hook in &self.hooks {
hook.after_update(row).await?;
}
Ok(())
}
async fn before_delete(&self, table: &str, id: &str) -> DbResult<()> {
for hook in &self.hooks {
hook.before_delete(table, id).await?;
}
Ok(())
}
async fn after_delete(&self, table: &str, id: &str) -> DbResult<()> {
for hook in &self.hooks {
hook.after_delete(table, id).await?;
}
Ok(())
}
}
impl Default for HookChain {
fn default() -> Self {
Self::new()
}
}
pub struct TimestampHook;
#[async_trait]
impl Hook for TimestampHook {
async fn before_insert(&self, row: &mut Row) -> DbResult<()> {
let now = chrono::Utc::now().to_rfc3339();
row.set("created_at", now.as_str());
row.set("updated_at", now.as_str());
Ok(())
}
async fn before_update(&self, row: &mut Row) -> DbResult<()> {
let now = chrono::Utc::now().to_rfc3339();
row.set("updated_at", now.as_str());
Ok(())
}
}