wasmer_cli/commands/app/
list.rs1use std::pin::Pin;
4
5use futures::{Stream, StreamExt};
6use wasmer_backend_api::types::{DeployApp, DeployAppsSortBy};
7
8use crate::{commands::AsyncCliCommand, config::WasmerEnv, opts::ListFormatOpts};
9
10#[derive(clap::Parser, Debug)]
12pub struct CmdAppList {
13 #[clap(flatten)]
14 fmt: ListFormatOpts,
15
16 #[clap(flatten)]
17 env: WasmerEnv,
18
19 #[clap(short = 'n', long)]
23 namespace: Option<String>,
24
25 #[clap(short = 'a', long)]
28 all: bool,
29
30 #[clap(long, default_value = "1000")]
32 max: usize,
33
34 #[clap(long, default_value = "false")]
36 paging_mode: bool,
37
38 #[clap(long, default_value = "last-updated")]
42 sort: AppSort,
43}
44
45#[derive(clap::ValueEnum, Clone, Copy, Debug)]
46pub enum AppSort {
47 Newest,
48 Oldest,
49 LastUpdated,
50}
51
52#[async_trait::async_trait]
53impl AsyncCliCommand for CmdAppList {
54 type Output = ();
55
56 async fn run_async(self) -> Result<(), anyhow::Error> {
57 let client = self.env.client()?;
58
59 let sort = match self.sort {
60 AppSort::Newest => DeployAppsSortBy::Newest,
61 AppSort::Oldest => DeployAppsSortBy::Oldest,
62 AppSort::LastUpdated => DeployAppsSortBy::MostActive,
63 };
64
65 let apps_stream: Pin<
66 Box<dyn Stream<Item = Result<Vec<DeployApp>, anyhow::Error>> + Send + Sync>,
67 > = if let Some(ns) = self.namespace.clone() {
68 Box::pin(wasmer_backend_api::query::namespace_apps(&client, ns, sort).await)
69 } else if self.all {
70 Box::pin(wasmer_backend_api::query::user_accessible_apps(&client, sort).await?)
71 } else {
72 Box::pin(wasmer_backend_api::query::user_apps(&client, sort).await)
73 };
74
75 let mut apps_stream = std::pin::pin!(apps_stream);
76
77 let mut rem = self.max;
78
79 let mut display_apps = vec![];
80
81 'list: while let Some(apps) = apps_stream.next().await {
82 let mut apps = apps?;
83
84 let limit = std::cmp::min(apps.len(), rem);
85
86 if limit == 0 {
87 break;
88 }
89
90 rem -= limit;
91
92 if self.paging_mode {
93 println!("{}", self.fmt.format.render(&apps));
94
95 loop {
96 println!("next page? [y, n]");
97
98 let mut rsp = String::new();
99 std::io::stdin().read_line(&mut rsp)?;
100
101 if rsp.trim() == "y" {
102 continue 'list;
103 }
104 if rsp.trim() == "n" {
105 break 'list;
106 }
107
108 println!("uknown response: {rsp}");
109 }
110 }
111
112 display_apps.extend(apps.drain(..limit));
113 }
114
115 if !display_apps.is_empty() {
116 println!("{}", self.fmt.format.render(&display_apps));
117 }
118
119 Ok(())
120 }
121}