reactive_graph_dynamic_graph_impl/object/relation/mutation/
update.rs1use crate::field::to_input_type_ref;
2use crate::object::types::DynamicGraphTypeDefinition;
3use async_graphql::dynamic::Field;
4use async_graphql::dynamic::FieldFuture;
5use async_graphql::dynamic::FieldValue;
6use async_graphql::dynamic::InputValue;
7use async_graphql::dynamic::TypeRef;
8use reactive_graph_dynamic_graph_api::ImmutablePropertyError;
9use reactive_graph_dynamic_graph_api::PropertyDataTypeError;
10use reactive_graph_graph::DataType;
11use reactive_graph_graph::Mutability::Immutable;
12use reactive_graph_graph::Mutability::Mutable;
13use reactive_graph_graph::PropertyInstanceSetter;
14use reactive_graph_graph::RelationType;
15use reactive_graph_reactive_model_impl::ReactiveRelation;
16use serde_json::Value;
17use serde_json::json;
18
19pub fn relation_update_field(relation_type: &RelationType) -> Option<Field> {
20 let relation_type_inner = relation_type.clone();
21 let dy_ty = DynamicGraphTypeDefinition::from(&relation_type.ty);
22 let mut update_field = Field::new("update", TypeRef::named_nn_list_nn(dy_ty.to_string()), move |ctx| {
23 let relation_type = relation_type_inner.clone();
24 FieldFuture::new(async move {
25 let relation_instances = ctx.parent_value.try_downcast_ref::<Vec<ReactiveRelation>>()?;
26 for relation_instance in relation_instances {
27 for property in relation_type.properties.iter() {
29 if let Ok(value) = ctx.args.try_get(&property.name) {
30 if property.mutability == Immutable {
32 return Err(ImmutablePropertyError(property.key().clone()).into());
33 }
34 match &property.data_type {
35 DataType::Null => {
36 return Err(PropertyDataTypeError::NullIsNotAValidDataType(property.key().clone()).into());
37 }
38 DataType::Bool => {
39 if value.boolean().is_err() {
40 return Err(PropertyDataTypeError::ValueIsNotOfTheExpectedDataType(
41 property.name.clone(),
42 property.data_type,
43 DataType::Bool,
44 )
45 .into());
46 }
47 }
48 DataType::Number => {
49 if value.f64().is_err() && value.i64().is_err() && value.u64().is_err() {
50 return Err(PropertyDataTypeError::ValueIsNotOfTheExpectedDataType(
51 property.name.clone(),
52 property.data_type,
53 DataType::Number,
54 )
55 .into());
56 }
57 }
58 DataType::String => {
59 if value.string().is_err() {
60 return Err(PropertyDataTypeError::ValueIsNotOfTheExpectedDataType(
61 property.name.clone(),
62 property.data_type,
63 DataType::String,
64 )
65 .into());
66 }
67 }
68 DataType::Array => {
69 if value.list().is_err() {
70 return Err(PropertyDataTypeError::ValueIsNotOfTheExpectedDataType(
71 property.name.clone(),
72 property.data_type,
73 DataType::Array,
74 )
75 .into());
76 }
77 }
78 DataType::Object => {
79 if value.object().is_err() {
80 return Err(PropertyDataTypeError::ValueIsNotOfTheExpectedDataType(
81 property.name.clone(),
82 property.data_type,
83 DataType::Object,
84 )
85 .into());
86 }
87 }
88 DataType::Any => {
89 }
91 }
92 }
93 }
94 for property in relation_type.properties.iter() {
96 if let Ok(value) = ctx.args.try_get(&property.name) {
97 match &property.data_type {
98 DataType::Null => {
99 return Err(PropertyDataTypeError::NullIsNotAValidDataType(property.key().clone()).into());
100 }
101 DataType::Bool => {
102 relation_instance.set_checked(&property.name, Value::Bool(value.boolean()?));
103 }
104 DataType::Number => {
105 if let Ok(value) = value.i64() {
106 relation_instance.set_checked(&property.name, json!(value));
107 } else if let Ok(value) = value.u64() {
108 relation_instance.set_checked(&property.name, json!(value));
109 } else if let Ok(value) = value.f64() {
110 relation_instance.set_checked(&property.name, json!(value));
111 } else {
112 return Err(PropertyDataTypeError::ValueIsNotOfTheExpectedDataType(
113 property.name.clone(),
114 property.data_type,
115 DataType::Number,
116 )
117 .into());
118 }
119 }
120 DataType::String => {
121 relation_instance.set_checked(&property.name, Value::String(value.string()?.to_string()));
122 }
123 DataType::Array => {
124 let _list = value.list()?;
125 let value = value.deserialize::<Value>()?;
126 if !value.is_array() {
127 return Err(PropertyDataTypeError::ValueIsNotOfTheExpectedDataType(
128 property.name.clone(),
129 property.data_type,
130 DataType::Array,
131 )
132 .into());
133 }
134 relation_instance.set_checked(&property.name, value);
135 }
136 DataType::Object => {
137 let value = value.deserialize::<Value>()?;
138 if !value.is_object() {
139 return Err(PropertyDataTypeError::ValueIsNotOfTheExpectedDataType(
140 property.name.clone(),
141 property.data_type,
142 DataType::Object,
143 )
144 .into());
145 }
146 relation_instance.set_checked(&property.name, value);
147 }
148 DataType::Any => {
149 let value = value.deserialize::<Value>()?;
151 relation_instance.set_checked(&property.name, value);
152 }
153 }
154 }
155 }
156 }
157 Ok(Some(FieldValue::list(
158 relation_instances
159 .iter()
160 .map(|relation_instance| FieldValue::owned_any(relation_instance.clone())),
161 )))
162 })
163 });
164 let mut has_updatable_property = false;
165 for property in relation_type.properties.iter() {
166 if property.mutability == Mutable {
167 if let Some(type_ref) = to_input_type_ref(property.value(), true) {
168 update_field = update_field.argument(InputValue::new(&property.name, type_ref));
169 has_updatable_property = true;
170 }
171 }
172 }
173 if !has_updatable_property {
174 return None;
175 }
176 Some(update_field)
177}