restructure generator
This commit is contained in:
@@ -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::{
|
||||
|
||||
Reference in New Issue
Block a user