Enhance CLAUDE.md with comprehensive project documentation
- Added repository URL - Documented all derive macro attributes and generated methods - Added Filter API usage examples - Documented database differences table - Added Value types reference - Added EntityChange audit trail schema - Included important usage notes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
aba05b2b52
commit
e89041b9c6
203
CLAUDE.md
203
CLAUDE.md
|
|
@ -1,77 +1,188 @@
|
||||||
# CLAUDE.md
|
# CLAUDE.md
|
||||||
|
|
||||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
This file provides guidance to Claude Code when working with this repository.
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
`sqlx-record` is a Rust library that provides derive macros for automatic CRUD operations and comprehensive audit trails for SQL entities. It supports MySQL, PostgreSQL, and SQLite via SQLx, tracking who changed what, when, and why with actor, session, and change set metadata.
|
`sqlx-record` is a Rust library that provides derive macros for automatic CRUD operations and comprehensive audit trails for SQL entities. It supports MySQL, PostgreSQL, and SQLite via SQLx, tracking who changed what, when, and why with actor, session, and change set metadata.
|
||||||
|
|
||||||
|
**Repository:** https://git.awesomike.com/pub/sqlx-record.git
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
### Workspace Structure
|
### Workspace Structure
|
||||||
- **Main library** (`src/`): Core entity CRUD and change tracking functionality
|
```
|
||||||
- **sqlx-record-derive** (`sqlx-record-derive/`): Procedural macro crate for deriving Entity and Update traits
|
sqlx-record/
|
||||||
- **sqlx-record-ctl** (`sqlx-record-ctl/`): Command-line utility for managing audit tables
|
├── src/ # Core library
|
||||||
|
│ ├── lib.rs # Public API exports and prelude
|
||||||
|
│ ├── models.rs # EntityChange struct, Action enum
|
||||||
|
│ ├── repositories.rs # Database query functions for entity changes
|
||||||
|
│ ├── value.rs # Type-safe Value enum, bind functions
|
||||||
|
│ ├── filter.rs # Filter enum for query conditions
|
||||||
|
│ └── helpers.rs # Utility macros
|
||||||
|
├── sqlx-record-derive/ # Procedural macro crate
|
||||||
|
│ └── src/
|
||||||
|
│ ├── lib.rs # #[derive(Entity, Update)] implementation
|
||||||
|
│ └── string_utils.rs # Pluralization helpers
|
||||||
|
├── sqlx-record-ctl/ # CLI tool for audit table management
|
||||||
|
│ └── src/main.rs
|
||||||
|
└── Cargo.toml # Workspace root
|
||||||
|
```
|
||||||
|
|
||||||
### Core Components
|
### Feature Flags
|
||||||
- **models.rs**: Defines `EntityChange` struct and `Action` enum for tracking entity modifications
|
- `derive`: Enables `#[derive(Entity, Update)]` procedural macros
|
||||||
- **repositories.rs**: Database query functions for creating and retrieving entity changes by various criteria (ID, entity, session, actor, change set)
|
- `static-validation`: Enables compile-time SQLx query validation
|
||||||
- **value.rs**: Type-safe value system supporting SQL types (integers, strings, UUIDs, dates, etc.) with `Value` enum and `Updater` for SQL operations
|
|
||||||
- **filter.rs**: Query filter system with `Filter` enum supporting SQL operations (Equal, Like, In, And, Or, etc.)
|
|
||||||
- **helpers.rs**: Utility functions and macros for the library
|
|
||||||
|
|
||||||
### Features
|
|
||||||
- `derive`: Enables procedural macro support for Entity and Update traits
|
|
||||||
- `static-validation`: Enables static SQLx validation during compilation
|
|
||||||
- `mysql`: MySQL database support
|
- `mysql`: MySQL database support
|
||||||
- `postgres`: PostgreSQL database support
|
- `postgres`: PostgreSQL database support
|
||||||
- `sqlite`: SQLite database support
|
- `sqlite`: SQLite database support
|
||||||
|
|
||||||
|
**Note:** You must enable at least one database feature.
|
||||||
|
|
||||||
## Development Commands
|
## Development Commands
|
||||||
|
|
||||||
### Building
|
|
||||||
```bash
|
```bash
|
||||||
# Build with MySQL support (default for backwards compatibility)
|
# Build with MySQL
|
||||||
cargo build --features mysql
|
cargo build --features mysql
|
||||||
|
|
||||||
# Build with PostgreSQL support
|
|
||||||
cargo build --features postgres
|
|
||||||
|
|
||||||
# Build with SQLite support
|
|
||||||
cargo build --features sqlite
|
|
||||||
|
|
||||||
# Build with derive macros
|
# Build with derive macros
|
||||||
cargo build --features "mysql,derive"
|
cargo build --features "mysql,derive"
|
||||||
```
|
|
||||||
|
|
||||||
### Testing
|
# Build CLI tool
|
||||||
```bash
|
|
||||||
cargo test --features mysql
|
|
||||||
```
|
|
||||||
|
|
||||||
### Working with workspace members
|
|
||||||
```bash
|
|
||||||
# Build specific workspace member
|
|
||||||
cargo build -p sqlx-record-derive --features mysql
|
|
||||||
cargo build -p sqlx-record-ctl --features mysql
|
cargo build -p sqlx-record-ctl --features mysql
|
||||||
|
|
||||||
# Test specific workspace member
|
# Test
|
||||||
cargo test -p sqlx-record --features mysql
|
cargo test --features mysql
|
||||||
```
|
|
||||||
|
|
||||||
### Releasing
|
# Release tag
|
||||||
The project uses a Makefile for tagging releases:
|
|
||||||
```bash
|
|
||||||
make tag
|
make tag
|
||||||
```
|
```
|
||||||
This creates a git tag based on the version in Cargo.toml and pushes it to the remote repository.
|
|
||||||
|
## Derive Macro API
|
||||||
|
|
||||||
|
### Entity Attributes
|
||||||
|
```rust
|
||||||
|
#[derive(Entity, FromRow)]
|
||||||
|
#[table_name = "users"] // or #[table_name("users")]
|
||||||
|
struct User {
|
||||||
|
#[primary_key] // Mark primary key field
|
||||||
|
id: Uuid,
|
||||||
|
|
||||||
|
#[rename("user_name")] // Map to different DB column
|
||||||
|
name: String,
|
||||||
|
|
||||||
|
#[version] // Auto-increment on update
|
||||||
|
version: u32,
|
||||||
|
|
||||||
|
#[field_type("BIGINT")] // SQLx type hint
|
||||||
|
count: i64,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generated Methods
|
||||||
|
|
||||||
|
**Insert:**
|
||||||
|
- `insert(&pool) -> Result<PkType, Error>`
|
||||||
|
|
||||||
|
**Get:**
|
||||||
|
- `get_by_{pk}(&pool, &pk) -> Result<Option<Self>, Error>`
|
||||||
|
- `get_by_{pks}(&pool, &[pk]) -> Result<Vec<Self>, Error>`
|
||||||
|
- `get_by_primary_key(&pool, &pk) -> Result<Option<Self>, Error>`
|
||||||
|
|
||||||
|
**Find:**
|
||||||
|
- `find(&pool, filters, index) -> Result<Vec<Self>, Error>`
|
||||||
|
- `find_one(&pool, filters, index) -> Result<Option<Self>, Error>`
|
||||||
|
- `find_ordered(&pool, filters, index, order_by) -> Result<Vec<Self>, Error>`
|
||||||
|
- `find_ordered_with_limit(&pool, filters, index, order_by, offset_limit) -> Result<Vec<Self>, Error>`
|
||||||
|
- `count(&pool, filters, index) -> Result<u64, Error>`
|
||||||
|
|
||||||
|
**Update:**
|
||||||
|
- `update(&self, &pool, form) -> Result<(), Error>`
|
||||||
|
- `update_by_{pk}(&pool, &pk, form) -> Result<(), Error>`
|
||||||
|
- `update_by_{pks}(&pool, &[pk], form) -> Result<(), Error>`
|
||||||
|
- `update_form() -> UpdateForm` - Creates builder
|
||||||
|
|
||||||
|
**Diff:**
|
||||||
|
- `model_diff(&form, &model) -> serde_json::Value`
|
||||||
|
- `db_diff(&form, &pk, &pool) -> Result<serde_json::Value, Error>`
|
||||||
|
- `diff_modify(&mut form, &model) -> serde_json::Value`
|
||||||
|
- `to_update_form(&self) -> UpdateForm`
|
||||||
|
- `initial_diff(&self) -> serde_json::Value`
|
||||||
|
|
||||||
|
**Metadata:**
|
||||||
|
- `table_name() -> &'static str`
|
||||||
|
- `entity_key(&pk) -> String`
|
||||||
|
- `entity_changes_table_name() -> String`
|
||||||
|
- `primary_key_field() -> &'static str`
|
||||||
|
- `primary_key_db_field() -> &'static str`
|
||||||
|
- `primary_key(&self) -> &PkType`
|
||||||
|
- `select_fields() -> Vec<&'static str>`
|
||||||
|
|
||||||
|
**Version (if #[version] field exists):**
|
||||||
|
- `get_version(&pool, &pk) -> Result<Option<VersionType>, Error>`
|
||||||
|
- `get_versions(&pool, &[pk]) -> Result<HashMap<PkType, VersionType>, Error>`
|
||||||
|
|
||||||
|
## Filter API
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use sqlx_record::prelude::*;
|
||||||
|
|
||||||
|
// Simple filters
|
||||||
|
let f = filters![("active", true), ("role", "admin")];
|
||||||
|
|
||||||
|
// Compound filters
|
||||||
|
let f = filter_or![("status", "active"), ("status", "pending")];
|
||||||
|
let f = filter_and![("age", 18), ("verified", true)];
|
||||||
|
|
||||||
|
// Filter enum variants
|
||||||
|
Filter::Equal("field", value)
|
||||||
|
Filter::NotEqual("field", value)
|
||||||
|
Filter::GreaterThan("field", value)
|
||||||
|
Filter::LessThan("field", value)
|
||||||
|
Filter::Like("field", pattern)
|
||||||
|
Filter::ILike("field", pattern) // Case-insensitive
|
||||||
|
Filter::In("field", vec![values])
|
||||||
|
Filter::NotIn("field", vec![values])
|
||||||
|
Filter::IsNull("field")
|
||||||
|
Filter::IsNotNull("field")
|
||||||
|
Filter::And(vec![filters])
|
||||||
|
Filter::Or(vec![filters])
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Differences
|
||||||
|
|
||||||
|
| Feature | MySQL | PostgreSQL | SQLite |
|
||||||
|
|---------|-------|------------|--------|
|
||||||
|
| Placeholder | `?` | `$1, $2, ...` | `?` |
|
||||||
|
| Table quote | `` ` `` | `"` | `"` |
|
||||||
|
| UUID type | `BINARY(16)` | `UUID` | `BLOB` |
|
||||||
|
| JSON type | `JSON` | `JSONB` | `TEXT` |
|
||||||
|
| ILIKE | `LOWER() LIKE LOWER()` | Native | `LOWER() LIKE LOWER()` |
|
||||||
|
| Index hints | `USE INDEX()` | N/A | N/A |
|
||||||
|
|
||||||
|
## Value Types
|
||||||
|
|
||||||
|
The `Value` enum supports:
|
||||||
|
- Integers: `Int8`, `Uint8`, `Int16`, `Uint16`, `Int32`, `Uint32`, `Int64`, `Uint64`
|
||||||
|
- `String`, `Bool`, `VecU8`
|
||||||
|
- `Uuid`
|
||||||
|
- `NaiveDate`, `NaiveDateTime`
|
||||||
|
|
||||||
|
## Entity Changes (Audit Trail)
|
||||||
|
|
||||||
|
The `EntityChange` struct tracks:
|
||||||
|
- `id`: Change record UUID
|
||||||
|
- `entity_id`: Target entity UUID
|
||||||
|
- `action`: insert/update/delete/restore/hard-delete
|
||||||
|
- `changed_at`: Timestamp (milliseconds)
|
||||||
|
- `actor_id`: Who made the change
|
||||||
|
- `session_id`: Session context
|
||||||
|
- `change_set_id`: Transaction grouping
|
||||||
|
- `new_value`: JSON payload of changes
|
||||||
|
|
||||||
## Important Notes
|
## Important Notes
|
||||||
|
|
||||||
- The library supports MySQL, PostgreSQL, and SQLite databases via SQLx feature flags
|
- Always enable a database feature (`mysql`, `postgres`, or `sqlite`)
|
||||||
- All entity changes include metadata: actor_id, session_id, change_set_id, and timestamps
|
- The `prelude` module exports commonly used items including `placeholder()` function
|
||||||
- The `new_value` field stores JSON data for tracking actual changes
|
- Query filters use `Filter::build_where_clause()` internally
|
||||||
- Procedural macros are optional and gated behind the "derive" feature
|
- Version fields auto-increment with overflow wrapping
|
||||||
- The library uses UUIDs for all entity identifiers
|
- The CLI tool requires a `entity_changes_metadata` table with `table_name` and `is_auditable` columns
|
||||||
- Query filters support both simple field-value pairs and complex nested And/Or logic
|
|
||||||
- PostgreSQL uses `$1, $2, ...` placeholders; MySQL/SQLite use `?`
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue