Skip to main content

Mountain/Environment/ConfigurationProvider/
InspectValue.rs

1//! Configuration value introspection across all scopes.
2//!
3//! Implements `InspectConfigurationValue` for `MountainEnvironment`.
4//! Unlike `GetValue` (which reads the merged cache), this function
5//! re-reads each configuration layer individually so callers can see
6//! exactly which scope provides a value:
7//!
8//! | Field | Source |
9//! |---|---|
10//! | `DefaultValue` | Extension `contributes.configuration` defaults |
11//! | `UserValue` | `<app-config>/settings.json` |
12//! | `WorkspaceValue` | workspace `settings.json` |
13//! | `EffectiveValue` | Workspace → User → Default (first non-`None`) |
14//!
15//! Returns `None` when the key is not present in any scope. Dot-notation
16//! keys (e.g. `"git.enabled"`) are resolved by splitting on `.` and
17//! walking the nested JSON tree, matching `GetValue`'s traversal.
18
19use CommonLibrary::{
20	Configuration::DTO::{
21		ConfigurationOverridesDTO::ConfigurationOverridesDTO,
22		InspectResultDataDTO::InspectResultDataDTO,
23	},
24	Error::CommonError::CommonError,
25};
26use serde_json::Value;
27use tauri::Manager;
28
29use crate::{Environment::Utility, dev_log};
30
31/// Inspects a configuration key to get its value from all relevant scopes.
32pub(super) async fn inspect_configuration_value(
33	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
34
35	key:String,
36
37	_overrides:ConfigurationOverridesDTO,
38) -> Result<Option<InspectResultDataDTO>, CommonError> {
39	dev_log!("config", "[ConfigurationProvider] Inspecting key: {}", key);
40
41	let user_settings_path = environment
42		.ApplicationHandle
43		.path()
44		.app_config_dir()
45		.map(|p| p.join("settings.json"))
46		.ok();
47
48	let workspace_settings_path = environment
49		.ApplicationState
50		.Workspace
51		.WorkspaceConfigurationPath
52		.lock()
53		.map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?
54		.clone();
55
56	// Read each configuration layer individually.
57	let default_config = super::Loading::collect_default_configurations(&environment.ApplicationState)?;
58
59	let user_config = super::Loading::read_and_parse_configuration_file(environment, &user_settings_path).await?;
60
61	let workspace_config =
62		super::Loading::read_and_parse_configuration_file(environment, &workspace_settings_path).await?;
63
64	let get_value_from_dot_path =
65		|node:&Value, path:&str| -> Option<Value> { path.split('.').try_fold(node, |n, k| n.get(k)).cloned() };
66
67	let mut result_dto = InspectResultDataDTO::default();
68
69	result_dto.DefaultValue = get_value_from_dot_path(&default_config, &key);
70
71	result_dto.UserValue = get_value_from_dot_path(&user_config, &key);
72
73	result_dto.WorkspaceValue = get_value_from_dot_path(&workspace_config, &key);
74
75	// Determine the final effective value based on the correct cascade order.
76	result_dto.EffectiveValue = result_dto
77		.WorkspaceValue
78		.clone()
79		.or_else(|| result_dto.UserValue.clone())
80		.or_else(|| result_dto.DefaultValue.clone());
81
82	if result_dto.EffectiveValue.is_some() {
83		Ok(Some(result_dto))
84	} else {
85		Ok(None)
86	}
87}