use anyhow::Result;
use clap::Parser;
use console::style;
use std::path::Path;
use super::frontend_codegen::BindingGeneratorInput;
use super::frontend_target::FrontendTarget;
const FORGE_VERSION: &str = env!("CARGO_PKG_VERSION");
use super::ui;
#[derive(Parser)]
pub struct GenerateCommand {
#[arg(long)]
pub force: bool,
#[arg(short, long)]
pub output: Option<String>,
#[arg(long)]
pub target: Option<FrontendTarget>,
#[arg(short, long)]
pub src: Option<String>,
#[arg(short = 'y', long)]
pub yes: bool,
}
impl GenerateCommand {
pub async fn execute(self) -> Result<()> {
let src_dir = self.src.unwrap_or_else(|| "src".to_string());
let src_path = Path::new(&src_dir);
let detected_target = self
.target
.or_else(|| FrontendTarget::detect(Path::new("frontend")))
.unwrap_or(FrontendTarget::SvelteKit);
let output_dir = self
.output
.unwrap_or_else(|| detected_target.default_output_dir().to_string());
let output_path = Path::new(&output_dir);
eprint!(" Scanning Rust source files...");
let registry = if src_path.exists() {
forge_codegen::parse_project(src_path)?
} else {
forge_core::schema::SchemaRegistry::new()
};
eprintln!(" done");
let has_schema = !registry.all_tables().is_empty()
|| !registry.all_enums().is_empty()
|| !registry.all_functions().is_empty();
eprint!(
" Generating {} bindings...",
detected_target.display_name()
);
detected_target.generate_bindings(&BindingGeneratorInput {
output_dir: &output_dir,
output_path,
registry: ®istry,
has_schema,
force: self.force,
})?;
eprintln!(" done");
println!();
if has_schema {
let table_count = registry.all_tables().len();
let enum_count = registry.all_enums().len();
let function_count = registry.all_functions().len();
println!(
" {} Generated bindings from {} models, {} enums, {} functions (v{})",
ui::ok(),
style(table_count).cyan(),
style(enum_count).cyan(),
style(function_count).cyan(),
FORGE_VERSION
);
}
println!(" {} Output: {}", ui::info(), style(&output_dir).cyan());
println!();
Ok(())
}
}