use crate::cli_generator::types::CliProject;
use crate::utils::error::{Error, Result};
use std::path::Path;
use tera::{Context, Tera};
const WORKSPACE_CARGO_TEMPLATE: &str = "cli/workspace/Cargo.toml.tmpl";
pub struct WorkspaceGenerator {
tera: Tera,
}
impl WorkspaceGenerator {
pub fn new(template_dir: &Path) -> Result<Self> {
let pattern = format!("{}/**/*.tmpl", template_dir.display());
let tera = Tera::new(&pattern).map_err(|e| {
Error::with_context(
"Failed to load templates",
&format!("{}: {}", template_dir.display(), e),
)
})?;
Ok(Self { tera })
}
pub fn generate(&self, project: &CliProject, output_dir: &Path) -> Result<()> {
let mut context = Context::new();
context.insert("project_name", &project.name);
let cli_crate = project
.cli_crate
.as_ref()
.ok_or_else(|| Error::new("cli_crate is required for workspace generation"))?;
let core_crate = project
.domain_crate
.as_ref()
.ok_or_else(|| Error::new("domain_crate is required for workspace generation"))?;
context.insert("cli_crate", cli_crate);
context.insert("core_crate", core_crate);
context.insert("version", &project.version);
context.insert("edition", &project.edition);
context.insert("license", &project.license);
context.insert("authors", &project.authors);
context.insert("resolver", &project.resolver);
context.insert("project", project);
let workspace_cargo = output_dir.join("Cargo.toml");
self.render_template(WORKSPACE_CARGO_TEMPLATE, &context, &workspace_cargo)
.map_err(|e| {
Error::with_context("Failed to generate workspace Cargo.toml", &e.to_string())
})?;
let crates_dir = output_dir.join("crates");
std::fs::create_dir_all(&crates_dir).map_err(|e| {
Error::with_context("Failed to create crates directory", &e.to_string())
})?;
Ok(())
}
fn render_template(&self, template: &str, context: &Context, output: &Path) -> Result<()> {
let content = self.tera.render(template, context).map_err(|e| {
Error::with_context("Failed to render template", &format!("{}: {}", template, e))
})?;
if let Some(parent) = output.parent() {
std::fs::create_dir_all(parent).map_err(|e| {
Error::with_context(
"Failed to create directory",
&format!("{}: {}", parent.display(), e),
)
})?;
}
std::fs::write(output, content).map_err(|e| {
Error::with_context(
"Failed to write file",
&format!("{}: {}", output.display(), e),
)
})?;
Ok(())
}
}