soroban_cli/commands/plugin/
search.rs1use serde::{Deserialize, Serialize};
2use std::io::Write;
3use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
4
5use crate::{commands::global, print::Print, utils::http};
6
7use super::super::config::locator;
8
9#[derive(thiserror::Error, Debug)]
10pub enum Error {
11 #[error(transparent)]
12 Config(#[from] locator::Error),
13
14 #[error("unable to retrieve the list of plugins from GitHub")]
15 Http(#[from] reqwest::Error),
16
17 #[error(transparent)]
18 Io(#[from] std::io::Error),
19}
20
21#[derive(Debug, clap::Parser, Clone)]
22#[group(skip)]
23pub struct Cmd;
24
25impl Cmd {
26 pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
27 let print = Print::new(global_args.quiet);
28 let url =
29 "https://api.github.com/search/repositories?q=topic%3Astellar-cli-plugin+fork%3Afalse+archived%3Afalse&per_page=100&sort=stars&order=desc";
30
31 let resp = http::client().get(url).send().await?;
32 let search: SearchResponse = resp.json().await?;
33
34 if search.total_count == 0 {
35 print.searchln("No plugins found.".to_string());
36 return Ok(());
37 }
38
39 let wording = if search.total_count == 1 {
40 "plugin"
41 } else {
42 "plugins"
43 };
44
45 print.searchln(format!(
46 "Found {total} {wording}:",
47 total = search.total_count
48 ));
49
50 let mut stdout = StandardStream::stdout(ColorChoice::Auto);
51
52 for item in search.items {
53 println!();
54 stdout.set_color(ColorSpec::new().set_fg(Some(Color::Blue)))?;
55 writeln!(&mut stdout, " {}", item.full_name)?;
56 stdout.reset()?;
57
58 if let Some(description) = item.description {
59 writeln!(&mut stdout, " {description}")?;
60 }
61
62 print.blankln(item.html_url.clone());
63 }
64 Ok(())
65 }
66}
67
68#[derive(Debug, Serialize, Deserialize)]
69struct SearchResponse {
70 total_count: u32,
71 incomplete_results: bool,
72 items: Vec<Repository>,
73}
74
75#[derive(Debug, Serialize, Deserialize)]
76struct Repository {
77 id: u64,
78 name: String,
79 full_name: String,
80 html_url: String,
81 description: Option<String>,
82}