use crate::cli::OutputFormat;
use crate::error::CommandError;
use crate::metadata::{ModuleEntry, Uag};
use crate::project;
use serde::Serialize;
pub(crate) fn execute(format: OutputFormat) -> Result<(), CommandError> {
let project = project::discover()?;
let artifact = crate::metadata::load(&project).map_err(CommandError::Metadata)?;
let modules: Vec<&ModuleEntry> = artifact.modules.values().collect();
match format {
OutputFormat::Human => print_human(&modules),
OutputFormat::Json => print_json(&artifact)?,
}
Ok(())
}
fn print_human(modules: &[&ModuleEntry]) {
if modules.is_empty() {
println!("no modules registered");
return;
}
for module in modules {
println!("== {} ==", module.name);
println!(" imports: {}", join_or_empty(&module.imports));
println!(" exports: {}", join_or_empty(&module.exports));
println!(" controllers: {}", join_or_empty(&module.controllers));
println!(" services: {}", join_or_empty(&module.services));
println!(" policies: {}", join_or_empty(&module.policies));
println!(" listeners: {}", join_listeners(&module.listeners));
println!(" jobs: {}", join_jobs(&module.jobs));
println!(" commands: {}", join_commands(&module.commands));
println!(" schedules: {}", join_schedules(&module.schedules));
}
}
fn print_json(artifact: &Uag) -> Result<(), CommandError> {
let modules: Vec<&ModuleEntry> = artifact.modules.values().collect();
#[derive(Serialize)]
struct Out<'a> {
modules: Vec<&'a ModuleEntry>,
}
println!("{}", serde_json::to_string_pretty(&Out { modules })?);
Ok(())
}
fn join_or_empty(items: &[String]) -> String {
if items.is_empty() {
"(none)".to_owned()
} else {
items.join(", ")
}
}
fn join_listeners(listeners: &[crate::metadata::ListenerEntry]) -> String {
if listeners.is_empty() {
return "(none)".to_owned();
}
listeners
.iter()
.map(|l| format!("{} -> {}", l.event, l.listener))
.collect::<Vec<_>>()
.join(", ")
}
fn join_jobs(jobs: &[crate::metadata::JobEntry]) -> String {
if jobs.is_empty() {
return "(none)".to_owned();
}
jobs.iter()
.map(|j| format!("{} v{} -> {}", j.kind, j.version, j.handler))
.collect::<Vec<_>>()
.join(", ")
}
fn join_commands(commands: &[crate::metadata::CommandEntry]) -> String {
if commands.is_empty() {
return "(none)".to_owned();
}
commands
.iter()
.map(|c| format!("{} -> {}", c.name, c.function))
.collect::<Vec<_>>()
.join(", ")
}
fn join_schedules(schedules: &[crate::metadata::ScheduleEntry]) -> String {
if schedules.is_empty() {
return "(none)".to_owned();
}
schedules
.iter()
.map(|s| format!("{} v{} -> {}", s.job, s.version, cadence_str(&s.cadence)))
.collect::<Vec<_>>()
.join(", ")
}
fn cadence_str(cadence: &crate::metadata::CadenceEntry) -> String {
match cadence {
crate::metadata::CadenceEntry::Every { seconds } => format!("every {seconds}s"),
crate::metadata::CadenceEntry::Daily { hour, minute } => {
format!("daily {hour:02}:{minute:02}")
}
}
}