actr_cli/commands/initialize/
mod.rs

1mod kotlin;
2mod python;
3mod swift;
4pub mod traits;
5
6use crate::commands::SupportedLanguage;
7use crate::error::{ActrCliError, Result};
8use crate::template::{ProjectTemplateName, TemplateContext};
9use handlebars::Handlebars;
10use kotlin::KotlinInitializer;
11use python::PythonInitializer;
12use std::path::Path;
13use swift::SwiftInitializer;
14
15pub use traits::{InitContext, ProjectInitializer};
16
17/// Generate a local.proto file with the given package name
18pub fn create_local_proto(
19    project_dir: &Path,
20    project_name: &str,
21    proto_dir: &str,
22    template: ProjectTemplateName,
23) -> Result<()> {
24    let proto_path = project_dir.join(proto_dir);
25    std::fs::create_dir_all(&proto_path)?;
26
27    // Load template file
28    let fixtures_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("fixtures");
29    let template_file_name = match template {
30        ProjectTemplateName::Echo => "local.echo.hbs",
31        ProjectTemplateName::DataStream => "local.data-stream.hbs",
32    };
33    let template_path = fixtures_root.join("protos").join(template_file_name);
34
35    let template_content = std::fs::read_to_string(&template_path).map_err(|e| {
36        ActrCliError::Io(std::io::Error::new(
37            std::io::ErrorKind::NotFound,
38            format!(
39                "Failed to read proto template {}: {}",
40                template_path.display(),
41                e
42            ),
43        ))
44    })?;
45
46    // Create template context
47    let template_context = TemplateContext::new(project_name, "", "");
48    let handlebars = Handlebars::new();
49
50    // Render template
51    let local_proto_content = handlebars
52        .render_template(&template_content, &template_context)
53        .map_err(|e| {
54            ActrCliError::Io(std::io::Error::new(
55                std::io::ErrorKind::InvalidData,
56                format!("Failed to render proto template: {}", e),
57            ))
58        })?;
59
60    let local_proto_path = proto_path.join("local.proto");
61    std::fs::write(&local_proto_path, local_proto_content)?;
62
63    tracing::info!("📄 Created {}", local_proto_path.display());
64    Ok(())
65}
66
67pub struct InitializerFactory;
68
69impl InitializerFactory {
70    pub fn get_initializer(language: SupportedLanguage) -> Result<Box<dyn ProjectInitializer>> {
71        match language {
72            SupportedLanguage::Rust => Err(ActrCliError::Unsupported(
73                "Rust initialization is handled by InitCommand".to_string(),
74            )),
75            SupportedLanguage::Python => Ok(Box::new(PythonInitializer)),
76            SupportedLanguage::Swift => Ok(Box::new(SwiftInitializer)),
77            SupportedLanguage::Kotlin => Ok(Box::new(KotlinInitializer)),
78        }
79    }
80}
81
82pub async fn execute_initialize(language: SupportedLanguage, context: &InitContext) -> Result<()> {
83    let initializer = InitializerFactory::get_initializer(language)?;
84    initializer.generate_project_structure(context).await?;
85    initializer.print_next_steps(context);
86    Ok(())
87}