entity-derive-impl 0.1.0

Internal proc-macro implementation for entity-derive. Use entity-derive instead.
docs.rs failed to build entity-derive-impl-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: entity-derive-impl-0.3.0

Quick Navigation

Attribute Quick Reference

Entity-Level #[entity(...)]

#[derive(Entity)]
#[entity(
    table = "users",      // Required: database table name
    schema = "public",    // Optional: database schema (default: "public")
    sql = "full",         // Optional: "full" | "trait" | "none" (default: "full")
    dialect = "postgres", // Optional: "postgres" | "clickhouse" | "mongodb" (default: "postgres")
    uuid = "v7"           // Optional: "v7" | "v4" (default: "v7")
)]
pub struct User { /* ... */ }

Field-Level Attributes

pub struct User {
    #[id]                           // Primary key, UUID v7, always in response
    pub id: Uuid,

    #[field(create, update, response)]  // In all DTOs
    pub name: String,

    #[field(create, response)]      // Create + Response only
    pub email: String,

    #[field(skip)]                  // Excluded from all DTOs
    pub password_hash: String,

    #[field(response)]
    #[auto]                         // Auto-generated (excluded from create/update)
    pub created_at: DateTime<Utc>,

    #[belongs_to(Organization)]     // Foreign key relation
    pub org_id: Uuid,

    #[filter]                        // Exact match filter in Query struct
    pub status: String,

    #[filter(like)]                  // ILIKE pattern filter
    pub name: String,

    #[filter(range)]                 // Range filter (generates from/to fields)
    pub created_at: DateTime<Utc>,
}

// Projections - partial views of the entity
#[projection(Public: id, name)]           // UserPublic struct
#[projection(Admin: id, name, email)]     // UserAdmin struct

Generated Code Overview

For a User entity, the macro generates:

Generated Type Description
CreateUserRequest DTO for POST requests
UpdateUserRequest DTO for PATCH requests (all fields Option<T>)
UserResponse DTO for API responses
UserRow Database row mapping (for sqlx::FromRow)
InsertableUser Struct for INSERT statements
UserQuery Query struct for type-safe filtering (if #[filter] used)
UserRepository Async trait with CRUD methods
impl UserRepository for PgPool PostgreSQL implementation
User{Projection} Projection structs (e.g., UserPublic, UserAdmin)
From<...> impls Type conversions between all structs

SQL Generation Modes

Mode Generates Trait Generates Impl Use Case
sql = "full" Standard CRUD, simple queries
sql = "trait" Custom SQL (joins, CTEs, search)
sql = "none" DTOs only, no database layer

Repository Methods

The generated {Name}Repository trait includes:

#[async_trait]
pub trait UserRepository: Send + Sync {
    type Error: std::error::Error + Send + Sync;

    /// Create a new entity
    async fn create(&self, dto: CreateUserRequest) -> Result<User, Self::Error>;

    /// Find entity by primary key
    async fn find_by_id(&self, id: Uuid) -> Result<Option<User>, Self::Error>;

    /// Update entity with partial data
    async fn update(&self, id: Uuid, dto: UpdateUserRequest) -> Result<User, Self::Error>;

    /// Delete entity by primary key
    async fn delete(&self, id: Uuid) -> Result<bool, Self::Error>;

    /// List entities with pagination
    async fn list(&self, limit: i64, offset: i64) -> Result<Vec<User>, Self::Error>;

    /// Query entities with type-safe filters (if #[filter] used)
    async fn query(&self, query: UserQuery) -> Result<Vec<User>, Self::Error>;

    // For each projection, generates optimized SELECT method
    async fn find_by_id_public(&self, id: Uuid) -> Result<Option<UserPublic>, Self::Error>;
    async fn find_by_id_admin(&self, id: Uuid) -> Result<Option<UserAdmin>, Self::Error>;
}

Projections

Define partial views of entities for optimized SELECT queries:

#[derive(Entity)]
#[entity(table = "users")]
#[projection(Public: id, name, avatar)]    // Public profile
#[projection(Admin: id, name, email, role)] // Admin view
pub struct User {
    #[id]
    pub id: Uuid,
    #[field(create, update, response)]
    pub name: String,
    #[field(create, response)]
    pub email: String,
    #[field(update, response)]
    pub avatar: Option<String>,
    #[field(response)]
    pub role: String,
}

// Generated: UserPublic, UserAdmin structs
// Generated: find_by_id_public, find_by_id_admin methods

// SQL: SELECT id, name, avatar FROM public.users WHERE id = $1
let public = repo.find_by_id_public(user_id).await?;

Error Handling

The generated implementation uses sqlx::Error as the error type. You can wrap it in your application's error type:

use entity_derive::Entity;

#[derive(Entity)]
#[entity(table = "users", sql = "trait")]  // Generate trait only
pub struct User { /* ... */ }

// Implement with your own error type
#[async_trait]
impl UserRepository for MyDatabase {
    type Error = MyAppError;  // Your custom error

    async fn create(&self, dto: CreateUserRequest) -> Result<User, Self::Error> {
        // Your implementation
    }
}

Compile-Time Guarantees

This crate provides several compile-time guarantees:

  • No sensitive data leaks: Fields marked #[field(skip)] are excluded from all DTOs
  • Type-safe updates: UpdateRequest fields are properly wrapped in Option
  • Consistent mapping: From impls are always in sync with field definitions
  • SQL injection prevention: All queries use parameterized bindings

Performance

  • Zero runtime overhead: All code generation happens at compile time
  • No reflection: Generated code is plain Rust structs and impls
  • Minimal dependencies: Only proc-macro essentials (syn, quote, darling)

Comparison with Alternatives

Feature entity-derive Diesel SeaORM
DTO generation
Repository pattern Partial
Type-safe SQL
Async support Partial
Boilerplate reduction ~90% ~50% ~60%