use domain::{DomainError, SongMeta, SongSummary, SortField, SortOrder}; use uuid::Uuid; #[derive(sqlx::FromRow)] pub(crate) struct SongRow { pub(crate) id: String, pub(crate) title: String, pub(crate) artist: String, pub(crate) original_key: Option, pub(crate) preview_chords: String, pub(crate) body: String, } pub(crate) fn sort_clause(field: SortField, order: SortOrder) -> &'static str { match (field, order) { (SortField::Title, SortOrder::Asc) => "ORDER BY title ASC", (SortField::Title, SortOrder::Desc) => "ORDER BY title DESC", (SortField::Artist, SortOrder::Asc) => "ORDER BY artist ASC", (SortField::Artist, SortOrder::Desc) => "ORDER BY artist DESC", (SortField::Date, SortOrder::Asc) => "ORDER BY created_at ASC", (SortField::Date, SortOrder::Desc) => "ORDER BY created_at DESC", } } pub(crate) fn row_to_summary(row: SongRow) -> Result { let id = Uuid::parse_str(&row.id).map_err(|e| DomainError::InfrastructureError(e.to_string()))?; let preview_chords: Vec = serde_json::from_str(&row.preview_chords) .map_err(|e| DomainError::InfrastructureError(e.to_string()))?; Ok(SongSummary { id, meta: SongMeta { title: row.title, artist: row.artist, original_key: row.original_key, capo: None, tuning: None, tempo: None, }, preview_chords, }) }