subgraph/graphql/entity/create_field/resolve_fields/resolve_document_field/
mod.rs1use async_graphql::{indexmap::IndexMap, Name, Value};
2use bson::{Bson, Document};
3use log::{debug, trace};
4
5use crate::{
6 configuration::subgraph::entities::service_entity_field::ServiceEntityFieldConfig,
7 graphql::entity::ServiceEntity, utils::document::get_from_document::DocumentValue,
8};
9
10impl ServiceEntity {
11 pub fn resolve_document_object_id_scalar(
12 document: &Document,
13 field: &ServiceEntityFieldConfig,
14 ) -> Result<Option<Value>, async_graphql::Error> {
15 debug!("Resolving Object ID Scalar");
16 let resolved =
17 field
18 .scalar
19 .get_from_document(document, &field.name, field.list.unwrap_or(false))?;
20
21 match resolved {
22 DocumentValue::ObjectID(object_id) => Ok(Some(Value::from(object_id.to_string()))),
23 DocumentValue::ObjectIDArray(object_ids) => Ok(Some(Value::List(
24 object_ids
25 .into_iter()
26 .map(|object_id| Value::from(object_id.to_string()))
27 .collect(),
28 ))),
29 DocumentValue::Null => Ok(Some(Value::Null)),
30 DocumentValue::None => Ok(None),
31 _ => Err(async_graphql::Error::from(
32 "Invalid result type for object id scalar",
33 )),
34 }
35 }
36
37 pub fn resolve_document_string_scalar(
38 document: &Document,
39 field: &ServiceEntityFieldConfig,
40 ) -> Result<Option<Value>, async_graphql::Error> {
41 debug!("Resolving String Scalar");
42 let resolved =
43 field
44 .scalar
45 .get_from_document(document, &field.name, field.list.unwrap_or(false))?;
46
47 match resolved {
48 DocumentValue::String(value) => Ok(Some(Value::from(value))),
49 DocumentValue::StringArray(values) => Ok(Some(Value::List(
50 values.into_iter().map(|value| Value::from(value)).collect(),
51 ))),
52 DocumentValue::None => Ok(None),
53 DocumentValue::Null => Ok(Some(Value::Null)),
54 _ => Err(async_graphql::Error::from(
55 "Invalid result type for string scalar",
56 )),
57 }
58 }
59
60 pub fn resolve_document_int_scalar(
61 document: &Document,
62 field: &ServiceEntityFieldConfig,
63 ) -> Result<Option<Value>, async_graphql::Error> {
64 debug!("Resolving Int Scalar");
65
66 let resolved =
67 field
68 .scalar
69 .get_from_document(document, &field.name, field.list.unwrap_or(false))?;
70
71 match resolved {
72 DocumentValue::Int(value) => Ok(Some(Value::from(value))),
73 DocumentValue::IntArray(values) => Ok(Some(Value::List(
74 values.into_iter().map(|value| Value::from(value)).collect(),
75 ))),
76 DocumentValue::None => Ok(None),
77 DocumentValue::Null => Ok(Some(Value::Null)),
78 _ => Err(async_graphql::Error::from(
79 "Invalid result type for int scalar",
80 )),
81 }
82 }
83
84 pub fn resolve_document_boolean_scalar(
85 document: &Document,
86 field: &ServiceEntityFieldConfig,
87 ) -> Result<Option<Value>, async_graphql::Error> {
88 debug!("Resolving Boolean Scalar");
89
90 let resolved =
91 field
92 .scalar
93 .get_from_document(document, &field.name, field.list.unwrap_or(false))?;
94
95 match resolved {
96 DocumentValue::Boolean(value) => Ok(Some(Value::from(value))),
97 DocumentValue::BooleanArray(values) => Ok(Some(Value::List(
98 values.into_iter().map(|value| Value::from(value)).collect(),
99 ))),
100 DocumentValue::Null => Ok(Some(Value::Null)),
101 DocumentValue::None => Ok(None),
102 _ => Err(async_graphql::Error::from(
103 "Invalid result type for boolean scalar",
104 )),
105 }
106 }
107
108 pub fn resolve_document_uuid_scalar(
109 document: &Document,
110 field: &ServiceEntityFieldConfig,
111 ) -> Result<Option<Value>, async_graphql::Error> {
112 debug!("Resolving UUID Scalar");
113
114 let resolved =
115 field
116 .scalar
117 .get_from_document(document, &field.name, field.list.unwrap_or(false))?;
118
119 match resolved {
120 DocumentValue::UUID(value) => Ok(Some(Value::from(value.to_string()))),
121 DocumentValue::UUIDArray(values) => Ok(Some(Value::List(
122 values
123 .into_iter()
124 .map(|value| Value::from(value.to_string()))
125 .collect(),
126 ))),
127 DocumentValue::Null => Ok(Some(Value::Null)),
128 DocumentValue::None => Ok(None),
129 _ => Err(async_graphql::Error::from(
130 "Invalid result type for UUID scalar",
131 )),
132 }
133 }
134
135 pub fn resolve_document_datetime_scalar(
136 document: &Document,
137 field: &ServiceEntityFieldConfig,
138 ) -> Result<Option<Value>, async_graphql::Error> {
139 debug!("Resolving DateTime Scalar");
140
141 let resolved =
142 field
143 .scalar
144 .get_from_document(document, &field.name, field.list.unwrap_or(false))?;
145
146 match resolved {
147 DocumentValue::DateTime(value) => Ok(Some(Value::from(value.to_rfc3339()))),
148 DocumentValue::DateTimeArray(values) => Ok(Some(Value::List(
149 values
150 .into_iter()
151 .map(|value| Value::from(value.to_rfc3339()))
152 .collect(),
153 ))),
154 DocumentValue::Null => Ok(Some(Value::Null)),
155 DocumentValue::None => Ok(None),
156 _ => Err(async_graphql::Error::from(
157 "Invalid result type for DateTime scalar",
158 )),
159 }
160 }
161
162 pub fn parse_bson_object(
163 value: &Bson,
164 field: &ServiceEntityFieldConfig,
165 ) -> Result<IndexMap<Name, Value>, async_graphql::Error> {
166 let document = match value.as_document() {
167 Some(document) => document,
168 None => return Err(async_graphql::Error::from("Invalid BSON Document")),
169 };
170
171 let mut index_map = IndexMap::new();
172
173 for (key, bson) in document.into_iter() {
174 let name = Name::new(key);
175 trace!("Found BSON Element Type: {:?}", bson.element_type());
176
177 let field = ServiceEntityFieldConfig::get_field(
178 field.fields.clone().unwrap_or(Vec::new()),
179 key.clone(),
180 )?;
181 let value = field
182 .scalar
183 .clone()
184 .document_field_to_async_graphql_value(document, &field)?;
185 if let Some(value) = value {
186 index_map.insert(name, value);
187 }
188 }
189 Ok(index_map)
190 }
191
192 pub fn resolve_document_object_scalar(
193 document: &Document,
194 field: &ServiceEntityFieldConfig,
195 ) -> Result<Option<Value>, async_graphql::Error> {
196 debug!("Resolve Document Object Scalar");
197 let value = document.get(&field.name);
198
199 if value.is_none() {
200 trace!("Value is None, returning null");
201 return Ok(None);
202 }
203
204 if field.list.unwrap_or(false) {
205 if let Some(Bson::Array(documents)) = document.get(field.name.clone()) {
206 let mut values = vec![];
207 for document in documents {
208 let value = ServiceEntity::parse_bson_object(document, field)?;
209 values.push(Value::Object(value));
210 }
211
212 return Ok(Some(Value::List(values)));
213 } else {
214 return Ok(Some(Value::List(vec![])));
215 }
216 }
217
218 let index_map = ServiceEntity::parse_bson_object(value.unwrap(), field)?;
219
220 Ok(Some(Value::from(index_map)))
221 }
222
223 pub fn resolve_document_enum_scalar(
224 document: &Document,
225 field: &ServiceEntityFieldConfig,
226 ) -> Result<Option<Value>, async_graphql::Error> {
227 debug!("Resolving Enum Scalar");
228
229 let resolved =
230 field
231 .scalar
232 .get_from_document(document, &field.name, field.list.unwrap_or(false))?;
233
234 match resolved {
235 DocumentValue::String(value) => Ok(Some(Value::from(value))),
236 DocumentValue::StringArray(values) => Ok(Some(Value::List(
237 values.into_iter().map(|value| Value::from(value)).collect(),
238 ))),
239 DocumentValue::None => Ok(None),
240 DocumentValue::Null => Ok(Some(Value::Null)),
241 _ => Err(async_graphql::Error::from(
242 "Invalid result type for enum scalar",
243 )),
244 }
245 }
246}