use anyhow::Result;
use audb::parser::GoldParser;
use audb::model::Project;
use console::{Term, style};
use std::path::PathBuf;
use walkdir::WalkDir;
pub fn run(gold_dir: &str) -> Result<()> {
let term = Term::stdout();
term.write_line("")?;
term.write_line(&format!(
"{} {}",
style("Validating gold files in:").bold().cyan(),
style(gold_dir).white()
))?;
term.write_line("")?;
let files = discover_gold_files(gold_dir)?;
if files.is_empty() {
term.write_line(&format!(
"{} No .au files found in {}",
style("⚠").yellow(),
gold_dir
))?;
term.write_line("")?;
return Ok(());
}
term.write_line(&format!(
"Found {} gold file{}",
style(files.len()).green(),
if files.len() == 1 { "" } else { "s" }
))?;
term.write_line("")?;
let mut gold_files = Vec::new();
let mut errors = Vec::new();
for path in &files {
let relative_path = path.strip_prefix(gold_dir).unwrap_or(path);
match GoldParser::parse_file(path) {
Ok(gold_file) => {
term.write_line(&format!(
" {} {}",
style("✓").green(),
style(relative_path.display()).dim()
))?;
gold_files.push(gold_file);
}
Err(e) => {
term.write_line(&format!(
" {} {}",
style("✗").red(),
style(relative_path.display()).dim()
))?;
term.write_line(&format!(" {}", style(format!("Error: {}", e)).red()))?;
errors.push((relative_path.to_path_buf(), e));
}
}
}
term.write_line("")?;
if !errors.is_empty() {
term.write_line(&format!(
"{} {} error{} found",
style("✗").red().bold(),
errors.len(),
if errors.len() == 1 { "" } else { "s" }
))?;
term.write_line("")?;
anyhow::bail!("Validation failed with {} error(s)", errors.len());
}
match Project::from_gold_files(gold_files) {
Ok(project) => {
term.write_line(&format!(
"{} Project validation successful",
style("✓").green().bold()
))?;
term.write_line("")?;
term.write_line(&format!(
" {} {} schemas",
style("Schemas:").dim(),
style(project.schemas.len()).green()
))?;
term.write_line(&format!(
" {} {} queries",
style("Queries:").dim(),
style(project.queries.len()).green()
))?;
term.write_line(&format!(
" {} {} endpoints",
style("Endpoints:").dim(),
style(project.endpoints.len()).green()
))?;
term.write_line("")?;
}
Err(e) => {
term.write_line(&format!(
"{} Project validation failed",
style("✗").red().bold()
))?;
term.write_line(&format!(" {}", style(format!("Error: {}", e)).red()))?;
term.write_line("")?;
anyhow::bail!("Project validation failed: {}", e);
}
}
Ok(())
}
fn discover_gold_files(gold_dir: &str) -> Result<Vec<PathBuf>> {
let gold_path = PathBuf::from(gold_dir);
if !gold_path.exists() {
anyhow::bail!("Gold directory does not exist: {}", gold_dir);
}
let mut files = Vec::new();
for entry in WalkDir::new(&gold_path)
.follow_links(true)
.into_iter()
.filter_map(|e| e.ok())
{
let path = entry.path();
if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("au") {
files.push(path.to_path_buf());
}
}
Ok(files)
}