use crate::generators::rust::model::{Field, Model};
use std::fmt::Write as _;
pub(super) fn render(model: &Model) -> String {
let mut body = String::new();
for field in &model.fields {
if let Some(column) = &field.rename {
let _ = writeln!(body, "\t#[serde(rename = \"{column}\")]");
let _ = writeln!(body, "\t#[sqlx(rename = \"{column}\")]");
}
if let Some(ts) = field.mapping.ts {
let _ = writeln!(body, "\t#[ts(type = \"{ts}\")]");
}
let _ = writeln!(body, "\tpub {}: {},", field.ident, field.mapping.rust);
}
body
}
pub(super) fn imports(model: &Model) -> String {
let mut file = String::new();
if !model.view && model.fields.iter().any(seeds_from_clock) {
file.push_str("use chrono::Utc;\n");
}
file.push_str(
"use serde::{Deserialize, Serialize};\n\
use sqlx::FromRow;\n\
use ts_rs::TS;\n\
use utoipa::ToSchema;\n\n",
);
file
}
fn seeds_from_clock(field: &Field) -> bool {
if !is_timestamp(field) {
return false;
}
matches!(
inner_type(&field.mapping.rust),
"chrono::DateTime<chrono::Utc>" | "chrono::NaiveDateTime"
)
}
pub(super) fn inner_type(rust: &str) -> &str {
match rust
.strip_prefix("Option<")
.and_then(|rest| rest.strip_suffix('>'))
{
Some(inner) => inner,
None => rust,
}
}
pub(super) fn is_timestamp(field: &Field) -> bool {
matches!(field.column.as_str(), "created_at" | "updated_at")
}