restructure generator

This commit is contained in:
2025-04-08 22:03:18 +04:00
parent 3ed3e079f2
commit 8fd390fe18
25 changed files with 595 additions and 377 deletions

View File

@@ -1,27 +1,167 @@
use super::{Module, ModulesContext};
use color_eyre::Result;
use serde::Deserialize;
use std::path::PathBuf;
use crate::generator::file::pathbuf_to_rust_path;
use super::{
discovery::DiscoveredSchema, sea_orm::SeaOrmConfig, templates::TemplateConfig, Module,
ModulesContext,
};
use color_eyre::{
eyre::{eyre, Context, ContextCompat},
Result,
};
use handlebars::Handlebars;
use heck::ToPascalCase;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize)]
#[serde(default)]
pub struct ModelsConfig {
pub enable: bool,
pub database_schema: String,
pub max_connections: u32,
pub acquire_timeout: u32,
pub path: Option<PathBuf>,
pub prelude: bool,
}
// #[derive(Debug)]
// pub struct ModelsModule;
//
// #[async_trait::async_trait]
// impl Module for ModelsModule {
// fn init(&self, ctx: &mut ModulesContext) -> Result<()> {
// Ok(())
// }
//
// async fn validate(&self, ctx: &mut ModulesContext) -> Result<bool> {
// Ok(false)
// }
// }
impl Default for ModelsConfig {
fn default() -> Self {
Self {
enable: false,
path: None,
prelude: true,
}
}
}
#[derive(Debug, Clone, Serialize)]
pub struct ModelTemplateContext {
entities_path: String,
model_path: String,
model_name: String,
entity_name: String,
active_model_name: String,
prelude_path: String,
}
impl ModelTemplateContext {
pub fn new(entities_path: String, model_name: String, prelude_path: String) -> Self {
let model_path = model_name.clone();
let active_model_name = format!("{}ActiveModel", model_name).to_pascal_case();
let model_name = format!("{}Model", model_name).to_pascal_case();
let entity_name = model_path.clone().to_pascal_case();
Self {
entities_path,
model_path,
model_name,
active_model_name,
prelude_path,
entity_name,
}
}
}
#[derive(Debug)]
pub struct ModelsModule;
#[async_trait::async_trait]
impl Module for ModelsModule {
fn init(&mut self, ctx: &mut ModulesContext) -> Result<()> {
ctx.get_config_auto::<ModelsConfig>("modules.model")?;
Ok(())
}
async fn validate(&mut self, ctx: &mut ModulesContext) -> Result<bool> {
let map = ctx.get_anymap();
if let (Some(config), Some(template_config), Some(sea_orm_config)) = (
map.get::<ModelsConfig>(),
map.get::<TemplateConfig>(),
map.get::<SeaOrmConfig>(),
) {
if config.enable && !template_config.enable {
return Err(eyre!(
"\"modules.template.enable\" must be enabled to use \"modules.model.enable\""
));
}
if config.enable && !sea_orm_config.enable {
return Err(eyre!(
"\"modules.sea_orm.enable\" must be enabled to use \"modules.model.enable\""
));
}
if config.enable && config.path.is_none() {
return Err(eyre!(
"\"modules.model.path\" must be set to use \"modules.model.enable\""
));
}
Ok(config.enable && template_config.enable)
} else {
// One or both keys are missing
Ok(false)
}
}
async fn execute(&mut self, ctx: &mut ModulesContext) -> Result<()> {
let mut files: Vec<(PathBuf, String)> = Vec::new();
let map = ctx.get_anymap();
if let (Some(config), Some(templates), Some(sea_orm_config), Some(schema)) = (
map.get::<ModelsConfig>(),
map.get::<Handlebars<'static>>(),
map.get::<SeaOrmConfig>(),
map.get::<DiscoveredSchema>(),
) {
let models_path = config.path.clone().unwrap();
tracing::info!(?models_path, "Models path");
let entities_path = sea_orm_config.path.clone().unwrap();
let mod_path = models_path.join("mod.rs");
if config.prelude {
files.push((mod_path.clone(), "pub mod prelude;".to_string()));
}
for table in &schema.tables {
tracing::debug!(?table, "Generating model for table");
let path = models_path.join(format!("{}.rs", table.name));
let relative_entities_path = pathdiff::diff_paths(&entities_path, &path)
.context("Failed to calculate relative path")?;
let relative_entities_rust_path = pathbuf_to_rust_path(relative_entities_path);
let context = ModelTemplateContext::new(
relative_entities_rust_path.clone(),
table.name.clone(),
"super::prelude".to_string(),
);
if config.prelude {
let prelude_part = templates
.render("model_prelude_part", &context)
.context("Failed to render model prelude part")?;
files.push((models_path.join("prelude.rs"), prelude_part.clone()));
}
files.push((mod_path.clone(), format!("pub mod {};", table.name)));
if path.exists() {
tracing::debug!(?path, "Model file already exists");
continue;
}
if config.prelude {
let content = templates
.render("model_prelude", &context)
.context("Failed to render model prelude")?;
files.push((path.clone(), content.clone()));
} else {
let content = templates
.render("model", &context)
.context("Failed to render model")?;
files.push((path.clone(), content.clone()));
}
}
} else {
// One or both keys are missing
}
tracing::info!(?files, "Generated model files");
let file_manager = ctx.get_file_manager();
for (output_path, content) in files {
file_manager.insert(&output_path, &content, None)?;
}
Ok(())
}
}
//
//
// use crate::{