refactor(application): strip comments, DRY ownership check + parse_content_type
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
/// Trigger a library sync for one or all providers.
|
||||
pub struct TriggerSyncCommand {
|
||||
/// Provider to sync. `None` means sync all registered providers.
|
||||
pub provider_id: Option<String>,
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ use std::sync::Arc;
|
||||
|
||||
use domain::ports::{EventPublisher, IProviderRegistry, LibraryCommand, LibraryQuery, LibrarySyncAdapter};
|
||||
|
||||
/// Dependencies for library write use cases (trigger sync).
|
||||
pub struct LibraryCommandDeps {
|
||||
pub library_command: Arc<dyn LibraryCommand>,
|
||||
pub library_query: Arc<dyn LibraryQuery>,
|
||||
@@ -11,7 +10,6 @@ pub struct LibraryCommandDeps {
|
||||
pub event_publisher: Arc<dyn EventPublisher>,
|
||||
}
|
||||
|
||||
/// Dependencies for library read use cases (search, list, get).
|
||||
pub struct LibraryQueryDeps {
|
||||
pub library_query: Arc<dyn LibraryQuery>,
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ use domain::DomainResult;
|
||||
use super::deps::LibraryQueryDeps;
|
||||
use super::queries::GetItemQuery;
|
||||
|
||||
/// Get a single library item by its composite ID.
|
||||
pub async fn execute(
|
||||
deps: &LibraryQueryDeps,
|
||||
query: GetItemQuery,
|
||||
|
||||
@@ -4,7 +4,6 @@ use domain::DomainResult;
|
||||
use super::deps::LibraryQueryDeps;
|
||||
use super::queries::GetSyncStatusQuery;
|
||||
|
||||
/// Get the latest sync status per provider.
|
||||
pub async fn execute(
|
||||
deps: &LibraryQueryDeps,
|
||||
_query: GetSyncStatusQuery,
|
||||
|
||||
@@ -4,7 +4,6 @@ use domain::DomainResult;
|
||||
use super::deps::LibraryQueryDeps;
|
||||
use super::queries::ListCollectionsQuery;
|
||||
|
||||
/// List library collections, optionally filtered by provider.
|
||||
pub async fn execute(
|
||||
deps: &LibraryQueryDeps,
|
||||
query: ListCollectionsQuery,
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use domain::errors::{DomainError, DomainResult};
|
||||
use domain::value_objects::ContentType;
|
||||
use domain::DomainResult;
|
||||
|
||||
use super::deps::LibraryQueryDeps;
|
||||
use super::parse_content_type;
|
||||
use super::queries::ListGenresQuery;
|
||||
|
||||
/// List genres available in the library, optionally filtered.
|
||||
pub async fn execute(deps: &LibraryQueryDeps, query: ListGenresQuery) -> DomainResult<Vec<String>> {
|
||||
let content_type = query
|
||||
.content_type
|
||||
@@ -17,17 +16,6 @@ pub async fn execute(deps: &LibraryQueryDeps, query: ListGenresQuery) -> DomainR
|
||||
.await
|
||||
}
|
||||
|
||||
fn parse_content_type(s: &str) -> DomainResult<ContentType> {
|
||||
match s {
|
||||
"movie" => Ok(ContentType::Movie),
|
||||
"episode" => Ok(ContentType::Episode),
|
||||
"short" => Ok(ContentType::Short),
|
||||
other => Err(DomainError::ValidationError(format!(
|
||||
"Unknown content type '{other}'. Use movie, episode, or short."
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/list_genres.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -4,7 +4,6 @@ use domain::DomainResult;
|
||||
use super::deps::LibraryQueryDeps;
|
||||
use super::queries::ListSeasonsQuery;
|
||||
|
||||
/// List season summaries for a specific series.
|
||||
pub async fn execute(
|
||||
deps: &LibraryQueryDeps,
|
||||
query: ListSeasonsQuery,
|
||||
|
||||
@@ -4,7 +4,6 @@ use domain::DomainResult;
|
||||
use super::deps::LibraryQueryDeps;
|
||||
use super::queries::ListShowsQuery;
|
||||
|
||||
/// List TV show summaries, optionally filtered.
|
||||
pub async fn execute(
|
||||
deps: &LibraryQueryDeps,
|
||||
query: ListShowsQuery,
|
||||
|
||||
@@ -16,3 +16,17 @@ pub use queries::{
|
||||
GetItemQuery, GetSyncStatusQuery, ListCollectionsQuery, ListGenresQuery, ListSeasonsQuery,
|
||||
ListShowsQuery, SearchItemsQuery,
|
||||
};
|
||||
|
||||
use domain::errors::{DomainError, DomainResult};
|
||||
use domain::value_objects::ContentType;
|
||||
|
||||
pub(crate) fn parse_content_type(s: &str) -> DomainResult<ContentType> {
|
||||
match s {
|
||||
"movie" => Ok(ContentType::Movie),
|
||||
"episode" => Ok(ContentType::Episode),
|
||||
"short" => Ok(ContentType::Short),
|
||||
other => Err(DomainError::ValidationError(format!(
|
||||
"Unknown content type '{other}'. Use movie, episode, or short."
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/// Search library items with filters.
|
||||
pub struct SearchItemsQuery {
|
||||
pub provider_id: Option<String>,
|
||||
pub content_type: Option<String>,
|
||||
@@ -12,34 +11,28 @@ pub struct SearchItemsQuery {
|
||||
pub limit: u32,
|
||||
}
|
||||
|
||||
/// List library collections.
|
||||
pub struct ListCollectionsQuery {
|
||||
pub provider_id: Option<String>,
|
||||
}
|
||||
|
||||
/// List TV show summaries.
|
||||
pub struct ListShowsQuery {
|
||||
pub provider_id: Option<String>,
|
||||
pub search_term: Option<String>,
|
||||
pub genres: Vec<String>,
|
||||
}
|
||||
|
||||
/// List seasons for a specific series.
|
||||
pub struct ListSeasonsQuery {
|
||||
pub series_name: String,
|
||||
pub provider_id: Option<String>,
|
||||
}
|
||||
|
||||
/// List genres available in the library.
|
||||
pub struct ListGenresQuery {
|
||||
pub content_type: Option<String>,
|
||||
pub provider_id: Option<String>,
|
||||
}
|
||||
|
||||
/// Get a single library item by its composite ID.
|
||||
pub struct GetItemQuery {
|
||||
pub item_id: String,
|
||||
}
|
||||
|
||||
/// Get the latest sync status per provider.
|
||||
pub struct GetSyncStatusQuery;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use domain::errors::{DomainError, DomainResult};
|
||||
use domain::DomainResult;
|
||||
use domain::models::LibraryItem;
|
||||
use domain::value_objects::{ContentType, LibrarySearchFilter};
|
||||
use domain::value_objects::LibrarySearchFilter;
|
||||
|
||||
use super::deps::LibraryQueryDeps;
|
||||
use super::parse_content_type;
|
||||
use super::queries::SearchItemsQuery;
|
||||
|
||||
/// Search library items with filters. Returns `(items, total_count)`.
|
||||
pub async fn execute(
|
||||
deps: &LibraryQueryDeps,
|
||||
query: SearchItemsQuery,
|
||||
@@ -48,17 +48,6 @@ pub async fn execute(
|
||||
deps.library_query.search(&filter).await
|
||||
}
|
||||
|
||||
fn parse_content_type(s: &str) -> DomainResult<ContentType> {
|
||||
match s {
|
||||
"movie" => Ok(ContentType::Movie),
|
||||
"episode" => Ok(ContentType::Episode),
|
||||
"short" => Ok(ContentType::Short),
|
||||
other => Err(DomainError::ValidationError(format!(
|
||||
"Unknown content type '{other}'. Use movie, episode, or short."
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/search.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -3,15 +3,6 @@ use domain::errors::{DomainError, DomainResult};
|
||||
use super::commands::TriggerSyncCommand;
|
||||
use super::deps::LibraryCommandDeps;
|
||||
|
||||
/// Validate and return provider IDs eligible for sync.
|
||||
///
|
||||
/// Checks that no sync is already running for the targeted provider(s).
|
||||
/// Returns the list of provider IDs to sync. The caller (API layer) is
|
||||
/// responsible for spawning the actual sync tasks, since `LibrarySyncAdapter`
|
||||
/// requires `&dyn IMediaProvider` references that only the infra layer holds.
|
||||
///
|
||||
/// Returns `Err(ValidationError)` if any targeted provider is already syncing
|
||||
/// (maps to 409 Conflict at the API layer).
|
||||
pub async fn execute(
|
||||
deps: &LibraryCommandDeps,
|
||||
cmd: TriggerSyncCommand,
|
||||
|
||||
Reference in New Issue
Block a user