use crate::model::Model;
use std::marker::PhantomData;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HookOperation {
Insert,
Update,
Delete,
}
#[derive(Debug, Clone, Copy)]
pub struct HookContext<'a> {
operation: HookOperation,
batch_index: Option<usize>,
in_transaction: bool,
_marker: PhantomData<&'a ()>,
}
impl<'a> HookContext<'a> {
pub fn new(operation: HookOperation) -> Self {
Self {
operation,
batch_index: None,
in_transaction: false,
_marker: PhantomData,
}
}
pub fn operation(&self) -> HookOperation {
self.operation
}
pub fn batch_index(&self) -> Option<usize> {
self.batch_index
}
pub fn in_transaction(&self) -> bool {
self.in_transaction
}
pub fn for_batch(&self, index: usize) -> Self {
Self {
operation: self.operation,
batch_index: Some(index),
in_transaction: self.in_transaction,
_marker: PhantomData,
}
}
pub fn transaction(mut self) -> Self {
self.in_transaction = true;
self
}
}
#[async_trait::async_trait]
pub trait BeforeInsert: Model {
async fn before_insert(&mut self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[async_trait::async_trait]
pub trait AfterInsert: Model {
async fn after_insert(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[async_trait::async_trait]
pub trait BeforeUpdate: Model {
async fn before_update(&mut self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[async_trait::async_trait]
pub trait AfterUpdate: Model {
async fn after_update(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[async_trait::async_trait]
pub trait BeforeDelete: Model {
async fn before_delete(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[async_trait::async_trait]
pub trait AfterDelete: Model {
async fn after_delete(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[doc(hidden)]
#[async_trait::async_trait]
pub trait HookBeforeInsert {
async fn call_before_insert(&mut self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[doc(hidden)]
#[async_trait::async_trait]
pub trait HookAfterInsert {
async fn call_after_insert(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[doc(hidden)]
#[async_trait::async_trait]
pub trait HookBeforeUpdate {
async fn call_before_update(&mut self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[doc(hidden)]
#[async_trait::async_trait]
pub trait HookAfterUpdate {
async fn call_after_update(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[doc(hidden)]
#[async_trait::async_trait]
pub trait HookBeforeDelete {
async fn call_before_delete(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[doc(hidden)]
#[async_trait::async_trait]
pub trait HookAfterDelete {
async fn call_after_delete(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()>;
}
#[async_trait::async_trait]
impl<M: BeforeInsert + Send> HookBeforeInsert for M {
async fn call_before_insert(&mut self, ctx: &mut HookContext<'_>) -> anyhow::Result<()> {
self.before_insert(ctx).await
}
}
#[async_trait::async_trait]
impl<M: AfterInsert + Send + Sync> HookAfterInsert for M {
async fn call_after_insert(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()> {
self.after_insert(ctx).await
}
}
#[async_trait::async_trait]
impl<M: BeforeUpdate + Send> HookBeforeUpdate for M {
async fn call_before_update(&mut self, ctx: &mut HookContext<'_>) -> anyhow::Result<()> {
self.before_update(ctx).await
}
}
#[async_trait::async_trait]
impl<M: AfterUpdate + Send + Sync> HookAfterUpdate for M {
async fn call_after_update(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()> {
self.after_update(ctx).await
}
}
#[async_trait::async_trait]
impl<M: BeforeDelete + Send + Sync> HookBeforeDelete for M {
async fn call_before_delete(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()> {
self.before_delete(ctx).await
}
}
#[async_trait::async_trait]
impl<M: AfterDelete + Send + Sync> HookAfterDelete for M {
async fn call_after_delete(&self, ctx: &mut HookContext<'_>) -> anyhow::Result<()> {
self.after_delete(ctx).await
}
}