Mountain/Environment/ConfigurationProvider/
UpdateValue.rs1use std::{path::PathBuf, sync::Arc};
23
24use CommonLibrary::{
25 Configuration::DTO::{
26 ConfigurationOverridesDTO::ConfigurationOverridesDTO,
27 ConfigurationTarget::ConfigurationTarget,
28 },
29 Effect::ApplicationRunTime::ApplicationRunTime as _,
30 Error::CommonError::CommonError,
31 FileSystem::{ReadFile::ReadFile, WriteFileBytes::WriteFileBytes},
32};
33use serde_json::{Map, Value};
34use tauri::Manager;
35
36use crate::{Environment::Utility, RunTime::ApplicationRunTime::ApplicationRunTime, dev_log};
37
38pub(super) async fn update_configuration_value(
40 environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
41
42 key:String,
43
44 value:Value,
45
46 target:ConfigurationTarget,
47
48 _overrides:ConfigurationOverridesDTO,
49
50 _scope_to_language:Option<bool>,
51) -> Result<(), CommonError> {
52 dev_log!(
53 "config",
54 "[ConfigurationProvider] Updating key '{}' in target {:?}",
55 key,
56 target
57 );
58
59 let runtime = environment.ApplicationHandle.state::<Arc<ApplicationRunTime>>().inner().clone();
60
61 let config_path:PathBuf = match target {
62 ConfigurationTarget::UserLocal | ConfigurationTarget::User => {
67 environment
68 .ApplicationHandle
69 .path()
70 .app_config_dir()
71 .map(|p| p.join("settings.json"))
72 .map_err(|error| {
73 CommonError::ConfigurationLoad {
74 Description:format!("Could not resolve user config path: {}", error),
75 }
76 })?
77 },
78
79 ConfigurationTarget::Workspace => {
80 environment
81 .ApplicationState
82 .Workspace
83 .WorkspaceConfigurationPath
84 .lock()
85 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?
86 .clone()
87 .ok_or_else(|| {
88 CommonError::ConfigurationLoad { Description:"No workspace configuration path set".into() }
89 })?
90 },
91
92 ConfigurationTarget::WorkspaceFolder => {
98 let FoldersGuard = environment
99 .ApplicationState
100 .Workspace
101 .WorkspaceFolders
102 .lock()
103 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
104
105 let First = FoldersGuard.first().ok_or_else(|| {
106 CommonError::ConfigurationLoad {
107 Description:"No workspace folders open for WorkspaceFolder target".into(),
108 }
109 })?;
110
111 let FolderPath = First.URI.to_file_path().map_err(|_| {
112 CommonError::ConfigurationLoad {
113 Description:format!("Workspace folder URI is not a local path: {}", First.URI),
114 }
115 })?;
116
117 FolderPath.join(".vscode").join("settings.json")
118 },
119
120 ConfigurationTarget::Memory => {
126 environment.ApplicationState.Configuration.SetGlobalValue(&key, value.clone());
127
128 dev_log!(
129 "config",
130 "[ConfigurationProvider] Memory target: stored in-memory value for '{}'",
131 key
132 );
133
134 return Ok(());
135 },
136
137 ConfigurationTarget::Default | ConfigurationTarget::Policy => {
139 return Err(CommonError::InvalidArgument {
140 ArgumentName:"target".into(),
141 Reason:format!("Configuration target {:?} is read-only", target),
142 });
143 },
144 };
145
146 let bytes = runtime.Run(ReadFile(config_path.clone())).await.unwrap_or_default();
148
149 let mut current_config:Value = serde_json::from_slice(&bytes).unwrap_or_else(|_| Value::Object(Map::new()));
150
151 if let Value::Object(map) = &mut current_config {
152 if value.is_null() {
153 map.remove(&key);
154
155 dev_log!("config", "[ConfigurationProvider] Removed configuration key '{}'", key);
156 } else {
157 map.insert(key.clone(), value.clone());
158
159 dev_log!("config", "[ConfigurationProvider] Updated configuration key '{}'", key);
160 }
161 }
162
163 let content_bytes = serde_json::to_vec_pretty(¤t_config)?;
164
165 runtime
166 .Run(WriteFileBytes(config_path.clone(), content_bytes, true, true))
167 .await?;
168
169 crate::Environment::ConfigurationProvider::Loading::ClearSettingsFileCache();
174
175 crate::Environment::ConfigurationProvider::Loading::initialize_and_merge_configurations(environment).await?;
177
178 Ok(())
179}