| Crates.io | cape |
| lib.rs | cape |
| version | 0.0.2 |
| created_at | 2025-09-27 15:31:41.839888+00 |
| updated_at | 2025-09-27 15:39:43.856301+00 |
| description | 🦸 An unintrusive ORM for Rust |
| homepage | |
| repository | https://github.com/mcaneris/cape |
| max_upload_size | |
| id | 1857423 |
| size | 63,626 |
⚠️ Work in Progress: This project is currently under active development and not ready for production use.
Cape is an unintrusive and lightweight wrapper ORM for Rust.
Most ORMs force core domain structs to mirror database schemas — IDs, foreign keys, and boilerplate that sullies the core domain model.
Cape flips this around by wrapping the domain model, just like a superhero’s cape. Core types stay clean and focused, while persistence details live in the wrapper.
Cape centers on a single generic type:
Record<T, R, S, K>
T → inner entity (core struct)R → relations (another Record, a tuple, or a Vec<Record>)S → persistence state (N, S)K → key type (i64, Uuid, etc.)use cape::prelude::*;
use uuid::Uuid;
#[derive(Debug, Clone)]
pub struct User {
pub username: String,
pub email: String,
}
#[derive(Debug, Clone)]
pub struct Post {
pub title: String,
pub body: String,
}
fn main() {
// New user, not yet persisted
let new_user: Record<User, (), N, Uuid> = Record::new(User {
username: "alice".into(),
email: "alice@example.com".into(),
});
assert!(new_user.is_dirty(), true);
// Stored user, persisted with a UUID
let stored_user = new_user.store(Uuid::new_v4(), chrono::Utc::now().naive_utc());
// New post with a stored author relation
let new_post: Record<Post, Record<User, (), S, Uuid>, N, i64> =
Record::with_relations(
Post { title: "Hello".into(), body: "Cape world!" },
stored_user,
);
// Move post into stored state
let stored_post = new_post.store(42, chrono::Utc::now().naive_utc());
assert!(new_user.is_dirty(), false);
println!("Post '{}' by {}",
stored_post.inner.title,
stored_post.relations.inner.username
);
}