actr_cli/commands/initialize/
mod.rs1mod 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
17pub fn create_protoc_plugin_config(project_dir: &Path) -> Result<()> {
19 const DEFAULT_PLUGIN_MIN_VERSION: &str = "0.1.10";
20
21 let config_path = project_dir.join(".protoc-plugin.toml");
22 if config_path.exists() {
23 return Ok(());
24 }
25
26 if let Some(parent) = config_path.parent() {
27 std::fs::create_dir_all(parent)?;
28 }
29
30 let content = format!(
31 "version = 1\n\n[plugins]\nprotoc-gen-actrframework = \"{DEFAULT_PLUGIN_MIN_VERSION}\"\nprotoc-gen-actrframework-swift = \"{DEFAULT_PLUGIN_MIN_VERSION}\"\n"
32 );
33
34 std::fs::write(&config_path, content)?;
35 tracing::info!("📄 Created .protoc-plugin.toml");
36 Ok(())
37}
38
39pub fn create_local_proto(
41 project_dir: &Path,
42 project_name: &str,
43 proto_dir: &str,
44 template: ProjectTemplateName,
45) -> Result<()> {
46 let proto_path = project_dir.join(proto_dir);
47 std::fs::create_dir_all(&proto_path)?;
48
49 let fixtures_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("fixtures");
51 let template_file_name = match template {
52 ProjectTemplateName::Echo => "local.echo.hbs",
53 ProjectTemplateName::DataStream => "local.data-stream.hbs",
54 };
55 let template_path = fixtures_root.join("protos").join(template_file_name);
56
57 let template_content = std::fs::read_to_string(&template_path).map_err(|e| {
58 ActrCliError::Io(std::io::Error::new(
59 std::io::ErrorKind::NotFound,
60 format!(
61 "Failed to read proto template {}: {}",
62 template_path.display(),
63 e
64 ),
65 ))
66 })?;
67
68 let template_context = TemplateContext::new(project_name, "", "");
70 let handlebars = Handlebars::new();
71
72 let local_proto_content = handlebars
74 .render_template(&template_content, &template_context)
75 .map_err(|e| {
76 ActrCliError::Io(std::io::Error::new(
77 std::io::ErrorKind::InvalidData,
78 format!("Failed to render proto template: {}", e),
79 ))
80 })?;
81
82 let local_proto_path = proto_path.join("local.proto");
83 std::fs::write(&local_proto_path, local_proto_content)?;
84
85 tracing::info!("📄 Created {}", local_proto_path.display());
86 Ok(())
87}
88
89pub struct InitializerFactory;
90
91impl InitializerFactory {
92 pub fn get_initializer(language: SupportedLanguage) -> Result<Box<dyn ProjectInitializer>> {
93 match language {
94 SupportedLanguage::Rust => Err(ActrCliError::Unsupported(
95 "Rust initialization is handled by InitCommand".to_string(),
96 )),
97 SupportedLanguage::Python => Ok(Box::new(PythonInitializer)),
98 SupportedLanguage::Swift => Ok(Box::new(SwiftInitializer)),
99 SupportedLanguage::Kotlin => Ok(Box::new(KotlinInitializer)),
100 }
101 }
102}
103
104pub async fn execute_initialize(language: SupportedLanguage, context: &InitContext) -> Result<()> {
105 let initializer = InitializerFactory::get_initializer(language)?;
106 initializer.generate_project_structure(context).await?;
107 initializer.print_next_steps(context);
108 Ok(())
109}