Skip to main content

forge_dioxus/
types.rs

1
2use std::marker::PhantomData;
3
4use serde::de::DeserializeOwned;
5use serde::{Deserialize, Serialize};
6
7use crate::ForgeClient;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
10pub struct ForgeError {
11    pub code: String,
12    pub message: String,
13    #[serde(default, skip_serializing_if = "Option::is_none")]
14    pub details: Option<serde_json::Value>,
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18pub struct ForgeClientError {
19    pub code: String,
20    pub message: String,
21    #[serde(default, skip_serializing_if = "Option::is_none")]
22    pub details: Option<serde_json::Value>,
23}
24
25impl ForgeClientError {
26    pub fn new(
27        code: impl Into<String>,
28        message: impl Into<String>,
29        details: Option<serde_json::Value>,
30    ) -> Self {
31        Self {
32            code: code.into(),
33            message: message.into(),
34            details,
35        }
36    }
37
38    pub fn as_forge_error(&self) -> ForgeError {
39        ForgeError {
40            code: self.code.clone(),
41            message: self.message.clone(),
42            details: self.details.clone(),
43        }
44    }
45}
46
47impl std::fmt::Display for ForgeClientError {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        write!(f, "{}: {}", self.code, self.message)
50    }
51}
52
53impl std::error::Error for ForgeClientError {}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
56#[serde(rename_all = "snake_case")]
57pub enum ConnectionState {
58    #[default]
59    Disconnected,
60    Connecting,
61    Connected,
62}
63
64#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
65pub struct QueryState<T> {
66    pub loading: bool,
67    pub data: Option<T>,
68    pub error: Option<ForgeError>,
69}
70
71impl<T> Default for QueryState<T> {
72    fn default() -> Self {
73        Self {
74            loading: true,
75            data: None,
76            error: None,
77        }
78    }
79}
80
81#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82pub struct SubscriptionState<T> {
83    pub loading: bool,
84    pub data: Option<T>,
85    pub error: Option<ForgeError>,
86    pub stale: bool,
87    pub connection_state: ConnectionState,
88}
89
90impl<T> Default for SubscriptionState<T> {
91    fn default() -> Self {
92        Self {
93            loading: true,
94            data: None,
95            error: None,
96            stale: false,
97            connection_state: ConnectionState::Disconnected,
98        }
99    }
100}
101
102#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
103#[serde(rename_all = "snake_case")]
104pub enum JobStatus {
105    Pending,
106    Claimed,
107    Running,
108    Completed,
109    Retry,
110    Failed,
111    DeadLetter,
112    CancelRequested,
113    Cancelled,
114    NotFound,
115}
116
117impl Default for JobStatus {
118    fn default() -> Self {
119        Self::Pending
120    }
121}
122
123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
124pub struct JobState<TOutput> {
125    pub job_id: String,
126    pub status: JobStatus,
127    pub progress: Option<f64>,
128    pub message: Option<String>,
129    pub output: Option<TOutput>,
130    pub error: Option<String>,
131}
132
133impl<TOutput> Default for JobState<TOutput> {
134    fn default() -> Self {
135        Self {
136            job_id: String::new(),
137            status: JobStatus::Pending,
138            progress: None,
139            message: None,
140            output: None,
141            error: None,
142        }
143    }
144}
145
146#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
147pub struct JobExecutionState<TOutput> {
148    pub loading: bool,
149    pub connection_state: ConnectionState,
150    pub state: JobState<TOutput>,
151}
152
153impl<TOutput> Default for JobExecutionState<TOutput> {
154    fn default() -> Self {
155        Self {
156            loading: true,
157            connection_state: ConnectionState::Disconnected,
158            state: JobState::default(),
159        }
160    }
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
164#[serde(rename_all = "snake_case")]
165pub enum WorkflowStatus {
166    Created,
167    Running,
168    Waiting,
169    Completed,
170    Compensating,
171    Compensated,
172    Failed,
173    NotFound,
174}
175
176impl Default for WorkflowStatus {
177    fn default() -> Self {
178        Self::Created
179    }
180}
181
182#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
183#[serde(rename_all = "snake_case")]
184pub struct WorkflowStepState {
185    pub name: String,
186    pub status: String,
187    pub error: Option<String>,
188}
189
190#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
191pub struct WorkflowState<TOutput> {
192    pub workflow_id: String,
193    pub status: WorkflowStatus,
194    pub step: Option<String>,
195    pub waiting_for: Option<String>,
196    pub steps: Vec<WorkflowStepState>,
197    pub output: Option<TOutput>,
198    pub error: Option<String>,
199}
200
201impl<TOutput> Default for WorkflowState<TOutput> {
202    fn default() -> Self {
203        Self {
204            workflow_id: String::new(),
205            status: WorkflowStatus::Created,
206            step: None,
207            waiting_for: None,
208            steps: Vec::new(),
209            output: None,
210            error: None,
211        }
212    }
213}
214
215#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
216pub struct WorkflowExecutionState<TOutput> {
217    pub loading: bool,
218    pub connection_state: ConnectionState,
219    pub state: WorkflowState<TOutput>,
220}
221
222impl<TOutput> Default for WorkflowExecutionState<TOutput> {
223    fn default() -> Self {
224        Self {
225            loading: true,
226            connection_state: ConnectionState::Disconnected,
227            state: WorkflowState::default(),
228        }
229    }
230}
231
232/// Mutation handle returned by `use_forge_mutation`. Clone into event handlers,
233/// call `.call(args)` to execute.
234#[derive(Clone)]
235pub struct Mutation<A, R> {
236    client: ForgeClient,
237    function_name: &'static str,
238    _phantom: PhantomData<fn(A) -> R>,
239}
240
241impl<A, R> Mutation<A, R>
242where
243    A: Serialize + 'static,
244    R: DeserializeOwned + 'static,
245{
246    pub(crate) fn new(client: ForgeClient, function_name: &'static str) -> Self {
247        Self {
248            client,
249            function_name,
250            _phantom: PhantomData,
251        }
252    }
253
254    pub async fn call(&self, args: A) -> Result<R, ForgeClientError> {
255        self.client.call(self.function_name, args).await
256    }
257}
258
259#[derive(Debug, Clone)]
260pub enum StreamEvent<T> {
261    Connection(ConnectionState),
262    Data(T),
263    Error(ForgeClientError),
264}
265
266#[derive(Debug, Clone, Deserialize)]
267pub(crate) struct RpcEnvelopeRaw {
268    pub success: bool,
269    #[serde(default)]
270    pub data: Option<serde_json::Value>,
271    #[serde(default)]
272    pub error: Option<ForgeError>,
273}
274
275#[derive(Debug, Clone, Deserialize)]
276pub(crate) struct ConnectedEvent {
277    pub session_id: Option<String>,
278    pub session_secret: Option<String>,
279}
280
281#[derive(Debug, Clone, Deserialize)]
282pub(crate) struct SseEnvelopeRaw {
283    #[serde(default)]
284    pub payload: Option<serde_json::Value>,
285    #[serde(default)]
286    pub code: Option<String>,
287    #[serde(default)]
288    pub message: Option<String>,
289}