use chrono::Utc; use rand::random; use uuid::Uuid; mod conn_provider; mod filter; mod helpers; pub mod models; mod pagination; pub mod repositories; mod transaction; mod value; pub use pagination::{Page, PageRequest}; // transaction! macro is exported via #[macro_export] in transaction.rs // Re-export the sqlx_record_derive module on feature flag #[cfg(feature = "derive")] pub use sqlx_record_derive::{Entity, Update}; /// Creates a time-ordered UUID with timestamp prefix for better database indexing. /// First 8 bytes: millisecond timestamp (big-endian) /// Last 8 bytes: random data #[inline] pub fn new_uuid() -> Uuid { let timestamp = Utc::now().timestamp_millis() as u64; let random = random::(); let mut bytes = [0u8; 16]; bytes[..8].copy_from_slice(×tamp.to_be_bytes()); bytes[8..].copy_from_slice(&random.to_be_bytes()); Uuid::from_bytes(bytes) } /// Creates a lookup table entity struct with an associated code enum. /// /// Generates: /// - A struct with `code`, `name`, `description`, and `is_active` fields /// - An enum `{Name}Code` with variants for each code /// - Constants on the struct for each code string /// - `Display` impl for the enum /// - `TryFrom<&str>` impl for the enum /// /// # Example /// ```ignore /// lookup_table!(UserStatus, "active", "inactive", "suspended"); /// // Creates: /// // - struct UserStatus { code, name, description, is_active } /// // - enum UserStatusCode { Active, Inactive, Suspended } /// // - UserStatus::ACTIVE, UserStatus::INACTIVE, UserStatus::SUSPENDED constants /// ``` #[macro_export] macro_rules! lookup_table { ($name:ident, $($code:literal),+ $(,)?) => { #[allow(dead_code)] #[derive(Debug, Clone, sqlx_record::Entity, sqlx::FromRow)] pub struct $name { #[primary_key] pub code: String, pub name: String, pub description: String, pub is_active: bool, } paste::paste! { #[allow(dead_code)] #[derive(Debug, Clone, PartialEq, Eq)] pub enum [<$name Code>] { $( #[allow(non_camel_case_types)] [<$code:camel>], )+ } impl std::fmt::Display for [<$name Code>] { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { $( [<$name Code>]::[<$code:camel>] => write!(f, $code), )+ } } } #[allow(dead_code)] impl $name { $( pub const [<$code:upper>]: &'static str = $code; )+ } impl TryFrom<&str> for [<$name Code>] { type Error = String; fn try_from(s: &str) -> Result { match s { $( $code => Ok([<$name Code>]::[<$code:camel>]), )+ _ => Err(format!("Unknown {} code: {}", stringify!($name).to_lowercase(), s)), } } } } }; } /// Creates a code enum without an associated entity struct. /// /// Use this when you need type-safe code constants but the lookup data /// is stored elsewhere or doesn't need CRUD operations. /// /// Generates: /// - An enum `{Name}Code` with variants for each code /// - Constants on a unit struct for each code string /// - `Display` impl for the enum /// - `TryFrom<&str>` impl for the enum /// /// # Example /// ```ignore /// lookup_options!(RefundPolicy, "pro-rata", "full-24-hours", "no-refunds"); /// // Creates: /// // - enum RefundPolicyCode { ProRata, Full24Hours, NoRefunds } /// // - RefundPolicy::PRO_RATA, RefundPolicy::FULL_24_HOURS, etc. /// ``` #[macro_export] macro_rules! lookup_options { ($name:ident, $($code:literal),+ $(,)?) => { paste::paste! { #[allow(dead_code)] #[derive(Debug, Clone, PartialEq, Eq)] pub enum [<$name Code>] { $( #[allow(non_camel_case_types)] [<$code:camel>], )+ } impl std::fmt::Display for [<$name Code>] { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { $( [<$name Code>]::[<$code:camel>] => write!(f, $code), )+ } } } /// Constants for code string values #[allow(dead_code)] pub struct $name; #[allow(dead_code)] impl $name { $( pub const [<$code:upper>]: &'static str = $code; )+ } impl TryFrom<&str> for [<$name Code>] { type Error = String; fn try_from(s: &str) -> Result { match s { $( $code => Ok([<$name Code>]::[<$code:camel>]), )+ _ => Err(format!("Unknown {} code: {}", stringify!($name).to_lowercase(), s)), } } } } }; } pub mod prelude { pub use crate::filter::*; pub use crate::pagination::{Page, PageRequest}; pub use crate::value::*; pub use crate::values; pub use crate::{filter_and as and, filter_or as or}; pub use crate::{filter_and, filter_or, filters, update_entity_func}; pub use crate::{lookup_options, lookup_table, new_uuid, transaction}; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub use crate::conn_provider::ConnProvider; #[cfg(feature = "derive")] pub use sqlx_record_derive::{Entity, Update}; }