pub mod api;
pub mod htmx;
pub mod microservice;
pub mod minimal;
pub mod saas;
use std::path::Path;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Template {
Api,
Saas,
Htmx,
Microservice,
Minimal,
}
impl Template {
pub fn from_str(s: &str) -> anyhow::Result<Self> {
match s {
"api" => Ok(Self::Api),
"saas" => Ok(Self::Saas),
"htmx" => Ok(Self::Htmx),
"microservice" => Ok(Self::Microservice),
"minimal" => Ok(Self::Minimal),
_ => anyhow::bail!(
"Unknown template '{s}'. Valid options: api, saas, htmx, microservice, minimal"
),
}
}
pub fn label(&self) -> &'static str {
match self {
Self::Api => "api",
Self::Saas => "saas",
Self::Htmx => "htmx",
Self::Microservice => "microservice",
Self::Minimal => "minimal",
}
}
pub fn handles_directory_creation(&self) -> bool {
matches!(self, Self::Api)
}
pub fn generate(&self, project_name: &str, root: &Path) -> anyhow::Result<()> {
match self {
Self::Api => api::generate(project_name, root),
Self::Saas => saas::generate(project_name, root),
Self::Htmx => htmx::generate(project_name, root),
Self::Microservice => microservice::generate(project_name, root),
Self::Minimal => minimal::generate(project_name, root),
}
}
}
pub fn prompt_template() -> anyhow::Result<Template> {
use dialoguer::Select;
let items = &[
"api REST API with JWT auth + CRUD ready",
"saas Multi-tenant SaaS (magic link, billing hooks)",
"htmx Full-stack with Htmx + Minijinja templates",
"microservice Minimal service with health endpoint + Docker",
"minimal Bare skeleton (axum + sqlx only)",
];
let sel = Select::new()
.with_prompt("Choose a template")
.items(items)
.default(0)
.interact()?;
Ok(match sel {
0 => Template::Api,
1 => Template::Saas,
2 => Template::Htmx,
3 => Template::Microservice,
_ => Template::Minimal,
})
}