1mod columns;
3mod entities;
4mod model;
5mod roots;
6
7use alibi_entity_codegen::{self as codegen, EntityRole};
8use columns::{columns, table_attribute};
9use entities::{account_impl, session_impl, user_impl, verification_impl};
10use model::model_impl;
11use proc_macro::TokenStream as ProcMacroTokenStream;
12use proc_macro2::TokenStream;
13use quote::quote;
14use roots::resolve_roots;
15use syn::{DeriveInput, parse_macro_input};
16
17fn try_generate_model(input: &DeriveInput) -> syn::Result<TokenStream> {
18 let roots = resolve_roots();
19 let table = table_attribute(input)?;
20 let fields = codegen::named_fields(input)?;
21 let columns = columns(input, fields)?;
22 model_impl(&input.ident, &table, &columns, None, &roots)
23}
24
25fn try_generate_entity(input: &DeriveInput) -> syn::Result<TokenStream> {
26 let mut roots = resolve_roots();
27 let attributes = codegen::parse_auth_attributes(input, true)?;
28 roots.id_generator = codegen::generated_id(&attributes, &roots.core);
29 let fields = codegen::named_fields(input)?;
30 codegen::validate_core_fields(input, attributes.role, fields)?;
31 let columns = columns(input, fields)?;
32 let entity_fields: Vec<codegen::EntityField> = columns
33 .iter()
34 .map(|column| codegen::EntityField {
35 ident: column.ident.clone(),
36 camel: column.camel.clone(),
37 physical: column.renamed.then(|| column.physical.clone()),
38 })
39 .collect();
40 let ident = &input.ident;
41 let table = attributes.table.clone().unwrap_or_else(|| {
42 match attributes.role {
43 EntityRole::User => "user",
44 EntityRole::Session => "session",
45 EntityRole::Account => "account",
46 EntityRole::Verification => "verification",
47 }
48 .to_owned()
49 });
50 let model = model_impl(ident, &table, &columns, Some(attributes.role), &roots)?;
51 let secondary = attributes.secondary_storage;
52 let core_root = &roots.core;
53 let role_impl = match attributes.role {
54 EntityRole::User => {
55 let auth = codegen::auth_user_impl(ident, fields, &entity_fields, secondary, core_root);
56 let model = user_impl(ident, fields, &columns, &roots)?;
57 quote! { #auth #model }
58 }
59 EntityRole::Session => {
60 let auth =
61 codegen::auth_session_impl(ident, fields, &entity_fields, secondary, core_root);
62 let model = session_impl(ident, fields, &columns, &roots)?;
63 quote! { #auth #model }
64 }
65 EntityRole::Account => {
66 let auth = codegen::auth_account_impl(ident, &entity_fields, core_root);
67 let model = account_impl(ident, fields, &columns, &roots)?;
68 quote! { #auth #model }
69 }
70 EntityRole::Verification => {
71 let auth = codegen::auth_verification_impl(ident, core_root);
72 let model = verification_impl(ident, fields, &columns, &roots)?;
73 quote! { #auth #model }
74 }
75 };
76 Ok(quote! { #model #role_impl })
77}
78
79#[proc_macro_derive(AuthEntity, attributes(auth))]
109pub fn derive_auth_entity(input: ProcMacroTokenStream) -> ProcMacroTokenStream {
110 let input = parse_macro_input!(input as DeriveInput);
111 try_generate_entity(&input)
112 .unwrap_or_else(syn::Error::into_compile_error)
113 .into()
114}
115
116#[proc_macro_derive(SqlxModel, attributes(auth))]
124pub fn derive_sqlx_model(input: ProcMacroTokenStream) -> ProcMacroTokenStream {
125 let input = parse_macro_input!(input as DeriveInput);
126 try_generate_model(&input)
127 .unwrap_or_else(syn::Error::into_compile_error)
128 .into()
129}