use super::build_api_client;
use crate::{api, config::Config, models::Workspace, output::OutputFormat};
use anyhow::{Context, Result};
use clap::{Args, Subcommand};
use colored::Colorize;
use std::io::{IsTerminal, stdout};
use tokio::runtime::Builder as RuntimeBuilder;
#[derive(Subcommand, Debug)]
pub enum WorkspaceCommand {
List(WorkspaceListArgs),
Show(WorkspaceShowArgs),
}
#[derive(Args, Debug)]
pub struct WorkspaceListArgs {
#[arg(long)]
pub limit: Option<usize>,
#[arg(long, value_enum)]
pub output: Option<OutputFormat>,
}
#[derive(Args, Debug)]
pub struct WorkspaceShowArgs {
#[arg(value_name = "WORKSPACE")]
pub workspace: String,
#[arg(long, value_enum)]
pub output: Option<OutputFormat>,
}
fn determine_output(value: Option<OutputFormat>) -> OutputFormat {
value.unwrap_or_else(|| {
if stdout().is_terminal() {
OutputFormat::Table
} else {
OutputFormat::Json
}
})
}
pub fn handle_workspace_command(command: WorkspaceCommand, config: &Config) -> Result<()> {
let client = build_api_client(config)?;
let runtime = RuntimeBuilder::new_current_thread()
.enable_all()
.build()
.context("failed to initialize async runtime")?;
runtime.block_on(async move {
match command {
WorkspaceCommand::List(args) => list_workspaces_command(&client, args).await,
WorkspaceCommand::Show(args) => show_workspace_command(&client, args).await,
}
})
}
async fn list_workspaces_command(client: &api::ApiClient, args: WorkspaceListArgs) -> Result<()> {
let params = crate::models::WorkspaceListParams { limit: args.limit };
let workspaces = api::list_workspaces(client, params).await?;
if workspaces.is_empty() {
println!("No workspaces found.");
return Ok(());
}
let format = determine_output(args.output);
match format {
OutputFormat::Table => {
if stdout().is_terminal() {
println!(
"{:<20} {:<40} {}",
"GID".bold(),
"Name".bold(),
"Type".bold()
);
println!("{}", "─".repeat(80));
}
for workspace in &workspaces {
let workspace_type = if workspace.is_organization {
"Organization"
} else {
"Workspace"
};
if stdout().is_terminal() {
println!(
"{:<20} {:<40} {}",
workspace.gid, workspace.name, workspace_type
);
} else {
println!("{}\t{}\t{}", workspace.gid, workspace.name, workspace_type);
}
}
if stdout().is_terminal() {
println!("\n{} workspaces listed.", workspaces.len());
}
}
OutputFormat::Markdown => {
println!("| GID | Name | Type |");
println!("|---|---|---|");
for workspace in &workspaces {
let workspace_type = if workspace.is_organization {
"Organization"
} else {
"Workspace"
};
println!(
"| {} | {} | {} |",
workspace.gid, workspace.name, workspace_type
);
}
}
OutputFormat::Csv => {
println!("gid,name,type");
for workspace in &workspaces {
let workspace_type = if workspace.is_organization {
"Organization"
} else {
"Workspace"
};
println!("{},{},{}", workspace.gid, workspace.name, workspace_type);
}
}
OutputFormat::Json => {
let json = serde_json::to_string_pretty(&workspaces)
.context("failed to serialize workspaces to JSON")?;
println!("{json}");
}
}
Ok(())
}
async fn show_workspace_command(client: &api::ApiClient, args: WorkspaceShowArgs) -> Result<()> {
let workspace = api::get_workspace(client, &args.workspace).await?;
let format = determine_output(args.output);
if matches!(format, OutputFormat::Json) {
let json = serde_json::to_string_pretty(&workspace)
.context("failed to serialize workspace to JSON")?;
println!("{json}");
} else {
print_workspace_detail(&workspace);
}
Ok(())
}
fn print_workspace_detail(workspace: &Workspace) {
let gid = &workspace.gid;
let name = &workspace.name;
println!("GID: {gid}");
println!("Name: {name}");
println!(
"Type: {}",
if workspace.is_organization {
"Organization"
} else {
"Workspace"
}
);
if !workspace.email_domains.is_empty() {
println!("Email Domains:");
for domain in &workspace.email_domains {
println!(" - {domain}");
}
}
}