Mountain/Environment/ConfigurationProvider/
Loading.rs1use std::{path::PathBuf, sync::Arc};
4
5use CommonLibrary::{
6 Effect::ApplicationRunTime::ApplicationRunTime as _,
7 Error::CommonError::CommonError,
8 FileSystem::ReadFile::ReadFile,
9};
10use serde_json::{Map, Value};
11use tauri::Manager;
12
13use crate::{
14 ApplicationState::DTO::MergedConfigurationStateDTO::MergedConfigurationStateDTO,
15 Environment::Utility,
16 RunTime::ApplicationRunTime::RuntimeStruct::ApplicationRunTime,
17 dev_log,
18};
19
20pub(super) async fn read_and_parse_configuration_file(
22 environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
23 path:&Option<PathBuf>,
24) -> Result<Value, CommonError> {
25 if let Some(p) = path {
26 let runtime = environment.ApplicationHandle.state::<Arc<ApplicationRunTime>>().inner().clone();
27
28 if let Ok(bytes) = runtime.Run(ReadFile(p.clone())).await {
29 return Ok(serde_json::from_slice(&bytes).unwrap_or_else(|_| Value::Object(Map::new())));
30 }
31 }
32
33 Ok(Value::Object(Map::new()))
34}
35
36pub async fn initialize_and_merge_configurations(
39 environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
40) -> Result<(), CommonError> {
41 dev_log!(
42 "config",
43 "[ConfigurationProvider] Re-initializing and merging all configurations..."
44 );
45
46 let default_config = collect_default_configurations(&environment.ApplicationState)?;
47
48 let user_settings_path = environment
49 .ApplicationHandle
50 .path()
51 .app_config_dir()
52 .map(|p| p.join("settings.json"))
53 .ok();
54
55 let workspace_settings_path = environment
56 .ApplicationState
57 .Workspace
58 .WorkspaceConfigurationPath
59 .lock()
60 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
61 .clone();
62
63 let user_config = read_and_parse_configuration_file(environment, &user_settings_path).await?;
64
65 let workspace_config = read_and_parse_configuration_file(environment, &workspace_settings_path).await?;
66
67 let mut merged = default_config.as_object().cloned().unwrap_or_default();
70
71 if let Some(user_map) = user_config.as_object() {
72 for (key, value) in user_map {
73 if value.is_object() && merged.get(key.as_str()).is_some_and(|v| v.is_object()) {
75 if let (Some(user_value), Some(_base_value)) =
76 (value.as_object(), merged.get(key.as_str()).and_then(|v| v.as_object()))
77 {
78 for (inner_key, inner_value) in user_value {
79 merged.get_mut(key.as_str()).and_then(|v| v.as_object_mut()).map(|m| {
80 m.insert(inner_key.clone(), inner_value.clone());
81 });
82 }
83 }
84 } else {
85 merged.insert(key.clone(), value.clone());
86 }
87 }
88 }
89
90 if let Some(workspace_map) = workspace_config.as_object() {
91 for (key, value) in workspace_map {
92 if value.is_object() && merged.get(key.as_str()).is_some_and(|v| v.is_object()) {
93 if let (Some(workspace_value), Some(_base_value)) =
94 (value.as_object(), merged.get(key.as_str()).and_then(|v| v.as_object()))
95 {
96 for (inner_key, inner_value) in workspace_value {
97 merged.get_mut(key.as_str()).and_then(|v| v.as_object_mut()).map(|m| {
98 m.insert(inner_key.clone(), inner_value.clone());
99 });
100 }
101 }
102 } else {
103 merged.insert(key.clone(), value.clone());
104 }
105 }
106 }
107
108 let configuration_size = merged.len();
109 let final_config = MergedConfigurationStateDTO::Create(Value::Object(merged));
110
111 *environment
112 .ApplicationState
113 .Configuration
114 .GlobalConfiguration
115 .lock()
116 .map_err(Utility::MapApplicationStateLockErrorToCommonError)? = final_config.Data;
117
118 dev_log!(
119 "config",
120 "[ConfigurationProvider] Configuration merged successfully with {} top-level keys.",
121 configuration_size
122 );
123
124 Ok(())
125}
126
127pub(super) fn collect_default_configurations(
129 application_state:&crate::ApplicationState::ApplicationState,
130) -> Result<Value, CommonError> {
131 let mut default_config = Map::new();
132
133 for extension in application_state
135 .Extension
136 .ScannedExtensions
137 .ScannedExtensions
138 .lock()
139 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
140 .values()
141 {
142 if let Some(contributes) = &extension.Contributes {
143 if let Some(config_array) = contributes.get("configuration").and_then(|c| c.as_array()) {
144 for config_value in config_array {
145 if let (Some(key), Some(value)) =
147 (config_value.get("key").and_then(|k| k.as_str()), config_value.get("value"))
148 {
149 if let Some(value_obj) = value.as_object() {
150 default_config.insert(key.to_string(), Value::Object(value_obj.clone()));
151 }
152 }
153 }
154 }
155 }
156 }
157
158 Ok(Value::Object(default_config))
159}