better_auth_entity_codegen/
accessors.rs1use super::*;
2#[expect(
4 clippy::too_many_lines,
5 reason = "Keep the generated AuthUser implementation together as one quoted trait contract"
6)]
7#[must_use]
8pub fn auth_user_impl(
9 ident: &Ident,
10 fields: &FieldsNamed,
11 entity_fields: &[EntityField],
12 secondary: bool,
13 core_root: &TokenStream,
14) -> TokenStream {
15 let has = |name: &str| has_field(fields, name);
16 let optional = |name: &str| optional_field(fields, name);
17 let secondary_codec = if secondary {
18 secondary_codec(fields, core_root)
19 } else {
20 quote! {}
21 };
22 let additional_output = additional_output(EntityRole::User, entity_fields, core_root);
23 let text_getter = |name: &str| {
24 let field = Ident::new(name, Span::call_site());
25 if optional(name) {
26 quote! { fn #field(&self) -> Option<&str> { self.#field.as_deref() } }
27 } else {
28 quote! { fn #field(&self) -> Option<&str> { Some(self.#field.as_str()) } }
29 }
30 };
31 let email_impl = text_getter("email");
32 let name_impl = text_getter("name");
33 let username_impl = if has("username") {
34 quote! { fn username(&self) -> Option<&str> { self.username.as_deref() } }
35 } else {
36 quote! { fn username(&self) -> Option<&str> { None } }
37 };
38 let display_username_impl = if has("display_username") {
39 quote! { fn display_username(&self) -> Option<&str> { self.display_username.as_deref() } }
40 } else {
41 quote! { fn display_username(&self) -> Option<&str> { None } }
42 };
43 let two_factor_impl = if has("two_factor_enabled") {
44 if optional("two_factor_enabled") {
45 quote! {
46 fn two_factor_enabled(&self) -> bool { self.two_factor_enabled.unwrap_or(false) }
47 fn two_factor_enabled_value(&self) -> Option<bool> { self.two_factor_enabled }
48 }
49 } else {
50 quote! { fn two_factor_enabled(&self) -> bool { self.two_factor_enabled } }
51 }
52 } else {
53 quote! {
54 fn two_factor_enabled(&self) -> bool { false }
55 fn two_factor_enabled_value(&self) -> Option<bool> { None }
56 }
57 };
58 let role_impl = if has("role") {
59 quote! { fn role(&self) -> Option<&str> { self.role.as_deref() } }
60 } else {
61 quote! { fn role(&self) -> Option<&str> { None } }
62 };
63 let banned_impl = if has("banned") {
64 if optional("banned") {
65 quote! {
66 fn banned(&self) -> bool { self.banned.unwrap_or(false) }
67 fn banned_value(&self) -> Option<bool> { self.banned }
68 }
69 } else {
70 quote! { fn banned(&self) -> bool { self.banned } }
71 }
72 } else {
73 quote! {
74 fn banned(&self) -> bool { false }
75 fn banned_value(&self) -> Option<bool> { None }
76 }
77 };
78 let ban_reason_impl = if has("ban_reason") {
79 quote! { fn ban_reason(&self) -> Option<&str> { self.ban_reason.as_deref() } }
80 } else {
81 quote! { fn ban_reason(&self) -> Option<&str> { None } }
82 };
83 let ban_expires_impl = if has("ban_expires") {
84 quote! { fn ban_expires(&self) -> Option<::chrono::DateTime<::chrono::Utc>> { #core_root::entity::AuthTimestamp::into_utc(self.ban_expires) } }
85 } else {
86 quote! { fn ban_expires(&self) -> Option<::chrono::DateTime<::chrono::Utc>> { None } }
87 };
88 let metadata_impl = if has("metadata") {
89 quote! { fn metadata(&self) -> &::serde_json::Value { &self.metadata } }
90 } else {
91 quote! { fn metadata(&self) -> &::serde_json::Value {
92 static EMPTY: ::std::sync::LazyLock<::serde_json::Value> =
93 ::std::sync::LazyLock::new(|| ::serde_json::json!({}));
94 &EMPTY
95 } }
96 };
97 let mut optional_user_getters = Vec::new();
98 for name in ["is_anonymous", "phone_number_verified"] {
99 if has(name) {
100 let field = Ident::new(name, Span::call_site());
101 optional_user_getters.push(quote! { fn #field(&self) -> Option<bool> { self.#field } });
102 }
103 }
104 for name in ["phone_number", "last_login_method"] {
105 if has(name) {
106 let field = Ident::new(name, Span::call_site());
107 optional_user_getters
108 .push(quote! { fn #field(&self) -> Option<&str> { self.#field.as_deref() } });
109 }
110 }
111 quote! {
112 impl #core_root::entity::AuthUser for #ident {
113 #secondary_codec
114 #additional_output
115 fn id(&self) -> ::std::borrow::Cow<'_, str> { ::std::borrow::Cow::Borrowed(&self.id) }
116 #email_impl
117 #name_impl
118 fn email_verified(&self) -> bool { self.email_verified }
119 fn image(&self) -> Option<&str> { self.image.as_deref() }
120 fn created_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.created_at) }
121 fn updated_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.updated_at) }
122 #username_impl
123 #display_username_impl
124 #two_factor_impl
125 #role_impl
126 #banned_impl
127 #ban_reason_impl
128 #ban_expires_impl
129 #metadata_impl
130 #(#optional_user_getters)*
131 }
132 }
133}
134
135#[must_use]
137pub fn auth_session_impl(
138 ident: &Ident,
139 fields: &FieldsNamed,
140 entity_fields: &[EntityField],
141 secondary: bool,
142 core_root: &TokenStream,
143) -> TokenStream {
144 let has = |name: &str| has_field(fields, name);
145 let secondary_codec = if secondary {
146 secondary_codec(fields, core_root)
147 } else {
148 quote! {}
149 };
150 let additional_output = additional_output(EntityRole::Session, entity_fields, core_root);
151 let impersonated_by_impl = if has("impersonated_by") {
152 quote! { fn impersonated_by(&self) -> Option<&str> { self.impersonated_by.as_deref() } }
153 } else {
154 quote! { fn impersonated_by(&self) -> Option<&str> { None } }
155 };
156 let active_org_impl = if has("active_organization_id") {
157 quote! { fn active_organization_id(&self) -> Option<&str> { self.active_organization_id.as_deref() } }
158 } else {
159 quote! { fn active_organization_id(&self) -> Option<&str> { None } }
160 };
161 let active_team_impl = if has("active_team_id") {
162 quote! { fn active_team_id(&self) -> Option<&str> { self.active_team_id.as_deref() } }
163 } else {
164 quote! {}
165 };
166 quote! {
167 impl #core_root::entity::AuthSession for #ident {
168 #secondary_codec
169 #additional_output
170 fn id(&self) -> ::std::borrow::Cow<'_, str> { ::std::borrow::Cow::Borrowed(&self.id) }
171 fn expires_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.expires_at) }
172 fn token(&self) -> &str { &self.token }
173 fn created_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.created_at) }
174 fn updated_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.updated_at) }
175 fn ip_address(&self) -> Option<&str> { self.ip_address.as_deref() }
176 fn user_agent(&self) -> Option<&str> { self.user_agent.as_deref() }
177 fn user_id(&self) -> ::std::borrow::Cow<'_, str> { ::std::borrow::Cow::Borrowed(&self.user_id) }
178 #impersonated_by_impl
179 #active_org_impl
180 #active_team_impl
181 fn active(&self) -> bool { self.active }
182 }
183 }
184}
185
186#[must_use]
188pub fn auth_account_impl(
189 ident: &Ident,
190 entity_fields: &[EntityField],
191 core_root: &TokenStream,
192) -> TokenStream {
193 let additional_output = additional_output(EntityRole::Account, entity_fields, core_root);
194 quote! {
195 impl #core_root::entity::AuthAccount for #ident {
196 #additional_output
197 fn id(&self) -> ::std::borrow::Cow<'_, str> { ::std::borrow::Cow::Borrowed(&self.id) }
198 fn account_id(&self) -> &str { &self.account_id }
199 fn provider_id(&self) -> &str { &self.provider_id }
200 fn user_id(&self) -> ::std::borrow::Cow<'_, str> { ::std::borrow::Cow::Borrowed(&self.user_id) }
201 fn access_token(&self) -> Option<&str> { self.access_token.as_deref() }
202 fn refresh_token(&self) -> Option<&str> { self.refresh_token.as_deref() }
203 fn id_token(&self) -> Option<&str> { self.id_token.as_deref() }
204 fn access_token_expires_at(&self) -> Option<::chrono::DateTime<::chrono::Utc>> { #core_root::entity::AuthTimestamp::into_utc(self.access_token_expires_at) }
205 fn refresh_token_expires_at(&self) -> Option<::chrono::DateTime<::chrono::Utc>> { #core_root::entity::AuthTimestamp::into_utc(self.refresh_token_expires_at) }
206 fn scope(&self) -> Option<&str> { self.scope.as_deref() }
207 fn password(&self) -> Option<&str> { self.password.as_deref() }
208 fn created_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.created_at) }
209 fn updated_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.updated_at) }
210 }
211 }
212}
213
214#[must_use]
216pub fn auth_verification_impl(ident: &Ident, core_root: &TokenStream) -> TokenStream {
217 quote! {
218 impl #core_root::entity::AuthVerification for #ident {
219 fn id(&self) -> ::std::borrow::Cow<'_, str> { ::std::borrow::Cow::Borrowed(&self.id) }
220 fn identifier(&self) -> &str { &self.identifier }
221 fn value(&self) -> &str { &self.value }
222 fn expires_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.expires_at) }
223 fn created_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.created_at) }
224 fn updated_at(&self) -> ::chrono::DateTime<::chrono::Utc> { #core_root::entity::AuthTimestamp::into_utc(self.updated_at) }
225 }
226 }
227}