faucet_cli/commands/
list.rs1use crate::cli::ListArgs;
7use crate::conformance::tier_for;
8use crate::error::CliResult;
9use crate::registry::{sink_descriptions, sink_exists, source_descriptions, source_exists};
10use crate::registry_index::RegistryIndex;
11use crate::state::available_state_kinds;
12#[cfg(feature = "quality")]
13use crate::transforms::quality_descriptions;
14use crate::transforms::transform_descriptions;
15
16pub async fn run(args: ListArgs) -> CliResult<()> {
18 if args.available {
19 return list_available(args);
20 }
21 println!("Sources:");
22 print_connectors(&source_descriptions(), true);
23 println!();
24 println!("Sinks:");
25 print_connectors(&sink_descriptions(), false);
26 println!();
27 println!("Transforms:");
28 print_two_column(&transform_descriptions());
29 println!();
30 #[cfg(feature = "quality")]
31 {
32 println!("Quality checks:");
33 print_two_column(&quality_descriptions());
34 println!();
35 }
36 println!("State stores: {}", available_state_kinds().join(", "));
37 #[cfg(feature = "schedule")]
38 println!("Scheduler: compiled in (run `faucet schedule --help`, `faucet schema schedule`)");
39 Ok(())
40}
41
42fn list_available(args: ListArgs) -> CliResult<()> {
45 let idx = RegistryIndex::load(args.index.as_deref())?;
46 let mut connectors: Vec<_> = idx.connectors.iter().collect();
47 connectors.sort_by(|a, b| {
48 (a.kind.as_str(), a.name.as_str()).cmp(&(b.kind.as_str(), b.name.as_str()))
49 });
50 println!(
51 "Registry connectors ({} total). ● = compiled into this binary, ○ = available via `faucet install`:\n",
52 connectors.len()
53 );
54 for c in connectors {
55 let compiled = match c.kind.as_str() {
56 "source" => source_exists(&c.name),
57 "sink" => sink_exists(&c.name),
58 _ => false,
59 };
60 let mark = if compiled { '●' } else { '○' };
61 let badge = if c.verified { "verified" } else { "community" };
62 let tier = c.tier.as_deref().unwrap_or("-");
63 println!(
64 " {mark} {kind:<6} {name:<14} {tier:<12} {desc} [{badge}]",
65 kind = c.kind,
66 name = c.name,
67 desc = c.description
68 );
69 }
70 Ok(())
71}
72
73fn print_two_column(entries: &[(&'static str, &'static str)]) {
74 if entries.is_empty() {
75 println!(" (none — rebuild faucet-cli with the relevant features enabled)");
76 return;
77 }
78 let width = entries.iter().map(|(n, _)| n.len()).max().unwrap_or(0);
79 for (name, desc) in entries {
80 println!(" {name:<width$} {desc}", width = width);
81 }
82}
83
84fn print_connectors(entries: &[(&'static str, &'static str)], is_source: bool) {
87 if entries.is_empty() {
88 println!(" (none — rebuild faucet-cli with the relevant features enabled)");
89 return;
90 }
91 let width = entries.iter().map(|(n, _)| n.len()).max().unwrap_or(0);
92 for (name, desc) in entries {
93 let tier = tier_for(name, is_source);
94 println!(
95 " {badge} {name:<width$} {tier:<12} {desc}",
96 badge = tier.badge(),
97 tier = tier.label(),
98 width = width,
99 );
100 }
101}