use cargo_generate::{generate, GenerateArgs};
use cargo_metadata::{MetadataCommand, Package};
use clap::Args;
use log::info;
use crate::config::{config_file_path, BaizeConfig, BaizeTemplate};
use crate::utils::mod_utils::update_mod_rs;
#[derive(Clone, Debug, Args)]
pub struct GenerateEntityCommand {
#[arg(short, long = "crate")]
pub crate_name: String,
#[arg(short, long, help = "Entity名称. 例如: account")]
pub entity: String,
#[arg(short, long, help = "数据库表前缀. 例如: acc")]
pub db_prefix: String,
#[arg(long, short, number_of_values = 1, value_parser, help = "模板参数,例如:--config key=value")]
pub template_values: Vec<String>,
}
impl GenerateEntityCommand {
pub fn run(mut self) -> anyhow::Result<()> {
let metadata = MetadataCommand::new()
.no_deps() .exec()
.expect("无法获取 cargo metadata");
let core_crate_name = format!("{}-core", self.crate_name);
let core_package = metadata
.packages
.iter()
.find(|p| p.name.to_string() == core_crate_name)
.ok_or_else(|| anyhow::anyhow!("未找到指定 crate 的 core 包"))?;
info!("core package. name: {}, manifest_path: {}", core_package.name, core_package.manifest_path);
let sdk_crate_name = format!("{}-sdk", self.crate_name);
let sdk_package = metadata
.packages
.iter()
.find(|p| p.name.to_string() == sdk_crate_name)
.ok_or_else(|| anyhow::anyhow!("未找到指定 crate 的 sdk 包"))?;
info!("sdk package. name: {}, manifest_path: {}", sdk_package.name, sdk_package.manifest_path);
self.template_values.insert(0, format!("entity={}", self.entity));
self.template_values.insert(1, format!("db_prefix={}", self.db_prefix));
let config_file = config_file_path(metadata.workspace_root.as_std_path());
let config_str = std::fs::read_to_string(config_file)?;
let config: BaizeConfig = toml::from_str(&config_str)?;
self.run_cargo_generate(core_package, config.templates.get("db").unwrap())?; self.run_cargo_generate(core_package, config.templates.get("domain").unwrap())?;
self.run_cargo_generate(core_package, config.templates.get("service-core").unwrap())?;
self.run_cargo_generate(sdk_package, config.templates.get("service-sdk").unwrap())?;
Ok(())
}
fn run_cargo_generate(&self, package: &Package, template: &BaizeTemplate) -> anyhow::Result<()> {
let mut args = GenerateArgs::default();
args.template_path.path = Some(template.path.to_string_lossy().to_string());
args.init = template.config.init;
args.name = Some(self.crate_name.clone());
args.define = self.template_values.iter().map(ToString::to_string).collect::<Vec<_>>();
let mut target_path = package.manifest_path.clone();
target_path.pop(); target_path.push(template.config.destination.clone()); args.destination = Some(target_path.into_std_path_buf());
let path = generate(args)
.inspect(|path| info!("Generated: {}", path.display()))
.inspect_err(|err| info!("Generate Failed. error: {}", err))?;
update_mod_rs(path)?;
Ok(())
}
}