| Crates.io | dibs |
| lib.rs | dibs |
| version | 0.1.0 |
| created_at | 2026-01-17 20:35:55.806579+00 |
| updated_at | 2026-01-17 20:35:55.806579+00 |
| description | Postgres toolkit for Rust, powered by facet reflection |
| homepage | |
| repository | https://github.com/bearcove/dibs |
| max_upload_size | |
| id | 2051091 |
| size | 9,964 |
Call dibs on your database schema.
A Postgres toolkit for Rust, powered by facet reflection.
dibs is a batteries-included Postgres library that gives you:
All built on facet's reflection system - no code generation, no build.rs, no macros that hide what's happening.
use dibs::prelude::*;
use facet::Facet;
#[derive(Facet)]
#[facet(dibs::table = "users")]
pub struct User {
#[facet(dibs::pk)]
pub id: i64,
#[facet(dibs::unique)]
pub email: String,
pub name: String,
#[facet(dibs::fkey = tenants::id)]
pub tenant_id: i64,
pub created_at: jiff::Timestamp,
}
// Queries
let user = db.find::<User>(42).await?;
let users = db.query::<User>()
.filter(User::tenant_id.eq(5))
.order_by(User::created_at.desc())
.all()
.await?;
// Mutations
db.insert(&new_user).await?;
db.update(&user).await?;
db.delete::<User>(42).await?;
Migrations are Rust functions, not SQL files. This lets you do complex data migrations with real logic:
use dibs::prelude::*;
#[dibs::migration("2026-01-17-normalize-emails")]
async fn normalize_emails(ctx: &mut MigrationContext) -> Result<()> {
// Add column
ctx.execute("ALTER TABLE users ADD COLUMN email_normalized TEXT").await?;
// Backfill in batches (don't lock the table)
ctx.backfill(|tx| async move {
tx.execute(
"UPDATE users SET email_normalized = LOWER(TRIM(email))
WHERE email_normalized IS NULL
LIMIT 1000",
&[]
).await
}).await?;
// Add constraint
ctx.execute(
"ALTER TABLE users ADD CONSTRAINT users_email_normalized_unique
UNIQUE (email_normalized)"
).await?;
Ok(())
}
Run migrations:
$ dibs migrate
Applied 2026-01-17-normalize-emails (32ms)
Compare your Rust types against the live database:
$ dibs diff
Changes detected:
users:
+ email_normalized: TEXT (nullable)
~ name: VARCHAR(100) -> TEXT
tenants:
(no changes)
Run `dibs generate` to create a migration.
Generate a migration skeleton:
$ dibs generate add-email-normalized
Created: migrations/2026-01-17-add-email-normalized.rs
dibs migrate Run pending migrations
dibs rollback Rollback the last migration
dibs status Show migration status
dibs diff Compare schema to database
dibs generate Generate a migration skeleton
dibs schema Dump the current schema
MIT OR Apache-2.0