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