serverust_cli/
scaffold.rs1use std::fs;
8use std::path::{Path, PathBuf};
9
10use anyhow::{Context, Result, bail};
11
12use crate::cli::GenerateKind;
13use crate::templates;
14
15pub fn new_project(base: &Path, name: &str) -> Result<()> {
17 let root = base.join(name);
18 if root.exists() {
19 bail!("target directory '{}' already exists", root.display());
20 }
21 fs::create_dir_all(root.join("src/modules"))
22 .with_context(|| format!("creating src/modules in {}", root.display()))?;
23 fs::create_dir_all(root.join("src/shared"))
24 .with_context(|| format!("creating src/shared in {}", root.display()))?;
25
26 write_file(
27 &root.join("Cargo.toml"),
28 &templates::project_cargo_toml(name),
29 )?;
30 write_file(
31 &root.join("serverust.toml"),
32 &templates::project_serverust_toml(name),
33 )?;
34 write_file(&root.join("src/main.rs"), &templates::project_main_rs())?;
35 write_file(
36 &root.join("src/modules/mod.rs"),
37 &templates::project_modules_mod_rs(),
38 )?;
39 write_file(
40 &root.join("src/shared/mod.rs"),
41 &templates::project_shared_mod_rs(),
42 )?;
43 Ok(())
44}
45
46pub fn generate(base: &Path, kind: GenerateKind, name: &str) -> Result<()> {
49 match kind {
50 GenerateKind::Resource => generate_resource(base, name),
51 GenerateKind::Module => generate_module(base, name, false),
52 GenerateKind::Controller => generate_single_module_file(
53 base,
54 name,
55 format!("{name}.controller.rs"),
56 templates::controller(name),
57 ),
58 GenerateKind::Service => generate_single_module_file(
59 base,
60 name,
61 format!("{name}.service.rs"),
62 templates::service(name),
63 ),
64 GenerateKind::Pipe => generate_shared(
65 base,
66 "pipes",
67 format!("{name}.pipe.rs"),
68 templates::pipe(name),
69 ),
70 GenerateKind::Guard => generate_shared(
71 base,
72 "guards",
73 format!("{name}.guard.rs"),
74 templates::guard(name),
75 ),
76 GenerateKind::Interceptor => generate_shared(
77 base,
78 "interceptors",
79 format!("{name}.interceptor.rs"),
80 templates::interceptor(name),
81 ),
82 GenerateKind::Filter => generate_shared(
83 base,
84 "filters",
85 format!("{name}.filter.rs"),
86 templates::filter(name),
87 ),
88 }
89}
90
91fn generate_module(base: &Path, name: &str, with_dto: bool) -> Result<()> {
92 let dir = base.join("src/modules").join(name);
93 fs::create_dir_all(&dir).with_context(|| format!("creating {}", dir.display()))?;
94 write_file(
95 &dir.join("mod.rs"),
96 &if with_dto {
97 templates::resource_mod_rs(name)
98 } else {
99 templates::module_mod_rs(name)
100 },
101 )?;
102 write_file(
103 &dir.join(format!("{name}.controller.rs")),
104 &templates::controller(name),
105 )?;
106 write_file(
107 &dir.join(format!("{name}.service.rs")),
108 &templates::service(name),
109 )?;
110 if with_dto {
111 write_file(&dir.join(format!("{name}.dto.rs")), &templates::dto(name))?;
112 }
113 Ok(())
114}
115
116fn generate_resource(base: &Path, name: &str) -> Result<()> {
117 generate_module(base, name, true)
118}
119
120fn generate_single_module_file(
121 base: &Path,
122 name: &str,
123 filename: String,
124 body: String,
125) -> Result<()> {
126 let dir = base.join("src/modules").join(name);
127 fs::create_dir_all(&dir).with_context(|| format!("creating {}", dir.display()))?;
128 write_file(&dir.join(filename), &body)
129}
130
131fn generate_shared(base: &Path, kind_dir: &str, filename: String, body: String) -> Result<()> {
132 let dir = base.join("src/shared").join(kind_dir);
133 fs::create_dir_all(&dir).with_context(|| format!("creating {}", dir.display()))?;
134 write_file(&dir.join(filename), &body)
135}
136
137fn write_file(path: &PathBuf, body: &str) -> Result<()> {
138 fs::write(path, body).with_context(|| format!("writing {}", path.display()))
139}