use cratestack_core::Model;
use quote::quote;
use crate::shared::{
ident, model_name_set, relation_model_fields, scalar_model_fields, to_snake_case,
};
use super::types::relation_link;
pub(crate) fn order_catalog_ident(model_name: &str) -> syn::Ident {
ident(&format!(
"{}_ORDER_CATALOG",
to_snake_case(model_name).to_uppercase()
))
}
pub(crate) fn generate_model_order_catalog(
model: &Model,
models: &[Model],
) -> Result<proc_macro2::TokenStream, String> {
let model_names = model_name_set(models);
let catalog_ident = order_catalog_ident(&model.name);
let scalars = scalar_model_fields(model, &model_names)
.into_iter()
.map(|field| {
let api_name = &field.name;
let column = to_snake_case(&field.name);
quote! { (#api_name, #column) }
})
.collect::<Vec<_>>();
let relations = relation_model_fields(model, &model_names)
.into_iter()
.map(|relation_field| {
let link = relation_link(model, relation_field, models)?;
if link.is_to_many {
return Ok(None);
}
let api_name = &relation_field.name;
let parent_table = link.parent_table.as_str();
let parent_column = link.parent_column.as_str();
let related_table = link.related_table.as_str();
let related_column = link.related_column.as_str();
let target_catalog_ident = order_catalog_ident(&relation_field.ty.name);
Ok(Some(quote! {
::cratestack::OrderRelationEdge {
api_name: #api_name,
hop: ::cratestack::RelationHop::new(
#parent_table,
#parent_column,
#related_table,
#related_column,
::cratestack::RelationQuantifier::ToOne,
),
target: &#target_catalog_ident,
}
}))
})
.collect::<Result<Vec<_>, String>>()?
.into_iter()
.flatten()
.collect::<Vec<_>>();
Ok(quote! {
static #catalog_ident: ::cratestack::OrderCatalog = ::cratestack::OrderCatalog {
scalars: &[#(#scalars),*],
relations: &[#(#relations),*],
};
})
}