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