mod columns;
mod entities;
mod model;
mod roots;
use alibi_entity_codegen::{self as codegen, EntityRole};
use columns::{columns, table_attribute};
use entities::{account_impl, session_impl, user_impl, verification_impl};
use model::model_impl;
use proc_macro::TokenStream as ProcMacroTokenStream;
use proc_macro2::TokenStream;
use quote::quote;
use roots::resolve_roots;
use syn::{DeriveInput, parse_macro_input};
fn try_generate_model(input: &DeriveInput) -> syn::Result<TokenStream> {
let roots = resolve_roots();
let table = table_attribute(input)?;
let fields = codegen::named_fields(input)?;
let columns = columns(input, fields)?;
model_impl(&input.ident, &table, &columns, None, &roots)
}
fn try_generate_entity(input: &DeriveInput) -> syn::Result<TokenStream> {
let mut roots = resolve_roots();
let attributes = codegen::parse_auth_attributes(input, true)?;
roots.id_generator = codegen::generated_id(&attributes, &roots.core);
let fields = codegen::named_fields(input)?;
codegen::validate_core_fields(input, attributes.role, fields)?;
let columns = columns(input, fields)?;
let entity_fields: Vec<codegen::EntityField> = columns
.iter()
.map(|column| codegen::EntityField {
ident: column.ident.clone(),
camel: column.camel.clone(),
physical: column.renamed.then(|| column.physical.clone()),
})
.collect();
let ident = &input.ident;
let table = attributes.table.clone().unwrap_or_else(|| {
match attributes.role {
EntityRole::User => "user",
EntityRole::Session => "session",
EntityRole::Account => "account",
EntityRole::Verification => "verification",
}
.to_owned()
});
let model = model_impl(ident, &table, &columns, Some(attributes.role), &roots)?;
let secondary = attributes.secondary_storage;
let core_root = &roots.core;
let role_impl = match attributes.role {
EntityRole::User => {
let auth = codegen::auth_user_impl(ident, fields, &entity_fields, secondary, core_root);
let model = user_impl(ident, fields, &columns, &roots)?;
quote! { #auth #model }
}
EntityRole::Session => {
let auth =
codegen::auth_session_impl(ident, fields, &entity_fields, secondary, core_root);
let model = session_impl(ident, fields, &columns, &roots)?;
quote! { #auth #model }
}
EntityRole::Account => {
let auth = codegen::auth_account_impl(ident, &entity_fields, core_root);
let model = account_impl(ident, fields, &columns, &roots)?;
quote! { #auth #model }
}
EntityRole::Verification => {
let auth = codegen::auth_verification_impl(ident, core_root);
let model = verification_impl(ident, fields, &columns, &roots)?;
quote! { #auth #model }
}
};
Ok(quote! { #model #role_impl })
}
#[proc_macro_derive(AuthEntity, attributes(auth))]
pub fn derive_auth_entity(input: ProcMacroTokenStream) -> ProcMacroTokenStream {
let input = parse_macro_input!(input as DeriveInput);
try_generate_entity(&input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
#[proc_macro_derive(SqlxModel, attributes(auth))]
pub fn derive_sqlx_model(input: ProcMacroTokenStream) -> ProcMacroTokenStream {
let input = parse_macro_input!(input as DeriveInput);
try_generate_model(&input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}