diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index de0d32877cb..2f699679e07 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -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, 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 @@ -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, 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 @@ -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); } @@ -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, anyhow::Error>> + '_ { let namespace = namespace.clone(); @@ -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?; diff --git a/lib/backend-api/src/types.rs b/lib/backend-api/src/types.rs index 0d66847984d..e86e7d0c912 100644 --- a/lib/backend-api/src/types.rs +++ b/lib/backend-api/src/types.rs @@ -633,6 +633,7 @@ mod queries { #[derive(cynic::QueryVariables, Debug)] pub struct GetCurrentUserWithAppsVars { pub after: Option, + pub sort: Option, } #[derive(cynic::QueryFragment, Debug)] @@ -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, } @@ -1104,6 +1105,7 @@ mod queries { pub struct GetNamespaceAppsVars { pub name: String, pub after: Option, + pub sort: Option, } #[derive(cynic::QueryFragment, Debug)] @@ -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, } diff --git a/lib/cli/src/commands/app/list.rs b/lib/cli/src/commands/app/list.rs index d16e9a0f5c1..94bb6221ad7 100644 --- a/lib/cli/src/commands/app/list.rs +++ b/lib/cli/src/commands/app/list.rs @@ -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}; @@ -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 + #[clap(long, default_value = "last-updated")] + sort: AppSort, +} + +#[derive(clap::ValueEnum, Clone, Copy, Debug)] +pub enum AppSort { + Newest, + Oldest, + LastUpdated, } #[async_trait::async_trait] @@ -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, 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);