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#[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}