1use crate::{Error, Result};
2use std::future::Future;
3use std::pin::Pin;
4
5pub type HookResult = Result<(), Box<dyn std::error::Error + Send + Sync>>;
6pub type BoxFuture<'a> = Pin<Box<dyn Future<Output = HookResult> + Send + 'a>>;
7
8pub trait ModelHooks: Sized {
18 fn before_save(&mut self) -> BoxFuture<'_> {
20 Box::pin(async { Ok(()) })
21 }
22
23 fn after_save(&self) -> BoxFuture<'_> {
25 Box::pin(async { Ok(()) })
26 }
27
28 fn before_create(&mut self) -> BoxFuture<'_> {
30 Box::pin(async { Ok(()) })
31 }
32
33 fn after_create(&self) -> BoxFuture<'_> {
35 Box::pin(async { Ok(()) })
36 }
37
38 fn before_update(&mut self) -> BoxFuture<'_> {
40 Box::pin(async { Ok(()) })
41 }
42
43 fn after_update(&self) -> BoxFuture<'_> {
45 Box::pin(async { Ok(()) })
46 }
47
48 fn before_delete(&self) -> BoxFuture<'_> {
50 Box::pin(async { Ok(()) })
51 }
52
53 fn after_delete(&self) -> BoxFuture<'_> {
55 Box::pin(async { Ok(()) })
56 }
57}
58
59fn run(r: HookResult) -> Result<()> {
63 r.map_err(Error::Hook)
64}
65
66#[doc(hidden)]
67pub async fn before_insert<M: ModelHooks>(m: &mut M) -> Result<()> {
68 run(m.before_save().await)?;
69 run(m.before_create().await)
70}
71
72#[doc(hidden)]
73pub async fn after_insert<M: ModelHooks>(m: &M) -> Result<()> {
74 run(m.after_create().await)?;
75 run(m.after_save().await)
76}
77
78#[doc(hidden)]
79pub async fn before_update<M: ModelHooks>(m: &mut M) -> Result<()> {
80 run(m.before_save().await)?;
81 run(m.before_update().await)
82}
83
84#[doc(hidden)]
85pub async fn after_update<M: ModelHooks>(m: &M) -> Result<()> {
86 run(m.after_update().await)?;
87 run(m.after_save().await)
88}
89
90#[doc(hidden)]
91pub async fn before_delete<M: ModelHooks>(m: &M) -> Result<()> {
92 run(m.before_delete().await)
93}
94
95#[doc(hidden)]
96pub async fn after_delete<M: ModelHooks>(m: &M) -> Result<()> {
97 run(m.after_delete().await)
98}