From fb5dee0701852ec019ebdd896ab690e277e98495 Mon Sep 17 00:00:00 2001 From: Psychotoxical <171614930+Psychotoxical@users.noreply.github.com> Date: Wed, 1 Jul 2026 14:58:25 +0200 Subject: [PATCH] refactor(ipc): consume generated bindings for library catalog/genre reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FE cutover for the D1 slice: libraryGetCatalogYearBounds and libraryGetGenreAlbumCounts now call the generated commands.* bindings instead of a hand-written invoke('cmd', ...), unwrapping the specta Result union (rethrow on error — behavior-preserving). The duplicated hand DTOs collapse into named aliases of the generated CatalogYearBoundsDto / GenreAlbumCountDto, so the shape lives in one place (the contract) and consumers stay unchanged. Verified the guard end to end: a serde-rename of the Rust field (contract change, Rust still compiles) regenerated bindings and made tsc fail at the FE consumer; reverted. cargo + tsc now enforce this slice's contract at compile time. --- src/lib/api/library/dto.ts | 15 +++++---------- src/lib/api/library/stats.ts | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/lib/api/library/dto.ts b/src/lib/api/library/dto.ts index 44c88788..cba26fca 100644 --- a/src/lib/api/library/dto.ts +++ b/src/lib/api/library/dto.ts @@ -4,6 +4,7 @@ * `lib/api/library.ts` god-module; the wrappers (reads/sync/stats/events) and the * `@/lib/api/library` barrel re-export these, so consumers are unchanged. */ +import type { CatalogYearBoundsDto, GenreAlbumCountDto } from '@/generated/bindings'; export interface TrackRefDto { serverId: string; @@ -363,16 +364,10 @@ export type PlaySessionYearBounds = { maxYear: number | null; }; -export type CatalogYearBounds = { - minYear: number | null; - maxYear: number | null; -}; - -export type GenreAlbumCountRow = { - value: string; - albumCount: number; - songCount: number; -}; +// Sourced from the tauri-specta contract (single source of truth); kept as named +// aliases so existing consumers stay unchanged while the shape lives in one place. +export type CatalogYearBounds = CatalogYearBoundsDto; +export type GenreAlbumCountRow = GenreAlbumCountDto; export type LibraryGenreAlbumsRequest = { serverId: string; diff --git a/src/lib/api/library/stats.ts b/src/lib/api/library/stats.ts index c6d43355..bf6d8580 100644 --- a/src/lib/api/library/stats.ts +++ b/src/lib/api/library/stats.ts @@ -4,6 +4,7 @@ * `@/lib/api/library` barrel. */ import { invoke } from '@tauri-apps/api/core'; +import { commands } from '@/generated/bindings'; import { serverIndexKeyForId, mapServerIdFromIndexKey } from './internal'; import type { CatalogYearBounds, @@ -19,22 +20,23 @@ import type { PlaySessionRecentTrack, } from './dto'; -export function libraryGetCatalogYearBounds(args: { serverId: string }): Promise { +export async function libraryGetCatalogYearBounds(args: { + serverId: string; +}): Promise { const indexKey = serverIndexKeyForId(args.serverId); - return invoke('library_get_catalog_year_bounds', { - serverId: indexKey, - }); + const res = await commands.libraryGetCatalogYearBounds(indexKey); + if (res.status === 'error') throw new Error(res.error); + return res.data; } -export function libraryGetGenreAlbumCounts(args: { +export async function libraryGetGenreAlbumCounts(args: { serverId: string; libraryScope?: string; }): Promise { const indexKey = serverIndexKeyForId(args.serverId); - return invoke('library_get_genre_album_counts', { - serverId: indexKey, - libraryScope: args.libraryScope, - }); + const res = await commands.libraryGetGenreAlbumCounts(indexKey, args.libraryScope ?? null); + if (res.status === 'error') throw new Error(res.error); + return res.data; } /** Paginated albums for one genre from the local track index. */