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
43fn ensure_directory(path: &Path) -> Result<(), TemplateError> {
53 if !path.exists() {
54 create_dir_all(path)?;
55 }
56 Ok(())
57}
58
59fn 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)?;
108 Ok(())
109}
110
111fn write_empty_mod_rs(path: &Path) -> Result<(), TemplateError> {
121 write(path, "\n")?;
122 Ok(())
123}
124
125fn create_controller_template(
136 target_dir: &Path,
137 _component_name: &str,
138) -> Result<(), TemplateError> {
139 ensure_directory(target_dir)?;
140 let mod_rs: PathBuf = target_dir.join("mod.rs");
141 write_mod_rs(&mod_rs, &["fn", "impl", "struct"])?;
142 let fn_rs: PathBuf = target_dir.join("fn.rs");
143 write(&fn_rs, "use super::*;\n")?;
144 let impl_rs: PathBuf = target_dir.join("impl.rs");
145 write(&impl_rs, "use super::*;\n")?;
146 let struct_rs: PathBuf = target_dir.join("struct.rs");
147 write(&struct_rs, "use super::*;\n")?;
148 Ok(())
149}
150
151fn create_view_template(target_dir: &Path, _component_name: &str) -> Result<(), TemplateError> {
162 ensure_directory(target_dir)?;
163 let mod_rs: PathBuf = target_dir.join("mod.rs");
164 write_mod_rs(&mod_rs, &["fn", "impl", "struct"])?;
165 let fn_rs: PathBuf = target_dir.join("fn.rs");
166 write(&fn_rs, "use super::*;\n")?;
167 let impl_rs: PathBuf = target_dir.join("impl.rs");
168 write(&impl_rs, "use super::*;\n")?;
169 let struct_rs: PathBuf = target_dir.join("struct.rs");
170 write(&struct_rs, "use super::*;\n")?;
171 Ok(())
172}
173
174fn create_service_template(target_dir: &Path, _component_name: &str) -> Result<(), TemplateError> {
185 ensure_directory(target_dir)?;
186 let mod_rs: PathBuf = target_dir.join("mod.rs");
187 write_mod_rs(&mod_rs, &["impl", "struct"])?;
188 let impl_rs: PathBuf = target_dir.join("impl.rs");
189 write(&impl_rs, "use super::*;\n")?;
190 let struct_rs: PathBuf = target_dir.join("struct.rs");
191 write(&struct_rs, "use super::*;\n")?;
192 Ok(())
193}
194
195fn create_domain_template(target_dir: &Path, _component_name: &str) -> Result<(), TemplateError> {
206 ensure_directory(target_dir)?;
207 let mod_rs: PathBuf = target_dir.join("mod.rs");
208 write_mod_rs(&mod_rs, &["impl", "struct"])?;
209 let impl_rs: PathBuf = target_dir.join("impl.rs");
210 write(&impl_rs, "use super::*;\n")?;
211 let struct_rs: PathBuf = target_dir.join("struct.rs");
212 write(&struct_rs, "use super::*;\n")?;
213 Ok(())
214}
215
216fn create_mapper_template(target_dir: &Path, _component_name: &str) -> Result<(), TemplateError> {
227 ensure_directory(target_dir)?;
228 let mod_rs: PathBuf = target_dir.join("mod.rs");
229 write_mod_rs(
230 &mod_rs,
231 &["const", "enum", "fn", "impl", "static", "struct"],
232 )?;
233 let const_rs: PathBuf = target_dir.join("const.rs");
234 write(&const_rs, "use super::*;\n")?;
235 let enum_rs: PathBuf = target_dir.join("enum.rs");
236 write(&enum_rs, "use super::*;\n")?;
237 let fn_rs: PathBuf = target_dir.join("fn.rs");
238 write(&fn_rs, "use super::*;\n")?;
239 let impl_rs: PathBuf = target_dir.join("impl.rs");
240 write(&impl_rs, "use super::*;\n")?;
241 let static_rs: PathBuf = target_dir.join("static.rs");
242 write(&static_rs, "use super::*;\n")?;
243 let struct_rs: PathBuf = target_dir.join("struct.rs");
244 write(&struct_rs, "use super::*;\n")?;
245 Ok(())
246}
247
248fn create_utils_template(target_dir: &Path, _component_name: &str) -> Result<(), TemplateError> {
259 ensure_directory(target_dir)?;
260 let mod_rs: PathBuf = target_dir.join("mod.rs");
261 write_mod_rs(&mod_rs, &["fn"])?;
262 let fn_rs: PathBuf = target_dir.join("fn.rs");
263 write(&fn_rs, "use super::*;\n")?;
264 Ok(())
265}
266
267fn create_exception_template(
278 target_dir: &Path,
279 _component_name: &str,
280) -> Result<(), TemplateError> {
281 ensure_directory(target_dir)?;
282 let mod_rs: PathBuf = target_dir.join("mod.rs");
283 write_empty_mod_rs(&mod_rs)?;
284 Ok(())
285}
286
287fn create_repository_template(
298 target_dir: &Path,
299 _component_name: &str,
300) -> Result<(), TemplateError> {
301 ensure_directory(target_dir)?;
302 let mod_rs: PathBuf = target_dir.join("mod.rs");
303 write_mod_rs(&mod_rs, &["impl", "struct"])?;
304 let impl_rs: PathBuf = target_dir.join("impl.rs");
305 write(&impl_rs, "use super::*;\n")?;
306 let struct_rs: PathBuf = target_dir.join("struct.rs");
307 write(&struct_rs, "use super::*;\n")?;
308 Ok(())
309}
310
311fn create_model_template(
323 target_dir: &Path,
324 _component_name: &str,
325 sub_type: &ModelSubType,
326) -> Result<(), TemplateError> {
327 let sub_type_name: String = get_model_sub_type_name(sub_type);
328 let model_dir: PathBuf = target_dir.join(&sub_type_name);
329 ensure_directory(&model_dir)?;
330 let mod_rs: PathBuf = model_dir.join("mod.rs");
331 write_mod_rs(&mod_rs, &["struct"])?;
332 let struct_rs: PathBuf = model_dir.join("struct.rs");
333 write(&struct_rs, "use super::*;\n")?;
334 Ok(())
335}
336
337pub async fn execute_template(
349 template_type: TemplateType,
350 component_name: &str,
351 model_sub_type: Option<ModelSubType>,
352) -> Result<(), TemplateError> {
353 let config: TemplateConfig =
354 TemplateConfig::new(template_type, component_name.to_string(), model_sub_type);
355 let base_path: PathBuf = PathBuf::from(&config.base_directory);
356 let dir_name: String = get_directory_name(&config.template_type);
357 let type_dir: PathBuf = base_path.join(&dir_name);
358 let target_dir: PathBuf = type_dir.join(&config.component_name);
359 if target_dir.exists() {
360 return Err(TemplateError::DirectoryExists(
361 target_dir.to_string_lossy().to_string(),
362 ));
363 }
364 ensure_directory(&type_dir)?;
365 match config.template_type {
366 TemplateType::Controller => {
367 create_controller_template(&target_dir, &config.component_name)?
368 }
369 TemplateType::View => create_view_template(&target_dir, &config.component_name)?,
370 TemplateType::Service => create_service_template(&target_dir, &config.component_name)?,
371 TemplateType::Domain => create_domain_template(&target_dir, &config.component_name)?,
372 TemplateType::Mapper => create_mapper_template(&target_dir, &config.component_name)?,
373 TemplateType::Utils => create_utils_template(&target_dir, &config.component_name)?,
374 TemplateType::Exception => create_exception_template(&target_dir, &config.component_name)?,
375 TemplateType::Repository => {
376 create_repository_template(&target_dir, &config.component_name)?
377 }
378 TemplateType::Model => {
379 let sub_type: ModelSubType = config.model_sub_type.ok_or_else(|| {
380 TemplateError::InvalidModelSubType("Missing model subtype".to_string())
381 })?;
382 create_model_template(&target_dir, &config.component_name, &sub_type)?;
383 }
384 }
385 let _: Result<(), std::io::Error> = crate::fmt::format_path(&target_dir).await;
386 log::info!(
387 "Created {} '{}' at {}",
388 dir_name,
389 config.component_name,
390 target_dir.display()
391 );
392 Ok(())
393}