Mountain/Environment/
CommandProvider.rs1#![allow(non_snake_case, non_camel_case_types)]
16
17use std::{future::Future, pin::Pin, sync::Arc};
18
19use Common::{
20 Command::CommandExecutor::CommandExecutor,
21 Error::CommonError::CommonError,
22 IPC::DTO::ProxyTarget::ProxyTarget,
23};
24use async_trait::async_trait;
25use log::{debug, error, info};
26use serde_json::{Value, json};
27use tauri::{AppHandle, Manager, Runtime, WebviewWindow};
28
29use super::MountainEnvironment::MountainEnvironment;
30use crate::{RunTime::ApplicationRunTime::ApplicationRunTime, Vine::Client};
31
32pub enum CommandHandler<R:Runtime + 'static> {
34 Native(
36 fn(
37 AppHandle<R>,
38
39 WebviewWindow<R>,
40
41 Arc<ApplicationRunTime>,
42
43 Value,
44 ) -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>>,
45 ),
46
47 Proxied { SideCarIdentifier:String, CommandIdentifier:String },
49}
50
51impl<R:Runtime> Clone for CommandHandler<R> {
52 fn clone(&self) -> Self {
53 match self {
54 Self::Native(Function) => Self::Native(*Function),
55
56 Self::Proxied { SideCarIdentifier, CommandIdentifier } => {
57 Self::Proxied {
58 SideCarIdentifier:SideCarIdentifier.clone(),
59
60 CommandIdentifier:CommandIdentifier.clone(),
61 }
62 },
63 }
64 }
65}
66
67#[async_trait]
68impl CommandExecutor for MountainEnvironment {
69 async fn ExecuteCommand(&self, CommandIdentifier:String, Argument:Value) -> Result<Value, CommonError> {
72 let HandlerInfoOption = self
73 .ApplicationState
74 .CommandRegistry
75 .lock()
76 .map_err(super::Utility::MapApplicationStateLockErrorToCommonError)?
77 .get(&CommandIdentifier)
78 .cloned();
79
80 match HandlerInfoOption {
81 Some(CommandHandler::Native(Function)) => {
82 debug!("[CommandProvider] Executing NATIVE command '{}'.", CommandIdentifier);
83
84 let RunTime:Arc<ApplicationRunTime> =
85 self.ApplicationHandle.state::<Arc<ApplicationRunTime>>().inner().clone();
86
87 let MainWindow = self.ApplicationHandle.get_webview_window("main").ok_or_else(|| {
88 CommonError::UserInterfaceInteraction {
89 Reason:"Main window not found for command execution".into(),
90 }
91 })?;
92
93 Function(self.ApplicationHandle.clone(), MainWindow, RunTime, Argument)
94 .await
95 .map_err(|Error| CommonError::CommandExecution { CommandIdentifier, Reason:Error })
96 },
97
98 Some(CommandHandler::Proxied { SideCarIdentifier, CommandIdentifier: ProxiedCommandIdentifier }) => {
99 debug!(
100 "[CommandProvider] Executing PROXIED command '{}' on sidecar '{}'.",
101 CommandIdentifier, SideCarIdentifier
102 );
103
104 let RPCParameters = json!([ProxiedCommandIdentifier, Argument]);
105
106 let RPCMethod = format!("{}$ExecuteContributedCommand", ProxyTarget::ExtHostCommands.GetTargetPrefix());
107
108 Client::SendRequest(&SideCarIdentifier, RPCMethod, RPCParameters, 30000)
109 .await
110 .map_err(|Error| CommonError::IPCError { Description:Error.to_string() })
111 },
112
113 None => {
114 error!("[CommandProvider] Command '{}' not found in registry.", CommandIdentifier);
115
116 Err(CommonError::CommandNotFound { Identifier:CommandIdentifier })
117 },
118 }
119 }
120
121 async fn RegisterCommand(&self, SideCarIdentifier:String, CommandIdentifier:String) -> Result<(), CommonError> {
123 info!(
124 "[CommandProvider] Registering PROXY command '{}' from sidecar '{}'",
125 CommandIdentifier, SideCarIdentifier
126 );
127
128 let mut Registry = self
129 .ApplicationState
130 .CommandRegistry
131 .lock()
132 .map_err(super::Utility::MapApplicationStateLockErrorToCommonError)?;
133
134 Registry.insert(
135 CommandIdentifier.clone(),
136 CommandHandler::Proxied { SideCarIdentifier, CommandIdentifier },
137 );
138
139 Ok(())
140 }
141
142 async fn UnregisterCommand(&self, _SideCarIdentifier:String, CommandIdentifier:String) -> Result<(), CommonError> {
144 info!("[CommandProvider] Unregistering command '{}'", CommandIdentifier);
145
146 self.ApplicationState
147 .CommandRegistry
148 .lock()
149 .map_err(super::Utility::MapApplicationStateLockErrorToCommonError)?
150 .remove(&CommandIdentifier);
151
152 Ok(())
153 }
154
155 async fn GetAllCommands(&self) -> Result<Vec<String>, CommonError> {
157 debug!("[CommandProvider] Getting all command identifiers.");
158
159 let Registry = self
160 .ApplicationState
161 .CommandRegistry
162 .lock()
163 .map_err(super::Utility::MapApplicationStateLockErrorToCommonError)?;
164
165 Ok(Registry.keys().cloned().collect())
166 }
167}