#![allow(dead_code)]
use crate::paths;
use crate::types::ProjectConfig;
use anyhow::{Context, Result};
use std::path::{Path, PathBuf};
pub struct ConfigService;
impl ConfigService {
pub async fn load_from(path: &Path) -> Result<ProjectConfig> {
if !path.exists() {
anyhow::bail!(
"Project configuration not found at {}. Run 'mecha10 init' first.",
path.display()
);
}
let content = tokio::fs::read_to_string(path)
.await
.with_context(|| format!("Failed to read configuration file: {}", path.display()))?;
let config: ProjectConfig = serde_json::from_str(&content)
.with_context(|| format!("Failed to parse configuration file: {}", path.display()))?;
Ok(config)
}
pub fn find_config() -> Result<PathBuf> {
Self::find_config_from(&std::env::current_dir()?)
}
pub fn find_config_from(start_dir: &Path) -> Result<PathBuf> {
let mut current_dir = start_dir.to_path_buf();
loop {
let config_path = current_dir.join(paths::PROJECT_CONFIG);
if config_path.exists() {
return Ok(config_path);
}
match current_dir.parent() {
Some(parent) => current_dir = parent.to_path_buf(),
None => {
anyhow::bail!(
"No mecha10.json found in {} or any parent directory.\n\n\
Run 'mecha10 init' to create a new project.",
start_dir.display()
)
}
}
}
}
pub fn is_initialized(dir: &Path) -> bool {
dir.join(paths::PROJECT_CONFIG).exists()
}
pub fn is_initialized_here() -> bool {
PathBuf::from(paths::PROJECT_CONFIG).exists()
}
pub async fn load_robot_id(path: &Path) -> Result<String> {
let config = Self::load_from(path).await?;
Ok(config.robot.id)
}
pub fn validate(path: &Path) -> Result<()> {
use mecha10_core::schema_validation::validate_project_config;
if !path.exists() {
anyhow::bail!(
"Configuration file not found: {}\n\nRun 'mecha10 init' to create a new project.",
path.display()
);
}
validate_project_config(path).context("Configuration validation failed")
}
pub fn resolve_and_validate(path: Option<&Path>) -> Result<PathBuf> {
Self::resolve_and_validate_with_node_schema_resolver(path, None)
}
pub fn resolve_and_validate_with_node_schema_resolver(
path: Option<&Path>,
node_schema_resolver: Option<&mecha10_core::schema_validation::NodeSchemaResolver>,
) -> Result<PathBuf> {
use mecha10_core::schema_validation::{
validate_config_file_with_node_schema_resolver, validate_project_config_with_node_schema_resolver,
};
let target = match path {
Some(p) => p.to_path_buf(),
None => Self::find_config()?,
};
if !target.exists() {
anyhow::bail!("Configuration file not found: {}", target.display());
}
let result = match path {
Some(_) => validate_config_file_with_node_schema_resolver(&target, node_schema_resolver),
None => validate_project_config_with_node_schema_resolver(&target, node_schema_resolver),
};
result.map_err(|e| anyhow::anyhow!("Configuration validation failed for {}: {}", target.display(), e))?;
Ok(target)
}
}