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