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 log::info;
11use serde_json::{Map, Value};
12use tauri::Manager;
13
14use crate::{
15 ApplicationState::DTO::MergedConfigurationStateDTO::MergedConfigurationStateDTO,
16 Environment::Utility,
17 RunTime::ApplicationRunTime::RuntimeStruct::ApplicationRunTime,
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 info!("[ConfigurationProvider] Re-initializing and merging all configurations...");
42
43 let default_config = collect_default_configurations(&environment.ApplicationState)?;
44
45 let user_settings_path = environment
46 .ApplicationHandle
47 .path()
48 .app_config_dir()
49 .map(|p| p.join("settings.json"))
50 .ok();
51
52 let workspace_settings_path = environment
53 .ApplicationState
54 .Workspace
55 .WorkspaceConfigurationPath
56 .lock()
57 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
58 .clone();
59
60 let user_config = read_and_parse_configuration_file(environment, &user_settings_path).await?;
61
62 let workspace_config = read_and_parse_configuration_file(environment, &workspace_settings_path).await?;
63
64 let mut merged = default_config.as_object().cloned().unwrap_or_default();
67
68 if let Some(user_map) = user_config.as_object() {
69 for (key, value) in user_map {
70 if value.is_object() && merged.get(key.as_str()).is_some_and(|v| v.is_object()) {
72 if let (Some(user_value), Some(_base_value)) =
73 (value.as_object(), merged.get(key.as_str()).and_then(|v| v.as_object()))
74 {
75 for (inner_key, inner_value) in user_value {
76 merged.get_mut(key.as_str()).and_then(|v| v.as_object_mut()).map(|m| {
77 m.insert(inner_key.clone(), inner_value.clone());
78 });
79 }
80 }
81 } else {
82 merged.insert(key.clone(), value.clone());
83 }
84 }
85 }
86
87 if let Some(workspace_map) = workspace_config.as_object() {
88 for (key, value) in workspace_map {
89 if value.is_object() && merged.get(key.as_str()).is_some_and(|v| v.is_object()) {
90 if let (Some(workspace_value), Some(_base_value)) =
91 (value.as_object(), merged.get(key.as_str()).and_then(|v| v.as_object()))
92 {
93 for (inner_key, inner_value) in workspace_value {
94 merged.get_mut(key.as_str()).and_then(|v| v.as_object_mut()).map(|m| {
95 m.insert(inner_key.clone(), inner_value.clone());
96 });
97 }
98 }
99 } else {
100 merged.insert(key.clone(), value.clone());
101 }
102 }
103 }
104
105 let configuration_size = merged.len();
106 let final_config = MergedConfigurationStateDTO::Create(Value::Object(merged));
107
108 *environment
109 .ApplicationState
110 .Configuration
111 .GlobalConfiguration
112 .lock()
113 .map_err(Utility::MapApplicationStateLockErrorToCommonError)? = final_config.Data;
114
115 info!(
116 "[ConfigurationProvider] Configuration merged successfully with {} top-level keys.",
117 configuration_size
118 );
119
120 Ok(())
121}
122
123pub(super) fn collect_default_configurations(
125 application_state:&crate::ApplicationState::ApplicationState,
126) -> Result<Value, CommonError> {
127 let mut default_config = Map::new();
128
129 for extension in application_state
131 .Extension
132 .ScannedExtensions
133 .ScannedExtensions
134 .lock()
135 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
136 .values()
137 {
138 if let Some(contributes) = &extension.Contributes {
139 if let Some(config_array) = contributes.get("configuration").and_then(|c| c.as_array()) {
140 for config_value in config_array {
141 if let (Some(key), Some(value)) =
143 (config_value.get("key").and_then(|k| k.as_str()), config_value.get("value"))
144 {
145 if let Some(value_obj) = value.as_object() {
146 default_config.insert(key.to_string(), Value::Object(value_obj.clone()));
147 }
148 }
149 }
150 }
151 }
152 }
153
154 Ok(Value::Object(default_config))
155}