Mountain/IPC/WindServiceHandlers/Extension/
ExtensionUninstall.rs1#![allow(non_snake_case)]
2use std::{path::PathBuf, sync::Arc};
7
8use serde_json::{Value, json};
9use tauri::{AppHandle, Emitter};
10
11use crate::{
12 ExtensionManagement::VsixInstaller,
13 IPC::WindServiceHandlers::Extension::NotifyCocoonDeltaExtensions::NotifyCocoonDeltaExtensions,
14 RunTime::ApplicationRunTime::ApplicationRunTime,
15 dev_log,
16};
17
18pub async fn ExtensionUninstall(
19 ApplicationHandle:AppHandle,
20 Runtime:Arc<ApplicationRunTime>,
21 Args:Vec<Value>,
22) -> Result<Value, String> {
23 let OTELStart = crate::IPC::DevLog::NowNano();
24
25 let Identifier = match Args.first().and_then(|Value| {
26 Value
27 .as_str()
28 .map(str::to_owned)
29 .or_else(|| Value.get("id").and_then(|Inner| Inner.as_str()).map(str::to_owned))
30 }) {
31 Some(Value) => Value,
32 None => {
33 dev_log!("extensions", "extensions:uninstall no-op: Arguments[0] missing identifier");
34 crate::otel_span!("extensions:uninstall:noop-missing-id", OTELStart);
35 return Ok(Value::Null);
36 },
37 };
38
39 let Descriptor = Runtime
40 .Environment
41 .ApplicationState
42 .Extension
43 .ScannedExtensions
44 .Get(&Identifier);
45
46 let InstallDirectory = Descriptor
47 .as_ref()
48 .and_then(|Description| Description.ExtensionLocation.get("path").and_then(|V| V.as_str()))
49 .map(PathBuf::from);
50
51 if let Some(Directory) = InstallDirectory.clone() {
52 let DirectoryForBlocking = Directory.clone();
53
54 tokio::task::spawn_blocking(move || VsixInstaller::UninstallExtension(&DirectoryForBlocking))
55 .await
56 .map_err(|Error| format!("extensions:uninstall join error: {}", Error))?
57 .map_err(|Error| format!("extensions:uninstall failed: {}", Error))?;
58 }
59
60 let RemovedDescriptor = Descriptor
61 .as_ref()
62 .map(|Description| serde_json::to_value(Description).unwrap_or(Value::Null))
63 .unwrap_or(Value::Null);
64
65 Runtime
66 .Environment
67 .ApplicationState
68 .Extension
69 .ScannedExtensions
70 .Remove(&Identifier);
71
72 if !RemovedDescriptor.is_null() {
73 NotifyCocoonDeltaExtensions(Vec::new(), vec![RemovedDescriptor]);
74 }
75
76 if let Err(Error) = ApplicationHandle.emit(
77 "sky://extensions/uninstalled",
78 json!({
79 "identifier": Identifier,
80 "location": InstallDirectory.as_ref().map(|Value| Value.to_string_lossy().to_string()),
81 }),
82 ) {
83 dev_log!("extensions", "warn: failed to emit sky://extensions/uninstalled: {}", Error);
84 }
85
86 dev_log!("extensions", "extensions:uninstall succeeded: {}", Identifier);
87
88 crate::otel_span!(
89 "extensions:uninstall:ok",
90 OTELStart,
91 &[("extension.identifier", Identifier.as_str())]
92 );
93
94 Ok(Value::Bool(true))
95}