DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/Environment/
MountainEnvironment.rs1use 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 pub fn Create(ApplicationHandle:AppHandle<Wry>, ApplicationState:Arc<ApplicationState>) -> Self {
93 dev_log!("lifecycle", "[MountainEnvironment] New instance created.");
94
95 #[cfg(feature = "AirIntegration")]
96 {
97 Self { ApplicationHandle, ApplicationState, AirClient:None }
98 }
99
100 #[cfg(not(feature = "AirIntegration"))]
101 {
102 Self { ApplicationHandle, ApplicationState }
103 }
104 }
105
106 #[cfg(feature = "AirIntegration")]
112 pub fn CreateWithAir(
113 ApplicationHandle:AppHandle<Wry>,
114
115 ApplicationState:Arc<ApplicationState>,
116
117 AirClient:Option<AirServiceClient<tonic::transport::Channel>>,
118 ) -> Self {
119 dev_log!(
120 "lifecycle",
121 "[MountainEnvironment] New instance created with Air client: {}",
122 AirClient.is_some()
123 );
124
125 Self { ApplicationHandle, ApplicationState, AirClient }
126 }
127
128 #[cfg(feature = "AirIntegration")]
135 pub fn SetAirClient(&mut self, AirClient:Option<AirServiceClient<tonic::transport::Channel>>) {
136 dev_log!("lifecycle", "[MountainEnvironment] Air client updated: {}", AirClient.is_some());
137
138 self.AirClient = AirClient;
139 }
140
141 #[cfg(feature = "AirIntegration")]
147 pub async fn IsAirAvailable(&self) -> bool {
148 if let Some(_AirClient) = &self.AirClient {
152 dev_log!(
154 "lifecycle",
155 "[MountainEnvironment] Air client configured (health check disabled pending integration)"
156 );
157
158 true
159 } else {
160 dev_log!("lifecycle", "[MountainEnvironment] No Air client configured");
161
162 false
163 }
164 }
165
166 #[cfg(not(feature = "AirIntegration"))]
168 pub async fn IsAirAvailable(&self) -> bool { false }
169
170 async fn ScanExtensionDirectory(&self, path:&std::path::PathBuf) -> Result<Vec<serde_json::Value>, CommonError> {
177 use std::fs;
178
179 let mut extensions = Vec::new();
180
181 if !path.exists() || !path.is_dir() {
183 dev_log!(
184 "lifecycle",
185 "warn: [ExtensionManagementService] Extension directory does not exist: {:?}",
186 path
187 );
188
189 return Ok(extensions);
190 }
191
192 let entries = fs::read_dir(path).map_err(|error| {
194 CommonError::FileSystemIO {
195 Path:path.clone(),
196 Description:format!("Failed to read extension directory: {}", error),
197 }
198 })?;
199
200 for entry in entries {
201 let entry = entry.map_err(|error| {
202 CommonError::FileSystemIO {
203 Path:path.clone(),
204 Description:format!("Failed to read directory entry: {}", error),
205 }
206 })?;
207
208 let entry_path = entry.path();
209
210 if entry_path.is_dir() {
211 let package_json_path = entry_path.join("package.json");
213
214 if package_json_path.exists() {
215 match fs::read_to_string(&package_json_path) {
216 Ok(content) => {
217 match serde_json::from_str::<Value>(&content) {
218 Ok(mut package_json) => {
219 if let Some(obj) = package_json.as_object_mut() {
221 obj.insert(
222 "ExtensionLocation".to_string(),
223 Value::String(entry_path.to_string_lossy().to_string()),
224 );
225 }
226
227 extensions.push(package_json);
228
229 dev_log!(
230 "lifecycle",
231 "[ExtensionManagementService] Found extension at: {:?}",
232 entry_path
233 );
234 },
235
236 Err(error) => {
237 dev_log!(
238 "lifecycle",
239 "warn: [ExtensionManagementService] Failed to parse package.json at {:?}: {}",
240 package_json_path,
241 error
242 );
243 },
244 }
245 },
246
247 Err(error) => {
248 dev_log!(
249 "lifecycle",
250 "warn: [ExtensionManagementService] Failed to read package.json at {:?}: {}",
251 package_json_path,
252 error
253 );
254 },
255 }
256 }
257 }
258 }
259
260 Ok(extensions)
261 }
262}
263
264impl Environment for MountainEnvironment {}
265
266#[async_trait]
268impl ExtensionManagementService for MountainEnvironment {
269 async fn ScanForExtensions(&self) -> Result<(), CommonError> {
274 dev_log!("lifecycle", "[ExtensionManagementService] Scanning for extensions...");
275
276 let ScanPaths:Vec<std::path::PathBuf> = {
278 let ScanPathsGuard = self
279 .ApplicationState
280 .Extension
281 .Registry
282 .ExtensionScanPaths
283 .lock()
284 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
285
286 ScanPathsGuard.clone()
287 };
288
289 let mut extensions = Vec::new();
290
291 for path in ScanPaths {
293 if let Ok(mut scan_result) = self.ScanExtensionDirectory(&path).await {
294 extensions.append(&mut scan_result);
295 }
296 }
297
298 let mut ScannedExtensionsGuard = self
300 .ApplicationState
301 .Extension
302 .ScannedExtensions
303 .ScannedExtensions
304 .lock()
305 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
306
307 ScannedExtensionsGuard.clear();
308
309 for extension in extensions {
310 match serde_json::from_value::<ExtensionDescriptionStateDTO>(extension.clone()) {
313 Ok(Dto) => {
314 let Key = Dto
316 .Identifier
317 .as_object()
318 .and_then(|O| O.get("value"))
319 .and_then(|V| V.as_str())
320 .unwrap_or(&Dto.Name)
321 .to_string();
322
323 if !Key.is_empty() {
324 ScannedExtensionsGuard.insert(Key, Dto);
325 }
326 },
327
328 Err(Error) => {
329 let Name = extension.get("name").and_then(|V| V.as_str()).unwrap_or("?");
330
331 dev_log!(
332 "lifecycle",
333 "warn: [ExtensionManagementService] Failed to parse extension '{}': {}",
334 Name,
335 Error
336 );
337 },
338 }
339 }
340
341 dev_log!(
342 "lifecycle",
343 "[ExtensionManagementService] Found {} extensions",
344 ScannedExtensionsGuard.len()
345 );
346
347 Ok(())
348 }
349
350 async fn GetExtensions(&self) -> Result<Vec<Value>, CommonError> {
356 let ScannedExtensionsGuard = self
357 .ApplicationState
358 .Extension
359 .ScannedExtensions
360 .ScannedExtensions
361 .lock()
362 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
363
364 let GuardLen = ScannedExtensionsGuard.len();
365
366 let Extensions:Vec<Value> = ScannedExtensionsGuard
367 .values()
368 .map(|ext| serde_json::to_value(ext).unwrap_or(Value::Null))
369 .collect();
370
371 let SerializedCount = Extensions.iter().filter(|v| !v.is_null()).count();
372
373 dev_log!(
374 "lifecycle",
375 "[MountainEnvironment] GetExtensions: ScannedExtensions map={} entries, serialized={} non-null",
376 GuardLen,
377 SerializedCount
378 );
379
380 Ok(Extensions)
381 }
382
383 async fn GetExtension(&self, id:String) -> Result<Option<Value>, CommonError> {
388 let ScannedExtensionsGuard = self
389 .ApplicationState
390 .Extension
391 .ScannedExtensions
392 .ScannedExtensions
393 .lock()
394 .map_err(|Error| CommonError::StateLockPoisoned { Context:Error.to_string() })?;
395
396 if let Some(extension_dto) = ScannedExtensionsGuard.get(&id) {
397 let mut extension_value = serde_json::Map::new();
399
400 extension_value.insert("Identifier".to_string(), extension_dto.Identifier.clone());
401
402 extension_value.insert("Name".to_string(), Value::String(extension_dto.Name.clone()));
403
404 extension_value.insert("Version".to_string(), Value::String(extension_dto.Version.clone()));
405
406 extension_value.insert("Publisher".to_string(), Value::String(extension_dto.Publisher.clone()));
407
408 extension_value.insert("Engines".to_string(), extension_dto.Engines.clone());
409
410 if let Some(main) = &extension_dto.Main {
411 extension_value.insert("Main".to_string(), Value::String(main.clone()));
412 }
413
414 if let Some(browser) = &extension_dto.Browser {
415 extension_value.insert("Browser".to_string(), Value::String(browser.clone()));
416 }
417
418 if let Some(module_type) = &extension_dto.ModuleType {
419 extension_value.insert("ModuleType".to_string(), Value::String(module_type.clone()));
420 }
421
422 extension_value.insert("IsBuiltin".to_string(), Value::Bool(extension_dto.IsBuiltin));
423
424 extension_value.insert("IsUnderDevelopment".to_string(), Value::Bool(extension_dto.IsUnderDevelopment));
425
426 extension_value.insert("ExtensionLocation".to_string(), extension_dto.ExtensionLocation.clone());
427
428 if let Some(activation_events) = &extension_dto.ActivationEvents {
429 let events:Vec<Value> = activation_events.iter().map(|e| Value::String(e.clone())).collect();
430
431 extension_value.insert("ActivationEvents".to_string(), Value::Array(events));
432 }
433
434 if let Some(contributes) = &extension_dto.Contributes {
435 extension_value.insert("Contributes".to_string(), contributes.clone());
436 }
437
438 Ok(Some(Value::Object(extension_value)))
439 } else {
440 Ok(None)
441 }
442 }
443}
444
445impl_provider!(CommandExecutor);
449
450impl_provider!(ConfigurationProvider);
451
452impl_provider!(ConfigurationInspector);
453
454impl_provider!(CustomEditorProvider);
456
457impl_provider!(DebugService);
458
459impl_provider!(DocumentProvider);
461
462impl_provider!(DiagnosticManager);
463
464impl_provider!(FileSystemReader);
466
467impl_provider!(FileSystemWriter);
468
469impl_provider!(FileWatcherProvider);
470
471impl_provider!(IPCProvider);
473
474impl_provider!(KeybindingProvider);
475
476impl_provider!(LanguageFeatureProviderRegistry);
478
479impl_provider!(OutputChannelManager);
480
481impl_provider!(SecretProvider);
483
484impl_provider!(SourceControlManagementProvider);
485
486impl_provider!(StatusBarProvider);
488
489impl_provider!(StorageProvider);
490
491impl_provider!(SynchronizationProvider);
493
494impl_provider!(TerminalProvider);
495
496impl_provider!(TestController);
498
499impl_provider!(TreeViewProvider);
500
501impl_provider!(UserInterfaceProvider);
503
504impl_provider!(WebviewProvider);
505
506impl_provider!(WorkspaceProvider);
508
509impl_provider!(WorkspaceEditApplier);
510
511impl_provider!(ExtensionManagementService);
513
514impl_provider!(SearchProvider);