libsql_orm/
lib.rs

1//! # libsql-orm
2//!
3//! A powerful, async-first ORM for [libsql](https://github.com/libsql/libsql) with first-class support for **Cloudflare Workers** and WebAssembly environments.
4//!
5//! ## ✨ Features
6//!
7//! - 🚀 **Cloudflare Workers Ready** - Built specifically for edge computing environments
8//! - 🔄 **Async/Await Support** - Fully async API with excellent performance  
9//! - 🎯 **Type-Safe** - Leverages Rust's type system for compile-time safety
10//! - 📊 **Rich Query Builder** - Fluent API for complex queries
11//! - 🔍 **Advanced Filtering** - Search, pagination, sorting, and aggregations
12//! - 🛠️ **Migration System** - Database schema management and versioning
13//! - 🎨 **Derive Macros** - Automatic model generation with `#[derive(Model)]`
14//! - 📦 **Bulk Operations** - Efficient batch inserts, updates, and deletes
15//! - 🌐 **WASM Compatible** - Optimized for WebAssembly targets
16//! - 🔄 **Type Conversion** - Automatic conversion between SQLite and Rust types
17//! - 🔄 **Upsert Operations** - Smart create_or_update and upsert methods
18//! - 📝 **Built-in Logging** - Comprehensive logging for debugging and monitoring
19//!
20//! ## 🚀 Quick Start
21//!
22//! ```rust
23//! use libsql_orm::{Model, Database};
24//! use serde::{Deserialize, Serialize};
25//! use chrono::{DateTime, Utc};
26//!
27//! #[derive(Model, Debug, Clone, Serialize, Deserialize)]
28//! struct User {
29//!     pub id: Option<i64>,
30//!     pub name: String,
31//!     pub email: String,
32//!     pub age: Option<i32>,
33//!     pub is_active: bool,
34//!     pub created_at: DateTime<Utc>,
35//! }
36//!
37//! async fn example() -> Result<(), Box<dyn std::error::Error>> {
38//!     // Connect to database
39//!     let db = Database::new_connect("libsql://your-db.turso.io", "your-auth-token").await?;
40//!     
41//!     // Create a user
42//!     let user = User {
43//!         id: None,
44//!         name: "Alice".to_string(),
45//!         email: "alice@example.com".to_string(),
46//!         age: Some(30),
47//!         is_active: true,
48//!         created_at: Utc::now(),
49//!     };
50//!     
51//!     // Save to database
52//!     let saved_user = user.create(&db).await?;
53//!     println!("Created user with ID: [MASKED]");
54//!     
55//!     // Find users
56//!     let users = User::find_all(&db).await?;
57//!     println!("Found {} users", users.len());
58//!     
59//!     // Use smart upsert operations
60//!     let user_with_id = User {
61//!         id: Some(123),  // Will update if exists, create if not
62//!         name: "Updated Name".to_string(),
63//!         email: "updated@example.com".to_string(),
64//!         age: Some(31),
65//!         is_active: true,
66//!         created_at: Utc::now(),
67//!     };
68//!     let smart_saved = user_with_id.create_or_update(&db).await?;
69//!     
70//!     // Upsert by unique constraint
71//!     let unique_user = User {
72//!         id: None,
73//!         name: "Unique User".to_string(),
74//!         email: "unique@example.com".to_string(),  // Check by email
75//!         age: Some(25),
76//!         is_active: true,
77//!         created_at: Utc::now(),
78//!     };
79//!     let upserted = unique_user.upsert(&["email"], &db).await?;
80//!     
81//!     Ok(())
82//! }
83//! ```
84//!
85//! ## 🔄 Upsert Operations
86//!
87//! Smart create-or-update operations for efficient data management:
88//!
89//! ```rust
90//! use libsql_orm::{Model, Database};
91//!
92//! // Method 1: create_or_update (based on primary key)
93//! let user = User { id: Some(123), name: "John".to_string(), ... };
94//! let saved = user.create_or_update(&db).await?;  // Updates if ID exists, creates if not
95//!
96//! // Method 2: upsert (based on unique constraints)
97//! let user = User { id: None, email: "john@example.com".to_string(), ... };
98//! let saved = user.upsert(&["email"], &db).await?;  // Updates if email exists, creates if not
99//!
100//! // Multiple unique constraints
101//! let saved = user.upsert(&["email", "username"], &db).await?;
102//! ```
103//!
104//! ## 📝 Built-in Logging
105//!
106//! Comprehensive logging for debugging and monitoring:
107//!
108//! ```rust
109//! // All database operations are automatically logged
110//! // Logs appear in browser console (WASM) or standard logging (native)
111//!
112//! let user = User::new("John", "john@example.com");
113//!
114//! // Logs: [INFO] users: Creating record in table: users
115//! // Logs: [DEBUG] users: SQL: INSERT INTO users (...) VALUES (...)
116//! let saved = user.create(&db).await?;
117//!
118//! // Logs: [DEBUG] users: Finding record by ID: 123
119//! let found = User::find_by_id(123, &db).await?;
120//!
121//! // Logs: [INFO] users: Updating record with ID: 123
122//! let updated = found.unwrap().update(&db).await?;
123//! ```
124//!
125//! ## 📚 Advanced Usage
126//!
127//! ### Custom Table Names and Boolean Type Safety
128//!
129//! ```rust
130//! use libsql_orm::{Model, orm_column, deserialize_bool};
131//! use serde::{Serialize, Deserialize};
132//!
133//! #[derive(Model, Debug, Clone, Serialize, Deserialize)]
134//! #[table_name("user_accounts")]  // Custom table name
135//! struct User {
136//!     #[orm_column(type = "INTEGER PRIMARY KEY AUTOINCREMENT")]
137//!     pub id: Option<i64>,
138//!     
139//!     #[orm_column(not_null, unique)]
140//!     pub email: String,
141//!     
142//!     pub is_active: bool,        // ✅ Automatic SQLite integer ↔ Rust bool conversion
143//!     pub is_verified: bool,      // ✅ Type-safe boolean operations
144//!     
145//!     // For edge cases, use custom deserializer
146//!     #[serde(deserialize_with = "deserialize_bool")]
147//!     pub has_premium: bool,      // ✅ Manual boolean conversion
148//!     
149//!     #[orm_column(type = "TEXT DEFAULT 'active'")]
150//!     pub status: String,
151//! }
152//!
153//! // Boolean filtering works seamlessly
154//! let active_users = User::find_where(
155//!     FilterOperator::Eq("is_active".to_string(), Value::Boolean(true)),
156//!     &db
157//! ).await?;
158//! ```
159//!
160//! ### Query Builder
161//!
162//! ```rust
163//! use libsql_orm::{QueryBuilder, FilterOperator, Sort, SortOrder, Pagination};
164//!
165//! // Complex query with filtering and pagination
166//! let query = QueryBuilder::new("users")
167//!     .select(&["id", "name", "email"])
168//!     .r#where(FilterOperator::Gte("age".to_string(), Value::Integer(18)))
169//!     .order_by(Sort::new("created_at", SortOrder::Desc))
170//!     .limit(10)
171//!     .offset(20);
172//!
173//! let (sql, params) = query.build()?;
174//! ```
175//!
176//! ### Cloudflare Workers Integration
177//!
178//! ```rust
179//! use worker::*;
180//! use libsql_orm::{Model, Database, MigrationManager, generate_migration};
181//!
182//! #[event(fetch)]
183//! async fn fetch(req: Request, env: Env, _ctx: Context) -> Result<Response> {
184//!     let database_url = env.var("LIBSQL_DATABASE_URL")?.to_string();
185//!     let auth_token = env.var("LIBSQL_AUTH_TOKEN")?.to_string();
186//!     
187//!     let db = Database::new_connect(&database_url, &auth_token).await
188//!         .map_err(|e| format!("Database connection failed: {}", e))?;
189//!     
190//!     // Your application logic here
191//!     let users = User::find_all(&db).await
192//!         .map_err(|e| format!("Query failed: {}", e))?;
193//!         
194//!     Response::from_json(&users)
195//! }
196//! ```
197pub mod database;
198pub mod error;
199pub mod filters;
200pub mod macros;
201pub mod migrations;
202pub mod model;
203pub mod pagination;
204pub mod query;
205pub mod types;
206
207#[cfg(test)]
208mod tests;
209
210pub use database::Database;
211pub use error::{Error, Result};
212pub use filters::{Filter, FilterOperator, SearchFilter, Sort};
213pub use migrations::{templates, Migration, MigrationBuilder, MigrationManager};
214pub use model::Model;
215pub use pagination::{CursorPaginatedResult, CursorPagination, PaginatedResult, Pagination};
216pub use query::{QueryBuilder, QueryResult};
217pub use types::*;
218
219// Export the boolean deserializer
220pub use types::deserialize_bool;
221
222// Re-export commonly used types
223pub use chrono;
224pub use serde::{Deserialize, Serialize};
225pub use uuid::Uuid;
226
227/// Re-export the Model macro for convenience
228pub use libsql_orm_macros::{generate_migration, orm_column, Model};