cargo_smith/commands/
resource.rs1use clap::Args;
2use anyhow::{bail, Result};
3use std::path::Path;
4use tokio::fs;
5
6use crate::templates::{template_engine::TemplateEngine, types::CargoMold};
7
8#[derive(Args)]
9pub struct ResourceArgs {
10 pub name: String,
11}
12
13const MODEL_RS_TPL: &str = include_str!("../templates/resource/traditional/model_rs.tpl");
14const HANDLER_RS_TPL: &str = include_str!("../templates/resource/traditional/handler_rs.tpl");
15const ROUTES_RS_TPL: &str = include_str!("../templates/resource/traditional/routes_rs.tpl");
16
17pub async fn execute(args: ResourceArgs) -> anyhow::Result<()> {
18
19 if !Path::new(".cargo-smith").exists() {
20 bail!(
21 "Not a cargo-mold project.\n\
22 Run this command in a project created with `cargo mold new`\n\
23 Or create a new project with: `cargo mold new {}`",
24 args.name
25 );
26 }
27
28 println!("Generating resource: {}", args.name);
29
30 let files = [
31 ("src/models/{}.rs", MODEL_RS_TPL),
32 ("src/handlers/{}_handlers.rs", HANDLER_RS_TPL),
33 ("src/routes/{}_routes.rs", ROUTES_RS_TPL),
34 ];
35
36 for (output_path_pattern, template_content) in files {
37 let output_path = output_path_pattern.replace("{}", &args.name);
38 TemplateEngine::generate_resource_template(&args.name, &output_path, template_content).await?;
39 }
40
41 update_modules(&args.name).await?;
42 update_resource_cargo_mold(args.name.clone()).await?;
43
44 println!("Resource '{}' created successfully!", args.name);
45 println!("Generated files:");
46 println!(" - src/models/{}.rs", args.name);
47 println!(" - src/handlers/{}_handlers.rs", args.name);
48 println!(" - src/routes/{}_routes.rs", args.name);
49
50 Ok(())
51}
52
53async fn update_modules(resource_name: &str) -> Result<()> {
54 update_mod_file("src/models/mod.rs", &format!("pub mod {};", resource_name)).await?;
56 update_mod_file("src/handlers/mod.rs", &format!("pub mod {}_handlers;", resource_name)).await?;
57 update_mod_file("src/routes/mod.rs", &format!("pub mod {}_routes;", resource_name)).await?;
58
59 Ok(())
60}
61
62async fn update_mod_file(file_path: &str, module_declaration: &str) -> Result<()> {
63 if !Path::new(file_path).exists() {
64 return Ok(());
65 }
66
67 let mut content = fs::read_to_string(file_path).await?;
68
69 if !content.contains(module_declaration) {
70 if !content.ends_with('\n') {
71 content.push('\n');
72 }
73 content.push_str(module_declaration);
74 content.push('\n');
75
76 fs::write(file_path, content).await?;
77 }
78
79 Ok(())
80}
81
82async fn update_resource_cargo_mold(name: String) -> Result<()> {
83
84 let content = fs::read_to_string(".cargo-smith").await?;
85
86 let mut config: CargoMold = toml::from_str(&content)?;
87
88 if !config.generated.resources.contains(&name) {
89 config.generated.resources.push(name);
90 let updated_content = toml::to_string_pretty(&config)?;
91 fs::write(".cargo-smith", updated_content).await?;
92 }
93 Ok(())
94}
95
96