yozefu_app/configuration/
global_config.rs1use std::{
4 fs,
5 path::{Path, PathBuf},
6};
7
8use indexmap::IndexMap;
9use itertools::Itertools;
10use lib::Error;
11use serde::{Deserialize, Serialize};
12
13use crate::{
14 APPLICATION_NAME,
15 configuration::{ClusterConfig, ConsumerConfig},
16};
17
18use super::cluster_config::SchemaRegistryConfig;
19
20const EXAMPLE_PROMPTS: &[&str] = &[
21 r#"timestamp between "2 hours ago" and "1 hour ago" limit 100 from beginning"#,
22 r#"offset > 100000 and value contains "music" limit 10"#,
23 r#"key == "ABC" and timestamp >= "2 days ago""#,
24];
25
26#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
28#[cfg_attr(test, derive(schemars::JsonSchema))]
29pub struct GlobalConfig {
30 #[serde(skip)]
32 pub path: PathBuf,
33 #[serde(default = "default_url_template")]
35 pub default_url_template: String,
36 pub initial_query: String,
38 #[serde(default = "default_theme")]
40 pub theme: String,
41 pub highlighter_theme: Option<String>,
43 pub clusters: IndexMap<String, ClusterConfig>,
45 #[serde(default)]
46 pub consumer: ConsumerConfig,
48 pub default_kafka_config: IndexMap<String, String>,
50 pub history: Vec<String>,
52 #[serde(default = "default_show_shortcuts")]
54 pub show_shortcuts: bool,
55 #[serde(default = "default_export_directory")]
56 pub export_directory: PathBuf,
57 pub log_file: Option<PathBuf>,
59}
60
61fn default_url_template() -> String {
62 "http://localhost/cluster/{topic}/{partition}/{offset}".to_string()
63}
64
65fn default_export_directory() -> PathBuf {
66 PathBuf::from(format!("./{APPLICATION_NAME}-exports"))
67}
68
69fn default_theme() -> String {
70 if cfg!(target_os = "windows") {
71 "dark".to_string()
72 } else {
73 "light".to_string()
74 }
75}
76
77fn default_show_shortcuts() -> bool {
78 true
79}
80
81impl GlobalConfig {
82 pub fn new(path: &Path) -> Self {
83 Self {
84 path: path.to_path_buf(),
85 default_url_template: default_url_template(),
86 history: EXAMPLE_PROMPTS
87 .iter()
88 .map(|e| (*e).to_string())
89 .collect_vec(),
90 initial_query: "from end - 10".to_string(),
91 clusters: IndexMap::default(),
92 default_kafka_config: IndexMap::default(),
93 theme: default_theme(),
94 highlighter_theme: None,
95 show_shortcuts: true,
96 export_directory: default_export_directory(),
97 consumer: ConsumerConfig::default(),
98 log_file: None,
99 }
100 }
101
102 pub fn read(file: &Path) -> Result<Self, Error> {
104 let content = fs::read_to_string(file);
105 if let Err(e) = &content {
106 return Err(Error::Error(format!(
107 "Failed to read the configuration file {:?}: {}",
108 file.display(),
109 e
110 )));
111 }
112
113 let content = content.unwrap();
114 let mut config: Self = serde_json::from_str(&content).map_err(|e| {
115 Error::Error(format!(
116 "Failed to parse the configuration file {:?}: {}",
117 file.display(),
118 e
119 ))
120 })?;
121 config.path = file.to_path_buf();
122 Ok(config)
123 }
124
125 pub fn log_file(&self) -> Option<PathBuf> {
127 self.log_file.clone()
128 }
129
130 pub fn url_template_of(&self, cluster: &str) -> String {
132 self.clusters
133 .get(cluster)
134 .and_then(|e| e.url_template.clone())
135 .unwrap_or(self.default_url_template.clone())
136 }
137
138 pub(crate) fn consumer_config_of(&self, cluster: &str) -> ConsumerConfig {
140 self.clusters
141 .get(cluster)
142 .and_then(|e| e.consumer.clone())
143 .unwrap_or(self.consumer.clone())
144 }
145
146 pub fn schema_registry_config_of(&self, cluster: &str) -> Option<SchemaRegistryConfig> {
148 self.clusters
149 .get(cluster.trim())
150 .and_then(|config| config.schema_registry.clone())
151 }
152}
153
154#[test]
155fn generate_json_schema_for_global_config() {
156 use schemars::schema_for;
157 let mut schema = schema_for!(GlobalConfig);
158 schema.insert("$id".into(), "https://raw.githubusercontent.com/MAIF/yozefu/refs/heads/main/docs/json-schemas/global-config.json".into());
159 fs::write(
160 PathBuf::from(env!("CARGO_MANIFEST_DIR"))
161 .parent()
162 .unwrap()
163 .parent()
164 .unwrap()
165 .join("docs")
166 .join("json-schemas")
167 .join("global-config.json"),
168 serde_json::to_string_pretty(&schema).unwrap(),
169 )
170 .unwrap();
171}