feat(domain): add StoredSong, SongSummary, SongRepositoryPort
This commit is contained in:
@@ -7,5 +7,7 @@ pub mod transposer;
|
||||
pub use note::Note;
|
||||
pub use chord::Chord;
|
||||
pub use song::{ChordPosition, LyricLine, Section, SectionKind, SongMeta, Song};
|
||||
pub use song::{song_preview_chords, StoredSong, SongSummary};
|
||||
pub use ports::{FetchError, ParseError, TabFetcherPort, TabParserPort, TabSource};
|
||||
pub use ports::{RepositoryError, SongRepositoryPort};
|
||||
pub use transposer::{ChordTransposer, TransposeError};
|
||||
|
||||
@@ -35,3 +35,22 @@ pub trait TabFetcherPort: Send + Sync {
|
||||
pub trait TabParserPort: Send + Sync {
|
||||
fn parse(&self, html: &str) -> Result<Song, ParseError>;
|
||||
}
|
||||
|
||||
use uuid::Uuid;
|
||||
use crate::song::{StoredSong, SongSummary};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum RepositoryError {
|
||||
#[error("Song not found")]
|
||||
NotFound,
|
||||
#[error("Database error: {0}")]
|
||||
Internal(String),
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait SongRepositoryPort: Send + Sync {
|
||||
async fn save(&self, song: &Song) -> Result<StoredSong, RepositoryError>;
|
||||
async fn list(&self) -> Result<Vec<SongSummary>, RepositoryError>;
|
||||
async fn get(&self, id: Uuid) -> Result<Option<Song>, RepositoryError>;
|
||||
async fn delete(&self, id: Uuid) -> Result<(), RepositoryError>;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,40 @@ pub struct Song {
|
||||
pub sections: Vec<Section>,
|
||||
}
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct StoredSong {
|
||||
pub id: Uuid,
|
||||
pub song: Song,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SongSummary {
|
||||
pub id: Uuid,
|
||||
pub meta: SongMeta,
|
||||
pub preview_chords: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn song_preview_chords(song: &Song) -> Vec<String> {
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
let mut result = Vec::new();
|
||||
'outer: for section in &song.sections {
|
||||
for line in §ion.lines {
|
||||
for cp in &line.chords {
|
||||
let name = cp.chord.name(true);
|
||||
if seen.insert(name.clone()) {
|
||||
result.push(name);
|
||||
if result.len() >= 5 {
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user