bounce/query/traits.rs
1use async_trait::async_trait;
2use std::hash::Hash;
3use std::rc::Rc;
4
5use crate::root_state::BounceStates;
6
7/// A Result returned by queries.
8pub type QueryResult<T> = std::result::Result<Rc<T>, <T as Query>::Error>;
9
10/// A trait to be implemented on queries.
11///
12/// # Note
13///
14/// This trait is implemented with [async_trait](macro@async_trait), you should apply an `#[async_trait(?Send)]`
15/// attribute to your implementation of this trait.
16///
17/// # Example
18///
19/// ```
20/// use std::rc::Rc;
21/// use std::convert::Infallible;
22/// use bounce::prelude::*;
23/// use bounce::query::{Query, QueryResult};
24/// use yew::prelude::*;
25/// use async_trait::async_trait;
26///
27/// #[derive(Debug, PartialEq)]
28/// struct User {
29/// id: u64,
30/// name: String,
31/// }
32///
33/// #[derive(Debug, PartialEq)]
34/// struct UserQuery {
35/// value: User
36/// }
37///
38/// #[async_trait(?Send)]
39/// impl Query for UserQuery {
40/// type Input = u64;
41/// type Error = Infallible;
42///
43/// async fn query(_states: &BounceStates, input: Rc<u64>) -> QueryResult<Self> {
44/// // fetch user
45///
46/// Ok(UserQuery{ value: User { id: *input, name: "John Smith".into() } }.into())
47/// }
48/// }
49/// ```
50///
51/// See: [`use_query`](super::use_query()) and [`use_query_value`](super::use_query_value())
52#[async_trait(?Send)]
53pub trait Query: PartialEq {
54 /// The Input type of a query.
55 ///
56 /// The input type must implement Hash and Eq as it is used as the key of results in a
57 /// HashMap.
58 type Input: Hash + Eq + 'static;
59
60 /// The Error type of a query.
61 type Error: 'static + std::error::Error + PartialEq + Clone;
62
63 /// Runs a query.
64 ///
65 /// This method will only be called when the result is not already cached.
66 ///
67 /// # Note
68 ///
69 /// When implementing this method with async_trait, you can use the following function
70 /// signature:
71 ///
72 /// ```ignore
73 /// async fn query(states: &BounceStates, input: Rc<Self::Input>) -> QueryResult<Self>
74 /// ```
75 async fn query(states: &BounceStates, input: Rc<Self::Input>) -> QueryResult<Self>;
76}
77
78/// A Result returned by mutations.
79pub type MutationResult<T> = std::result::Result<Rc<T>, <T as Mutation>::Error>;
80
81/// A trait to be implemented on mutations.
82///
83/// # Note
84///
85/// This trait is implemented with [async_trait](macro@async_trait), you should apply an `#[async_trait(?Send)]`
86/// attribute to your implementation of this trait.
87///
88/// # Example
89///
90/// ```
91/// use std::rc::Rc;
92/// use std::convert::Infallible;
93/// use bounce::prelude::*;
94/// use bounce::query::{Mutation, MutationResult};
95/// use yew::prelude::*;
96/// use async_trait::async_trait;
97///
98/// #[derive(Debug, PartialEq)]
99/// struct User {
100/// id: u64,
101/// name: String,
102/// }
103///
104/// #[derive(Debug, PartialEq)]
105/// struct UpdateUserMutation {
106/// }
107///
108/// #[async_trait(?Send)]
109/// impl Mutation for UpdateUserMutation {
110/// type Input = User;
111/// type Error = Infallible;
112///
113/// async fn run(_states: &BounceStates, _input: Rc<User>) -> MutationResult<Self> {
114/// // updates the user information.
115///
116/// Ok(UpdateUserMutation {}.into())
117/// }
118/// }
119/// ```
120///
121/// See: [`use_mutation`](super::use_mutation())
122#[async_trait(?Send)]
123pub trait Mutation: PartialEq {
124 /// The Input type.
125 type Input: 'static;
126
127 /// The Error type.
128 type Error: 'static + std::error::Error + PartialEq + Clone;
129
130 /// Runs a mutation.
131 ///
132 /// # Note
133 ///
134 /// When implementing this method with async_trait, you can use the following function
135 /// signature:
136 ///
137 /// ```ignore
138 /// async fn run(states: &BounceStates, input: Rc<Self::Input>) -> MutationResult<Self>
139 /// ```
140 async fn run(states: &BounceStates, input: Rc<Self::Input>) -> MutationResult<Self>;
141}