integrationos_domain/domain/connection/
api_model_config.rs1use http::HeaderMap;
2use js_sandbox_ios::Script;
3use serde::{de::DeserializeOwned, Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::BTreeMap;
6
7use crate::{prelude::schema::json_schema::JsonSchema, IntegrationOSError, InternalError};
8
9#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
10#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
11#[serde(rename_all = "camelCase")]
12pub struct ApiModelConfig {
13 pub base_url: String,
14 pub path: String,
15 pub auth_method: AuthMethod,
16 #[serde(
17 with = "http_serde_ext::header_map::option",
18 skip_serializing_if = "Option::is_none",
19 default
20 )]
21 pub headers: Option<HeaderMap>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub query_params: Option<BTreeMap<String, String>>,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub content: Option<ContentType>,
26 pub schemas: SchemasInput,
27 pub samples: SamplesInput,
28 pub responses: Vec<ResponseBody>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub paths: Option<ModelPaths>,
31}
32
33#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Default)]
34#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
35#[serde(rename_all = "camelCase")]
36pub enum ContentType {
38 Json,
39 Form,
40 #[default]
41 Other,
42}
43
44impl ApiModelConfig {
45 pub fn uri(&self) -> String {
48 let mut base_url = self.base_url.to_owned();
49 let path = self.path.to_owned();
50 if base_url.ends_with('/') && path.starts_with('/') {
51 base_url.pop();
52 }
53 base_url + &path
54 }
55}
56
57#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
58#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
59pub struct ModelPaths {
60 pub request: Option<RequestModelPaths>,
61 pub response: Option<ResponseModelPaths>,
62}
63
64#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
65#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
66#[serde(rename_all = "camelCase")]
67pub struct RequestModelPaths {
68 pub object: Option<String>,
69}
70
71#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
72#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
73#[serde(rename_all = "camelCase")]
74pub struct ResponseModelPaths {
75 pub object: Option<String>,
76 pub id: Option<String>,
77 pub cursor: Option<String>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
81#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
82#[serde(rename_all = "camelCase")]
83pub struct SamplesInput {
84 #[serde(
85 with = "http_serde_ext::header_map::option",
86 skip_serializing_if = "Option::is_none",
87 default
88 )]
89 pub headers: Option<http::HeaderMap>,
90 pub query_params: Option<Value>,
91 pub path_params: Option<Value>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub body: Option<Value>,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
97#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
98#[serde(rename_all = "camelCase")]
99pub struct SchemasInput {
100 pub headers: Option<JsonSchema>,
101 pub query_params: Option<JsonSchema>,
102 pub path_params: Option<JsonSchema>,
103 pub body: Option<JsonSchema>,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
107#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
108#[serde(rename_all = "camelCase")]
109pub struct ResponseBody {
110 pub status_code: u16,
111 #[serde(
112 with = "http_serde_ext::header_map::option",
113 skip_serializing_if = "Option::is_none",
114 default
115 )]
116 pub headers: Option<http::HeaderMap>,
117 pub body: Option<Value>,
118}
119
120#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
121#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
122#[serde(tag = "type")]
123pub enum AuthMethod {
124 BearerToken {
125 value: String,
126 },
127 ApiKey {
128 key: String,
129 value: String,
130 },
131 BasicAuth {
132 username: String,
133 password: String,
134 },
135 OAuthLegacy {
136 #[serde(rename = "hashAlgorithm")]
137 hash_algorithm: OAuthLegacyHashAlgorithm,
138 #[serde(skip_serializing_if = "Option::is_none")]
139 realm: Option<String>,
140 },
141 OAuth,
142 None,
143}
144
145#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
146#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
147pub enum OAuthLegacyHashAlgorithm {
148 #[serde(rename = "HMAC-SHA1")]
149 HmacSha1,
150 #[serde(rename = "HMAC-SHA256")]
151 HmacSha256,
152 #[serde(rename = "HMAC-SHA512")]
153 HmacSha512,
154 #[serde(rename = "PLAINTEXT")]
155 PlainText,
156}
157
158#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
159#[serde(rename_all = "camelCase")]
160pub struct Function(pub Compute);
161
162#[cfg(feature = "dummy")]
163impl<T> fake::Dummy<T> for Function {
164 fn dummy_with_rng<R: rand::prelude::Rng + ?Sized>(_: &T, _: &mut R) -> Self {
165 use fake::{Fake, Faker};
166 Function(Compute {
167 entry: Faker.fake(),
168 function: Faker.fake(),
169 language: Lang::JavaScript,
170 })
171 }
172}
173
174impl Function {
175 pub fn compute<T: DeserializeOwned>(&self, payload: &Value) -> Result<T, IntegrationOSError> {
176 let mut js_code = Script::from_string(&self.0.function).map_err(|e| {
177 InternalError::script_error(
178 &e.to_string(),
179 Some("Failed to create script from function"),
180 )
181 })?;
182 let response: T = js_code.call(&self.0.entry, (payload,)).map_err(|e| {
183 InternalError::script_error(&e.to_string(), Some("Failed to call function"))
184 })?;
185
186 Ok(response)
187 }
188}
189
190#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
191#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
192#[serde(rename_all = "camelCase")]
193pub struct Compute {
194 pub entry: String,
195 pub function: String,
196 pub language: Lang,
197}
198
199#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Default)]
200#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
201#[serde(rename_all = "lowercase")]
202pub enum Lang {
203 #[default]
204 JavaScript,
205 TypeScript,
206 Rust,
207}