1use crate::{QueryError, QueryKey};
4use std::future::Future;
5use std::pin::Pin;
6use std::sync::Arc;
7
8pub type MutateFn<T, P> =
10 Arc<dyn Fn(P) -> Pin<Box<dyn Future<Output = Result<T, QueryError>> + Send>> + Send + Sync>;
11
12#[derive(Debug, Clone, Default)]
14pub enum MutationState<T: Clone> {
15 #[default]
16 Idle,
17 Pending,
18 Success(T),
19 Error(QueryError),
20}
21
22impl<T: Clone> MutationState<T> {
23 pub fn is_idle(&self) -> bool {
24 matches!(self, Self::Idle)
25 }
26
27 pub fn is_pending(&self) -> bool {
28 matches!(self, Self::Pending)
29 }
30
31 pub fn is_success(&self) -> bool {
32 matches!(self, Self::Success(_))
33 }
34
35 pub fn is_error(&self) -> bool {
36 matches!(self, Self::Error(_))
37 }
38
39 pub fn data(&self) -> Option<&T> {
40 match self {
41 Self::Success(d) => Some(d),
42 _ => None,
43 }
44 }
45
46 pub fn error(&self) -> Option<&QueryError> {
47 match self {
48 Self::Error(e) => Some(e),
49 _ => None,
50 }
51 }
52}
53
54pub struct Mutation<T, P>
65where
66 T: Clone + Send + Sync + 'static,
67 P: Clone + Send + 'static,
68{
69 pub mutate_fn: MutateFn<T, P>,
70 pub invalidate_keys: Vec<QueryKey>,
71}
72
73impl<T, P> Mutation<T, P>
74where
75 T: Clone + Send + Sync + 'static,
76 P: Clone + Send + 'static,
77{
78 pub fn new<F, Fut>(mutate_fn: F) -> Self
80 where
81 F: Fn(P) -> Fut + Send + Sync + 'static,
82 Fut: Future<Output = Result<T, QueryError>> + Send + 'static,
83 {
84 Self {
85 mutate_fn: Arc::new(move |p| Box::pin(mutate_fn(p))),
86 invalidate_keys: Vec::new(),
87 }
88 }
89
90 pub fn invalidates(mut self, keys: impl IntoIterator<Item = QueryKey>) -> Self {
92 self.invalidate_keys.extend(keys);
93 self
94 }
95
96 pub fn invalidates_key(mut self, key: QueryKey) -> Self {
98 self.invalidate_keys.push(key);
99 self
100 }
101}