use std::fs;
use std::path::{Path, PathBuf};
use anyhow::{Context, Result, bail};
use crate::cli::GenerateKind;
use crate::templates;
pub fn new_project(base: &Path, name: &str) -> Result<()> {
let root = base.join(name);
if root.exists() {
bail!("target directory '{}' already exists", root.display());
}
fs::create_dir_all(root.join("src/modules"))
.with_context(|| format!("creating src/modules in {}", root.display()))?;
fs::create_dir_all(root.join("src/shared"))
.with_context(|| format!("creating src/shared in {}", root.display()))?;
write_file(
&root.join("Cargo.toml"),
&templates::project_cargo_toml(name),
)?;
write_file(
&root.join("serverust.toml"),
&templates::project_serverust_toml(name),
)?;
write_file(&root.join("src/main.rs"), &templates::project_main_rs())?;
write_file(
&root.join("src/modules/mod.rs"),
&templates::project_modules_mod_rs(),
)?;
write_file(
&root.join("src/shared/mod.rs"),
&templates::project_shared_mod_rs(),
)?;
Ok(())
}
pub fn generate(base: &Path, kind: GenerateKind, name: &str) -> Result<()> {
match kind {
GenerateKind::Resource => generate_resource(base, name),
GenerateKind::Module => generate_module(base, name, false),
GenerateKind::Controller => generate_single_module_file(
base,
name,
format!("{name}.controller.rs"),
templates::controller(name),
),
GenerateKind::Service => generate_single_module_file(
base,
name,
format!("{name}.service.rs"),
templates::service(name),
),
GenerateKind::Pipe => generate_shared(
base,
"pipes",
format!("{name}.pipe.rs"),
templates::pipe(name),
),
GenerateKind::Guard => generate_shared(
base,
"guards",
format!("{name}.guard.rs"),
templates::guard(name),
),
GenerateKind::Interceptor => generate_shared(
base,
"interceptors",
format!("{name}.interceptor.rs"),
templates::interceptor(name),
),
GenerateKind::Filter => generate_shared(
base,
"filters",
format!("{name}.filter.rs"),
templates::filter(name),
),
}
}
fn generate_module(base: &Path, name: &str, with_dto: bool) -> Result<()> {
let dir = base.join("src/modules").join(name);
fs::create_dir_all(&dir).with_context(|| format!("creating {}", dir.display()))?;
write_file(
&dir.join("mod.rs"),
&if with_dto {
templates::resource_mod_rs(name)
} else {
templates::module_mod_rs(name)
},
)?;
write_file(
&dir.join(format!("{name}.controller.rs")),
&templates::controller(name),
)?;
write_file(
&dir.join(format!("{name}.service.rs")),
&templates::service(name),
)?;
if with_dto {
write_file(&dir.join(format!("{name}.dto.rs")), &templates::dto(name))?;
}
Ok(())
}
fn generate_resource(base: &Path, name: &str) -> Result<()> {
generate_module(base, name, true)
}
fn generate_single_module_file(
base: &Path,
name: &str,
filename: String,
body: String,
) -> Result<()> {
let dir = base.join("src/modules").join(name);
fs::create_dir_all(&dir).with_context(|| format!("creating {}", dir.display()))?;
write_file(&dir.join(filename), &body)
}
fn generate_shared(base: &Path, kind_dir: &str, filename: String, body: String) -> Result<()> {
let dir = base.join("src/shared").join(kind_dir);
fs::create_dir_all(&dir).with_context(|| format!("creating {}", dir.display()))?;
write_file(&dir.join(filename), &body)
}
fn write_file(path: &PathBuf, body: &str) -> Result<()> {
fs::write(path, body).with_context(|| format!("writing {}", path.display()))
}