ormkit 0.3.0

A compile-time safe async ORM for PostgreSQL powered by SQLx
Documentation
# Ormkit Core ORM Guide

This guide covers the core ORM features for everyday use. Read this to get started with Ormkit in 10-15 minutes.

## Table of Contents

1. [Defining Entities]#defining-entities
2. [Type-Safe Queries]#type-safe-queries
3. [Repository Operations]#repository-operations
4. [Query Builder]#query-builder
5. [Transactions]#transactions
6. [Pagination]#pagination

---

## Defining Entities

Entities represent your database tables as Rust structs.

```rust
use ormkit::Entity;
use uuid::Uuid;
use chrono::{DateTime, Utc};

#[derive(ormkit::Entity, Debug, Clone)]
#[ormkit(table = "users")]
struct User {
    #[ormkit(id)]
    id: Uuid,

    email: String,
    name: String,

    created_at: DateTime<Utc>,
}
```

**Key Points:**
- `#[ormkit(table = "...")]` specifies the database table name
- `#[ormkit(id)]` marks the primary key field
- Field names must match your database column names (snake_case)

### Supported Types

- `Uuid` - UUID primary keys
- `String` - VARCHAR/TEXT
- `i32`, `i64` - INTEGER/BIGINT
- `f32`, `f64` - REAL/DOUBLE PRECISION
- `bool` - BOOLEAN
- `DateTime<Utc>` - TIMESTAMP
- `serde_json::Value` - JSONB
- `Option<T>` - Nullable columns

---

## Type-Safe Queries

Ormkit provides a fluent, type-safe query DSL:

```rust
use ormkit::Entity;

// Single filter
let user: User = User::query()
    .filter(User::email().eq("user@example.com"))
    .fetch_one(&pool)
    .await?;

// Multiple filters
let users: Vec<User> = User::query()
    .filter(User::age().gte(18))
    .filter(User::status().eq("active"))
    .fetch_all(&pool)
    .await?;

// Ordering and limits
let recent_users: Vec<User> = User::query()
    .order_by(User::created_at(), ormkit::query::Order::Desc)
    .limit(10)
    .fetch_all(&pool)
    .await?;
```

**Available Operators:**
- `eq`, `ne` - Equality
- `lt`, `lte`, `gt`, `gte` - Comparison
- `like`, `ilike` - Pattern matching
- `is_null`, `is_not_null` - Null checks
- `in` - IN clause

---

## Repository Operations

The `Repository` provides CRUD operations:

```rust
use ormkit::{Repository, Entity};
use ormkit::active_value::ActiveValue;

let repo = Repository::<User>::new(&pool);

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

// Insert new entity
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_by_id(user_id).await?;
```

### ActiveModel Pattern

`ActiveModel` tracks field changes for efficient partial updates:

```rust
// Create from entity
let mut model = user.into_active_model();

// Set new values (only these fields will be updated)
model.name = ActiveValue::Set("New Name");

// Unset fields are not updated
let updated = repo.update(model).await?;
```

---

## Query Builder

For dynamic queries (admin panels, filters):

```rust
use ormkit::{FilterOp, Order};

let mut query = User::query();

// Apply filters dynamically
if let Some(email) = email_filter {
    query = query.filter("email", FilterOp::Eq, email);
}
if let Some(min_age) = min_age_filter {
    query = query.filter("age", FilterOp::Gte, min_age);
}

// Dynamic ordering
query = query.order_by("created_at", Order::Desc);

// Execute
let users = query.fetch_all(&pool).await?;
```

**Note:** Prefer the type-safe DSL for static queries. Use string-based queries only when necessary.

---

## Transactions

Automatic commit/rollback with closures:

```rust
use ormkit::transaction;

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

    // All operations use the transaction
    let user = repo.find_by_id(user_id).await?;
    let mut model = user.into_active_model();
    model.name = ActiveValue::Set("Updated".to_string());
    repo.update(model).await?;

    // Return value becomes transaction result
    Ok::<(), ormkit::OrmkitError>(())
}).await?;

// Transaction commits on Ok, rolls back on Err
```

### Nested Transactions

Uses PostgreSQL SAVEPOINTs:

```rust
transaction(&pool, |tx1| async move {
    // Outer transaction
    transaction(&tx1, |tx2| async move {
        // Inner transaction (SAVEPOINT)
        Ok(())
    }).await
}).await
```

---

## Pagination

### Offset Pagination

```rust
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.email);
}
```

### Cursor Pagination

For large datasets or real-time feeds:

```rust
use ormkit::pagination::CursorRequest;

let request = CursorRequest::new(cursor, 25);
let page = repo.paginate_cursor(&request).await?;
```

---

## Next Steps

- **Production Features**: See [PRODUCTION_FEATURES.md]PRODUCTION_FEATURES.md for migrations and schema validation
- **Performance**: See [PERFORMANCE_OPTIMIZATIONS.md]PERFORMANCE_OPTIMIZATIONS.md for caching and optimization
- **API Reference**: See [docs.rs]https://docs.rs/ormkit for complete API documentation

---

**Need help?**
- Check the [Error Handling Guide]ERROR_HANDLING.md
- See [Performance Optimizations]PERFORMANCE_OPTIMIZATIONS.md for optimization tips