reactive_graph_command_impl/
command_manager_impl.rs

1use async_trait::async_trait;
2use serde_json::json;
3use std::sync::Arc;
4
5use reactive_graph_command_api::CommandManager;
6use reactive_graph_command_api::CommandRegistrationError;
7use reactive_graph_command_model::component::COMPONENT_COMMAND;
8use reactive_graph_command_model::component::CommandProperties::COMMAND_NAME;
9use reactive_graph_command_model::entity::Command;
10use reactive_graph_command_model::error::NoSuchCommand;
11use reactive_graph_graph::EntityType;
12use reactive_graph_graph::EntityTypeId;
13use reactive_graph_graph::PropertyInstanceGetter;
14use reactive_graph_lifecycle::Lifecycle;
15use reactive_graph_reactive_model_impl::ReactiveEntity;
16use reactive_graph_reactive_service_api::ReactiveEntityManager;
17use reactive_graph_type_system_api::EntityTypeManager;
18use springtime_di::Component;
19use springtime_di::component_alias;
20
21#[derive(Component)]
22pub struct CommandManagerImpl {
23    entity_type_manager: Arc<dyn EntityTypeManager + Send + Sync>,
24    reactive_entity_manager: Arc<dyn ReactiveEntityManager + Send + Sync>,
25}
26
27#[async_trait]
28#[component_alias]
29impl CommandManager for CommandManagerImpl {
30    fn get_command(&self, name: &str) -> Result<Command, NoSuchCommand> {
31        let name = name.into();
32        match self
33            .reactive_entity_manager
34            .get_by_component(&COMPONENT_COMMAND)
35            .iter()
36            .find(|e| e.as_string(COMMAND_NAME).is_some_and(|command_name| command_name == name))
37        {
38            Some(e) => Command::try_from(e.clone()).map_err(NoSuchCommand::NotACommand),
39            None => Err(NoSuchCommand::CommandNotFound(name)),
40        }
41    }
42
43    fn get_commands(&self) -> Vec<Command> {
44        self.reactive_entity_manager
45            .get_by_component(&COMPONENT_COMMAND)
46            .iter()
47            .filter_map(|e| Command::try_from(e.clone()).ok())
48            .collect()
49    }
50
51    fn register_command(&self, command: Command) -> Result<(), CommandRegistrationError> {
52        let ty = command.ty();
53        if !self.entity_type_manager.has(&ty) {
54            return Err(CommandRegistrationError::EntityTypeNotFound(ty));
55        }
56        let _ = self
57            .reactive_entity_manager
58            .register_reactive_instance(command.get_instance())
59            .map_err(CommandRegistrationError::ReactiveEntityRegistrationError);
60        Ok(())
61    }
62
63    fn register_singleton_command(&self, command: Command, entity_type: EntityType) -> Result<(), CommandRegistrationError> {
64        let _ = self
65            .entity_type_manager
66            .register(entity_type)
67            .map_err(CommandRegistrationError::EntityTypeRegistrationError)?;
68        let _ = self
69            .reactive_entity_manager
70            .register_reactive_instance(command.get_instance())
71            .map_err(CommandRegistrationError::ReactiveEntityRegistrationError);
72        Ok(())
73    }
74}
75
76#[async_trait]
77impl Lifecycle for CommandManagerImpl {
78    async fn init(&self) {
79        let reactive_entity_manager = self.reactive_entity_manager.clone();
80
81        let executor = Box::new(move |_: &ReactiveEntity| json!(reactive_entity_manager.get_by_component(&COMPONENT_COMMAND).len()));
82        let command = Command::builder()
83            .ty(EntityTypeId::new_from_type("core", "num_commands"))
84            .help("Number of commands")
85            .description("Number of commands")
86            .executor(executor)
87            .build();
88        let entity_type: EntityType = command.get_entity_type();
89        let _ = self.register_singleton_command(command, entity_type);
90
91        // if let Ok((command, entity_type)) = Command::new()
92        //     .singleton_from_type("core", "num_commands")
93        //     .help("Number of commands")
94        //     .no_arguments()
95        //     .executor(move |_| json!(reactive_entity_manager.get_by_component(&COMPONENT_COMMAND).len()))
96        //     .build_with_type()
97        // {
98        //     let _ = self.register_singleton_command(command, entity_type);
99        // }
100    }
101}