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)
This commit is contained in:
Justin Edmund 2025-11-24 02:27:48 -08:00
parent 9f2854bfdc
commit 0438daa6e3

View file

@ -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<AppleMusicAlbum, 'attributes'> {
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<AppleMus
if (result) {
// Store the storefront information with the album
const matchedAlbum = result.album as any
const matchedAlbum = result.album as ExtendedAppleMusicAlbum
matchedAlbum._storefront = result.storefront
return result.album
}
@ -389,7 +406,7 @@ export async function findAlbum(artist: string, album: string): Promise<AppleMus
const albumResponse = await searchAlbums(`${artist} ${albumName}`, 5, storefront)
if (albumResponse.results?.albums?.data?.length) {
const album = albumResponse.results.albums.data[0]
const matchedAlbum = album as any
const matchedAlbum = album as ExtendedAppleMusicAlbum
matchedAlbum._storefront = storefront
return album
}
@ -413,7 +430,7 @@ export async function findAlbum(artist: string, album: string): Promise<AppleMus
_singleSongPreview: matchingSong.attributes?.previews?.[0]?.url
},
_storefront: storefront
} as any
} as SyntheticAlbum
}
}
} catch (error) {
@ -437,7 +454,7 @@ export async function findAlbum(artist: string, album: string): Promise<AppleMus
}
// Transform Apple Music album data to match existing format
export async function transformAlbumData(appleMusicAlbum: AppleMusicAlbum) {
export async function transformAlbumData(appleMusicAlbum: AppleMusicAlbum | SyntheticAlbum) {
const attributes = appleMusicAlbum.attributes
// Get preview URL from tracks if album doesn't have one
@ -445,12 +462,13 @@ export async function transformAlbumData(appleMusicAlbum: AppleMusicAlbum) {
let tracks: Array<{ name: string; previewUrl?: string; durationMs?: number }> = []
// 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,