use crate::coherence::coherence_violations;
use crate::doctor;
use crate::error::CliError;
use crate::project::{App, ensure_page_toolchain, observe_step};
pub fn check() -> Result<(), CliError> {
let app = App::find_from_current_dir()?;
doctor::require(doctor::CHECK_PREREQUISITES, "frame check")?;
ensure_page_toolchain(&app)?;
let mut failed: Vec<String> = Vec::new();
match app.load_config() {
Ok(config) => {
let violations = coherence_violations(&config);
if violations.is_empty() {
println!("frame.toml OK");
} else {
eprintln!("frame.toml FAIL: port coherence");
for violation in &violations {
eprintln!(" {violation}");
}
failed.push("frame.toml".to_owned());
}
}
Err(error) => {
report_config_failure(&error);
failed.push("frame.toml".to_owned());
}
}
let steps: [(&str, &str, &[&str], std::path::PathBuf); 3] = [
("page types", "npm", &["run", "typecheck"], app.page_dir()),
("component", "gleam", &["check"], app.component_dir()),
("host", "cargo", &["check", "--workspace"], app.root.clone()),
];
for (label, program, args, directory) in steps {
if observe_step(program, args, &directory)? {
println!("{label:<12} OK");
} else {
println!("{label:<12} FAIL");
failed.push(label.to_owned());
}
}
if failed.is_empty() {
println!("frame check: PASS");
Ok(())
} else {
Err(CliError::VerdictFailed {
verb: "frame check",
failed,
})
}
}
fn report_config_failure(error: &CliError) {
eprintln!("frame.toml FAIL: {error}");
let mut source = std::error::Error::source(error);
while let Some(cause) = source {
eprintln!(" caused by: {cause}");
source = cause.source();
}
}