1use std::{collections::HashMap, sync::Arc};
2
3use futures_util::future::BoxFuture;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7use crate::{
8 error::IIIError,
9 protocol::{RegisterFunctionMessage, RegisterTriggerTypeMessage},
10 triggers::TriggerHandler,
11};
12
13pub type RemoteFunctionHandler =
14 Arc<dyn Fn(Value) -> BoxFuture<'static, Result<Value, IIIError>> + Send + Sync>;
15
16#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
22pub struct FieldPath(pub String);
23
24impl FieldPath {
25 pub fn new(path: impl Into<String>) -> Self {
26 Self(path.into())
27 }
28
29 pub fn root() -> Self {
30 Self(String::new())
31 }
32}
33
34impl From<&str> for FieldPath {
35 fn from(value: &str) -> Self {
36 Self(value.to_string())
37 }
38}
39
40impl From<String> for FieldPath {
41 fn from(value: String) -> Self {
42 Self(value)
43 }
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(tag = "type", rename_all = "lowercase")]
49pub enum UpdateOp {
50 Set {
52 path: FieldPath,
53 value: Option<Value>,
54 },
55
56 Merge {
58 path: Option<FieldPath>,
59 value: Value,
60 },
61
62 Increment { path: FieldPath, by: i64 },
64
65 Decrement { path: FieldPath, by: i64 },
67
68 Remove { path: FieldPath },
70}
71
72impl UpdateOp {
73 pub fn set(path: impl Into<FieldPath>, value: impl Into<Option<Value>>) -> Self {
75 Self::Set {
76 path: path.into(),
77 value: value.into(),
78 }
79 }
80
81 pub fn increment(path: impl Into<FieldPath>, by: i64) -> Self {
83 Self::Increment {
84 path: path.into(),
85 by,
86 }
87 }
88
89 pub fn decrement(path: impl Into<FieldPath>, by: i64) -> Self {
91 Self::Decrement {
92 path: path.into(),
93 by,
94 }
95 }
96
97 pub fn remove(path: impl Into<FieldPath>) -> Self {
99 Self::Remove { path: path.into() }
100 }
101
102 pub fn merge(value: impl Into<Value>) -> Self {
104 Self::Merge {
105 path: None,
106 value: value.into(),
107 }
108 }
109
110 pub fn merge_at(path: impl Into<FieldPath>, value: impl Into<Value>) -> Self {
112 Self::Merge {
113 path: Some(path.into()),
114 value: value.into(),
115 }
116 }
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct UpdateResult {
122 pub old_value: Option<Value>,
124 pub new_value: Value,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct SetResult {
130 pub old_value: Option<Value>,
132 pub new_value: Value,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct DeleteResult {
138 pub old_value: Option<Value>,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct StreamUpdateInput {
145 pub key: String,
146 pub ops: Vec<UpdateOp>,
147}
148
149#[derive(Clone)]
150pub struct RemoteFunctionData {
151 pub message: RegisterFunctionMessage,
152 pub handler: RemoteFunctionHandler,
153}
154
155#[derive(Clone)]
156pub struct RemoteTriggerTypeData {
157 pub message: RegisterTriggerTypeMessage,
158 pub handler: Arc<dyn TriggerHandler>,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct ApiRequest<T = Value> {
163 #[serde(default)]
164 pub query_params: HashMap<String, String>,
165 #[serde(default)]
166 pub path_params: HashMap<String, String>,
167 #[serde(default)]
168 pub headers: HashMap<String, String>,
169 #[serde(default)]
170 pub path: String,
171 #[serde(default)]
172 pub method: String,
173 #[serde(default)]
174 pub body: T,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct ApiResponse<T = Value> {
179 pub status_code: u16,
180 #[serde(default)]
181 pub headers: HashMap<String, String>,
182 pub body: T,
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn api_request_defaults_when_missing_fields() {
191 let request: ApiRequest = serde_json::from_str("{}").unwrap();
192
193 assert!(request.query_params.is_empty());
194 assert!(request.path_params.is_empty());
195 assert!(request.headers.is_empty());
196 assert_eq!(request.path, "");
197 assert_eq!(request.method, "");
198 assert!(request.body.is_null());
199 }
200}