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 log::{info, warn};
15use serde_json::{Map, Value};
16use tauri::Manager;
17
18use crate::{Environment::Utility, RunTime::ApplicationRunTime::RuntimeStruct::ApplicationRunTime};
19
20/// Updates a configuration value in the appropriate `settings.json` file.
21pub(super) async fn update_configuration_value(
22	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
23	key:String,
24	value:Value,
25	target:ConfigurationTarget,
26	_overrides:ConfigurationOverridesDTO,
27	_scope_to_language:Option<bool>,
28) -> Result<(), CommonError> {
29	info!("[ConfigurationProvider] Updating key '{}' in target {:?}", key, target);
30
31	let runtime = environment.ApplicationHandle.state::<Arc<ApplicationRunTime>>().inner().clone();
32
33	let config_path:PathBuf = match target {
34		ConfigurationTarget::User => {
35			environment
36				.ApplicationHandle
37				.path()
38				.app_config_dir()
39				.map(|p| p.join("settings.json"))
40				.map_err(|error| {
41					CommonError::ConfigurationLoad {
42						Description:format!("Could not resolve user config path: {}", error),
43					}
44				})?
45		},
46
47		ConfigurationTarget::Workspace => {
48			environment
49				.ApplicationState
50				.Workspace
51				.WorkspaceConfigurationPath
52				.lock()
53				.map_err(Utility::MapApplicationStateLockErrorToCommonError)?
54				.clone()
55				.ok_or_else(|| {
56					CommonError::ConfigurationLoad { Description:"No workspace configuration path set".into() }
57				})?
58		},
59
60		_ => {
61			warn!("[ConfigurationProvider] Unsupported configuration target: {:?}", target);
62
63			return Err(CommonError::NotImplemented {
64				FeatureName:"This configuration target is not supported".into(),
65			});
66		},
67	};
68
69	// Read the file, modify it, and write it back.
70	let bytes = runtime.Run(ReadFile(config_path.clone())).await.unwrap_or_default();
71
72	let mut current_config:Value = serde_json::from_slice(&bytes).unwrap_or_else(|_| Value::Object(Map::new()));
73
74	if let Value::Object(map) = &mut current_config {
75		if value.is_null() {
76			map.remove(&key);
77			info!("[ConfigurationProvider] Removed configuration key '{}'", key);
78		} else {
79			map.insert(key.clone(), value.clone());
80			info!("[ConfigurationProvider] Updated configuration key '{}'", key);
81		}
82	}
83
84	let content_bytes = serde_json::to_vec_pretty(&current_config)?;
85
86	runtime
87		.Run(WriteFileBytes(config_path.clone(), content_bytes, true, true))
88		.await?;
89
90	// Re-merge all configurations to update the live state.
91	crate::Environment::ConfigurationProvider::Loading::initialize_and_merge_configurations(environment).await?;
92
93	Ok(())
94}