42 releases (7 breaking)

new 0.8.4 Jan 9, 2025
0.8.3 Dec 20, 2024
0.7.2 Nov 26, 2024
0.5.2 Jul 19, 2024

#513 in Database interfaces

Download history 269/week @ 2024-09-20 411/week @ 2024-09-27 28/week @ 2024-10-04 168/week @ 2024-10-11 54/week @ 2024-10-18 36/week @ 2024-10-25 33/week @ 2024-11-01 6/week @ 2024-11-08 141/week @ 2024-11-15 443/week @ 2024-11-22 205/week @ 2024-11-29 356/week @ 2024-12-06 173/week @ 2024-12-13 288/week @ 2024-12-20 50/week @ 2024-12-27 77/week @ 2025-01-03

605 downloads per month
Used in 4 crates

MIT license

255KB
4K SLoC

GeekORM

GitHub Crates.io Version Crates.io Downloads (recent) GitHub Stars GitHub Issues Licence

Overview

GeekORM is a simple Object Relation Mapper for empowering your Rust development.

✨ Features

  • Focus on simplicity
  • Rely on Derive Macros to generate code for your structs
    • Using Table
    • Using Data
  • Dynamically build queries
    • Select, Create, Update, and Insert queries
  • Extensive crate features
  • Field Attribute Helpers
    • foreign_key: Set the foreign key for a join
    • rand: Generate random strings (set lenght, set prefix, set enviroment)
    • hash or password: Generate secure Hashes of passwords (set algorithm)
  • Support for Backends
  • Documentation

📦 Usage

You can install the library from crates.io:

cargo add geekorm

Manual - GitHub

cargo install --git https://github.com/42ByteLabs/geekorm

🏃 Getting Started

Once you have installed geekorm, you can start using the derive macros like the following:

use anyhow::Result;
use geekorm::prelude::*;

#[derive(Table, Debug, Default, serde::Serialize, serde::Deserialize)]
struct Users {
    #[geekorm(primary_key, auto_increment)]
    id: PrimaryKeyInteger,
    /// Unique username field
    #[geekorm(unique)]
    username: String,
    /// Password field with automatic hashing
    #[geekorm(hash)]
    password: String,
    /// User Type Enum (defaults to `User`)
    #[geekorm(new = "UserType::User")]
    user_type: UserType,
    /// Optional postcode field (nullable in the database)
    postcode: Option<String>,
    /// Randomly generated session token
    #[geekorm(rand = "42", rand_prefix = "session_")]
    session: String,

    /// Created and Updated timestamps
    #[geekorm(new = "chrono::Utc::now()")]
    created_at: chrono::DateTime<chrono::Utc>,
    #[geekorm(new = "chrono::Utc::now()", on_update = "chrono::Utc::now()")]
    updated_at: chrono::DateTime<chrono::Utc>,
}

#[derive(Data, Debug, Default, Clone)]
enum UserType {
    Admin,
    Modirator,
    #[default]
    User,
}

#[tokio::main]
async fn main() -> Result<()> {
    // Setup the database and connection
    let db = libsql::Builder::new_local(":memory:").build().await
        .expect("Failed to create database");
    let connection = db.connect()
        .expect("Failed to connect to database");

    // Create the table in the database
    Users::create_table(&connection).await?;

    // Use the generated `new` function to create a new User
    // using the default values set in the struct.
    let mut user = Users::new("GeekMasher", "ThisIsNotMyPassword");
    // Saving the new User in the database
    user.save(&connection).await?;
    // Print the Primary Key value set by the database (auto_increment)
    println!("User ID: {:?}", user.id);

    // Updating the Users postcode (optional field)
    user.postcode = Some("SW1A 1AA".to_string());
    user.update(&connection).await?;

    // Fetch the Admin Users
    let admin_users = Users::fetch_by_user_type(&connection, UserType::Admin).await?;
    println!("Admin Users: {:?}", admin_users);

    // Counts the number of Users in the database
    let total_users = Users::total(&connection).await?;

    // Enums are used to help columns with a limited set of values
    // and GeekORM will handle the conversion for you.
    user.user_type = UserType::Admin;
    // or you can use the `.from()` or `.into()` functions
    user.user_type = UserType::from("Admin");
    user.user_type = "Admin".into();

    // GeekORM offers a number of helper functions to make your life easier.
    
    // Search unique fields or search tagged fields
    let search = Users::search(&connection, "GeekMasher").await?;

    // Automatically hashing passwords for you.
    user.hash_password("ThisIsStillNotMyPassword")?;

    // Automatically generate random strings for you.
    user.regenerate_session();

    // Go back to basics and build your own queries dynamically using
    // the QueryBuilder built into GeekORM
    let query = Users::query_select()
        .where_eq("username", "GeekMasher")
        .order_by("id", geekorm::QueryOrder::Desc)
        .limit(1)
        .build()?;

    // Execute the query and return the results
    let users = Users::query(&connection, query).await?;
    println!("Users: {:?}", users);

    Ok(())
}

🏄 Create Features

There are a number of opt-in features supported by GeekORM. Features can be added either using cargo add geekorm -F all or added them directly in your Cargo.toml file.

  • all: Enable all the major stable features
  • new: Generate Table::new(...) functions
  • helpers: Generate a number of helper functions
    • Select Table::select_by_primary_key()
    • Select column Table::select_by_{field}()
  • rand: Support Generating random strings
  • hash: Support Generating password hashes
  • Backends
    • libsql: Add LibSQL backend support
    • rusqlite: Add Rusqlite backend support

🧑‍🤝‍🧑 Maintainers / Contributors

Mathew Payne
Mathew Payne

💻 👀
Cale
Cale

🎨

🦸 Support

Please create GitHub Issues if there are bugs or feature requests.

This project uses Semantic Versioning (v2) and with major releases, breaking changes will occur.

📓 License

This project is licensed under the terms of the MIT open source license. Please refer to MIT for the full terms.

Dependencies

~2–13MB
~159K SLoC