# cratestack-sqlx
SQLx-backed Postgres delegates for CrateStack models.
## Overview
`cratestack-sqlx` provides async model delegates backed by PostgreSQL via SQLx. It's the server-side database layer that `include_schema!` generates delegate implementations for.
## Installation
```toml
[dependencies]
cratestack-sqlx = "0.2"
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid"] }
```
## Usage
### Delegate Methods
Generated by `include_schema!`:
```rust
use cratestack::include_schema;
include_schema!("schema.cstack");
let pool = sqlx::PgPool::connect(&database_url).await?;
let cool = cratestack_schema::CrateStack::builder(pool).build();
// Find by ID
let user: Option<User> = cool.user().find_by_id(&ctx, user_id).await?;
// Find many with filters
let posts = cool.post()
.find_many()
.where_expr(
post::published().is_true()
.and(post::author().email().eq("owner@example.com"))
)
.order_by(post::createdAt().desc())
.limit(20)
.run(&ctx)
.await?;
// Create
let user = cool.user().create(ctx, CreateUserInput {
email: "user@example.com".to_owned(),
name: "Alice".to_owned(),
}).await?;
// Update
let user = cool.user().update(ctx, user_id, UpdateUserInput {
name: Some("Bob".to_owned()),
..Default::default()
}).await?;
// Delete
cool.user().delete(ctx, user_id).await?;
```
### Projections
Select specific fields and relations:
```rust
let user = cool.user()
.find_unique()
.select(User::select()
.id()
.email()
.include_posts(Post::include_selection()
.id()
.title()
)
)
.run(&ctx)
.await?;
```
### Transactions
```rust
use sqlx::Acquire;
let mut tx = pool.begin().await?;
let account = Account::find_by_id(&mut *tx, from_id).await?;
Account::update_balance(&mut *tx, from_id, -amount).await?;
Account::update_balance(&mut *tx, to_id, amount).await?;
tx.commit().await?;
```
## Transaction Isolation
Use explicit isolation for procedures:
```cstack
mutation procedure transfer(amount: Decimal, to: String): Transfer {
@isolation("serializable")
}
```
```rust
// Generated procedure wrapper handles isolation
let result = cool.transfer(ctx, TransferInput { amount, to }).await?;
```
## Audit Integration
Enable audit on models:
```cstack
model Transfer {
id String @id
amount Decimal
@@audit
}
```
Audit events are recorded transactionally with the mutation via `AuditSink`.
## Decimal Backend
Select backend at compile time:
```toml
[features]
default = ["decimal-rust-decimal"] # 128-bit fixed
decimal-bigdecimal = ["cratestack-sqlx/decimal-bigdecimal"]
```
## Related Crates
- `cratestack-core` - Core types
- `cratestack-sql` - Dialect-agnostic SQL primitives
- `cratestack-rusqlite` - SQLite backend (on-device, sync)
## License
MIT