1mod columns;
3mod entities;
4mod model;
5mod roots;
6
7use alibi_entity_codegen::{self as codegen, EntityRole, Insert};
8use columns::Column;
9use columns::column_of;
10use columns::columns;
11use columns::physical;
12use columns::table_attribute;
13use entities::account_impl;
14use entities::session_impl;
15use entities::user_impl;
16use entities::verification_impl;
17use model::additional_fields;
18use model::model_impl;
19use proc_macro::TokenStream as ProcMacroTokenStream;
20use proc_macro_crate::{FoundCrate, crate_name};
21use proc_macro2::{Ident, Span, TokenStream};
22use quote::quote;
23use roots::Roots;
24use roots::resolve_roots;
25use syn::{DeriveInput, FieldsNamed, LitStr, parse_macro_input};
26
27fn try_generate_model(input: &DeriveInput) -> syn::Result<TokenStream> {
28 let roots = resolve_roots();
29 let table = table_attribute(input)?;
30 let fields = codegen::named_fields(input)?;
31 let columns = columns(input, fields)?;
32 model_impl(&input.ident, &table, &columns, None, &roots)
33}
34
35fn try_generate_entity(input: &DeriveInput) -> syn::Result<TokenStream> {
36 let mut roots = resolve_roots();
37 let attributes = codegen::parse_auth_attributes(input, true)?;
38 roots.id_generator = codegen::generated_id(&attributes, &roots.core);
39 let fields = codegen::named_fields(input)?;
40 codegen::validate_core_fields(input, attributes.role, fields)?;
41 let columns = columns(input, fields)?;
42 let entity_fields: Vec<codegen::EntityField> = columns
43 .iter()
44 .map(|column| codegen::EntityField {
45 ident: column.ident.clone(),
46 camel: column.camel.clone(),
47 physical: column.renamed.then(|| column.physical.clone()),
48 })
49 .collect();
50 let ident = &input.ident;
51 let table = attributes.table.clone().unwrap_or_else(|| {
52 match attributes.role {
53 EntityRole::User => "users",
54 EntityRole::Session => "sessions",
55 EntityRole::Account => "accounts",
56 EntityRole::Verification => "verifications",
57 }
58 .to_owned()
59 });
60 let model = model_impl(ident, &table, &columns, Some(attributes.role), &roots)?;
61 let secondary = attributes.secondary_storage;
62 let core_root = &roots.core;
63 let role_impl = match attributes.role {
64 EntityRole::User => {
65 let auth = codegen::auth_user_impl(ident, fields, &entity_fields, secondary, core_root);
66 let model = user_impl(ident, fields, &columns, &roots)?;
67 quote! { #auth #model }
68 }
69 EntityRole::Session => {
70 let auth =
71 codegen::auth_session_impl(ident, fields, &entity_fields, secondary, core_root);
72 let model = session_impl(ident, fields, &columns, &roots)?;
73 quote! { #auth #model }
74 }
75 EntityRole::Account => {
76 let auth = codegen::auth_account_impl(ident, &entity_fields, core_root);
77 let model = account_impl(ident, fields, &columns, &roots)?;
78 quote! { #auth #model }
79 }
80 EntityRole::Verification => {
81 let auth = codegen::auth_verification_impl(ident, core_root);
82 let model = verification_impl(ident, fields, &columns, &roots)?;
83 quote! { #auth #model }
84 }
85 };
86 Ok(quote! { #model #role_impl })
87}
88
89#[proc_macro_derive(AuthEntity, attributes(auth))]
119pub fn derive_auth_entity(input: ProcMacroTokenStream) -> ProcMacroTokenStream {
120 let input = parse_macro_input!(input as DeriveInput);
121 try_generate_entity(&input)
122 .unwrap_or_else(syn::Error::into_compile_error)
123 .into()
124}
125
126#[proc_macro_derive(SqlxModel, attributes(auth))]
134pub fn derive_sqlx_model(input: ProcMacroTokenStream) -> ProcMacroTokenStream {
135 let input = parse_macro_input!(input as DeriveInput);
136 try_generate_model(&input)
137 .unwrap_or_else(syn::Error::into_compile_error)
138 .into()
139}