mecha10_cli_core/services/
config.rs1#![allow(dead_code)]
2
3use crate::paths;
8use crate::types::ProjectConfig;
9use anyhow::{Context, Result};
10use std::path::{Path, PathBuf};
11
12pub struct ConfigService;
13
14impl ConfigService {
15 pub async fn load_from(path: &Path) -> Result<ProjectConfig> {
19 if !path.exists() {
20 anyhow::bail!(
21 "Project configuration not found at {}. Run 'mecha10 init' first.",
22 path.display()
23 );
24 }
25
26 let content = tokio::fs::read_to_string(path)
27 .await
28 .with_context(|| format!("Failed to read configuration file: {}", path.display()))?;
29
30 let config: ProjectConfig = serde_json::from_str(&content)
31 .with_context(|| format!("Failed to parse configuration file: {}", path.display()))?;
32
33 Ok(config)
34 }
35
36 pub fn find_config() -> Result<PathBuf> {
38 Self::find_config_from(&std::env::current_dir()?)
39 }
40
41 pub fn find_config_from(start_dir: &Path) -> Result<PathBuf> {
43 let mut current_dir = start_dir.to_path_buf();
44
45 loop {
46 let config_path = current_dir.join(paths::PROJECT_CONFIG);
47 if config_path.exists() {
48 return Ok(config_path);
49 }
50
51 match current_dir.parent() {
52 Some(parent) => current_dir = parent.to_path_buf(),
53 None => {
54 anyhow::bail!(
55 "No mecha10.json found in {} or any parent directory.\n\n\
56 Run 'mecha10 init' to create a new project.",
57 start_dir.display()
58 )
59 }
60 }
61 }
62 }
63
64 pub fn is_initialized(dir: &Path) -> bool {
66 dir.join(paths::PROJECT_CONFIG).exists()
67 }
68
69 pub fn is_initialized_here() -> bool {
71 PathBuf::from(paths::PROJECT_CONFIG).exists()
72 }
73
74 pub async fn load_robot_id(path: &Path) -> Result<String> {
76 let config = Self::load_from(path).await?;
77 Ok(config.robot.id)
78 }
79
80 pub fn validate(path: &Path) -> Result<()> {
82 use mecha10_core::schema_validation::validate_project_config;
83
84 if !path.exists() {
85 anyhow::bail!(
86 "Configuration file not found: {}\n\nRun 'mecha10 init' to create a new project.",
87 path.display()
88 );
89 }
90
91 validate_project_config(path).context("Configuration validation failed")
92 }
93
94 pub fn resolve_and_validate(path: Option<&Path>) -> Result<PathBuf> {
98 use mecha10_core::schema_validation::{validate_config_file, validate_project_config};
99
100 let target = match path {
101 Some(p) => p.to_path_buf(),
102 None => Self::find_config()?,
103 };
104
105 if !target.exists() {
106 anyhow::bail!("Configuration file not found: {}", target.display());
107 }
108
109 let result = match path {
110 Some(_) => validate_config_file(&target),
111 None => validate_project_config(&target),
112 };
113
114 result.map_err(|e| anyhow::anyhow!("Configuration validation failed for {}: {}", target.display(), e))?;
115
116 Ok(target)
117 }
118}