Combine track search with live YouTube Music results

GET /tracks now merges the local catalog page with a live YouTube Music
search (deduplicated against tracks already provisioned locally) whenever a
name filter is given, appending the YouTube hits after the local matches and
carrying a continuation token for further pages. Each item is tagged with its
source via the new TrackSearchItemResponse/TracksSearchResponse shapes,
wrapping the existing TrackApplicationResponse or a raw YouTubeSongResult so
neither type had to change.

GET /youtube/search is removed along with its now-unused handler; the
web-player's explore page, its /api/tracks proxy, and the YouTube filler
helper are updated to call the combined endpoint instead of hitting the two
separately.
This commit is contained in:
2026-09-10 09:55:58 +02:00
parent c418844178
commit 92a06a3c15
15 changed files with 266 additions and 240 deletions
@@ -26,11 +26,6 @@ export const load: PageServerLoad = async ({ url, locals, fetch }) => {
params: { query: { name: query || undefined, pageNumber: page, pageSize: PAGE_SIZE } }
});
const searchPromise =
query.length >= SEARCH_MIN_LENGTH
? api.GET('/youtube/search', { params: { query: { query } } })
: Promise.resolve(null);
const playlistsPromise = api.GET('/playlists/users/{userId}', {
params: { path: { userId: user.sub }, query: { pageNumber: 1, pageSize: 50 } }
});
@@ -46,9 +41,8 @@ export const load: PageServerLoad = async ({ url, locals, fetch }) => {
? api.GET('/youtube/albums', { params: { query: { query } } })
: Promise.resolve(null);
const [tracksRes, searchRes, playlistsRes, albumsRes, youtubeAlbumsRes] = await Promise.all([
const [tracksRes, playlistsRes, albumsRes, youtubeAlbumsRes] = await Promise.all([
tracksPromise,
searchPromise,
playlistsPromise,
albumsPromise,
youtubeAlbumsPromise
@@ -61,8 +55,6 @@ export const load: PageServerLoad = async ({ url, locals, fetch }) => {
tracks,
albums: albumsRes?.data?.items ?? [],
youtubeAlbums: youtubeAlbumsRes?.data?.items ?? [],
ytResults: searchRes?.data ?? null,
ytError: Boolean(searchRes?.error),
users: searchUsers(query),
youtubeFiller: query
? Promise.resolve(null)