This commit is contained in:
2026-05-05 05:03:11 +02:00
parent 3e994995d7
commit f2c227e08f
132 changed files with 5767 additions and 4461 deletions

View File

@@ -20,7 +20,7 @@ pub struct KbConfig {
impl KbConfig {
/// Returns the default path of the JSON configuration file.
pub fn default_path() -> std::path::PathBuf {
kb_workspace_root_dir().join("config.json")
return kb_workspace_root_dir().join("config.json");
}
/// Loads a configuration from a JSON file and validates it.
@@ -34,7 +34,7 @@ impl KbConfig {
"cannot read configuration file '{}': {error}",
path_ref.display()
)));
}
},
};
let config_result = serde_json::from_str::<Self>(&content);
let config = match config_result {
@@ -44,36 +44,28 @@ impl KbConfig {
"cannot parse configuration file '{}': {error}",
path_ref.display()
)));
}
},
};
let validation_result = config.validate();
match validation_result {
Ok(()) => Ok(config),
Err(error) => Err(error),
Ok(()) => return Ok(config),
Err(error) => return Err(error),
}
}
/// Validates the current configuration.
pub fn validate(&self) -> Result<(), crate::KbError> {
if self.app.name.trim().is_empty() {
return Err(crate::KbError::Config(
"app.name must not be empty".to_string(),
));
return Err(crate::KbError::Config("app.name must not be empty".to_string()));
}
if self.app.environment.trim().is_empty() {
return Err(crate::KbError::Config(
"app.environment must not be empty".to_string(),
));
return Err(crate::KbError::Config("app.environment must not be empty".to_string()));
}
if self.logging.level.trim().is_empty() {
return Err(crate::KbError::Config(
"logging.level must not be empty".to_string(),
));
return Err(crate::KbError::Config("logging.level must not be empty".to_string()));
}
if self.logging.directory.trim().is_empty() {
return Err(crate::KbError::Config(
"logging.directory must not be empty".to_string(),
));
return Err(crate::KbError::Config("logging.directory must not be empty".to_string()));
}
if self.logging.file_prefix.trim().is_empty() {
return Err(crate::KbError::Config(
@@ -81,9 +73,7 @@ impl KbConfig {
));
}
if self.data.sqlite_path.trim().is_empty() {
return Err(crate::KbError::Config(
"data.sqlite_path must not be empty".to_string(),
));
return Err(crate::KbError::Config("data.sqlite_path must not be empty".to_string()));
}
if self.data.wallets_directory.trim().is_empty() {
return Err(crate::KbError::Config(
@@ -131,7 +121,7 @@ impl KbConfig {
return Err(error);
}
}
Ok(())
return Ok(());
}
/// Creates the basic runtime directories required by the current configuration.
@@ -165,7 +155,7 @@ impl KbConfig {
}
}
}
Ok(())
return Ok(());
}
/// Finds one HTTP endpoint by its logical name.
@@ -173,10 +163,11 @@ impl KbConfig {
&self,
endpoint_name: &str,
) -> std::option::Option<&KbHttpEndpointConfig> {
self.solana
return self
.solana
.http_endpoints
.iter()
.find(|endpoint| endpoint.name == endpoint_name)
.find(|endpoint| return endpoint.name == endpoint_name);
}
/// Returns a named WebSocket endpoint by reference.
@@ -184,10 +175,11 @@ impl KbConfig {
&self,
endpoint_name: &str,
) -> std::option::Option<&KbWsEndpointConfig> {
self.solana
return self
.solana
.ws_endpoints
.iter()
.find(|endpoint| endpoint.name == endpoint_name)
.find(|endpoint| return endpoint.name == endpoint_name);
}
fn validate_http_endpoint(
@@ -196,11 +188,9 @@ impl KbConfig {
endpoint_names: &mut std::vec::Vec<std::string::String>,
) -> Result<(), crate::KbError> {
if endpoint.name.trim().is_empty() {
return Err(crate::KbError::Config(
"http endpoint name must not be empty".to_string(),
));
return Err(crate::KbError::Config("http endpoint name must not be empty".to_string()));
}
if endpoint_names.iter().any(|name| name == &endpoint.name) {
if endpoint_names.iter().any(|name| return name == &endpoint.name) {
return Err(crate::KbError::Config(format!(
"duplicated endpoint name '{}'",
endpoint.name
@@ -237,7 +227,7 @@ impl KbConfig {
)));
}
endpoint_names.push(endpoint.name.clone());
Ok(())
return Ok(());
}
fn validate_ws_endpoint(
@@ -246,11 +236,9 @@ impl KbConfig {
endpoint_names: &mut std::vec::Vec<std::string::String>,
) -> Result<(), crate::KbError> {
if endpoint.name.trim().is_empty() {
return Err(crate::KbError::Config(
"ws endpoint name must not be empty".to_string(),
));
return Err(crate::KbError::Config("ws endpoint name must not be empty".to_string()));
}
if endpoint_names.iter().any(|name| name == &endpoint.name) {
if endpoint_names.iter().any(|name| return name == &endpoint.name) {
return Err(crate::KbError::Config(format!(
"duplicated endpoint name '{}'",
endpoint.name
@@ -299,7 +287,7 @@ impl KbConfig {
)));
}
endpoint_names.push(endpoint.name.clone());
Ok(())
return Ok(());
}
}
@@ -350,7 +338,7 @@ pub struct KbLoggingConfig {
impl KbLoggingConfig {
/// Returns the resolved logging directory path.
pub fn directory_path(&self) -> std::path::PathBuf {
kb_resolve_workspace_relative_path(&self.directory)
return kb_resolve_workspace_relative_path(&self.directory);
}
}
@@ -366,12 +354,12 @@ pub struct KbDataConfig {
impl KbDataConfig {
/// Returns the resolved SQLite database path.
pub fn sqlite_path_buf(&self) -> std::path::PathBuf {
kb_resolve_workspace_relative_path(&self.sqlite_path)
return kb_resolve_workspace_relative_path(&self.sqlite_path);
}
/// Returns the resolved wallets directory path.
pub fn wallets_directory_path(&self) -> std::path::PathBuf {
kb_resolve_workspace_relative_path(&self.wallets_directory)
return kb_resolve_workspace_relative_path(&self.wallets_directory);
}
}
@@ -433,7 +421,7 @@ impl KbHttpEndpointConfig {
Some(env_var_name) => env_var_name,
None => {
return Ok(self.url.clone());
}
},
};
let api_key_result = std::env::var(env_var_name);
let api_key = match api_key_result {
@@ -443,13 +431,13 @@ impl KbHttpEndpointConfig {
"cannot resolve api key env var '{}' for http endpoint '{}': {}",
env_var_name, self.name, error
)));
}
},
};
let placeholder = format!("${{{}}}", env_var_name);
if self.url.contains(&placeholder) {
return Ok(self.url.replace(&placeholder, &api_key));
}
Ok(self.url.clone())
return Ok(self.url.clone());
}
}
@@ -487,7 +475,7 @@ pub struct KbWsEndpointConfig {
impl KbWsEndpointConfig {
/// Returns the resolved endpoint URL.
pub fn resolved_url(&self) -> Result<std::string::String, crate::KbError> {
kb_resolve_endpoint_url(&self.url, &self.api_key_env_var)
return kb_resolve_endpoint_url(&self.url, &self.api_key_env_var);
}
}
@@ -512,7 +500,7 @@ pub struct KbSqliteDatabaseConfig {
impl KbSqliteDatabaseConfig {
/// Returns the resolved SQLite database path.
pub fn path_buf(&self) -> std::path::PathBuf {
kb_resolve_workspace_relative_path(&self.path)
return kb_resolve_workspace_relative_path(&self.path);
}
}
@@ -531,8 +519,8 @@ pub struct KbDatabaseConfig {
fn kb_workspace_root_dir() -> std::path::PathBuf {
let manifest_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
match manifest_dir.parent() {
Some(parent) => parent.to_path_buf(),
None => manifest_dir,
Some(parent) => return parent.to_path_buf(),
None => return manifest_dir,
}
}
@@ -541,7 +529,7 @@ fn kb_resolve_workspace_relative_path<P: AsRef<std::path::Path>>(path: P) -> std
if input_path.is_absolute() {
return input_path;
}
kb_workspace_root_dir().join(input_path)
return kb_workspace_root_dir().join(input_path);
}
fn kb_resolve_endpoint_url(
@@ -553,7 +541,7 @@ fn kb_resolve_endpoint_url(
Some(env_var_name) => env_var_name,
None => {
return Ok(url.to_string());
}
},
};
let placeholder = format!("${{{env_var_name}}}");
if !url.contains(&placeholder) {
@@ -567,7 +555,7 @@ fn kb_resolve_endpoint_url(
"environment variable '{}' is required to resolve endpoint url '{}': {error}",
env_var_name, url
)));
}
},
};
Ok(url.replace(&placeholder, &env_value))
return Ok(url.replace(&placeholder, &env_value));
}