Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Changelog

All notable changes to the crudcrate project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

[0.9.1] - 2026-06-01

Fixed

  • LIKE queries broken on Postgres. build_like_condition and the fulltext search functions used ? as the bind placeholder in Expr::cust_with_values templates. Sea-query’s Postgres backend uses $ as its placeholder character, so the ? was passed through as a literal — Postgres then parsed ? ESCAPE '!' as a JSONB operator followed by a type cast, producing type "escape" does not exist. Fixed by using $1 for Postgres and ? for MySQL/SQLite.

  • build_like_condition missing ESCAPE clause. The LIKE condition for like_filterable fields used sea-query’s .like() which never emitted an ESCAPE clause. Rewritten to use Expr::cust_with_values with ESCAPE '!', matching the fulltext functions.

  • Fulltext search on non-text columns. The fallback LIKE search path (when fulltext_searchable_columns() is empty) applied UPPER(col) LIKE ... to all searchable columns including booleans. Postgres and MySQL reject UPPER(boolean). Fixed by casting columns to TEXT (Postgres/SQLite) or CHAR (MySQL) before UPPER().

  • LIKE escape character conflicts with Postgres string quoting. Switched escape_like_wildcards from backslash to ! as the escape character. Backslash inside single-quoted SQL strings is ambiguous across backends (Postgres standard_conforming_strings).

Changed

  • Removed dead codegen helpers (runtime_fk_* functions) from crudcrate-derive.

  • Resolved clippy warnings across the workspace (collapsible ifs, duplicate match arms, missing error docs, unwrap after is_some).

  • Updated trybuild snapshot for rustc 1.96.

0.9.0 - 2026-05-19

Security

  • SecurityProfile config struct + presets. New crudcrate::SecurityProfile bundles the security-sensitive runtime defaults — strict filter parsing, scope propagation, deleted-ID exposure, and request body size — under one type with three presets: SecurityProfile::secure(), react_admin(), and legacy(). Override individual fields via Rust’s struct-update syntax: SecurityProfile { expose_deleted_ids: true, ..SecurityProfile::secure() }.

  • Per-resource override via derive attribute. #[crudcrate(security_profile = "secure" | "react_admin" | "legacy")] generates a CRUDResource::security_profile() impl that returns the named preset.

  • Global override via Axum extension. Apply .layer(Extension(SecurityProfile::secure())) on your router to override the per-resource setting at request time. Resolution order: Extension > CRUDResource::security_profile() > trait default.

  • Default profile flipped to secure(). New resources ship hardened defaults. See MIGRATION_0.9.md for the per-flag breakdown and opt-out instructions.

  • Explicit batch body limit. The generated router now applies an Axum DefaultBodyLimit::max(...) layer derived from SecurityProfile::max_request_body_bytes (default 2 MiB, matching axum-core’s baseline). Previous behavior relied on Axum’s implicit default and broke if any consumer wired DefaultBodyLimit::disable() up the tree.

  • Scope-propagation side-channel guard. Under secure() profile, joined filters (?filter={"vehicles.color":"..."}) on a child entity that has no exclude(scoped) scope condition are rejected with 400 Bad Request when the request carries a ScopeCondition. Prevents parent-existence side-channels via unscoped child columns.

  • Strict filter parsing. Under secure() profile, a malformed ?filter=... value returns 400 instead of silently dropping the filter and returning the unfiltered result.

  • Deleted-ID enumeration guard. Under secure() profile, batch delete responses return {"deleted": N} instead of the array of UUIDs that actually existed in the database, removing the existence-enumeration side-channel through the delete endpoint. react-admin frontends that rely on the ID array for cache invalidation should pin SecurityProfile::react_admin() or legacy().

  • Fulltext SQL bind parameterization. The Postgres / MySQL / SQLite fulltext condition builders now route the user query value through Expr::cust_with_values so the value is bound as a parameter rather than interpolated into the SQL string. Defense-in-depth — column names were already compile-time-known, but raw SimpleExpr::Custom(format!(...)) was removed everywhere user input could reach it.

Fixed

  • Join loading with operations attribute. Entities using #[crudcrate(operations = MyOps)] for create/update/delete hooks had their join loading silently bypassed on get_one and get_all — the codegen delegated entirely to CRUDOperations which does plain queries with no relation loading. The operations path now falls through to the standard join-loading codegen when the entity has join(...) fields, with before_get_one/after_get_one and before_get_all/after_get_all hooks wrapping the join-loaded body. get_one_scoped and get_all_scoped are also generated for this path (previously missing entirely).

  • FK column resolution in batch loading. The batch loader and join loader now resolve FK columns from the SeaORM RelationDef at runtime instead of guessing from the struct name convention. Joins with non-standard FK names (eg. author_ref instead of author_id) now load correctly.

Changed

  • Replaced unmaintained impls = "1" (no release since 2019) with an inline crudcrate::impls! macro. Same autoref-specialization semantics, 30 LOC, no behavior change.

  • Workspace dependencies bumped: axum 0.8.6 → 0.8.9, sea-orm 1.1.19 → 1.1.20, serde_json → 1.0.149, uuid → 1.23.1, tokio → 1.52.3, chrono → 0.4.44, tower-http → 0.6.11, utoipa → 5.5.0, plus proc-macro and rust_decimal patches.

  • url-escape (unmaintained dev dep) replaced with percent-encoding.

Documentation

  • README.md: added security caveat for the mysql feature, which pulls in rsa 0.9.10 (RUSTSEC-2023-0071, Marvin attack — no upstream fix).

0.8.1 - 2026-05-19

Security

  • Filter clause limit. Requests with more than 100 filter keys are rejected with 400 Bad Request (MAX_FILTER_CLAUSES = 100). Prevents query-planning DoS via oversized filter payloads.

  • DB error sanitization. Internal database error messages are stripped from client-facing responses. Only a generic prefix is returned; the full error is logged via tracing.

Added

  • Joined filters are now applied by the default handler. Requests like GET /customers?filter={"vehicles.make":"BMW"} previously parsed and whitelisted the filter but silently dropped it before hitting the database — users got unfiltered results. The default get_all_handler now resolves each JoinedFilter into a sub-query on the child table (with the child’s ScopeFilterable::scope_condition() applied), collects matching parent-FK values, and adds id IN (...) to the main condition. Query shape: one extra SELECT parent_fk FROM child WHERE ... per joined-filter field plus the usual list + count queries — no JOIN, no DISTINCT. Backed by test_suite/tests/joined_filter_http_test.rs and a runnable cargo run --example joined_filter.

  • New CRUDResource::resolve_joined_filters trait method. Takes the parsed condition plus the &[JoinedFilter] list and returns the augmented condition to use for both the list query and the count query. Default impl logs and returns the condition unchanged (backward compatible for non-derive users); the derive macro generates an override for every resource that declares join(..., filterable(...)) on any Vec<Child> field.

  • New public helper crudcrate::build_comparison_expr. Translates a column + FilterOperator + serde_json::Value into an Option<SimpleExpr> for use in custom filter resolvers.

Changed

  • crudcrate::filtering::ParsedFilters::joined_filters is now consumed by the handler (previously only populated by the parser and read by tests). No API change — the field was already public.

  • Pruned unused dependencies from the workspace.

Documentation

  • docs/src/features/filtering.md “Filtering on Related Entities” rewritten to describe the actual query shape, scope-safety guarantees, and the Vec<Child>-only limitation. Removed the stale “requires a custom read::many::body hook” note.
  • docs/src/features/relationships.md migrated from the deprecated join_filterable(...) / join_sortable(...) syntax to the current filterable(...) / sortable(...) inside join(...).

0.8.0 - 2026-04-17

Security

  • Atomic scope check in get_one: Scoped get_one requests now verify the scope condition in a single query (ID + scope filter), eliminating a TOCTOU race where a separate total_count() verification could see stale data between the fetch and the check.
  • FK column runtime validation: The derive macro generates #[cfg(test)] functions that verify convention-derived FK column names match the actual RelationDef from SeaORM at test time. Catches silent data mismatches from FK naming convention violations before they reach production.
  • SQL-level scope filtering for joins (all endpoints, all depths): Child entities with exclude(scoped) fields are now filtered at the SQL level (WHERE is_private = false) during join loading on both get_one_scoped and get_all_scoped, and at every depth when depth > 1. The scoped batch loader applies each child’s ScopeFilterable::scope_condition() to its Entity::find().filter(FK in parent_ids) query, and recurses via get_one_scoped (not get_one) for nested children. The in-memory ScopeFilterable::is_scope_visible() filter remains as defense-in-depth, but privacy is now enforced in the database, not just at serialisation time — private rows never leave Postgres on public endpoints.
  • require_scope attribute: New #[crudcrate(require_scope)] struct-level attribute. When set, read handlers return HTTP 500 if no ScopeCondition middleware is present — catches misconfigured routes that should be scoped but aren’t.

Added

  • Struct-level join definitions: Join fields can now be defined at the struct level instead of on the SeaORM Model. This keeps the Model lightweight and avoids stack overflow when loading entities with heavy join types. The join field only exists on the generated API struct.

    #[crudcrate(
        api_struct = "Site",
        join(name = "replicates", result = "Vec<SiteReplicate>", one, all, depth = 1)
    )]
    pub struct Model { /* no replicates field here */ }

    Field-level joins with #[sea_orm(ignore)] + #[crudcrate(non_db_attr, join(...))] still work for backward compatibility.

  • SQL-level column exclusion for exclude(list): Fields marked #[crudcrate(exclude(list))] with Option<T> types are now skipped at the SQL level in list queries — the database never transfers the data. Previously, exclude(list) only removed the field from the response struct while still fetching all columns. This dramatically improves performance for entities with large fields (photos, blobs, documents). Benchmarked at 7x improvement (1,013 → 7,121 req/s) on an endpoint with base64 photo data.

  • ScopeCondition for auth-aware query filtering: New ScopeCondition type that can be injected via Axum Extension to add conditions to read queries. Auth-system-agnostic — users write middleware to convert their auth state into a ScopeCondition. When present, get_all_handler merges the condition into the query filter, and get_one_handler verifies the fetched record passes the condition. Write operations are unaffected.

    use crudcrate::ScopeCondition;
    let public = Article::read_only_router(&db)
        .layer(Extension(ScopeCondition(
            Condition::all().add(article::Column::IsPrivate.eq(false))
        )));
  • read_only_router() method: Generates a router with only GET endpoints (get_one + get_all), no create/update/delete. Use with ScopeCondition for public/filtered API endpoints.

  • fk_column join parameter: Optional fk_column = "ColumnName" in join(...) attributes for entities where the FK column doesn’t follow the {StructName}Id convention. The convention remains the default; this is an escape hatch for non-standard schemas.

    #[crudcrate(join(one, all, depth = 1, fk_column = "OwnerUuid"))]
    pub items: Vec<Item>,
  • ScopeFilterable::scope_condition(): New trait method that returns a sea_orm::Condition matching an entity’s exclude(scoped) fields. Auto-generated by the derive macro. Enables SQL-level scope filtering for join queries.

  • get_one_scoped / get_all_scoped: New CRUDResource trait methods with scope-aware query variants. Default implementations delegate to the non-scoped get_one / get_all (safe for resources without join(all) children). The derive macro overrides both with SQL-level child-scope propagation. get_all_handler dispatches to get_all_scoped whenever a ScopeCondition extension is present.

Fixed

  • Stack overflow with many joins: All join-loading futures are now Box::pinned, moving large async state off the stack. Prevents stack overflow in debug builds with many join fields.
  • Async state machine bloat in debug builds: All join-loading futures are wrapped in Box::pin, preventing debug-build async state machine bloat from Related<E> monomorphization.

Changed

  • depth = 0 is now a compile error: Use depth = 1 for shallow loading. Previously depth = 0 could cause infinite recursion at runtime.
  • Compile-time bidirectional relation detection: Joins targeting an entity that has a Related<Self> impl (bidirectional/cyclic relationship) now produce a compile error unless an explicit depth is set. Previously, these silently caused infinite recursion at runtime via SeaORM’s Relation::def() chain. The error message explains the cycle and suggests the fix.
  • Compile-time warnings for risky join depths: Self-referencing joins without an explicit depth and joins with depth > 5 now emit #[deprecated] warnings at compile time, guiding users to set safe depth values.

0.7.2 - 2026-03-27

Added

  • Automatic enum field detection: Fields with types implementing sea_orm::ActiveEnum are now detected at compile time — no #[crudcrate(enum_field)] annotation needed. Uses zero-cost compile-time trait detection (inherent impl trick) to check each field’s type.
  • Case-insensitive enum array filtering: Array/IN filters on enum fields now apply UPPER(CAST(col AS TEXT)) on Postgres, matching the case-insensitive behavior already used for single-value enum filters.

Deprecated

  • #[crudcrate(enum_field)]: No longer required. Enum fields are auto-detected from the ActiveEnum trait implementation. The attribute still works for backward compatibility but can be safely removed.

Fixed

  • Array/IN filtering on enum fields: process_array_filter() now handles enum fields by casting to TEXT and uppercasing on Postgres. Previously, array filters on enum columns could fail on native Postgres ENUM types or produce case-sensitive results.

0.7.1 - 2026-03-09

Added

  • Transform Hooks: New transform phase in hook system for result modification
    • Hook execution order: pre → body → transform → post
    • Transform hooks receive the result and return a modified version
    • Allows enriching, decorating, or transforming CRUD results before returning
    • Supported for all operations: create, read, update, delete (one and many)
    • Example: #[crudcrate(read::one::transform = enrich_with_metadata)]
  • Partial Success for Batch Operations: New ?partial=true query parameter for batch endpoints
    • Returns HTTP 207 Multi-Status when some items succeed and some fail
    • Response includes succeeded and failed arrays with indices and error messages
    • Available for: POST /batch, PATCH /batch, DELETE /batch
    • New types: BatchResult<T>, BatchFailure, BatchOptions
    • Note: Partial mode processes items individually using single-item hooks (create::one::*, etc.), not batch hooks (create::many::*). Each item commits independently with no shared transaction.
  • Batch Create/Update Endpoints: POST /batch and PATCH /batch for bulk operations
    • Transaction-based all-or-nothing semantics by default
    • Pre-validation for batch updates ensures true atomicity across all DB backends
  • Runtime-Configurable Limits: Override batch and pagination limits per-resource
    • #[crudcrate(batch_limit = 500)] - Max items for batch create/update/delete (default: 100)
    • #[crudcrate(max_page_size = 500)] - Max items per page (default: 1000)
    • Trait methods fn batch_limit() and fn max_page_size() can be overridden for runtime logic (env vars, config)
  • Security Startup Log: Info-level log message when mounting CRUD routes
    • Reports resource name, table, batch_limit, max_page_size, and enabled security defaults
    • Silent when no tracing subscriber is configured
  • Batch Loading for Joins (N+1 Query Fix): Optimized get_all() with joins
    • Reduced from N+1 queries to 2 queries for depth=1 joins (1 for parents + 1 per join field). Deeper joins (depth > 1) may issue additional queries to load nested relations.
    • Uses WHERE parent_id IN (...) with in-memory grouping
  • Documentation Test Links: New mdbook preprocessor linking documentation examples to test files
  • IDE Documentation: Comprehensive attribute reference in crate-level documentation

Changed

  • Documentation Overhaul: Complete restructure of tutorial documentation
    • New progressive tutorial: First Steps → Auto IDs → Timestamps → Filtering → Sorting → Search → Hiding Fields → Relationships → Hooks
    • Simplified navigation structure in SUMMARY.md
    • Enhanced examples with “Run It Now” sections
    • Net reduction of ~800 lines while covering more features
  • DateTimeWithTimeZone schema fix: All generated model structs (API, Create, Update, List, Response) now resolve DateTimeWithTimeZone to chrono::DateTime<chrono::FixedOffset> so utoipa’s ToSchema derive recognizes it as a DateTime type
  • Generated API struct derives now use fully qualified paths (serde::Serialize, utoipa::ToSchema, etc.) to avoid conflicts with user imports
  • Bumped sea-orm from 1.1.17 to 1.1.19
  • Batch operation limit checking now uses Self::batch_limit() method (configurable per-resource)
  • BATCH_LIMIT and MAX_PAGE_SIZE changed from associated constants to trait methods for runtime overridability
  • Batch loading uses .remove() from HashMap instead of .get().cloned() — moves data instead of copying

Fixed

  • UUID array filtering now passes native Uuid values to is_in() instead of stringified values, fixing incorrect query generation for UUID column arrays
  • max_page_size() trait method now enforced in HTTP pagination handler
  • delete_many() returns only actually-deleted IDs
  • update_many() removed redundant pre-validation queries outside the transaction (TOCTOU race)
  • Self-referencing join errors now logged via tracing::warn! instead of silently swallowed
  • Nested relation loading errors (get_one() fallbacks) now logged via tracing::warn!
  • to_snake_case in FK derivation now handles acronyms correctly
  • Batch loading uses PK field name from entity metadata instead of hardcoded id
  • update() trait default used plural instead of singular resource name in not-found error
  • delete_many() trait default had no batch limit check (now enforces batch_limit())
  • Broken cross-reference links in reference documentation
  • Clippy doc-markdown warnings

Removed

  • BatchUpdateItem<T>: Dead struct removed from public API
  • Dead code path: Unreachable self-referencing branch in batch loading
  • Documentation: Legacy tutorial structure replaced by progressive tutorials

0.7.0 - 2025-11-26

Security

  • Harden search queries with proper wildcard escaping
  • Improve input sanitization in filtering and pagination
  • Add pagination limits to prevent excessive queries

Added

  • Join Filtering: Filter by related entity columns using dot-notation syntax
    • filterable("col1", "col2") nested inside join(...) attribute
    • Query: ?filter={"vehicles.make":"BMW"}
    • All standard operators supported (_gt, _gte, _lt, _lte, _neq)
    • Single-level joins only (nested paths like vehicles.parts.name not supported)
  • Join Sorting: Sort by related entity columns using dot-notation syntax
    • sortable("col1", "col2") nested inside join(...) attribute
    • Query: ?sort=["vehicles.year","DESC"] or ?sort_by=vehicles.year&order=DESC
    • Single-level joins only (nested paths not supported)
  • Hook System: Attribute-based customization with {operation}::{cardinality}::{phase} syntax
    • Operations: create, read, update, delete
    • Cardinality: one (single), many (batch)
    • Phases: pre, body, post
    • Example: #[crudcrate(create::one::pre = validate_fn)]
  • Batch operations: create_many and update_many with hook support
  • ApiError error type: Consistent error handling with separate internal/client messages (fixes #3)
    • impl From<DbErr> for seamless Sea-ORM integration with automatic internal logging
    • Internal errors logged via tracing, generic message sent to client
    • Custom errors: ApiError::custom(StatusCode::IM_A_TEAPOT, "client msg", Some("internal log"))
    • Variants: NotFound, BadRequest, Unauthorized, Forbidden, Conflict, ValidationFailed, Database, Internal, Custom
  • Lifecycle hooks in CRUDOperations trait
  • Improved test coverage across modules

Changed

  • Major codebase refactoring (38% size reduction)
    • Removed index_analysis module
    • Simplified relation_validator.rs
    • Consolidated join/recursion handling
    • Modular codegen/ structure
  • Handler code generation refactored for hook flow
  • Replace eprintln! with tracing for logging
  • Legacy fn_* attributes auto-map to new hook syntax

Fixed

  • Improved error handling in join path parsing
  • Fixed flaky tests with serial execution
  • All clippy::pedantic warnings resolved

Removed

  • index_analysis module: Database index recommendations moved to external tooling (pgAdmin, MySQL Workbench, etc.)
  • register_crud_analyser! macro: No longer needed without index analysis
  • attributes.rs: Dead code (IDE autocomplete hints only, never used at runtime)
  • join_strategies/ module: Consolidated into codegen/joins/
  • field_analyzer.rs: Reorganized into fields/ module
  • Redundant examples: minimal_debug.rs, minimal_spring.rs, test_router_only.rs
  • Verbose documentation: ~400 lines of excessive doc comments trimmed

Dependencies

  • Added serial_test = "3.2" for test isolation
  • Added tracing for structured logging

0.6.1 - 2025-11-03

Fixed

  • Global path resolution of joined structs
  • Restructuring of crudcrate-derive into smaller modules, bit by bit.

0.6.0 - 2025-10-31

Added

  • Recursive Join Loading: Multi-level relationship loading with #[crudcrate(join(one, all))] attribute
  • Cyclic dependency detection at compile-time with actionable error messages
  • Unlimited join depth support with default depth warnings for relationships > 3 levels
  • exclude() function-style syntax for model exclusion: #[crudcrate(exclude(create, update))]
  • The get one response is now its own model, allowing for exclusion of fields from get one/create/update responses
  • New recursive_join example demonstrating nested relationship loading
  • Debug output functionality for procedural macros with debug_output attribute

Changed

  • derive: Removed requirement for Eq and PartialEq derives on generated API structs
  • derive: Improved multi-pass code generation to handle cyclic dependencies

Fixed

  • Database test cleanup logic for PostgreSQL and MySQL backends
  • Relationship loading in get_one() and get_all() endpoints

Dependencies

  • derive: Updated with recursive join support, cyclic dependency detection, and enhanced attribute parsing

0.5.0 - 2025-08-28

Added

  • Spring-RS framework support with minimal example in /examples
  • Restored CRUD benchmarks from 0.4.5

Changed

  • Moved crudcrate-derive and examples into repository
  • Simplified framework architecture - removed redundant code generation paths
  • Refactored macro code generation by splitting helpers.rs into focused modules

Removed

  • BREAKING: Case-sensitive enum filtering functionality

0.4.5 - 2025-08-25

Fixed

  • Batch delete endpoints now returns the array of successfully deleted resource UUIDs, suitable for a react-admin batch delete response.

0.4.4 - 2025-08-20

Added

  • Index analysis system for database optimization recommendations
  • analyse_indexes_for_resource and analyse_all_registered_models functions
  • Database-specific index recommendations with priority-based output

Changed

  • BREAKING (if still using CRUDResource manually): Added required TABLE_NAME constant to CRUDResource trait. This does not affect EntityToModel functionality.
  • Made validate_field_value function const
  • Improved code organization with extracted helper functions

Fixed

  • All clippy warnings (pessimistic and pedantic)
  • Test compilation errors and naming inconsistencies
  • Documentation examples and missing trait implementations

0.4.3 - 2025-08-19

Added

  • Testing: Integration tests for create_model=false compatibility with non_db_attr
  • Testing: Comprehensive test suite for use_target_models functionality with cross-model referencing

Fixed

  • derive: Resolved lingering compilation errors from List model update
  • derive: Fixed test compatibility issues following List model integration
  • Filter system: Minor improvements to filtering logic consistency

Dependencies

  • derive: Updated to latest version with enhanced List model support and improved compatibility

0.4.2 - 2025-08-18

Added

  • List Model Support: New List model generation capability for customizing fields returned in list/getAll endpoints, similar to Create and Update models
  • Generated List model behavior with field deselection support
  • Built-in getAll query optimization to only return fields specified in List model
  • derive: Support for reserved field names using r# syntax (e.g., r#type)
  • derive: Enhanced target model usage with CRUDResource structs for cross-model referencing
  • derive: Automatic From<> trait generation for List structs from Sea-ORM DB models

Changed

  • derive: Improved trait compatibility by re-adding PartialEq, Eq, Debug, and Clone derives to models for Sea-ORM compatibility
  • derive: Route generation now uses root-level paths instead of prefixed routes for better user control
  • derive: Enhanced use_target_models functionality for better cross-model integration

Fixed

  • derive: Fixed ActiveModel generation when create model excludes keys
  • derive: Fixed create_model=false compatibility with non_db_attr
  • derive: Improved function linking in crudcrate function overrides
  • derive: Fixed trait signature for Condition in get_all operations
  • derive: Various clippy warnings resolved

Dependencies

  • derive: Updated to 0.2.6 with List model support, reserved field handling, and enhanced model generation capabilities

0.4.1 - 2025-08-05

Added

  • Index analysis functionality with analyze_indexes_for_resource() and analyze_and_display_indexes() methods
  • Full-text search support in filtering system with fulltext_searchable_columns() method
  • REST-standard pagination and query filters alongside React Admin compatibility
  • Multi-database testing support (SQLite, PostgreSQL, MySQL) via DATABASE_URL environment variable
  • Comprehensive benchmark suite with performance testing across database backends
  • Security integration tests for SQL injection protection
  • Coverage reporting with Codecov integration
  • Database feature flags for selective driver compilation (mysql, postgresql, sqlite)
  • Binary size optimization through conditional database driver inclusion

Changed

  • Enhanced filtering system with enum case insensitivity and improved edge case handling
  • Updated README with minimal examples and comprehensive testing documentation
  • Restructured test infrastructure to support multiple database backends
  • Improved error handling in filter parsing with better validation
  • Removed Clone requirement from generated API structs (Create/Update models)
  • Optimized trait methods to use references instead of owned values where possible
  • Sea-ORM dependency now uses default-features = false with selective feature enabling
  • Enhanced README with database feature selection examples

Fixed

  • Enum filtering now supports case-insensitive matching
  • Filter edge cases handle malformed JSON gracefully
  • PostgreSQL test isolation issues with race conditions during parallel execution
  • Clippy warnings resolved across codebase
  • derive: Improved integration tests and restructured codebase

Dependencies

  • derive: Updated to 0.2.1 with full-text search support and enhanced router generation capabilities
  • derive: Removed Clone derives from generated structs to reduce memory overhead

0.4.0 - 2025-07-17

Added

  • Enhanced Router Generation: Automatic router generation via generate_router attribute in EntityToModels macro
  • Non-Database Field Support: Complete support for non-DB fields using #[sea_orm(ignore)] + #[crudcrate(non_db_attr = true)] pattern
  • Single-File API Capability: Full CRUD API can now be implemented in under 60 lines of code
  • Documentation improvements for non-DB field usage with examples
  • derive: EntityToModels macro with complete entity-to-API generation and CRUDResource implementation
  • derive: Router generation capability integrated into EntityToModels
  • derive: Enhanced support for non-database fields with proper Sea-ORM integration
  • derive: Comprehensive integration tests and restructured codebase

Changed

  • Enhanced EntityToModels macro to automatically generate router functions
  • Improved documentation with comprehensive non-DB field examples
  • Router generation now fully automated with zero boilerplate
  • derive: Enhanced ToCreateModel and ToUpdateModel with new trait system
  • derive: Added MergeIntoActiveModel trait implementation

Fixed

  • derive: Test infrastructure improvements and better error handling in macro generation

0.3.3 - 2025-06-23

Fixed

  • Fix newline formatting in auto-generated OpenAPI documentation
  • Remove debug messages from production builds

Changed

  • Accept enum exact comparison in filter queries
  • Filter on integer columns support

0.3.2 - 2025-06-06

Changed

  • Bump dependencies including crudcrate-derive for improved into() casting support

Dependencies

  • derive: Updated to 0.1.6 with improved .into() casting support and enhanced field attribute handling

0.3.1 - 2025-05-12

Changed

  • Update lockfile and enhance filtering capabilities for enum and integer columns

0.3.0 - 2025-04-05

Added

  • Major: Default implementations for get_one, get_all, and update_one in CRUDResource trait
  • New MergeIntoActiveModel trait for improved update model handling
  • Enhanced derive macro integration with new trait system

Changed

  • Restructured core trait system for better usability
  • Updated derive macro to reference new MergeIntoActiveModel trait

Dependencies

  • derive: Updated to 0.1.5 with IntoActiveModel trait for UpdateModel and improved trait derivations

0.2.5 - 2025-04-04

Added

  • Export serde_with for better serialization support
  • Enhanced error responses in API endpoints
  • Documentation for query parameters

Changed

  • Renamed openapi.rs to routes.rs for better organization
  • Updated dependencies

0.2.4 - 2025-03-11

Added

  • Description string support in CRUDResource
  • Auto-populated summary and description for macro-generated endpoints
  • Enhanced OpenAPI documentation generation

Dependencies

  • derive: Updated to 0.1.4 with improved serialization support using exported serde_with

0.2.3 - 2025-03-07

Added

  • Comprehensive OpenAPI macro support
  • Better API documentation generation

Fixed

  • Improved error responses in endpoints

0.2.2 - 2025-03-06

Added

  • Documentation for query parameters

0.2.1 - 2025-03-05

Added

  • Description string support in CRUDResource
  • Auto-populated summary and description for macro-generated endpoints

0.2.0 - 2025-03-05

Changed

  • Breaking: Major refactor from route-based to macro-based approach
  • Introduced crud_handlers! macro for generating CRUD endpoints
  • Simplified API creation process significantly

Removed

  • Legacy route-based implementation

0.1.4 - 2025-03-03

Fixed

  • Fixed return type of delete_one handler
  • Applied clippy suggestions for performance improvements

0.1.3 - 2025-02-19

Changed

  • Update crudcrate-derive to allow non-db parameters in update/create models

Dependencies

  • derive: Updated to 0.1.3 with support for auxiliary attributes in structs that don’t relate to DB model

0.1.2 - 2025-02-18

Changed

  • Update proc macro to 0.1.2

Dependencies

  • derive: Updated to 0.1.2 with improved trait derivations (Clone instead of Copy where appropriate)

0.1.0 - 2025-02-18

Added

  • Initial release of crudcrate
  • Basic CRUD operation framework
  • Sea-ORM and Axum integration
  • OpenAPI documentation support
  • Move common functions and traits from existing API
  • Import proc-macros from crudcrate-derive

Dependencies

  • derive: Initial release (0.1.0) with ToCreateModel and ToUpdateModel derive macros, field-level attribute support for CRUD customization, and integration with Sea-ORM ActiveModel system