oximod 0.2.5

MongoDB ODM for Rust inspired by Mongoose
Documentation
//! Validation example for the oximod crate
//!
//! Run with: `cargo run --example validate_usage`
//!
//! This demonstrates how to:
//! - Connect to MongoDB
//! - Use the `Model` derive macro
//! - Apply validations like `min_length`, `email`, `positive`, `pattern`, etc.
//! - Use Rust enums instead of enum_values

use mongodb::bson::oid::ObjectId;
use oximod::{Model, OxiClient};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
enum Role {
    Admin,
    User,
    Guest,
}

#[derive(Debug, Serialize, Deserialize, Model)]
#[db("validation_example_db")]
#[collection("users")]
struct User {
    #[serde(skip_serializing_if = "Option::is_none")]
    _id: Option<ObjectId>,

    #[validate(min_length = 3, max_length = 15)]
    username: String,

    #[validate(email)]
    #[index(unique)]
    email: String,

    #[validate(positive)]
    age: i32,

    #[validate(non_empty)]
    bio: Option<String>,

    #[validate(pattern = r"^SKU-[0-9]{4}$")]
    sku: Option<String>,

    #[validate(non_negative)]
    points: i32,

    #[validate(required)]
    role: Option<Role>,

    #[default(false)]
    active: bool,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    dotenv::dotenv().ok();
    let mongodb_uri = std::env::var("MONGODB_URI")
        .expect("MONGODB_URI must be set in your .env file or environment");

    OxiClient::init_global(mongodb_uri).await?;

    // Clean up from previous runs
    User::clear().await?;

    println!("📥 Inserting a valid user...");
    let valid_user = User::new()
        .username("arshia")
        .email("arshia@example.com")
        .age(25)
        .bio("Rustacean and full-stack dev")
        .sku("SKU-1234")
        .points(0)
        .role(Role::User)
        .active(true);

    valid_user.save().await?;
    println!("✅ Valid user inserted successfully.");

    println!("⚠️ Inserting an invalid user...");
    let invalid_user = User::new()
        .username("ab") // too short
        .email("not-an-email")
        .age(-1) // not positive
        .bio("   ") // empty
        .sku("WRONGSKU") // invalid pattern
        .points(-3); // not non-negative

    match invalid_user.save().await {
        Ok(_) => println!("❌ Unexpected success!"),
        Err(e) => {
            println!("🛑 Validation failed as expected:");
            println!("{:#}", e);
        }
    }

    Ok(())
}