declare enum ServiceTypes { AMAZON = 'amazon', AMAZON_MUSIC = 'amazonMusic', AUDIUS = 'audius', AUDIOMACK = 'audiomack', AWA = 'awa', BANDCAMP = 'bandcamp', BANDSINTOWN = 'bandsintown', DEEZER = 'deezer', DISCOGS = 'discogs', FACEBOOK = 'facebook', GAANA = 'gaana', INSTAGRAM = 'instagram', APPLE_MUSIC = 'appleMusic', IHEART_RADIO = 'iHeartRadio', ITUNES_STORE = 'itunesStore', JIO_SAAVN = 'jioSaavn', KKBOX = 'kkbox', LINE_MUSIC = 'lineMusic', MUSIC_BRAINZ = 'musicBrainz', NAPSTER = 'napster', NETEASE = 'netease', PANDORA = 'pandora', QOBUZ = 'qobuz', RESSO = 'resso', SEVEN_DIGITAL = 'sevenDigital', SOUNDCLOUD = 'soundcloud', SPOTIFY = 'spotify', TIDAL = 'tidal', TICKETMASTER = 'ticketmaster', TIKTOK = 'tiktok', TWITTER = 'twitter', WIKIPEDIA = 'wikipedia', WYNK_MUSIC = 'wynkMusic', YANDEX = 'yandex', YOUTUBE = 'youtube', YOUTUBE_MUSIC = 'youtubeMusic', } // enum to union - https://stackoverflow.com/a/52396706/516629 type ServiceType = `${ServiceTypes}`; type ItemGenres = string[]; declare enum ItemTypes { ARTIST = 'artist', ALBUM = 'album', TRACK = 'track', VIDEO = 'video', } interface Geolocation { latitude: number; longitude: number; } interface Link { url: string; countries?: string[]; } interface Image { url: string; width?: number; height?: number; dominantColor?: string; } type BaseSerialized = { id?: string; service: ServiceTypes; name?: string; originalName?: string; // not required as not all services have country specific content/links country?: string; images?: Image[]; links?: Link[]; type: unknown; link?: string; }; interface SerializedTrack extends BaseSerialized { type: ItemTypes.TRACK; artists?: SerializedArtist[]; albums?: SerializedAlbum[]; previewUrl?: string; duration?: number; isExplicit?: boolean; isrc?: string; } type TrackLyrics = { text: string }[]; interface SerializedVideo extends BaseSerialized { type: ItemTypes.VIDEO; channelTitle?: string; releaseDate?: Date; aspect: number | undefined; isEmbeddable?: boolean; } interface SerializedAlbum extends BaseSerialized { type: ItemTypes.ALBUM; name: string; artists?: SerializedArtist[]; tracks?: (SerializedTrack | SerializedVideo)[]; children?: SerializedChildAlbum[]; isSingle?: boolean; description?: string; releaseDate?: Date | string; totalTracks?: number; upc?: string; isExplicit?: boolean; } type SerializedChildAlbum = Pick< SerializedAlbum, 'type' | 'service' | 'id' | 'images' | 'links' | 'link' >; interface SerializedArtist extends BaseSerialized { type: ItemTypes.ARTIST; name: string; description?: string; genres?: ItemGenres; albums?: SerializedAlbum[]; children?: SerializedChildArtist[]; shows?: ArtistShow[]; } type SerializedChildArtist = Pick< SerializedArtist, 'type' | 'id' | 'images' | 'links' | 'link' > & { service: ServiceTypes; }; interface ArtistShow { name: string; venueName: string; url: string; // YYYY-MM-DD localDate: string; // HH:mm:ss // Optional because some shows don't have a start time, // in the case of festival tickets for example localTime?: string; geolocation?: Geolocation; } type ItemServices = { [K in ServiceType]: { id?: string; service?: ServiceTypes; link: string; }; }; type ReducedTrack = { type: 'track'; name: string; artists?: ReducedArtist[]; image?: Image; images?: Image[]; duration?: number; isrc?: string; isExplicit?: boolean; previewUrl?: string; releaseDate?: string; lyrics?: TrackLyrics; services?: ItemServices; albums?: ReducedAlbum[]; }; type ReducedAlbum = Pick< SerializedAlbum, 'name' | 'releaseDate' | 'upc' | 'isExplicit' | 'description' | 'totalTracks' > & { type: 'album'; artists?: ReducedArtist[]; image?: Image; images?: Image[]; previewUrl?: string; releaseDate?: string; services?: ItemServices; tracks?: ReducedTrack[]; }; type ReducedArtist = Pick & { type: 'artist'; image?: Image; previewUrl?: string; releaseDate?: string; services?: ItemServices; albums?: ReducedAlbum[]; }; /* eslint-disable @typescript-eslint/ban-types */ // force TS to use new naming type MusicfetchArtist = ReducedArtist & { _?: never }; type MusicfetchAlbum = ReducedAlbum & { _?: never }; type MusicfetchTrack = ReducedTrack & { _?: never }; type MusicfetchLookupResult< TResult = MusicfetchTrack | MusicfetchAlbum | MusicfetchArtist > = { result: TResult; performance: Record; }; type MusicfetchLookupArtistResult = MusicfetchLookupResult; type MusicfetchLookupAlbumUResult = MusicfetchLookupResult; type MusicfetchLookupTrackResult = MusicfetchLookupResult; export { type MusicfetchAlbum, type MusicfetchArtist, type MusicfetchLookupAlbumUResult, type MusicfetchLookupArtistResult, type MusicfetchLookupResult, type MusicfetchLookupTrackResult, type MusicfetchTrack, type ServiceType, ServiceTypes };