Mountain/IPC/WindServiceHandlers/
Extensions.rs1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3use std::sync::Arc;
6
7use CommonLibrary::ExtensionManagement::ExtensionManagementService::ExtensionManagementService;
8use serde_json::{Value, json};
9
10use crate::{
11 IPC::UriComponents::Normalize::Fn as NormalizeUri,
12 RunTime::ApplicationRunTime::ApplicationRunTime,
13 dev_log,
14};
15
16const EXTENSION_TYPE_SYSTEM:u8 = 0;
26const EXTENSION_TYPE_USER:u8 = 1;
27
28pub async fn ExtensionsGetInstalled(RunTime:Arc<ApplicationRunTime>, Arguments:Vec<Value>) -> Result<Value, String> {
53 let TypeFilter:Option<u8> = Arguments.first().and_then(|V| V.as_u64()).map(|N| N as u8);
54
55 let mut Extensions = RunTime
74 .Environment
75 .GetExtensions()
76 .await
77 .map_err(|Error| format!("extensions:getInstalled failed: {}", Error))?;
78 if Extensions.is_empty() {
79 const POLL_INTERVAL_MS:u64 = 50;
80 const MAX_WAIT_MS:u64 = 5000;
81 let mut Elapsed:u64 = 0;
82 while Extensions.is_empty() && Elapsed < MAX_WAIT_MS {
83 tokio::time::sleep(std::time::Duration::from_millis(POLL_INTERVAL_MS)).await;
84 Elapsed += POLL_INTERVAL_MS;
85 Extensions = RunTime
86 .Environment
87 .GetExtensions()
88 .await
89 .map_err(|Error| format!("extensions:getInstalled failed: {}", Error))?;
90 }
91 if !Extensions.is_empty() {
92 dev_log!(
93 "extensions",
94 "extensions:getInstalled awaited scan completion ({}ms) - now has {} entries",
95 Elapsed,
96 Extensions.len()
97 );
98 } else {
99 dev_log!(
100 "extensions",
101 "warn: extensions:getInstalled timed out after {}ms; returning empty list",
102 Elapsed
103 );
104 }
105 }
106
107 let Wrapped:Vec<Value> = Extensions
108 .into_iter()
109 .filter_map(|Manifest| {
110 let IsBuiltin = Manifest.get("isBuiltin").and_then(Value::as_bool).unwrap_or(true);
115 let ExtensionType = if IsBuiltin { EXTENSION_TYPE_SYSTEM } else { EXTENSION_TYPE_USER };
116
117 if let Some(Wanted) = TypeFilter {
118 if Wanted != ExtensionType {
119 return None;
120 }
121 }
122
123 let Publisher = Manifest
124 .get("publisher")
125 .and_then(Value::as_str)
126 .filter(|S| !S.is_empty())
127 .unwrap_or("unknown")
128 .to_string();
129 let Name = Manifest
130 .get("name")
131 .and_then(Value::as_str)
132 .filter(|S| !S.is_empty())
133 .unwrap_or("unknown")
134 .to_string();
135 let Id = format!("{}.{}", Publisher, Name);
136
137 let Location = NormalizeUri(Manifest.get("extensionLocation"));
145 let mut Manifest = match Manifest {
157 Value::Object(_) => Manifest,
158 _ => json!({}),
159 };
160 if let Value::Object(ref mut Map) = Manifest {
161 Map.insert("extensionLocation".to_string(), Location.clone());
162 Map.entry("publisher".to_string()).or_insert_with(|| json!(Publisher.clone()));
163 Map.entry("name".to_string()).or_insert_with(|| json!(Name.clone()));
164 Map.entry("version".to_string()).or_insert_with(|| json!("0.0.0"));
165 }
166
167 Some(json!({
168 "type": ExtensionType,
170 "isBuiltin": IsBuiltin,
171 "identifier": { "id": Id },
172 "manifest": Manifest,
173 "location": Location,
174 "targetPlatform": "undefined",
175 "isValid": true,
176 "validations": [],
177 "preRelease": false,
178 "isWorkspaceScoped": false,
180 "isMachineScoped": false,
181 "isApplicationScoped": false,
182 "publisherId": null,
183 "isPreReleaseVersion": false,
184 "hasPreReleaseVersion": false,
185 "private": false,
186 "updated": false,
187 "pinned": false,
188 "forceAutoUpdate": false,
189 "source": if IsBuiltin { "system" } else { "vsix" },
194 "size": 0,
195 }))
196 })
197 .collect();
198
199 dev_log!(
200 "extensions",
201 "extensions:getInstalled type={:?} returning {} ILocalExtension-shaped entries",
202 TypeFilter,
203 Wrapped.len()
204 );
205
206 Ok(json!(Wrapped))
207}
208
209pub async fn ExtensionsGetAll(RunTime:Arc<ApplicationRunTime>) -> Result<Value, String> {
211 let Extensions = RunTime
212 .Environment
213 .GetExtensions()
214 .await
215 .map_err(|Error| format!("extensions:getAll failed: {}", Error))?;
216
217 dev_log!("extensions", "extensions:getAll returning {} extensions", Extensions.len());
218 if let Some(First) = Extensions.first() {
219 dev_log!(
220 "extensions",
221 "extensions:getAll sample: {}",
222 serde_json::to_string(First)
223 .unwrap_or_default()
224 .chars()
225 .take(300)
226 .collect::<String>()
227 );
228 }
229 Ok(json!(Extensions))
230}
231
232pub async fn ExtensionsGet(RunTime:Arc<ApplicationRunTime>, Arguments:Vec<Value>) -> Result<Value, String> {
234 let Id = Arguments
235 .first()
236 .and_then(|V| V.as_str())
237 .ok_or_else(|| "extensions:get requires string id as first argument".to_string())?
238 .to_string();
239
240 let Extension = RunTime
241 .Environment
242 .GetExtension(Id)
243 .await
244 .map_err(|Error| format!("extensions:get failed: {}", Error))?;
245
246 Ok(Extension.unwrap_or(Value::Null))
247}
248
249pub async fn ExtensionsIsActive(RunTime:Arc<ApplicationRunTime>, Arguments:Vec<Value>) -> Result<Value, String> {
251 let Id = Arguments
252 .first()
253 .and_then(|V| V.as_str())
254 .ok_or_else(|| "extensions:isActive requires string id as first argument".to_string())?
255 .to_string();
256
257 let Extension = RunTime
258 .Environment
259 .GetExtension(Id)
260 .await
261 .map_err(|Error| format!("extensions:isActive failed: {}", Error))?;
262
263 Ok(json!(Extension.is_some()))
264}