Mountain/Environment/ConfigurationProvider/
UpdateValue.rs1use std::{path::PathBuf, sync::Arc};
4
5use CommonLibrary::{
6 Configuration::DTO::{
7 ConfigurationOverridesDTO::ConfigurationOverridesDTO,
8 ConfigurationTarget::ConfigurationTarget,
9 },
10 Effect::ApplicationRunTime::ApplicationRunTime as _,
11 Error::CommonError::CommonError,
12 FileSystem::{ReadFile::ReadFile, WriteFileBytes::WriteFileBytes},
13};
14use serde_json::{Map, Value};
15use tauri::Manager;
16
17use crate::{Environment::Utility, RunTime::ApplicationRunTime::ApplicationRunTime, dev_log};
18
19pub(super) async fn update_configuration_value(
21 environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
22 key:String,
23 value:Value,
24 target:ConfigurationTarget,
25 _overrides:ConfigurationOverridesDTO,
26 _scope_to_language:Option<bool>,
27) -> Result<(), CommonError> {
28 dev_log!(
29 "config",
30 "[ConfigurationProvider] Updating key '{}' in target {:?}",
31 key,
32 target
33 );
34
35 let runtime = environment.ApplicationHandle.state::<Arc<ApplicationRunTime>>().inner().clone();
36
37 let config_path:PathBuf = match target {
38 ConfigurationTarget::UserLocal | ConfigurationTarget::User => {
43 environment
44 .ApplicationHandle
45 .path()
46 .app_config_dir()
47 .map(|p| p.join("settings.json"))
48 .map_err(|error| {
49 CommonError::ConfigurationLoad {
50 Description:format!("Could not resolve user config path: {}", error),
51 }
52 })?
53 },
54
55 ConfigurationTarget::Workspace => {
56 environment
57 .ApplicationState
58 .Workspace
59 .WorkspaceConfigurationPath
60 .lock()
61 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?
62 .clone()
63 .ok_or_else(|| {
64 CommonError::ConfigurationLoad { Description:"No workspace configuration path set".into() }
65 })?
66 },
67
68 ConfigurationTarget::WorkspaceFolder => {
74 let FoldersGuard = environment
75 .ApplicationState
76 .Workspace
77 .WorkspaceFolders
78 .lock()
79 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
80 let First = FoldersGuard.first().ok_or_else(|| {
81 CommonError::ConfigurationLoad {
82 Description:"No workspace folders open for WorkspaceFolder target".into(),
83 }
84 })?;
85 let FolderPath = First.URI.to_file_path().map_err(|_| {
86 CommonError::ConfigurationLoad {
87 Description:format!("Workspace folder URI is not a local path: {}", First.URI),
88 }
89 })?;
90 FolderPath.join(".vscode").join("settings.json")
91 },
92
93 ConfigurationTarget::Memory => {
99 environment.ApplicationState.Configuration.SetGlobalValue(&key, value.clone());
100 dev_log!(
101 "config",
102 "[ConfigurationProvider] Memory target: stored in-memory value for '{}'",
103 key
104 );
105 return Ok(());
106 },
107
108 ConfigurationTarget::Default | ConfigurationTarget::Policy => {
110 return Err(CommonError::InvalidArgument {
111 ArgumentName:"target".into(),
112 Reason:format!("Configuration target {:?} is read-only", target),
113 });
114 },
115 };
116
117 let bytes = runtime.Run(ReadFile(config_path.clone())).await.unwrap_or_default();
119
120 let mut current_config:Value = serde_json::from_slice(&bytes).unwrap_or_else(|_| Value::Object(Map::new()));
121
122 if let Value::Object(map) = &mut current_config {
123 if value.is_null() {
124 map.remove(&key);
125 dev_log!("config", "[ConfigurationProvider] Removed configuration key '{}'", key);
126 } else {
127 map.insert(key.clone(), value.clone());
128 dev_log!("config", "[ConfigurationProvider] Updated configuration key '{}'", key);
129 }
130 }
131
132 let content_bytes = serde_json::to_vec_pretty(¤t_config)?;
133
134 runtime
135 .Run(WriteFileBytes(config_path.clone(), content_bytes, true, true))
136 .await?;
137
138 crate::Environment::ConfigurationProvider::Loading::ClearSettingsFileCache();
143
144 crate::Environment::ConfigurationProvider::Loading::initialize_and_merge_configurations(environment).await?;
146
147 Ok(())
148}