pub mod ai_ops;
pub mod column_enum;
pub mod crud_ops;
pub mod json_ops;
pub mod query_ops;
pub mod redis_ops;
mod save_entrypoints;
pub mod update_builder;
use crate::parser::{EncryptedFieldKind, ParsedModel};
use proc_macro2::TokenStream;
use quote::quote;
pub use ai_ops::generate_ai_methods;
pub use column_enum::generate_column_enum;
pub use crud_ops::{generate_delete_methods, generate_save_method};
pub use json_ops::generate_json_methods;
pub use query_ops::{generate_query_methods, generate_search_method};
pub use redis_ops::generate_redis_hash_methods;
pub use update_builder::generate_update_builder;
pub fn generate(parsed: &ParsedModel, relationship_methods: &[TokenStream]) -> TokenStream {
let name = &parsed.name;
let table_name = &parsed.table_name;
let builder_name = quote::format_ident!("{}QueryBuilder", name);
let observer_trait_name = quote::format_ident!("{}Observer", name);
let enum_def = generate_column_enum(parsed);
let json_methods = generate_json_methods(parsed);
let search_method = generate_search_method(parsed, &builder_name);
let save_method = generate_save_method(parsed);
let delete_methods = generate_delete_methods(parsed);
let query_methods = generate_query_methods(parsed, &builder_name);
let (update_builder_struct, update_builder_method) = generate_update_builder(parsed);
let redis_methods = generate_redis_hash_methods(parsed);
let ai_methods = generate_ai_methods(parsed);
let decrypt_encrypted_fields = parsed.encrypted_fields.iter().map(|field| {
let field_name = &field.name;
let column_name = field_name.to_string();
match field.kind {
EncryptedFieldKind::String => quote! {
self.#field_name = rullst_orm::privacy::decrypt_model_field(
&self.#field_name,
#table_name,
#column_name,
)?;
},
EncryptedFieldKind::OptionalString => quote! {
if let Some(encrypted_value) = self.#field_name.as_deref() {
self.#field_name = Some(rullst_orm::privacy::decrypt_model_field(
encrypted_value,
#table_name,
#column_name,
)?);
}
},
}
});
quote! {
#enum_def
#update_builder_struct
#ai_methods
#[rullst_orm::async_trait]
impl rullst_orm::RullstModel for #name {
fn table_name() -> &'static str {
#table_name
}
}
impl #name {
#(#relationship_methods)*
fn __rullst_decrypt_encrypted_fields(&mut self) -> Result<(), rullst_orm::Error> {
#(#decrypt_encrypted_fields)*
Ok(())
}
#json_methods
pub fn observe(observer: std::sync::Arc<dyn #observer_trait_name + Send + Sync>) {
let list = Self::observers();
let mut writer = list.write().unwrap_or_else(|poisoned| poisoned.into_inner());
writer.push(observer);
}
fn observers() -> &'static std::sync::RwLock<Vec<std::sync::Arc<dyn #observer_trait_name + Send + Sync>>> {
static LIST: std::sync::OnceLock<std::sync::RwLock<Vec<std::sync::Arc<dyn #observer_trait_name + Send + Sync>>>> = std::sync::OnceLock::new();
LIST.get_or_init(|| std::sync::RwLock::new(vec![]))
}
#search_method
#query_methods
#update_builder_method
#save_method
#delete_methods
#redis_methods
}
}
}