Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: Allow sorting in "app list" command #5025

Merged
merged 2 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions lib/backend-api/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1287,11 +1287,15 @@ pub async fn get_app_version_by_id_with_app(
/// NOTE: this will only include the first pages and does not provide pagination.
pub async fn user_apps(
client: &WasmerClient,
sort: types::DeployAppsSortBy,
) -> impl futures::Stream<Item = Result<Vec<types::DeployApp>, anyhow::Error>> + '_ {
futures::stream::try_unfold(None, move |cursor| async move {
let user = client
.run_graphql(types::GetCurrentUserWithApps::build(
GetCurrentUserWithAppsVars { after: cursor },
GetCurrentUserWithAppsVars {
after: cursor,
sort: Some(sort),
},
))
.await?
.viewer
Expand All @@ -1318,11 +1322,12 @@ pub async fn user_apps(
/// List all apps that are accessible by the current user.
pub async fn user_accessible_apps(
client: &WasmerClient,
sort: types::DeployAppsSortBy,
) -> Result<
impl futures::Stream<Item = Result<Vec<types::DeployApp>, anyhow::Error>> + '_,
anyhow::Error,
> {
let user_apps = user_apps(client).await;
let user_apps = user_apps(client, sort).await;

// Get all aps in user-accessible namespaces.
let namespace_res = client
Expand All @@ -1344,7 +1349,7 @@ pub async fn user_accessible_apps(

let mut ns_apps = vec![];
for ns in namespace_names {
let apps = namespace_apps(client, ns).await;
let apps = namespace_apps(client, ns, sort).await;
ns_apps.push(apps);
}

Expand All @@ -1357,6 +1362,7 @@ pub async fn user_accessible_apps(
pub async fn namespace_apps(
client: &WasmerClient,
namespace: String,
sort: types::DeployAppsSortBy,
) -> impl futures::Stream<Item = Result<Vec<types::DeployApp>, anyhow::Error>> + '_ {
let namespace = namespace.clone();

Expand All @@ -1365,6 +1371,7 @@ pub async fn namespace_apps(
.run_graphql(types::GetNamespaceApps::build(GetNamespaceAppsVars {
name: namespace.to_string(),
after: cursor,
sort: Some(sort),
}))
.await?;

Expand Down
6 changes: 4 additions & 2 deletions lib/backend-api/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ mod queries {
#[derive(cynic::QueryVariables, Debug)]
pub struct GetCurrentUserWithAppsVars {
pub after: Option<String>,
pub sort: Option<DeployAppsSortBy>,
}

#[derive(cynic::QueryFragment, Debug)]
Expand All @@ -647,7 +648,7 @@ mod queries {
pub struct UserWithApps {
pub id: cynic::Id,
pub username: String,
#[arguments(after: $after)]
#[arguments(after: $after, sortBy: $sort)]
pub apps: DeployAppConnection,
}

Expand Down Expand Up @@ -1104,6 +1105,7 @@ mod queries {
pub struct GetNamespaceAppsVars {
pub name: String,
pub after: Option<String>,
pub sort: Option<DeployAppsSortBy>,
}

#[derive(cynic::QueryFragment, Debug)]
Expand All @@ -1119,7 +1121,7 @@ mod queries {
pub struct NamespaceWithApps {
pub id: cynic::Id,
pub name: String,
#[arguments(after: $after)]
#[arguments(after: $after, sortBy: $sort)]
pub apps: DeployAppConnection,
}

Expand Down
27 changes: 23 additions & 4 deletions lib/cli/src/commands/app/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::pin::Pin;

use futures::{Stream, StreamExt};
use wasmer_api::types::DeployApp;
use wasmer_api::types::{DeployApp, DeployAppsSortBy};

use crate::{commands::AsyncCliCommand, config::WasmerEnv, opts::ListFormatOpts};

Expand Down Expand Up @@ -34,6 +34,19 @@ pub struct CmdAppList {
/// Asks whether to display the next page or not
#[clap(long, default_value = "false")]
paging_mode: bool,

/// Sort order for apps.
///
/// Use: --newest, --oldest or --last-updated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't clap print possible values already? Maybe it's different from ValueEnum'd enums.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't use to, they might have added it.

#[clap(long, default_value = "last-updated")]
sort: AppSort,
}

#[derive(clap::ValueEnum, Clone, Copy, Debug)]
pub enum AppSort {
Newest,
Oldest,
LastUpdated,
}

#[async_trait::async_trait]
Expand All @@ -43,14 +56,20 @@ impl AsyncCliCommand for CmdAppList {
async fn run_async(self) -> Result<(), anyhow::Error> {
let client = self.env.client()?;

let sort = match self.sort {
AppSort::Newest => DeployAppsSortBy::Newest,
AppSort::Oldest => DeployAppsSortBy::Oldest,
AppSort::LastUpdated => DeployAppsSortBy::MostActive,
};

let apps_stream: Pin<
Box<dyn Stream<Item = Result<Vec<DeployApp>, anyhow::Error>> + Send + Sync>,
> = if let Some(ns) = self.namespace.clone() {
Box::pin(wasmer_api::query::namespace_apps(&client, ns).await)
Box::pin(wasmer_api::query::namespace_apps(&client, ns, sort).await)
} else if self.all {
Box::pin(wasmer_api::query::user_accessible_apps(&client).await?)
Box::pin(wasmer_api::query::user_accessible_apps(&client, sort).await?)
} else {
Box::pin(wasmer_api::query::user_apps(&client).await)
Box::pin(wasmer_api::query::user_apps(&client, sort).await)
};

let mut apps_stream = std::pin::pin!(apps_stream);
Expand Down
Loading