ormkit 0.2.1

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

## Problem Statement

Current implementation requires manual trait implementation:

```rust
// Current - Manual implementation required
impl BelongsTo<User> for Post {
    fn foreign_key() -> &'static str {
        "user_id"
    }
    fn foreign_key_value(&self) -> Option<String> {
        Some(self.user_id.to_string())
    }
}
```

## Solution: Derive Macros for Relationships

### Target API

```rust
#[derive(ormkit::Entity)]
#[ormkit(table = "posts")]
struct Post {
    #[ormkit(id)]
    id: Uuid,
    title: String,

    #[ormkit(belongs_to = "User")]
    user_id: Uuid,
}

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

    // Virtual - not a real column
    #[ormkit(has_many = "Post")]
    posts: Vec<Post>,
}
```

### Usage Examples

```rust
// Load relationships
let posts_with_users = Post::query()
    .filter(Post::title().contains("Rust"))
    .with(Post::user())  // Load User relationship
    .fetch_all(&pool)
    .await?;

for post in posts_with_users {
    println!("{} by {}", post.title, post.user.name);
}

// Nested relationships
let posts_with_user_and_comments = Post::query()
    .with(Post::user())
    .with(Post::comments())
    .fetch_all(&pool)
    .await?;

// HasMany relationships
let users_with_posts = User::query()
    .filter(User::active().eq(true))
    .with(User::posts())
    .fetch_all(&pool)
    .await?;

for user in users_with_posts {
    println!("{} has {} posts", user.name, user.posts.len());
}
```

## Implementation Plan

### 1. BelongsTo Attribute Processing

Parse `#[ormkit(belongs_to = "EntityType")]` attribute:

- Extract target entity type
- Identify the foreign key field (the field with the attribute)
- Generate `BelongsTo<EntityType>` trait implementation
- Generate accessor method: `pub fn user(&self) -> RelationLoader<User>`

### 2. HasMany Attribute Processing

Parse `#[ormkit(has_many = "ChildType")]` attribute:

- Extract child entity type
- Generate `HasMany<ChildType>` trait implementation
- Infer foreign key column: `{entity_snake}_id`
- Generate accessor method: `pub fn posts(&self) -> RelationLoader<Vec<Post>>`

### 3. RelationLoader Type

A lightweight loader that fetches the relationship on demand:

```rust
pub struct RelationLoader<R> {
    entity_id: String,
    loaded: RefCell<Option<R>>,
    _phantom: PhantomData<R>,
}

impl<R> RelationLoader<R>
where
    R: Entity,
{
    /// Get the loaded relation, loading it if necessary
    pub async fn get(&self, pool: &PgPool) -> Option<&R> {
        // Lazy-load from database
    }

    /// Eagerly load the relationship
    pub async fn load(&self, pool: &PgPool) -> Result<(), LoadError> {
        // Load from database
    }
}
```

### 4. Query Builder Integration

Add `.with()` method to TypedQueryBuilder:

```rust
impl<E> TypedQueryBuilder<E>
where
    E: Entity,
{
    /// Eager load a relationship
    pub fn with<R>(self, relation: fn(&E) -> RelationLoader<R>) -> WithBuilder<E, R> {
        // ...
    }
}

pub struct WithBuilder<E, R> {
    query: TypedQueryBuilder<E>,
    _phantom: PhantomData<R>,
}

impl<E, R> WithBuilder<E, R>
where
    E: Entity + LoadRelation<R>,
    R: Entity,
{
    pub async fn fetch_all(self, pool: &PgPool) -> Result<Vec<Loaded<E, R>>, sqlx::Error> {
        // Execute query and load relationships in single batch
    }
}
```

## Generated Code Example

### Input:
```rust
#[derive(ormkit::Entity)]
#[ormkit(table = "posts")]
struct Post {
    #[ormkit(id)]
    id: Uuid,
    #[ormkit(belongs_to = "User")]
    user_id: Uuid,
}
```

### Generated:
```rust
// Implement BelongsTo<User>
impl ormkit::relations::BelongsTo<User> for Post {
    fn foreign_key() -> &'static str {
        "user_id"
    }

    fn foreign_key_value(&self) -> Option<String> {
        Some(self.user_id.to_string())
    }
}

// Add accessor method
impl Post {
    pub fn user(&self) -> ormkit::relations::RelationLoader<User> {
        ormkit::relations::RelationLoader::new(self.user_id.to_string())
    }
}
```

## Benefits

1. **No manual trait implementation** - Fully automated
2. **Type-safe** - Compile-time checking of relationships
3. **IDE autocomplete** - Accessor methods show up in IDE
4. **Flexible** - Supports both eager and lazy loading
5. **N+1 prevention** - Batch loading built-in

## Implementation Order

1. ✅ Parse `belongs_to` attribute in derive macro
2. ✅ Generate BelongsTo trait implementation
3. ✅ Generate accessor methods
4. ⏳ Parse `has_many` attribute
5. ⏳ Generate HasMany trait implementation
6. ⏳ Add RelationLoader type
7. ⏳ Integrate with TypedQueryBuilder
8. ⏳ Add comprehensive tests

## Example Usage After Implementation

```rust
// Simple BelongsTo
let posts = Post::query()
    .with(Post::user)
    .fetch_all(&pool)
    .await?;

for post in posts {
    println!("{}", post.user.name);  // Automatically loaded!
}

// HasMany
let users = User::query()
    .with(User::posts)
    .fetch_all(&pool)
    .await?;

for user in users {
    println!("{} has {} posts", user.name, user.posts.len());
}

// Nested
let posts = Post::query()
    .with(Post::user)
    .with_nested(|user| user.posts())
    .fetch_all(&pool)
    .await?;

// Conditions on relationships
let posts = Post::query()
    .filter(Post::user().name().eq("John"))
    .fetch_all(&pool)
    .await?;
```

This will make ormkit competitive with Django ORM, Eloquent, and ActiveRecord.