use std::{error::Error, fmt::Display}; use deadpool_postgres::{Object, Pool}; use serde::{Deserialize, Serialize}; use crate::error::{AppError, AppResult}; pub mod models; pub mod querys; #[derive(Clone)] pub struct Db { pool: Pool, } impl Db { pub fn new(pool: Pool) -> Self { Self { pool } } pub fn pool(&self) -> &Pool { &self.pool } pub async fn client(&self) -> AppResult { self.pool.get().await.map_err(db_error) } pub async fn health(&self) -> AppResult<()> { let client = self.client().await?; client.simple_query("SELECT 1").await.map_err(db_error)?; Ok(()) } } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub struct Pagination { pub limit: i64, pub offset: i64, } impl Pagination { pub const DEFAULT_LIMIT: i64 = 50; pub const MAX_LIMIT: i64 = 250; pub fn new(limit: i64, offset: i64) -> Self { Self { limit: limit.clamp(1, Self::MAX_LIMIT), offset: offset.max(0), } } } impl Default for Pagination { fn default() -> Self { Self::new(Self::DEFAULT_LIMIT, 0) } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Page { pub items: Vec, pub total: i64, pub limit: i64, pub offset: i64, } impl Page { pub fn new(items: Vec, total: i64, pagination: Pagination) -> Self { Self { items, total, limit: pagination.limit, offset: pagination.offset, } } } pub(crate) fn db_error(error: impl Display + Error) -> AppError { let mut message = error.to_string(); let mut source = error.source(); while let Some(cause) = source { message.push_str(": "); message.push_str(&cause.to_string()); source = cause.source(); } AppError::Database(message) }