reactive_graph_dynamic_graph_impl/field/entity/
mutation.rs

1use crate::field::property::field_arguments::add_entity_type_properties_as_field_arguments;
2use crate::field::property::filter::get_entity_instances_by_type_filter_by_properties;
3use crate::object::types::DynamicGraphTypeDefinition;
4use async_graphql::dynamic::Field;
5use async_graphql::dynamic::FieldFuture;
6use async_graphql::dynamic::FieldValue;
7use async_graphql::dynamic::InputValue;
8use async_graphql::dynamic::TypeRef;
9use reactive_graph_dynamic_graph_api::EntityInstanceIsNotOfType;
10use reactive_graph_dynamic_graph_api::EntityInstanceNotFound;
11use reactive_graph_graph::EntityType;
12use reactive_graph_reactive_service_api::ReactiveEntityManager;
13use std::str::FromStr;
14use std::sync::Arc;
15use uuid::Uuid;
16
17pub fn entity_mutation_field(entity_type: &EntityType) -> Option<Field> {
18    let ty = entity_type.ty.clone();
19    let entity_type_inner = entity_type.clone();
20    let dy_ty = DynamicGraphTypeDefinition::from(&entity_type.ty);
21    let mut field = Field::new(dy_ty.field_name(), TypeRef::named_nn(dy_ty.mutation_type_name()), move |ctx| {
22        let ty = ty.clone();
23        let entity_type = entity_type_inner.clone();
24        FieldFuture::new(async move {
25            let entity_instance_manager = ctx.data::<Arc<dyn ReactiveEntityManager + Send + Sync>>()?;
26            // Multiple ids
27            if let Ok(ids) = ctx.args.try_get("ids") {
28                let mut entity_instances = Vec::new();
29                for id in ids
30                    .list()?
31                    .iter()
32                    .filter_map(|id| id.string().map(str::to_string).ok())
33                    .filter_map(|id| Uuid::from_str(&id).ok())
34                {
35                    if let Some(entity_instance) = entity_instance_manager.get(id) {
36                        if entity_instance.ty != ty {
37                            return Err(EntityInstanceIsNotOfType(id, ty.clone()).into());
38                        }
39                        entity_instances.push(entity_instance);
40                    }
41                }
42                let field_value = FieldValue::owned_any(entity_instances);
43                return Ok(Some(field_value));
44            }
45            // Single ids
46            if let Ok(id) = ctx.args.try_get("id") {
47                let id = Uuid::from_str(id.string()?)?;
48                let entity_instance = entity_instance_manager.get(id).ok_or(EntityInstanceNotFound(id))?;
49                if entity_instance.ty != ty {
50                    return Err(EntityInstanceIsNotOfType(id, ty.clone()).into());
51                }
52                let entity_instances = vec![entity_instance];
53                let field_value = FieldValue::owned_any(entity_instances);
54                return Ok(Some(field_value));
55            }
56            // TODO: implement label matching
57            let instances = get_entity_instances_by_type_filter_by_properties(&ctx, &entity_type, entity_instance_manager);
58            let field_value = FieldValue::owned_any(instances);
59            Ok(Some(field_value))
60        })
61    })
62    .description(entity_type.description.clone())
63    .argument(InputValue::new("ids", TypeRef::named_nn_list(TypeRef::ID)))
64    .argument(InputValue::new("id", TypeRef::named(TypeRef::ID)))
65    // TODO: implement label matching
66    .argument(InputValue::new("label", TypeRef::named(TypeRef::STRING)));
67    field = add_entity_type_properties_as_field_arguments(field, entity_type, true, true);
68    Some(field)
69}