ormkit 0.2.1

Compile-time safe ORM with typed DSL, automatic relationships, multi-tenant support, audit trails, and row-level security
Documentation

ormkit

A comprehensive ORM layer for SQLx that provides type-safe database operations with minimal boilerplate.

Features

  • Derive Macros: Automatic implementation of Entity traits with #[derive(ormkit::Entity)]
  • ActiveModel Pattern: Track field changes for efficient partial updates
  • Repository Pattern: Generic CRUD operations for any entity
  • Query Builder: Type-safe dynamic query construction with filters and ordering
  • Pagination: Built-in offset and cursor-based pagination support
  • Transaction Management: Automatic commit/rollback with transaction guards
  • Batch Operations: Efficient bulk inserts, updates, and deletes
  • Relationship Loading: Prevents N+1 queries with eager/lazy loading strategies

Installation

[dependencies]
ormkit = "0.1"
ormkit-derive = "0.1"
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid", "json"] }

Quick Start

use ormkit::{Entity, Repository, QueryBuilder, Filter, Order, PaginationRequest};
use ormkit::active_value::ActiveValue;
use sqlx::PgPool;
use uuid::Uuid;

// Define an Entity using the derive macro
#[derive(ormkit::Entity, Debug, Clone)]
#[ormkit(table = "users")]
struct User {
    #[ormkit(id)]
    id: Uuid,
    email: String,
    name: String,
    created_at: chrono::DateTime<chrono::Utc>,
}

// Repository operations (CRUD)
async fn repository_example(pool: &PgPool) -> Result<(), Box<dyn std::error::Error>> {
    let repo = Repository::<User>::new(pool);

    // Find by ID
    let user = repo.find_by_id(user_id).await?;

    // Find all
    let all_users = repo.find_all().await?;

    // Insert with ActiveModel
    let mut user_model = UserActiveModel::default();
    user_model.email = ActiveValue::Set("user@example.com".to_string());
    user_model.name = ActiveValue::Set("John Doe".to_string());
    let user = repo.insert(user_model).await?;

    // Update (only changed fields are updated)
    let mut user_model = user.into_active_model();
    user_model.name = ActiveValue::Set("Jane Doe".to_string());
    repo.update(user_model).await?;

    // Delete
    repo.delete(user_id).await?;

    Ok(())
}

Core Features

Query Builder

use ormkit::{Filter, FilterOp, Order};

let users: Vec<User> = User::query()
    .filter("email", FilterOp::Eq, "user@example.com")
    .filter("created_at", FilterOp::Gt, chrono::Utc::now() - chrono::Duration::days(30))
    .order_by("created_at", Order::Desc)
    .limit(10)
    .fetch_all(&pool)
    .await?;

Pagination

use ormkit::pagination::PaginationRequest;

let repo = Repository::<User>::new(&pool);
let request = PaginationRequest::new(1, 25); // page 1, 25 per page
let page = repo.paginate(&request).await?;

println!("Page {} of {}", page.meta.page, page.meta.total_pages);
for user in page.items {
    println!("User: {}", user.email);
}

Batch Operations

use ormkit::batch::{insert_many, BatchOptions};

let new_users = vec![/* ... */];
let options = BatchOptions::new().batch_size(50);
let result = insert_many(&pool, &new_users, Some(options)).await?;

println!("Inserted {} users", result.successful);

Transactions

use ormkit::transaction::transaction;

let result = transaction(&pool, |tx| async move {
    let repo = Repository::<User>::new(&tx);

    let user = repo.find_by_id(user_id).await?;
    let mut user_model = user.into_active_model();
    user_model.name = ActiveValue::Set("Updated Name".to_string());

    repo.update(user_model).await?;

    Ok::<(), Box<dyn std::error::Error>>(())
}).await?;

Advanced Features

Relationships (Prevents N+1 Queries)

use ormkit::relations::RelationBuilder;

// Load related entities in a single query
let posts_with_users = RelationBuilder::for_entities(posts)
    .load::<User>(&pool)
    .await?;

for loaded in posts_with_users {
    println!("Post: {} by {}", loaded.entity.title, loaded.related.name);
}

Current Status

v0.1.0 - Core features fully functional:

  • ✅ Entity derive macros
  • ✅ Repository CRUD operations
  • ✅ Query builder with filters
  • ✅ Pagination (offset and cursor-based)
  • ✅ Transaction management
  • ✅ Batch operations
  • ⚠️ Relationship auto-loading (requires additional macro work)

For complex relationship loading, raw SQLx queries can still be used alongside ormkit.

Documentation

Full API documentation is available at docs.rs.

License

MIT OR Apache-2.0

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

See Also