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