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
+26
View File
@@ -48,6 +48,7 @@ pub struct RepositoryManagerWrapper(pub RepositoryManager);
/// Create a new repository instance
/// Returns a handle (UUID) for accessing the repository
#[tauri::command]
#[specta::specta]
pub async fn repository_create(
manager: State<'_, RepositoryManagerWrapper>,
db: State<'_, crate::commands::storage::DatabaseWrapper>,
@@ -108,6 +109,7 @@ pub async fn repository_create(
/// Destroy a repository instance
#[tauri::command]
#[specta::specta]
pub async fn repository_destroy(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -118,6 +120,7 @@ pub async fn repository_destroy(
/// Get libraries
#[tauri::command]
#[specta::specta]
pub async fn repository_get_libraries(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -138,6 +141,7 @@ pub async fn repository_get_libraries(
/// Get items in a container (library, folder, album, etc.)
#[tauri::command]
#[specta::specta]
pub async fn repository_get_items(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -152,6 +156,7 @@ pub async fn repository_get_items(
/// Get a single item by ID
#[tauri::command]
#[specta::specta]
pub async fn repository_get_item(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -165,6 +170,7 @@ pub async fn repository_get_item(
/// Get latest items in a library
#[tauri::command]
#[specta::specta]
pub async fn repository_get_latest_items(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -179,6 +185,7 @@ pub async fn repository_get_latest_items(
/// Get resume items (continue watching/listening)
#[tauri::command]
#[specta::specta]
pub async fn repository_get_resume_items(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -201,6 +208,7 @@ pub async fn repository_get_resume_items(
/// Get next up episodes
#[tauri::command]
#[specta::specta]
pub async fn repository_get_next_up_episodes(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -215,6 +223,7 @@ pub async fn repository_get_next_up_episodes(
/// Get recently played audio
#[tauri::command]
#[specta::specta]
pub async fn repository_get_recently_played_audio(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -228,6 +237,7 @@ pub async fn repository_get_recently_played_audio(
/// Get resume movies
#[tauri::command]
#[specta::specta]
pub async fn repository_get_resume_movies(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -241,6 +251,7 @@ pub async fn repository_get_resume_movies(
/// Get genres for a library
#[tauri::command]
#[specta::specta]
pub async fn repository_get_genres(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -254,6 +265,7 @@ pub async fn repository_get_genres(
/// Search for items
#[tauri::command]
#[specta::specta]
pub async fn repository_search(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -268,6 +280,7 @@ pub async fn repository_search(
/// Get playback info for an item
#[tauri::command]
#[specta::specta]
pub async fn repository_get_playback_info(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -281,6 +294,7 @@ pub async fn repository_get_playback_info(
/// Get video stream URL with optional seeking support
#[tauri::command]
#[specta::specta]
pub async fn repository_get_video_stream_url(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -303,6 +317,7 @@ pub async fn repository_get_video_stream_url(
/// Get audio stream URL for a track
#[tauri::command]
#[specta::specta]
pub async fn repository_get_audio_stream_url(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -317,6 +332,7 @@ pub async fn repository_get_audio_stream_url(
/// Report playback start
#[tauri::command]
#[specta::specta]
pub async fn repository_report_playback_start(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -331,6 +347,7 @@ pub async fn repository_report_playback_start(
/// Report playback progress
#[tauri::command]
#[specta::specta]
pub async fn repository_report_playback_progress(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -345,6 +362,7 @@ pub async fn repository_report_playback_progress(
/// Report playback stopped
#[tauri::command]
#[specta::specta]
pub async fn repository_report_playback_stopped(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -359,6 +377,7 @@ pub async fn repository_report_playback_stopped(
/// Get image URL for an item
#[tauri::command]
#[specta::specta]
pub fn repository_get_image_url(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -372,6 +391,7 @@ pub fn repository_get_image_url(
/// Get subtitle URL for a media item
#[tauri::command]
#[specta::specta]
#[allow(dead_code)]
pub fn repository_get_subtitle_url(
manager: State<'_, RepositoryManagerWrapper>,
@@ -387,6 +407,7 @@ pub fn repository_get_subtitle_url(
/// Get video download URL with quality preset
#[tauri::command]
#[specta::specta]
#[allow(dead_code)]
pub fn repository_get_video_download_url(
manager: State<'_, RepositoryManagerWrapper>,
@@ -401,6 +422,7 @@ pub fn repository_get_video_download_url(
/// Mark an item as favorite
#[tauri::command]
#[specta::specta]
pub async fn repository_mark_favorite(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -414,6 +436,7 @@ pub async fn repository_mark_favorite(
/// Unmark an item as favorite
#[tauri::command]
#[specta::specta]
pub async fn repository_unmark_favorite(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -427,6 +450,7 @@ pub async fn repository_unmark_favorite(
/// Get person details
#[tauri::command]
#[specta::specta]
pub async fn repository_get_person(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -440,6 +464,7 @@ pub async fn repository_get_person(
/// Get items by person (actor, director, etc.)
#[tauri::command]
#[specta::specta]
pub async fn repository_get_items_by_person(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,
@@ -454,6 +479,7 @@ pub async fn repository_get_items_by_person(
/// Get similar/related items for a media item
#[tauri::command]
#[specta::specta]
pub async fn repository_get_similar_items(
manager: State<'_, RepositoryManagerWrapper>,
handle: String,