1use crate::*;
2
3fn get_directory_name(template_type: &TemplateType) -> String {
13 match template_type {
14 TemplateType::Controller => "controller".to_string(),
15 TemplateType::Domain => "domain".to_string(),
16 TemplateType::Exception => "exception".to_string(),
17 TemplateType::Mapper => "mapper".to_string(),
18 TemplateType::Model => "model".to_string(),
19 TemplateType::Repository => "repository".to_string(),
20 TemplateType::Service => "service".to_string(),
21 TemplateType::Utils => "utils".to_string(),
22 TemplateType::View => "view".to_string(),
23 }
24}
25
26fn get_model_sub_type_name(sub_type: &ModelSubType) -> String {
36 match sub_type {
37 ModelSubType::Application => "application".to_string(),
38 ModelSubType::Request => "request".to_string(),
39 ModelSubType::Response => "response".to_string(),
40 }
41}
42
43async fn ensure_directory(path: &Path) -> Result<(), TemplateError> {
53 if !path.exists() {
54 create_dir_all(path).await?;
55 }
56 Ok(())
57}
58
59async fn write_mod_rs(path: &Path, modules: &[&str]) -> Result<(), TemplateError> {
70 let mut content: String = String::new();
71 for module in modules {
72 let mod_name: String = if module.starts_with("r#") {
73 module.to_string()
74 } else {
75 format!("r#{module}")
76 };
77 content.push_str(&format!("mod {mod_name};\n"));
78 }
79 content.push('\n');
80 let mut pub_use_parts: Vec<String> = Vec::new();
81 for module in modules {
82 let raw_name: &str = if let Some(stripped) = module.strip_prefix("r#") {
83 stripped
84 } else {
85 module
86 };
87 let mod_name: String = if module.starts_with("r#") {
88 module.to_string()
89 } else {
90 format!("r#{module}")
91 };
92 if raw_name == "const" || raw_name == "static" {
93 pub_use_parts.push(mod_name);
94 } else if raw_name == "enum" || raw_name == "fn" {
95 pub_use_parts.push(format!("{mod_name}::*"));
96 } else if raw_name == "struct" {
97 pub_use_parts.push(mod_name);
98 }
99 }
100 if !pub_use_parts.is_empty() {
101 content.push_str("pub use {");
102 content.push_str(&pub_use_parts.join(", "));
103 content.push_str("};\n");
104 }
105 content.push('\n');
106 content.push_str("use super::*;\n");
107 write(path, content).await?;
108 Ok(())
109}
110
111async fn write_empty_mod_rs(path: &Path) -> Result<(), TemplateError> {
121 write(path, "\n").await?;
122 Ok(())
123}
124
125async fn create_controller_template(
136 target_dir: &Path,
137 _component_name: &str,
138) -> Result<(), TemplateError> {
139 ensure_directory(target_dir).await?;
140 let mod_rs: PathBuf = target_dir.join("mod.rs");
141 write_mod_rs(&mod_rs, &["fn", "impl", "struct"]).await?;
142 let fn_rs: PathBuf = target_dir.join("fn.rs");
143 write(&fn_rs, "use super::*;\n").await?;
144 let impl_rs: PathBuf = target_dir.join("impl.rs");
145 write(&impl_rs, "use super::*;\n").await?;
146 let struct_rs: PathBuf = target_dir.join("struct.rs");
147 write(&struct_rs, "use super::*;\n").await?;
148 Ok(())
149}
150
151async fn create_view_template(
162 target_dir: &Path,
163 _component_name: &str,
164) -> Result<(), TemplateError> {
165 ensure_directory(target_dir).await?;
166 let mod_rs: PathBuf = target_dir.join("mod.rs");
167 write_mod_rs(&mod_rs, &["fn", "impl", "struct"]).await?;
168 let fn_rs: PathBuf = target_dir.join("fn.rs");
169 write(&fn_rs, "use super::*;\n").await?;
170 let impl_rs: PathBuf = target_dir.join("impl.rs");
171 write(&impl_rs, "use super::*;\n").await?;
172 let struct_rs: PathBuf = target_dir.join("struct.rs");
173 write(&struct_rs, "use super::*;\n").await?;
174 Ok(())
175}
176
177async fn create_service_template(
188 target_dir: &Path,
189 _component_name: &str,
190) -> Result<(), TemplateError> {
191 ensure_directory(target_dir).await?;
192 let mod_rs: PathBuf = target_dir.join("mod.rs");
193 write_mod_rs(&mod_rs, &["impl", "struct"]).await?;
194 let impl_rs: PathBuf = target_dir.join("impl.rs");
195 write(&impl_rs, "use super::*;\n").await?;
196 let struct_rs: PathBuf = target_dir.join("struct.rs");
197 write(&struct_rs, "use super::*;\n").await?;
198 Ok(())
199}
200
201async fn create_domain_template(
212 target_dir: &Path,
213 _component_name: &str,
214) -> Result<(), TemplateError> {
215 ensure_directory(target_dir).await?;
216 let mod_rs: PathBuf = target_dir.join("mod.rs");
217 write_mod_rs(&mod_rs, &["impl", "struct"]).await?;
218 let impl_rs: PathBuf = target_dir.join("impl.rs");
219 write(&impl_rs, "use super::*;\n").await?;
220 let struct_rs: PathBuf = target_dir.join("struct.rs");
221 write(&struct_rs, "use super::*;\n").await?;
222 Ok(())
223}
224
225async fn create_mapper_template(
236 target_dir: &Path,
237 _component_name: &str,
238) -> Result<(), TemplateError> {
239 ensure_directory(target_dir).await?;
240 let mod_rs: PathBuf = target_dir.join("mod.rs");
241 write_mod_rs(
242 &mod_rs,
243 &["const", "enum", "fn", "impl", "static", "struct"],
244 )
245 .await?;
246 let const_rs: PathBuf = target_dir.join("const.rs");
247 write(&const_rs, "use super::*;\n").await?;
248 let enum_rs: PathBuf = target_dir.join("enum.rs");
249 write(&enum_rs, "use super::*;\n").await?;
250 let fn_rs: PathBuf = target_dir.join("fn.rs");
251 write(&fn_rs, "use super::*;\n").await?;
252 let impl_rs: PathBuf = target_dir.join("impl.rs");
253 write(&impl_rs, "use super::*;\n").await?;
254 let static_rs: PathBuf = target_dir.join("static.rs");
255 write(&static_rs, "use super::*;\n").await?;
256 let struct_rs: PathBuf = target_dir.join("struct.rs");
257 write(&struct_rs, "use super::*;\n").await?;
258 Ok(())
259}
260
261async fn create_utils_template(
272 target_dir: &Path,
273 _component_name: &str,
274) -> Result<(), TemplateError> {
275 ensure_directory(target_dir).await?;
276 let mod_rs: PathBuf = target_dir.join("mod.rs");
277 write_mod_rs(&mod_rs, &["fn"]).await?;
278 let fn_rs: PathBuf = target_dir.join("fn.rs");
279 write(&fn_rs, "use super::*;\n").await?;
280 Ok(())
281}
282
283async fn create_exception_template(
294 target_dir: &Path,
295 _component_name: &str,
296) -> Result<(), TemplateError> {
297 ensure_directory(target_dir).await?;
298 let mod_rs: PathBuf = target_dir.join("mod.rs");
299 write_empty_mod_rs(&mod_rs).await?;
300 Ok(())
301}
302
303async fn create_repository_template(
314 target_dir: &Path,
315 _component_name: &str,
316) -> Result<(), TemplateError> {
317 ensure_directory(target_dir).await?;
318 let mod_rs: PathBuf = target_dir.join("mod.rs");
319 write_mod_rs(&mod_rs, &["impl", "struct"]).await?;
320 let impl_rs: PathBuf = target_dir.join("impl.rs");
321 write(&impl_rs, "use super::*;\n").await?;
322 let struct_rs: PathBuf = target_dir.join("struct.rs");
323 write(&struct_rs, "use super::*;\n").await?;
324 Ok(())
325}
326
327async fn create_model_template(
339 target_dir: &Path,
340 _component_name: &str,
341 sub_type: &ModelSubType,
342) -> Result<(), TemplateError> {
343 let sub_type_name: String = get_model_sub_type_name(sub_type);
344 let model_dir: PathBuf = target_dir.join(&sub_type_name);
345 ensure_directory(&model_dir).await?;
346 let mod_rs: PathBuf = model_dir.join("mod.rs");
347 write_mod_rs(&mod_rs, &["struct"]).await?;
348 let struct_rs: PathBuf = model_dir.join("struct.rs");
349 write(&struct_rs, "use super::*;\n").await?;
350 Ok(())
351}
352
353pub async fn execute_template(
365 template_type: TemplateType,
366 component_name: &str,
367 model_sub_type: Option<ModelSubType>,
368) -> Result<(), TemplateError> {
369 let config: TemplateConfig =
370 TemplateConfig::new(template_type, component_name.to_string(), model_sub_type);
371 let base_path: PathBuf = PathBuf::from(&config.base_directory);
372 let dir_name: String = get_directory_name(&config.template_type);
373 let type_dir: PathBuf = base_path.join(&dir_name);
374 let target_dir: PathBuf = type_dir.join(&config.component_name);
375 if target_dir.exists() {
376 return Err(TemplateError::DirectoryExists(
377 target_dir.to_string_lossy().to_string(),
378 ));
379 }
380 ensure_directory(&type_dir).await?;
381 match config.template_type {
382 TemplateType::Controller => {
383 create_controller_template(&target_dir, &config.component_name).await?
384 }
385 TemplateType::View => create_view_template(&target_dir, &config.component_name).await?,
386 TemplateType::Service => {
387 create_service_template(&target_dir, &config.component_name).await?
388 }
389 TemplateType::Domain => create_domain_template(&target_dir, &config.component_name).await?,
390 TemplateType::Mapper => create_mapper_template(&target_dir, &config.component_name).await?,
391 TemplateType::Utils => create_utils_template(&target_dir, &config.component_name).await?,
392 TemplateType::Exception => {
393 create_exception_template(&target_dir, &config.component_name).await?
394 }
395 TemplateType::Repository => {
396 create_repository_template(&target_dir, &config.component_name).await?
397 }
398 TemplateType::Model => {
399 let sub_type: ModelSubType = config.model_sub_type.ok_or_else(|| {
400 TemplateError::InvalidModelSubType("Missing model subtype".to_string())
401 })?;
402 create_model_template(&target_dir, &config.component_name, &sub_type).await?;
403 }
404 }
405 let _: Result<(), io::Error> = crate::fmt::format_path(&target_dir).await;
406 log::info!(
407 "Created {dir_name} '{}' at {}",
408 config.component_name,
409 target_dir.display()
410 );
411 Ok(())
412}