Skip to main content

faucet_cli/commands/
list.rs

1//! `faucet list` — show every compiled-in source, sink, transform, and
2//! state-store backend so users can discover what their binary supports.
3//! `--available` instead lists every connector in the registry index (#208),
4//! marking which are compiled into this binary.
5
6use crate::cli::ListArgs;
7use crate::error::CliResult;
8use crate::registry::{sink_descriptions, sink_exists, source_descriptions, source_exists};
9use crate::registry_index::RegistryIndex;
10use crate::state::available_state_kinds;
11#[cfg(feature = "quality")]
12use crate::transforms::quality_descriptions;
13use crate::transforms::transform_descriptions;
14
15/// Execute the `list` subcommand.
16pub async fn run(args: ListArgs) -> CliResult<()> {
17    if args.available {
18        return list_available(args);
19    }
20    println!("Sources:");
21    print_two_column(&source_descriptions());
22    println!();
23    println!("Sinks:");
24    print_two_column(&sink_descriptions());
25    println!();
26    println!("Transforms:");
27    print_two_column(&transform_descriptions());
28    println!();
29    #[cfg(feature = "quality")]
30    {
31        println!("Quality checks:");
32        print_two_column(&quality_descriptions());
33        println!();
34    }
35    println!("State stores: {}", available_state_kinds().join(", "));
36    #[cfg(feature = "schedule")]
37    println!("Scheduler:    compiled in (run `faucet schedule --help`, `faucet schema schedule`)");
38    Ok(())
39}
40
41/// `faucet list --available` — every connector in the registry index, with a
42/// marker for those already compiled into this binary.
43fn list_available(args: ListArgs) -> CliResult<()> {
44    let idx = RegistryIndex::load(args.index.as_deref())?;
45    let mut connectors: Vec<_> = idx.connectors.iter().collect();
46    connectors.sort_by(|a, b| {
47        (a.kind.as_str(), a.name.as_str()).cmp(&(b.kind.as_str(), b.name.as_str()))
48    });
49    println!(
50        "Registry connectors ({} total). ● = compiled into this binary, ○ = available via `faucet install`:\n",
51        connectors.len()
52    );
53    for c in connectors {
54        let compiled = match c.kind.as_str() {
55            "source" => source_exists(&c.name),
56            "sink" => sink_exists(&c.name),
57            _ => false,
58        };
59        let mark = if compiled { '●' } else { '○' };
60        let badge = if c.verified { "verified" } else { "community" };
61        println!(
62            "  {mark} {kind:<6} {name:<14} {desc}  [{badge}]",
63            kind = c.kind,
64            name = c.name,
65            desc = c.description
66        );
67    }
68    Ok(())
69}
70
71fn print_two_column(entries: &[(&'static str, &'static str)]) {
72    if entries.is_empty() {
73        println!("  (none — rebuild faucet-cli with the relevant features enabled)");
74        return;
75    }
76    let width = entries.iter().map(|(n, _)| n.len()).max().unwrap_or(0);
77    for (name, desc) in entries {
78        println!("  {name:<width$}  {desc}", width = width);
79    }
80}