Skip to main content

Mountain/Environment/ConfigurationProvider/
UpdateValue.rs

1//! Configuration value update and persistence.
2
3use 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::RuntimeStruct::ApplicationRunTime, dev_log};
18
19/// Updates a configuration value in the appropriate `settings.json` file.
20pub(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::User => {
39			environment
40				.ApplicationHandle
41				.path()
42				.app_config_dir()
43				.map(|p| p.join("settings.json"))
44				.map_err(|error| {
45					CommonError::ConfigurationLoad {
46						Description:format!("Could not resolve user config path: {}", error),
47					}
48				})?
49		},
50
51		ConfigurationTarget::Workspace => {
52			environment
53				.ApplicationState
54				.Workspace
55				.WorkspaceConfigurationPath
56				.lock()
57				.map_err(Utility::MapApplicationStateLockErrorToCommonError)?
58				.clone()
59				.ok_or_else(|| {
60					CommonError::ConfigurationLoad { Description:"No workspace configuration path set".into() }
61				})?
62		},
63
64		_ => {
65			dev_log!(
66				"config",
67				"warn: [ConfigurationProvider] Unsupported configuration target: {:?}",
68				target
69			);
70
71			return Err(CommonError::NotImplemented {
72				FeatureName:"This configuration target is not supported".into(),
73			});
74		},
75	};
76
77	// Read the file, modify it, and write it back.
78	let bytes = runtime.Run(ReadFile(config_path.clone())).await.unwrap_or_default();
79
80	let mut current_config:Value = serde_json::from_slice(&bytes).unwrap_or_else(|_| Value::Object(Map::new()));
81
82	if let Value::Object(map) = &mut current_config {
83		if value.is_null() {
84			map.remove(&key);
85			dev_log!("config", "[ConfigurationProvider] Removed configuration key '{}'", key);
86		} else {
87			map.insert(key.clone(), value.clone());
88			dev_log!("config", "[ConfigurationProvider] Updated configuration key '{}'", key);
89		}
90	}
91
92	let content_bytes = serde_json::to_vec_pretty(&current_config)?;
93
94	runtime
95		.Run(WriteFileBytes(config_path.clone(), content_bytes, true, true))
96		.await?;
97
98	// Re-merge all configurations to update the live state.
99	crate::Environment::ConfigurationProvider::Loading::initialize_and_merge_configurations(environment).await?;
100
101	Ok(())
102}