From 0438daa6e36bda2992a4777f66edd23c8d51b5d4 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 24 Nov 2025 02:27:48 -0800 Subject: [PATCH] fix: replace any types in Apple Music client (10 errors) Phase 1 Batch 6: Apple Music Client type safety improvements Fixed 10 any-type errors in 1 file: src/lib/server/apple-music-client.ts (10 errors) - Created ExtendedAppleMusicAlbum interface with _storefront property - Created ExtendedAttributes interface for synthetic album attributes - Created SyntheticAlbum interface for song-to-album conversions - Fixed findAlbum: first matchedAlbum cast (line 336) - Fixed findAlbum: second matchedAlbum cast (line 409) - Fixed findAlbum: synthetic album return type (line 433) - Fixed transformAlbumData: parameter type to AppleMusicAlbum | SyntheticAlbum - Fixed transformAlbumData: isSingle check using ExtendedAttributes (lines 465-471) - Fixed transformAlbumData: _storefront access using ExtendedAppleMusicAlbum (line 480) - Fixed transformAlbumData: tracks filter/map to use AppleMusicTrack type (lines 498-499) Progress: 22 any-type errors remaining (down from 32) --- src/lib/server/apple-music-client.ts | 39 +++++++++++++++++++++------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/lib/server/apple-music-client.ts b/src/lib/server/apple-music-client.ts index 26e84a3..9dd52bb 100644 --- a/src/lib/server/apple-music-client.ts +++ b/src/lib/server/apple-music-client.ts @@ -8,6 +8,23 @@ import { isAppleMusicError } from '$lib/types/apple-music' import { ApiRateLimiter } from './rate-limiter' import { logger } from './logger' +// Extended types for Apple Music data with custom metadata +interface ExtendedAppleMusicAlbum extends AppleMusicAlbum { + _storefront?: string +} + +interface ExtendedAttributes { + isSingle?: boolean + _singleSongId?: string + _singleSongPreview?: string + [key: string]: unknown +} + +interface SyntheticAlbum extends Omit { + attributes: AppleMusicAlbum['attributes'] & ExtendedAttributes + _storefront?: string +} + const APPLE_MUSIC_API_BASE = 'https://api.music.apple.com/v1' const DEFAULT_STOREFRONT = 'us' // Default to US storefront const JAPANESE_STOREFRONT = 'jp' // Japanese storefront @@ -316,7 +333,7 @@ export async function findAlbum(artist: string, album: string): Promise = [] // Check if this is a synthetic single album - if ((attributes as any).isSingle && (attributes as any)._singleSongPreview) { + const extendedAttrs = attributes as ExtendedAttributes + if (extendedAttrs.isSingle && extendedAttrs._singleSongPreview) { logger.music('debug', 'Processing synthetic single album') - previewUrl = (attributes as any)._singleSongPreview + previewUrl = extendedAttrs._singleSongPreview tracks = [{ name: attributes.name, - previewUrl: (attributes as any)._singleSongPreview, + previewUrl: extendedAttrs._singleSongPreview, durationMs: undefined // We'd need to fetch the song details for duration }] } @@ -458,7 +476,8 @@ export async function transformAlbumData(appleMusicAlbum: AppleMusicAlbum) { else if (appleMusicAlbum.id) { try { // Determine which storefront to use - const storefront = (appleMusicAlbum as any)._storefront || DEFAULT_STOREFRONT + const extendedAlbum = appleMusicAlbum as ExtendedAppleMusicAlbum + const storefront = extendedAlbum._storefront || DEFAULT_STOREFRONT // Fetch album details with tracks const endpoint = `/catalog/${storefront}/albums/${appleMusicAlbum.id}?include=tracks` @@ -476,8 +495,8 @@ export async function transformAlbumData(appleMusicAlbum: AppleMusicAlbum) { // Process all tracks tracks = tracksData - .filter((item: any) => item.type === 'songs') - .map((track: any) => { + .filter((item: AppleMusicTrack) => item.type === 'songs') + .map((track: AppleMusicTrack) => { return { name: track.attributes?.name || 'Unknown', previewUrl: track.attributes?.previews?.[0]?.url,