1use std::sync::Arc;
14
15#[cfg(feature = "AirIntegration")]
17use AirLibrary::Vine::Generated::air::air_service_client::AirServiceClient;
18use CommonLibrary::{
19 Command::CommandExecutor::CommandExecutor,
20 Configuration::{ConfigurationInspector::ConfigurationInspector, ConfigurationProvider::ConfigurationProvider},
21 CustomEditor::CustomEditorProvider::CustomEditorProvider,
22 Debug::DebugService::DebugService,
23 Diagnostic::DiagnosticManager::DiagnosticManager,
24 Document::DocumentProvider::DocumentProvider,
25 Environment::{Environment::Environment, Requires::Requires},
26 Error::CommonError::CommonError,
27 ExtensionManagement::ExtensionManagementService::ExtensionManagementService,
28 FileSystem::{
29 FileSystemReader::FileSystemReader,
30 FileSystemWriter::FileSystemWriter,
31 FileWatcherProvider::FileWatcherProvider,
32 },
33 IPC::IPCProvider::IPCProvider,
34 Keybinding::KeybindingProvider::KeybindingProvider,
35 LanguageFeature::LanguageFeatureProviderRegistry::LanguageFeatureProviderRegistry,
36 Output::OutputChannelManager::OutputChannelManager,
37 Search::SearchProvider::SearchProvider,
38 Secret::SecretProvider::SecretProvider,
39 SourceControlManagement::SourceControlManagementProvider::SourceControlManagementProvider,
40 StatusBar::StatusBarProvider::StatusBarProvider,
41 Storage::StorageProvider::StorageProvider,
42 Synchronization::SynchronizationProvider::SynchronizationProvider,
43 Terminal::TerminalProvider::TerminalProvider,
44 Testing::TestController::TestController,
45 TreeView::TreeViewProvider::TreeViewProvider,
46 UserInterface::UserInterfaceProvider::UserInterfaceProvider,
47 Webview::WebviewProvider::WebviewProvider,
48 Workspace::{WorkspaceEditApplier::WorkspaceEditApplier, WorkspaceProvider::WorkspaceProvider},
49};
50use async_trait::async_trait;
51use serde_json::Value;
52use tauri::{AppHandle, Wry};
53
54use crate::{
55 ApplicationState::{
56 DTO::ExtensionDescriptionStateDTO::ExtensionDescriptionStateDTO,
57 State::ApplicationState::ApplicationState,
58 },
59 dev_log,
60};
61use crate::impl_provider;
64
65#[derive(Clone)]
67pub struct MountainEnvironment {
73 pub ApplicationHandle:AppHandle<Wry>,
75
76 pub ApplicationState:Arc<ApplicationState>,
78
79 #[cfg(feature = "AirIntegration")]
84 pub AirClient:Option<AirServiceClient<tonic::transport::Channel>>,
85}
86
87impl MountainEnvironment {
88 #[allow(unused_mut)]
93 pub fn Create(ApplicationHandle:AppHandle<Wry>, ApplicationState:Arc<ApplicationState>) -> Self {
94 dev_log!("lifecycle", "[MountainEnvironment] New instance created.");
95
96 #[cfg(feature = "AirIntegration")]
97 {
98 Self { ApplicationHandle, ApplicationState, AirClient:None }
99 }
100
101 #[cfg(not(feature = "AirIntegration"))]
102 {
103 Self { ApplicationHandle, ApplicationState }
104 }
105 }
106
107 #[cfg(feature = "AirIntegration")]
113 pub fn CreateWithAir(
114 ApplicationHandle:AppHandle<Wry>,
115
116 ApplicationState:Arc<ApplicationState>,
117
118 AirClient:Option<AirServiceClient<tonic::transport::Channel>>,
119 ) -> Self {
120 dev_log!(
121 "lifecycle",
122 "[MountainEnvironment] New instance created with Air client: {}",
123 AirClient.is_some()
124 );
125
126 Self { ApplicationHandle, ApplicationState, AirClient }
127 }
128
129 #[cfg(feature = "AirIntegration")]
136 pub fn SetAirClient(&mut self, AirClient:Option<AirServiceClient<tonic::transport::Channel>>) {
137 dev_log!("lifecycle", "[MountainEnvironment] Air client updated: {}", AirClient.is_some());
138
139 self.AirClient = AirClient;
140 }
141
142 #[cfg(feature = "AirIntegration")]
148 pub async fn IsAirAvailable(&self) -> bool {
149 if let Some(_AirClient) = &self.AirClient {
153 dev_log!(
155 "lifecycle",
156 "[MountainEnvironment] Air client configured (health check disabled pending integration)"
157 );
158
159 true
160 } else {
161 dev_log!("lifecycle", "[MountainEnvironment] No Air client configured");
162
163 false
164 }
165 }
166
167 #[cfg(not(feature = "AirIntegration"))]
169 pub async fn IsAirAvailable(&self) -> bool { false }
170
171 async fn ScanExtensionDirectory(&self, path:&std::path::PathBuf) -> Result<Vec<serde_json::Value>, CommonError> {
178 use std::fs;
179
180 let mut extensions = Vec::new();
181
182 if !path.exists() || !path.is_dir() {
184 dev_log!(
185 "lifecycle",
186 "warn: [ExtensionManagementService] Extension directory does not exist: {:?}",
187 path
188 );
189
190 return Ok(extensions);
191 }
192
193 let entries = fs::read_dir(path).map_err(|error| {
195 CommonError::FileSystemIO {
196 Path:path.clone(),
197 Description:format!("Failed to read extension directory: {}", error),
198 }
199 })?;
200
201 for entry in entries {
202 let entry = entry.map_err(|error| {
203 CommonError::FileSystemIO {
204 Path:path.clone(),
205 Description:format!("Failed to read directory entry: {}", error),
206 }
207 })?;
208
209 let entry_path = entry.path();
210
211 if entry_path.is_dir() {
212 let package_json_path = entry_path.join("package.json");
214
215 if package_json_path.exists() {
216 match fs::read_to_string(&package_json_path) {
217 Ok(content) => {
218 match serde_json::from_str::<Value>(&content) {
219 Ok(mut package_json) => {
220 if let Some(obj) = package_json.as_object_mut() {
222 obj.insert(
223 "ExtensionLocation".to_string(),
224 Value::String(entry_path.to_string_lossy().to_string()),
225 );
226 }
227
228 extensions.push(package_json);
229
230 dev_log!(
231 "lifecycle",
232 "[ExtensionManagementService] Found extension at: {:?}",
233 entry_path
234 );
235 },
236
237 Err(error) => {
238 dev_log!(
239 "lifecycle",
240 "warn: [ExtensionManagementService] Failed to parse package.json at {:?}: {}",
241 package_json_path,
242 error
243 );
244 },
245 }
246 },
247
248 Err(error) => {
249 dev_log!(
250 "lifecycle",
251 "warn: [ExtensionManagementService] Failed to read package.json at {:?}: {}",
252 package_json_path,
253 error
254 );
255 },
256 }
257 }
258 }
259 }
260
261 Ok(extensions)
262 }
263}
264
265impl Environment for MountainEnvironment {}
266
267#[async_trait]
269impl ExtensionManagementService for MountainEnvironment {
270 async fn ScanForExtensions(&self) -> Result<(), CommonError> {
275 dev_log!("lifecycle", "[ExtensionManagementService] Scanning for extensions...");
276
277 let ScanPaths:Vec<std::path::PathBuf> = {
279 let ScanPathsGuard = self
280 .ApplicationState
281 .Extension
282 .Registry
283 .ExtensionScanPaths
284 .lock()
285 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
286
287 ScanPathsGuard.clone()
288 };
289
290 let mut extensions = Vec::new();
291
292 for path in ScanPaths {
294 if let Ok(mut scan_result) = self.ScanExtensionDirectory(&path).await {
295 extensions.append(&mut scan_result);
296 }
297 }
298
299 let mut ScannedExtensionsGuard = self
301 .ApplicationState
302 .Extension
303 .ScannedExtensions
304 .ScannedExtensions
305 .lock()
306 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
307
308 ScannedExtensionsGuard.clear();
309
310 for extension in extensions {
311 match serde_json::from_value::<ExtensionDescriptionStateDTO>(extension.clone()) {
314 Ok(Dto) => {
315 let Key = Dto
317 .Identifier
318 .as_object()
319 .and_then(|O| O.get("value"))
320 .and_then(|V| V.as_str())
321 .unwrap_or(&Dto.Name)
322 .to_string();
323
324 if !Key.is_empty() {
325 ScannedExtensionsGuard.insert(Key, Dto);
326 }
327 },
328
329 Err(Error) => {
330 let Name = extension.get("name").and_then(|V| V.as_str()).unwrap_or("?");
331
332 dev_log!(
333 "lifecycle",
334 "warn: [ExtensionManagementService] Failed to parse extension '{}': {}",
335 Name,
336 Error
337 );
338 },
339 }
340 }
341
342 dev_log!(
343 "lifecycle",
344 "[ExtensionManagementService] Found {} extensions",
345 ScannedExtensionsGuard.len()
346 );
347
348 Ok(())
349 }
350
351 async fn GetExtensions(&self) -> Result<Vec<Value>, CommonError> {
357 let ScannedExtensionsGuard = self
358 .ApplicationState
359 .Extension
360 .ScannedExtensions
361 .ScannedExtensions
362 .lock()
363 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
364
365 let GuardLen = ScannedExtensionsGuard.len();
366
367 let Extensions:Vec<Value> = ScannedExtensionsGuard
368 .values()
369 .map(|ext| serde_json::to_value(ext).unwrap_or(Value::Null))
370 .collect();
371
372 let SerializedCount = Extensions.iter().filter(|v| !v.is_null()).count();
373
374 dev_log!(
375 "lifecycle",
376 "[MountainEnvironment] GetExtensions: ScannedExtensions map={} entries, serialized={} non-null",
377 GuardLen,
378 SerializedCount
379 );
380
381 Ok(Extensions)
382 }
383
384 async fn GetExtension(&self, id:String) -> Result<Option<Value>, CommonError> {
389 let ScannedExtensionsGuard = self
390 .ApplicationState
391 .Extension
392 .ScannedExtensions
393 .ScannedExtensions
394 .lock()
395 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
396
397 if let Some(extension_dto) = ScannedExtensionsGuard.get(&id) {
398 let mut extension_value = serde_json::Map::new();
400
401 extension_value.insert("Identifier".to_string(), extension_dto.Identifier.clone());
402
403 extension_value.insert("Name".to_string(), Value::String(extension_dto.Name.clone()));
404
405 extension_value.insert("Version".to_string(), Value::String(extension_dto.Version.clone()));
406
407 extension_value.insert("Publisher".to_string(), Value::String(extension_dto.Publisher.clone()));
408
409 extension_value.insert("Engines".to_string(), extension_dto.Engines.clone());
410
411 if let Some(main) = &extension_dto.Main {
412 extension_value.insert("Main".to_string(), Value::String(main.clone()));
413 }
414
415 if let Some(browser) = &extension_dto.Browser {
416 extension_value.insert("Browser".to_string(), Value::String(browser.clone()));
417 }
418
419 if let Some(module_type) = &extension_dto.ModuleType {
420 extension_value.insert("ModuleType".to_string(), Value::String(module_type.clone()));
421 }
422
423 extension_value.insert("IsBuiltin".to_string(), Value::Bool(extension_dto.IsBuiltin));
424
425 extension_value.insert("IsUnderDevelopment".to_string(), Value::Bool(extension_dto.IsUnderDevelopment));
426
427 extension_value.insert("ExtensionLocation".to_string(), extension_dto.ExtensionLocation.clone());
428
429 if let Some(activation_events) = &extension_dto.ActivationEvents {
430 let events:Vec<Value> = activation_events.iter().map(|e| Value::String(e.clone())).collect();
431
432 extension_value.insert("ActivationEvents".to_string(), Value::Array(events));
433 }
434
435 if let Some(contributes) = &extension_dto.Contributes {
436 extension_value.insert("Contributes".to_string(), contributes.clone());
437 }
438
439 Ok(Some(Value::Object(extension_value)))
440 } else {
441 Ok(None)
442 }
443 }
444}
445
446impl_provider!(CommandExecutor);
450
451impl_provider!(ConfigurationProvider);
452
453impl_provider!(ConfigurationInspector);
454
455impl_provider!(CustomEditorProvider);
457
458impl_provider!(DebugService);
459
460impl_provider!(DocumentProvider);
462
463impl_provider!(DiagnosticManager);
464
465impl_provider!(FileSystemReader);
467
468impl_provider!(FileSystemWriter);
469
470impl_provider!(FileWatcherProvider);
471
472impl_provider!(IPCProvider);
474
475impl_provider!(KeybindingProvider);
476
477impl_provider!(LanguageFeatureProviderRegistry);
479
480impl_provider!(OutputChannelManager);
481
482impl_provider!(SecretProvider);
484
485impl_provider!(SourceControlManagementProvider);
486
487impl_provider!(StatusBarProvider);
489
490impl_provider!(StorageProvider);
491
492impl_provider!(SynchronizationProvider);
494
495impl_provider!(TerminalProvider);
496
497impl_provider!(TestController);
499
500impl_provider!(TreeViewProvider);
501
502impl_provider!(UserInterfaceProvider);
504
505impl_provider!(WebviewProvider);
506
507impl_provider!(WorkspaceProvider);
509
510impl_provider!(WorkspaceEditApplier);
511
512impl_provider!(ExtensionManagementService);
514
515impl_provider!(SearchProvider);