use anyhow::Result; use serde_json::Value; use sqlx::PgPool; use uuid::Uuid; #[derive(Debug, serde::Serialize)] pub struct HistoryEntry { pub version: i64, pub action: String, pub created_at: String, } pub async fn run( pool: &PgPool, namespace: &str, kind: &str, name: &str, limit: u32, user_id: Option, ) -> Result> { #[derive(sqlx::FromRow)] struct Row { version: i64, action: String, created_at: chrono::DateTime, } let rows: Vec = if let Some(uid) = user_id { sqlx::query_as( "SELECT version, action, created_at FROM entries_history \ WHERE namespace = $1 AND kind = $2 AND name = $3 AND user_id = $4 \ ORDER BY id DESC LIMIT $5", ) .bind(namespace) .bind(kind) .bind(name) .bind(uid) .bind(limit as i64) .fetch_all(pool) .await? } else { sqlx::query_as( "SELECT version, action, created_at FROM entries_history \ WHERE namespace = $1 AND kind = $2 AND name = $3 AND user_id IS NULL \ ORDER BY id DESC LIMIT $4", ) .bind(namespace) .bind(kind) .bind(name) .bind(limit as i64) .fetch_all(pool) .await? }; Ok(rows .into_iter() .map(|r| HistoryEntry { version: r.version, action: r.action, created_at: r.created_at.format("%Y-%m-%dT%H:%M:%SZ").to_string(), }) .collect()) } pub async fn run_json( pool: &PgPool, namespace: &str, kind: &str, name: &str, limit: u32, user_id: Option, ) -> Result { let entries = run(pool, namespace, kind, name, limit, user_id).await?; Ok(serde_json::to_value(entries)?) }