Skip to main content

codlet_sqlx/
lib.rs

1//! SQLite and PostgreSQL storage adapters for codlet (RFC-011, RFC-034).
2//!
3//! ## Backends
4//!
5//! | Feature | Type | Connection | Use case |
6//! |---------|------|-----------|----------|
7//! | `sqlite` (default) | `SqliteStore` | `"sqlite::memory:"`, `"sqlite:path/to/db"` | Local dev, single-server |
8//! | `postgres` | `PostgresStore` | `postgres://…` | Multi-instance production |
9//!
10//! Enable one or both backends:
11//!
12//! ```toml
13//! # SQLite only (default — no extra flags needed):
14//! codlet-sqlx = { version = "…" }
15//!
16//! # PostgreSQL only — SQLite driver not compiled:
17//! codlet-sqlx = { version = "…", default-features = false, features = ["postgres"] }
18//!
19//! # Both backends simultaneously:
20//! codlet-sqlx = { version = "…", features = ["sqlite", "postgres"] }
21//! ```
22//!
23//! ## Atomicity guarantee
24//!
25//! Every one-time transition (code claim, form-token consume) uses a single
26//! `UPDATE … WHERE … AND <guard>` followed by `rows_affected()`. For
27//! PostgreSQL, `READ COMMITTED` + row-level locking means concurrent updates
28//! serialise at the row — exactly one wins. No `SERIALIZABLE` or `RETURNING`
29//! needed (RFC-034 §7).
30//!
31//! ## Conformance
32//!
33//! All stores pass the `codlet-conformance` suite including the concurrent
34//! claim race test (RFC-022, RFC-023).
35
36#![forbid(unsafe_code)]
37
38// SQLite modules: compiled only when the `sqlite` feature is active.
39#[cfg(feature = "sqlite")]
40pub mod admin;
41#[cfg(feature = "sqlite")]
42pub mod code;
43#[cfg(feature = "sqlite")]
44pub mod migration;
45#[cfg(feature = "sqlite")]
46pub mod session;
47#[cfg(feature = "sqlite")]
48pub mod token;
49
50// PostgreSQL modules: compiled only when the `postgres` feature is active.
51#[cfg(feature = "postgres")]
52pub mod postgres;
53
54#[cfg(feature = "sqlite")]
55pub use migration::run_migrations;
56
57#[cfg(feature = "postgres")]
58pub use postgres::{PostgresStore, run_postgres_migrations};
59
60/// A handle wrapping a [`sqlx::SqlitePool`] that implements all codlet
61/// store traits (RFC-011).
62///
63/// Clone is cheap (the pool is reference-counted internally).
64///
65/// Requires the `sqlite` Cargo feature (enabled by default).
66#[cfg(feature = "sqlite")]
67#[derive(Debug, Clone)]
68pub struct SqliteStore {
69    pub(crate) pool: sqlx::SqlitePool,
70}
71
72#[cfg(feature = "sqlite")]
73impl SqliteStore {
74    /// Construct from an existing pool.
75    ///
76    /// Call [`run_migrations`] on the pool before any store operations.
77    #[must_use]
78    pub fn new(pool: sqlx::SqlitePool) -> Self {
79        Self { pool }
80    }
81
82    /// Borrow the underlying pool.
83    #[must_use]
84    pub fn pool(&self) -> &sqlx::SqlitePool {
85        &self.pool
86    }
87}