use indexmap::IndexMap;
use crate::tree::Tree;
pub struct RouteGenerator;
impl RouteGenerator {
pub fn generate(tree: &Tree) -> IndexMap<String, String> {
let mut routes = vec![
"use axum::{Router, routing::{get, post, put, delete}};".to_string(),
"use crate::handlers::prelude::*;".to_string(),
String::new(),
"pub fn app_router() -> Router {".to_string(),
" Router::new()".to_string(),
];
for controller in tree.all_controllers() {
let model_name = controller.name.trim_end_matches("Controller").to_string();
let handler_mod = crate::generators::model_generator::to_snake_case(&model_name);
let resource = pluralize(&handler_mod);
if controller.is_resource() {
let is_api = controller.is_api_resource();
if is_api {
routes.push(format!(
" .route(\"/{}\", get({}::handlers::{}::index).post({}::handlers::{}::store))",
resource, handler_mod, handler_mod, handler_mod, handler_mod
));
routes.push(format!(
" .route(\"/{{id}}\", get({}::handlers::{}::show).put({}::handlers::{}::update).delete({}::handlers::{}::destroy))",
resource, handler_mod, handler_mod, handler_mod, handler_mod, handler_mod
));
} else {
routes.push(format!(
" .route(\"/{}\", get({}::handlers::{}::index).post({}::handlers::{}::store))",
resource, handler_mod, handler_mod, handler_mod, handler_mod
));
routes.push(format!(
" .route(\"/{{id}}\", get({}::handlers::{}::show).put({}::handlers::{}::update).delete({}::handlers::{}::destroy))",
resource, handler_mod, handler_mod, handler_mod, handler_mod, handler_mod
));
routes.push(format!(
" .route(\"/{}/new\", get({}::handlers::{}::create))",
resource, handler_mod, handler_mod
));
routes.push(format!(
" .route(\"/{{id}}/edit\", get({}::handlers::{}::edit))",
resource, handler_mod
));
}
} else {
for (method_name, _) in &controller.methods {
let http_method = method_to_http(method_name);
let path = if *method_name == "index" {
format!("/{}", resource)
} else {
format!("/{}/{}", resource, method_name)
};
routes.push(format!(
" .route(\"{}\", {}({}::handlers::{}::{}))",
path, http_method, handler_mod, handler_mod, method_name
));
}
}
}
routes.push("}".to_string());
let mut files = IndexMap::new();
files.insert("src/routes.rs".to_string(), routes.join("\n"));
files
}
}
fn method_to_http(method: &str) -> &str {
match method {
"index" | "create" | "show" | "edit" => "get",
"store" => "post",
"update" => "put",
"destroy" => "delete",
_ => "get",
}
}
fn pluralize(s: &str) -> String {
if s.ends_with('s') || s.ends_with('x') || s.ends_with('z') || s.ends_with("ch") || s.ends_with("sh") {
format!("{}es", s)
} else if s.ends_with('y') && !s.ends_with("ay") && !s.ends_with("ey") && !s.ends_with("oy") && !s.ends_with("uy") {
format!("{}ies", &s[..s.len() - 1])
} else {
format!("{}s", s)
}
}