use anyhow::Result;
use clap::{Parser, Subcommand};
use colored::*;
use crate::application::{
commands::{Create{{EntityName}}Command, Update{{EntityName}}Command, Delete{{EntityName}}Command},
queries::{Get{{EntityName}}Query, List{{EntityName}}Query},
services::{{EntityName}}ApplicationService,
bulk_operations::{BulkOperationProgress, {{EntityName}}BulkOperationsHandler, BulkOperationConfig},
};
use crate::domain::entity::{{EntityName}};
#[derive(Parser)]
#[command(name = "{{module_name}}")]
#[command(about = "Manage {{ModuleName}} entities in the system")]
pub struct {{EntityName}}Commands {
#[command(subcommand)]
pub action: {{EntityName}}Action,
}
#[derive(Subcommand)]
pub enum {{EntityName}}Action {
Create {
#[arg(short, long)]
data: Option<String>,
#[arg(short, long)]
file: Option<String>,
#[arg(long, default_value = "cli-user")]
user_id: String,
},
Get {
id: String,
},
List {
#[arg(short, long, default_value = "1")]
page: usize,
#[arg(short, long, default_value = "20")]
page_size: usize,
#[arg(short, long)]
sort_by: Option<String>,
#[arg(long, default_value = "asc")]
sort_direction: String,
#[arg(short, long)]
search: Option<String>,
},
Update {
id: String,
#[arg(short, long)]
data: Option<String>,
#[arg(short, long)]
file: Option<String>,
#[arg(long, default_value = "cli-user")]
user_id: String,
},
Delete {
id: String,
#[arg(long, default_value = "cli-user")]
user_id: String,
},
BulkCreate {
#[arg(short, long)]
file: String,
#[arg(long, default_value = "1000")]
batch_size: usize,
#[arg(long, default_value = "10")]
max_concurrency: usize,
#[arg(long, default_value = "true")]
continue_on_error: bool,
#[arg(long, default_value = "true")]
show_progress: bool,
},
ListTrash {
#[arg(short, long, default_value = "1")]
page: usize,
#[arg(short, long, default_value = "20")]
page_size: usize,
},
Restore {
id: String,
#[arg(long, default_value = "cli-user")]
user_id: String,
},
EmptyTrash {
#[arg(long)]
confirm: bool,
#[arg(long, default_value = "cli-user")]
user_id: String,
},
}
pub struct {{EntityName}}CliHandler {
service: Arc<{{EntityName}}ApplicationService>,
}
impl {{EntityName}}CliHandler {
pub fn new(service: Arc<{{EntityName}}ApplicationService>) -> Self {
Self { service }
}
pub async fn handle(&self, command: {{EntityName}}Commands) -> Result<()> {
match command.action {
{{EntityName}}Action::Create { data, file, user_id } => {
self.create_{{entity_name}}(data, file, user_id).await
}
{{EntityName}}Action::Get { id } => {
self.get_{{entity_name}}(&id).await
}
{{EntityName}}Action::List { page, page_size, sort_by, sort_direction, search } => {
self.list_{{entity_name_plural}}(page, page_size, sort_by, sort_direction, search).await
}
{{EntityName}}Action::Update { id, data, file, user_id } => {
self.update_{{entity_name}}(&id, data, file, user_id).await
}
{{EntityName}}Action::Delete { id, user_id } => {
self.delete_{{entity_name}}(&id, user_id).await
}
{{EntityName}}Action::BulkCreate { file, batch_size, max_concurrency, continue_on_error, show_progress } => {
self.bulk_create_{{entity_name_plural}}_csv(file, batch_size, max_concurrency, continue_on_error, show_progress).await
}
{{EntityName}}Action::ListTrash { page, page_size } => {
self.list_trash(page, page_size).await
}
{{EntityName}}Action::Restore { id, user_id } => {
self.restore_{{entity_name}}(&id, user_id).await
}
{{EntityName}}Action::EmptyTrash { confirm, user_id } => {
self.empty_trash(confirm, user_id).await
}
}
}
async fn display_{{entity_name}}(&self, {{entity_name}}: &{{EntityName}}) -> Result<()> {
println!("{}", "📋 {{EntityName}} Details:".cyan());
println!("{}", format!(" ID: {}", {{entity_name}}.id).white());
let status_indicator = match {{entity_name}}.status.as_str() {
"active" => "🟢",
"inactive" => "🔴",
_ => "⚪",
};
println!("{}", format!(" Status: {} {}", status_indicator, {{entity_name}}.status).white());
if let Some(created_at) = &{{entity_name}}.created_at {
println!("{}", format!(" Created: {}", created_at).white());
let time_since_creation = chrono::Utc::now().signed_duration_since(*created_at);
println!("{}", format!(" Age: {} days", time_since_creation.num_days()).blue());
}
if let Some(updated_at) = &{{entity_name}}.updated_at {
println!("{}", format!(" Updated: {}", updated_at).white());
}
if let Ok(computed) = {{entity_name}}.computed_fields() {
if let Some(is_active) = computed.get("is_active") {
let active_status = if is_active.as_bool().unwrap_or(false) { "Active" } else { "Inactive" };
let status_color = if is_active.as_bool().unwrap_or(false) { "green" } else { "red" };
println!("{}", format!(" Computed Status: {}", active_status).color(status_color));
}
}
if !{{entity_name}}.metadata.is_empty() {
println!("{}", " Metadata:".white());
for (key, value) in &{{entity_name}}.metadata {
println!("{}", format!(" {}: {}", key, value).dimmed());
}
}
Ok(())
}
fn display_progress(&self, progress: BulkOperationProgress) {
print!("\r");
let progress_bar = if progress.total_items > 0 {
let percentage = progress.completion_percentage();
let bar_width = 30;
let filled_width = (bar_width as f64 * percentage / 100.0) as usize;
let empty_width = bar_width - filled_width;
format!(
"█{}{} {:.1}%",
"█".repeat(filled_width),
"░".repeat(empty_width),
percentage
)
} else {
"Processing...".to_string()
};
let status_color = if progress.failed_items == 0 { "green" } else { "yellow" };
print!(
"\r🔄 {} | {} | {}/{} | {}",
progress_bar.cyan(),
format!("{:.1} ops/s", progress.items_per_second()).white(),
progress.successful_items,
progress.total_items,
format!("{} errors", progress.failed_items).color(status_color)
);
use std::io::{self, Write};
let _ = io::stdout().flush();
}
async fn create_{{entity_name}}(&self, data: Option<String>, file: Option<String>, user_id: String) -> Result<()> {
todo!("Generate create implementation for {{EntityName}}")
}
async fn get_{{entity_name}}(&self, id: &str) -> Result<()> {
todo!("Generate get implementation for {{EntityName}}")
}
async fn list_{{entity_name_plural}}(&self, page: usize, page_size: usize, sort_by: Option<String>, sort_direction: String, search: Option<String>) -> Result<()> {
todo!("Generate list implementation for {{EntityName}}")
}
async fn update_{{entity_name}}(&self, id: &str, data: Option<String>, file: Option<String>, user_id: String) -> Result<()> {
todo!("Generate update implementation for {{EntityName}}")
}
async fn delete_{{entity_name}}(&self, id: &str, user_id: String) -> Result<()> {
todo!("Generate delete implementation for {{EntityName}}")
}
async fn bulk_create_{{entity_name_plural}}_csv(&self, file: String, batch_size: usize, max_concurrency: usize, continue_on_error: bool, show_progress: bool) -> Result<()> {
todo!("Generate bulk create implementation for {{EntityName}}")
}
async fn list_trash(&self, page: usize, page_size: usize) -> Result<()> {
todo!("Generate list trash implementation for {{EntityName}}")
}
async fn restore_{{entity_name}}(&self, id: &str, user_id: String) -> Result<()> {
todo!("Generate restore implementation for {{EntityName}}")
}
async fn empty_trash(&self, confirm: bool, user_id: String) -> Result<()> {
todo!("Generate empty trash implementation for {{EntityName}}")
}
}