Workstream E (backend): wire tauri-specta — annotate commands, derive Type, generate-ready Builder

- Add #[specta::specta] to all 201 #[tauri::command] functions.
- Derive specta::Type on all IPC DTOs (repository/types, settings, player/storage/
  download command DTOs, player enums, jellyfin SessionInfo/NowPlayingItem/PlayState,
  ThumbnailCacheStats, DownloadInfo, CacheConfig, etc.).
- Replace tauri::generate_handler! with a tauri_specta::Builder + collect_commands!
  in lib.rs (exports bindings.ts in debug builds).

Two contract changes required by specta constraints (frontend migration follows):
- specta caps command arity at 10 args: download_item_and_start / download_item /
  download_video now take a single request struct (params bundled, body unchanged
  via destructuring).
- specta can't parse split serde rename_all: SessionInfo/NowPlayingItem/PlayState
  switched to rename_all = "PascalCase" (Jellyfin deserialization preserved; these
  now serialize PascalCase to the frontend).

cargo check --lib is clean (0 errors). Frontend migration to bindings.ts is the next step.
This commit is contained in:
2026-06-20 18:20:25 +02:00
parent 55f1b85f12
commit ada3ed64ab
40 changed files with 598 additions and 354 deletions
@@ -8,7 +8,7 @@ use crate::commands::{DatabaseWrapper, SmartCacheWrapper};
use crate::storage::db_service::{DatabaseService, Query, QueryParam};
/// SmartCache statistics
#[derive(Debug, Clone, serde::Serialize)]
#[derive(specta::Type, Debug, Clone, serde::Serialize)]
pub struct SmartCacheStats {
pub total_size: u64,
pub storage_limit: u64,
@@ -19,6 +19,7 @@ pub struct SmartCacheStats {
/// Get SmartCache statistics
#[tauri::command]
#[specta::specta]
pub async fn get_smart_cache_stats(
db: State<'_, DatabaseWrapper>,
smart_cache: State<'_, SmartCacheWrapper>,
@@ -67,6 +68,7 @@ pub async fn get_smart_cache_stats(
/// Update SmartCache configuration
#[tauri::command]
#[specta::specta]
pub async fn update_smart_cache_config(
smart_cache: State<'_, SmartCacheWrapper>,
config: crate::download::cache::CacheConfig,
@@ -79,6 +81,7 @@ pub async fn update_smart_cache_config(
/// Get SmartCache configuration
#[tauri::command]
#[specta::specta]
pub async fn get_smart_cache_config(
smart_cache: State<'_, SmartCacheWrapper>,
) -> Result<crate::download::cache::CacheConfig, String> {
@@ -89,7 +92,7 @@ pub async fn get_smart_cache_config(
}
/// Album recommendation info
#[derive(Debug, Clone, serde::Serialize)]
#[derive(specta::Type, Debug, Clone, serde::Serialize)]
pub struct AlbumRecommendation {
pub album_id: String,
pub album_name: String,
@@ -99,7 +102,7 @@ pub struct AlbumRecommendation {
}
/// Album affinity status info
#[derive(Debug, Clone, serde::Serialize)]
#[derive(specta::Type, Debug, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AlbumAffinityStatus {
pub album_id: String,
@@ -110,6 +113,7 @@ pub struct AlbumAffinityStatus {
/// Get album recommendations based on play history
#[tauri::command]
#[specta::specta]
pub async fn get_album_recommendations(
db: State<'_, DatabaseWrapper>,
smart_cache: State<'_, SmartCacheWrapper>,
@@ -189,6 +193,7 @@ pub async fn get_album_recommendations(
/// Get album affinity status for all tracked albums
/// This shows the SmartCache's internal play history and threshold status
#[tauri::command]
#[specta::specta]
pub fn get_album_affinity_status(
smart_cache: State<'_, SmartCacheWrapper>,
) -> Result<Vec<AlbumAffinityStatus>, String> {