refactor(domain): Row structs for from_persistence, ID newtypes, kill clippy.toml

- delete clippy.toml (too-many-arguments-threshold=20 hack)
- ChannelRow/MediaItemRow/LibraryItemRow structs for from_persistence
- SnapshotId/ActivityEventId/PlaybackRecordId newtypes
- DomainError variants use ChannelId/UserId instead of Uuid
- ActivityEvent.channel_id: Option<ChannelId> not Option<Uuid>
- InMemory repos key on newtype IDs
- AlgorithmicParams struct for schedule engine
- update all adapters/application/presentation callers
This commit is contained in:
2026-07-12 05:00:49 +02:00
parent 031cba5cfb
commit c0e685a4ee
65 changed files with 684 additions and 695 deletions

View File

@@ -1,4 +1,4 @@
use domain::models::LibraryItem;
use domain::models::{LibraryItem, LibraryItemRow};
use domain::value_objects::ContentType;
use crate::library::list_collections;
@@ -10,46 +10,46 @@ mod helpers;
fn seed_with_collections(repo: &std::sync::Arc<domain::testing::InMemoryLibraryRepository>) {
let mut store = repo.items.lock().unwrap();
let item = LibraryItem::from_persistence(
"test::m1".into(),
"test".into(),
"m1".into(),
"Die Hard".into(),
ContentType::Movie,
7800,
None,
None,
None,
None,
vec![],
vec![],
Some("col-1".into()),
Some("Movies".into()),
Some("movies".into()),
None,
"2026-01-01".into(),
);
let item = LibraryItem::from_persistence(LibraryItemRow {
id: "test::m1".into(),
provider_id: "test".into(),
external_id: "m1".into(),
title: "Die Hard".into(),
content_type: ContentType::Movie,
duration_secs: 7800,
series_name: None,
season_number: None,
episode_number: None,
year: None,
genres: vec![],
tags: vec![],
collection_id: Some("col-1".into()),
collection_name: Some("Movies".into()),
collection_type: Some("movies".into()),
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
store.insert(item.id().to_string(), item);
let item2 = LibraryItem::from_persistence(
"test::e1".into(),
"test".into(),
"e1".into(),
"BB S01E01".into(),
ContentType::Episode,
2700,
Some("Breaking Bad".into()),
Some(1),
Some(1),
None,
vec![],
vec![],
Some("col-2".into()),
Some("TV Shows".into()),
Some("tvshows".into()),
None,
"2026-01-01".into(),
);
let item2 = LibraryItem::from_persistence(LibraryItemRow {
id: "test::e1".into(),
provider_id: "test".into(),
external_id: "e1".into(),
title: "BB S01E01".into(),
content_type: ContentType::Episode,
duration_secs: 2700,
series_name: Some("Breaking Bad".into()),
season_number: Some(1),
episode_number: Some(1),
year: None,
genres: vec![],
tags: vec![],
collection_id: Some("col-2".into()),
collection_name: Some("TV Shows".into()),
collection_type: Some("tvshows".into()),
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
store.insert(item2.id().to_string(), item2);
}

View File

@@ -1,4 +1,4 @@
use domain::models::LibraryItem;
use domain::models::{LibraryItem, LibraryItemRow};
use domain::value_objects::ContentType;
use crate::library::list_genres;
@@ -10,44 +10,44 @@ mod helpers;
fn seed_with_genres(repo: &std::sync::Arc<domain::testing::InMemoryLibraryRepository>) {
let mut store = repo.items.lock().unwrap();
let item1 = LibraryItem::from_persistence(
"test::m1".into(),
"test".into(),
"m1".into(),
"Die Hard".into(),
ContentType::Movie,
7800,
None,
None,
None,
None,
vec!["Action".into(), "Thriller".into()],
vec![],
None,
None,
None,
None,
"2026-01-01".into(),
);
let item2 = LibraryItem::from_persistence(
"test::m2".into(),
"test".into(),
"m2".into(),
"Alien".into(),
ContentType::Movie,
7020,
None,
None,
None,
None,
vec!["Sci-Fi".into(), "Action".into()],
vec![],
None,
None,
None,
None,
"2026-01-01".into(),
);
let item1 = LibraryItem::from_persistence(LibraryItemRow {
id: "test::m1".into(),
provider_id: "test".into(),
external_id: "m1".into(),
title: "Die Hard".into(),
content_type: ContentType::Movie,
duration_secs: 7800,
series_name: None,
season_number: None,
episode_number: None,
year: None,
genres: vec!["Action".into(), "Thriller".into()],
tags: vec![],
collection_id: None,
collection_name: None,
collection_type: None,
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
let item2 = LibraryItem::from_persistence(LibraryItemRow {
id: "test::m2".into(),
provider_id: "test".into(),
external_id: "m2".into(),
title: "Alien".into(),
content_type: ContentType::Movie,
duration_secs: 7020,
series_name: None,
season_number: None,
episode_number: None,
year: None,
genres: vec!["Sci-Fi".into(), "Action".into()],
tags: vec![],
collection_id: None,
collection_name: None,
collection_type: None,
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
store.insert(item1.id().to_string(), item1);
store.insert(item2.id().to_string(), item2);

View File

@@ -1,4 +1,4 @@
use domain::models::LibraryItem;
use domain::models::{LibraryItem, LibraryItemRow};
use domain::value_objects::ContentType;
use crate::library::list_seasons;
@@ -11,25 +11,25 @@ fn seed_episodes(repo: &std::sync::Arc<domain::testing::InMemoryLibraryRepositor
let mut store = repo.items.lock().unwrap();
for (i, season) in [1u32, 1, 2, 2, 2, 3].iter().enumerate() {
let item = LibraryItem::from_persistence(
format!("test::e{i}"),
"test".into(),
format!("e{i}"),
format!("BB S{season:02}E{:02}", i + 1),
ContentType::Episode,
2700,
Some("Breaking Bad".into()),
Some(*season),
Some(i as u32 + 1),
None,
vec![],
vec![],
None,
None,
None,
None,
"2026-01-01".into(),
);
let item = LibraryItem::from_persistence(LibraryItemRow {
id: format!("test::e{i}"),
provider_id: "test".into(),
external_id: format!("e{i}"),
title: format!("BB S{season:02}E{:02}", i + 1),
content_type: ContentType::Episode,
duration_secs: 2700,
series_name: Some("Breaking Bad".into()),
season_number: Some(*season),
episode_number: Some(i as u32 + 1),
year: None,
genres: vec![],
tags: vec![],
collection_id: None,
collection_name: None,
collection_type: None,
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
store.insert(item.id().to_string(), item);
}
}

View File

@@ -1,4 +1,4 @@
use domain::models::LibraryItem;
use domain::models::{LibraryItem, LibraryItemRow};
use domain::value_objects::ContentType;
use crate::library::list_shows;
@@ -20,25 +20,25 @@ fn seed_episodes(repo: &std::sync::Arc<domain::testing::InMemoryLibraryRepositor
.iter()
.enumerate()
{
let item = LibraryItem::from_persistence(
format!("test::e{i}"),
"test".into(),
format!("e{i}"),
format!("{series} S{season:02}E{i:02}"),
ContentType::Episode,
2700,
Some(series.to_string()),
Some(*season),
Some(i as u32 + 1),
None,
vec![],
vec![],
None,
None,
None,
None,
"2026-01-01".into(),
);
let item = LibraryItem::from_persistence(LibraryItemRow {
id: format!("test::e{i}"),
provider_id: "test".into(),
external_id: format!("e{i}"),
title: format!("{series} S{season:02}E{i:02}"),
content_type: ContentType::Episode,
duration_secs: 2700,
series_name: Some(series.to_string()),
season_number: Some(*season),
episode_number: Some(i as u32 + 1),
year: None,
genres: vec![],
tags: vec![],
collection_id: None,
collection_name: None,
collection_type: None,
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
store.insert(item.id().to_string(), item);
}
}

View File

@@ -1,4 +1,4 @@
use domain::models::LibraryItem;
use domain::models::{LibraryItem, LibraryItemRow};
use domain::value_objects::ContentType;
use crate::library::queries::SearchItemsQuery;
@@ -22,63 +22,63 @@ fn seed_items(repo: &std::sync::Arc<domain::testing::InMemoryLibraryRepository>)
fn seed_items_with_genres(repo: &std::sync::Arc<domain::testing::InMemoryLibraryRepository>) {
let mut store = repo.items.lock().unwrap();
let action = LibraryItem::from_persistence(
"test::m1".into(),
"test".into(),
"m1".into(),
"Die Hard".into(),
ContentType::Movie,
7800,
None,
None,
None,
Some(1988),
vec!["Action".into(), "Thriller".into()],
vec![],
None,
None,
None,
None,
"2026-01-01".into(),
);
let scifi = LibraryItem::from_persistence(
"test::m2".into(),
"test".into(),
"m2".into(),
"Alien".into(),
ContentType::Movie,
7020,
None,
None,
None,
Some(1979),
vec!["Sci-Fi".into(), "Horror".into()],
vec![],
None,
None,
None,
None,
"2026-01-01".into(),
);
let comedy = LibraryItem::from_persistence(
"test::m3".into(),
"test".into(),
"m3".into(),
"Airplane!".into(),
ContentType::Movie,
5280,
None,
None,
None,
Some(1980),
vec!["Comedy".into()],
vec![],
None,
None,
None,
None,
"2026-01-01".into(),
);
let action = LibraryItem::from_persistence(LibraryItemRow {
id: "test::m1".into(),
provider_id: "test".into(),
external_id: "m1".into(),
title: "Die Hard".into(),
content_type: ContentType::Movie,
duration_secs: 7800,
series_name: None,
season_number: None,
episode_number: None,
year: Some(1988),
genres: vec!["Action".into(), "Thriller".into()],
tags: vec![],
collection_id: None,
collection_name: None,
collection_type: None,
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
let scifi = LibraryItem::from_persistence(LibraryItemRow {
id: "test::m2".into(),
provider_id: "test".into(),
external_id: "m2".into(),
title: "Alien".into(),
content_type: ContentType::Movie,
duration_secs: 7020,
series_name: None,
season_number: None,
episode_number: None,
year: Some(1979),
genres: vec!["Sci-Fi".into(), "Horror".into()],
tags: vec![],
collection_id: None,
collection_name: None,
collection_type: None,
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
let comedy = LibraryItem::from_persistence(LibraryItemRow {
id: "test::m3".into(),
provider_id: "test".into(),
external_id: "m3".into(),
title: "Airplane!".into(),
content_type: ContentType::Movie,
duration_secs: 5280,
series_name: None,
season_number: None,
episode_number: None,
year: Some(1980),
genres: vec!["Comedy".into()],
tags: vec![],
collection_id: None,
collection_name: None,
collection_type: None,
thumbnail_url: None,
synced_at: "2026-01-01".into(),
});
store.insert(action.id().to_string(), action);
store.insert(scifi.id().to_string(), scifi);