From 8f042ad448a2ca15ae95a25d73fad739cbe48239 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Tue, 25 Apr 2023 16:25:26 -0700 Subject: [PATCH] Pass full server to controller --- src/renderer/api/navidrome/navidrome-api.ts | 58 +++++- .../api/navidrome/navidrome-controller.ts | 177 +++++++----------- .../api/navidrome/navidrome-normalize.ts | 2 +- src/renderer/api/navidrome/navidrome-types.ts | 3 + src/renderer/api/subsonic/subsonic-api.ts | 27 ++- .../api/subsonic/subsonic-controller.ts | 58 ++---- 6 files changed, 144 insertions(+), 181 deletions(-) diff --git a/src/renderer/api/navidrome/navidrome-api.ts b/src/renderer/api/navidrome/navidrome-api.ts index 3eccfaff..05bfed59 100644 --- a/src/renderer/api/navidrome/navidrome-api.ts +++ b/src/renderer/api/navidrome/navidrome-api.ts @@ -1,5 +1,7 @@ import { initClient, initContract } from '@ts-rest/core'; import axios, { Method, AxiosError, AxiosResponse, isAxiosError } from 'axios'; +import omitBy from 'lodash/omitBy'; +import qs from 'qs'; import { ndType } from './navidrome-types'; import { resultWithHeaders } from '/@/renderer/api/utils'; import { toast } from '/@/renderer/components'; @@ -15,6 +17,7 @@ export const contract = c.router({ path: 'playlist/:id/tracks', responses: { 200: resultWithHeaders(ndType._response.addToPlaylist), + 500: resultWithHeaders(ndType._response.error), }, }, authenticate: { @@ -23,6 +26,7 @@ export const contract = c.router({ path: 'auth/login', responses: { 200: resultWithHeaders(ndType._response.authenticate), + 500: resultWithHeaders(ndType._response.error), }, }, createPlaylist: { @@ -31,6 +35,7 @@ export const contract = c.router({ path: 'playlist', responses: { 200: resultWithHeaders(ndType._response.createPlaylist), + 500: resultWithHeaders(ndType._response.error), }, }, deletePlaylist: { @@ -39,6 +44,7 @@ export const contract = c.router({ path: 'playlist/:id', responses: { 200: resultWithHeaders(ndType._response.deletePlaylist), + 500: resultWithHeaders(ndType._response.error), }, }, getAlbumArtistDetail: { @@ -46,6 +52,7 @@ export const contract = c.router({ path: 'artist/:id', responses: { 200: resultWithHeaders(ndType._response.albumArtist), + 500: resultWithHeaders(ndType._response.error), }, }, getAlbumArtistList: { @@ -54,6 +61,7 @@ export const contract = c.router({ query: ndType._parameters.albumArtistList, responses: { 200: resultWithHeaders(ndType._response.albumArtistList), + 500: resultWithHeaders(ndType._response.error), }, }, getAlbumDetail: { @@ -61,6 +69,7 @@ export const contract = c.router({ path: 'album/:id', responses: { 200: resultWithHeaders(ndType._response.album), + 500: resultWithHeaders(ndType._response.error), }, }, getAlbumList: { @@ -69,6 +78,7 @@ export const contract = c.router({ query: ndType._parameters.albumList, responses: { 200: resultWithHeaders(ndType._response.albumList), + 500: resultWithHeaders(ndType._response.error), }, }, getGenreList: { @@ -76,6 +86,7 @@ export const contract = c.router({ path: 'genre', responses: { 200: resultWithHeaders(ndType._response.genreList), + 500: resultWithHeaders(ndType._response.error), }, }, getPlaylistDetail: { @@ -83,6 +94,7 @@ export const contract = c.router({ path: 'playlist/:id', responses: { 200: resultWithHeaders(ndType._response.playlist), + 500: resultWithHeaders(ndType._response.error), }, }, getPlaylistList: { @@ -91,6 +103,7 @@ export const contract = c.router({ query: ndType._parameters.playlistList, responses: { 200: resultWithHeaders(ndType._response.playlistList), + 500: resultWithHeaders(ndType._response.error), }, }, getPlaylistSongList: { @@ -99,6 +112,7 @@ export const contract = c.router({ query: ndType._parameters.songList, responses: { 200: resultWithHeaders(ndType._response.playlistSongList), + 500: resultWithHeaders(ndType._response.error), }, }, getSongDetail: { @@ -106,6 +120,7 @@ export const contract = c.router({ path: 'song/:id', responses: { 200: resultWithHeaders(ndType._response.song), + 500: resultWithHeaders(ndType._response.error), }, }, getSongList: { @@ -114,6 +129,7 @@ export const contract = c.router({ query: ndType._parameters.songList, responses: { 200: resultWithHeaders(ndType._response.songList), + 500: resultWithHeaders(ndType._response.error), }, }, getUserList: { @@ -122,6 +138,7 @@ export const contract = c.router({ query: ndType._parameters.userList, responses: { 200: resultWithHeaders(ndType._response.userList), + 500: resultWithHeaders(ndType._response.error), }, }, removeFromPlaylist: { @@ -131,6 +148,7 @@ export const contract = c.router({ query: ndType._parameters.removeFromPlaylist, responses: { 200: resultWithHeaders(ndType._response.removeFromPlaylist), + 500: resultWithHeaders(ndType._response.error), }, }, updatePlaylist: { @@ -139,12 +157,17 @@ export const contract = c.router({ path: 'playlist/:id', responses: { 200: resultWithHeaders(ndType._response.updatePlaylist), + 500: resultWithHeaders(ndType._response.error), }, }, }); const axiosClient = axios.create({}); +axiosClient.defaults.paramsSerializer = (params) => { + return qs.stringify(params, { arrayFormat: 'repeat' }); +}; + axiosClient.interceptors.response.use( (response) => { const serverId = useAuthStore.getState().currentServer?.id; @@ -175,20 +198,37 @@ axiosClient.interceptors.response.use( }, ); -export const ndApiClient = (args: { server: ServerListItem | string; signal?: AbortSignal }) => { - const { server, signal } = args; +const parsePath = (fullPath: string) => { + const [path, params] = fullPath.split('?'); + + const parsedParams = qs.parse(params); + const notNilParams = omitBy(parsedParams, (value) => value === 'undefined' || value === 'null'); + + return { + params: notNilParams, + path, + }; +}; + +export const ndApiClient = (args: { + server?: ServerListItem; + signal?: AbortSignal; + url?: string; +}) => { + const { server, url, signal } = args; return initClient(contract, { api: async ({ path, method, headers, body }) => { let baseUrl: string | undefined; let token: string | undefined; - if (typeof server === 'object') { - const selectedServer = useAuthStore.getState().actions.getServer(server.id); - baseUrl = `${selectedServer?.url}/api`; - token = selectedServer?.ndCredential; + const { params, path: api } = parsePath(path); + + if (server) { + baseUrl = `${server?.url}/api`; + token = server?.ndCredential; } else { - baseUrl = server; + baseUrl = url; } try { @@ -199,8 +239,9 @@ export const ndApiClient = (args: { server: ServerListItem | string; signal?: Ab ...(token && { 'x-nd-authorization': `Bearer ${token}` }), }, method: method as Method, + params, signal, - url: `${baseUrl}/${path}`, + url: `${baseUrl}/${api}`, }); return { body: { data: result.data, headers: result.headers }, @@ -222,5 +263,6 @@ export const ndApiClient = (args: { server: ServerListItem | string; signal?: Ab 'Content-Type': 'application/json', }, baseUrl: '', + jsonQuery: false, }); }; diff --git a/src/renderer/api/navidrome/navidrome-controller.ts b/src/renderer/api/navidrome/navidrome-controller.ts index fabc73b2..de39a86f 100644 --- a/src/renderer/api/navidrome/navidrome-controller.ts +++ b/src/renderer/api/navidrome/navidrome-controller.ts @@ -49,7 +49,7 @@ const authenticate = async ( ): Promise => { const cleanServerUrl = url.replace(/\/$/, ''); - const res = await ndApiClient({ server: cleanServerUrl }).authenticate({ + const res = await ndApiClient({ url: cleanServerUrl }).authenticate({ body: { password: body.password, username: body.username, @@ -69,19 +69,15 @@ const authenticate = async ( }; const getUserList = async (args: UserListArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getUserList({ + const res = await ndApiClient(apiClientProps).getUserList({ query: { _end: query.startIndex + (query.limit || 0), _order: sortOrderMap.navidrome[query.sortOrder], _sort: userListSortMap.navidrome[query.sortBy], _start: query.startIndex, - ...query.ndParams, + ...query._custom?.navidrome, }, }); @@ -97,13 +93,9 @@ const getUserList = async (args: UserListArgs): Promise => { }; const getGenreList = async (args: GenreListArgs): Promise => { - const { server, signal } = args; + const { apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getGenreList({}); + const res = await ndApiClient(apiClientProps).getGenreList({}); if (res.status !== 200) { throw new Error('Failed to get genre list'); @@ -119,13 +111,9 @@ const getGenreList = async (args: GenreListArgs): Promise => const getAlbumArtistDetail = async ( args: AlbumArtistDetailArgs, ): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getAlbumArtistDetail({ + const res = await ndApiClient(apiClientProps).getAlbumArtistDetail({ params: { id: query.id, }, @@ -135,17 +123,17 @@ const getAlbumArtistDetail = async ( throw new Error('Failed to get album artist detail'); } - return ndNormalize.albumArtist(res.body.data, server); + if (!apiClientProps.server) { + throw new Error('Server is required'); + } + + return ndNormalize.albumArtist(res.body.data, apiClientProps.server); }; const getAlbumArtistList = async (args: AlbumArtistListArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getAlbumArtistList({ + const res = await ndApiClient(apiClientProps).getAlbumArtistList({ query: { _end: query.startIndex + (query.limit || 0), _order: sortOrderMap.navidrome[query.sortOrder], @@ -160,27 +148,29 @@ const getAlbumArtistList = async (args: AlbumArtistListArgs): Promise ndNormalize.albumArtist(albumArtist, server)), + items: res.body.data.map((albumArtist) => + ndNormalize.albumArtist(albumArtist, apiClientProps.server), + ), startIndex: query.startIndex, totalRecordCount: Number(res.body.headers.get('x-total-count') || 0), }; }; const getAlbumDetail = async (args: AlbumDetailArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const albumRes = await ndApiClient({ server, signal }).getAlbumDetail({ + const albumRes = await ndApiClient(apiClientProps).getAlbumDetail({ params: { id: query.id, }, }); - const songsData = await ndApiClient({ server, signal }).getSongList({ + const songsData = await ndApiClient(apiClientProps).getSongList({ query: { _end: 0, _order: 'ASC', @@ -194,17 +184,16 @@ const getAlbumDetail = async (args: AlbumDetailArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getAlbumList({ + const res = await ndApiClient(apiClientProps).getAlbumList({ query: { _end: query.startIndex + (query.limit || 0), _order: sortOrderMap.navidrome[query.sortOrder], @@ -221,20 +210,18 @@ const getAlbumList = async (args: AlbumListArgs): Promise => } return { - items: res.body.data.map((album) => ndNormalize.album(album, server)), + items: res.body.data.map((album) => ndNormalize.album(album, apiClientProps.server)), startIndex: query?.startIndex || 0, totalRecordCount: Number(res.body.headers.get('x-total-count') || 0), }; }; const getSongList = async (args: SongListArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } + console.log('query :>> ', query); - const res = await ndApiClient({ server, signal }).getSongList({ + const res = await ndApiClient(apiClientProps).getSongList({ query: { _end: query.startIndex + (query.limit || -1), _order: sortOrderMap.navidrome[query.sortOrder], @@ -252,20 +239,16 @@ const getSongList = async (args: SongListArgs): Promise => { } return { - items: res.body.data.map((song) => ndNormalize.song(song, server, '')), + items: res.body.data.map((song) => ndNormalize.song(song, apiClientProps.server, '')), startIndex: query?.startIndex || 0, totalRecordCount: Number(res.body.headers.get('x-total-count') || 0), }; }; const getSongDetail = async (args: SongDetailArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getSongDetail({ + const res = await ndApiClient(apiClientProps).getSongDetail({ params: { id: query.id, }, @@ -275,23 +258,19 @@ const getSongDetail = async (args: SongDetailArgs): Promise throw new Error('Failed to get song detail'); } - return ndNormalize.song(res.body.data, server, ''); + return ndNormalize.song(res.body.data, apiClientProps.server, ''); }; const createPlaylist = async (args: CreatePlaylistArgs): Promise => { - const { body, server } = args; + const { body, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server }).createPlaylist({ + const res = await ndApiClient(apiClientProps).createPlaylist({ body: { comment: body.comment, name: body.name, - public: body._custom.navidrome?.public, - rules: body._custom.navidrome?.rules, - sync: body._custom.navidrome?.sync, + public: body._custom?.navidrome?.public, + rules: body._custom?.navidrome?.rules, + sync: body._custom?.navidrome?.sync, }, }); @@ -306,19 +285,15 @@ const createPlaylist = async (args: CreatePlaylistArgs): Promise => { - const { query, body, server, signal } = args; + const { query, body, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).updatePlaylist({ + const res = await ndApiClient(apiClientProps).updatePlaylist({ body: { comment: body.comment || '', name: body.name, - public: body.ndParams?.public || false, - rules: body.ndParams?.rules ? body.ndParams?.rules : undefined, - sync: body.ndParams?.sync || undefined, + public: body._custom?.navidrome?.public || false, + rules: body._custom?.navidrome?.rules ? body._custom.navidrome.rules : undefined, + sync: body._custom?.navidrome?.sync || undefined, }, params: { id: query.id, @@ -335,13 +310,9 @@ const updatePlaylist = async (args: UpdatePlaylistArgs): Promise => { - const { query, server } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server }).deletePlaylist({ + const res = await ndApiClient(apiClientProps).deletePlaylist({ body: null, params: { id: query.id, @@ -356,13 +327,9 @@ const deletePlaylist = async (args: DeletePlaylistArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getPlaylistList({ + const res = await ndApiClient(apiClientProps).getPlaylistList({ query: { _end: query.startIndex + (query.limit || 0), _order: sortOrderMap.navidrome[query.sortOrder], @@ -377,20 +344,16 @@ const getPlaylistList = async (args: PlaylistListArgs): Promise ndNormalize.playlist(item, server)), + items: res.body.data.map((item) => ndNormalize.playlist(item, apiClientProps.server)), startIndex: query?.startIndex || 0, totalRecordCount: Number(res.body.headers.get('x-total-count') || 0), }; }; const getPlaylistDetail = async (args: PlaylistDetailArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getPlaylistDetail({ + const res = await ndApiClient(apiClientProps).getPlaylistDetail({ params: { id: query.id, }, @@ -400,19 +363,15 @@ const getPlaylistDetail = async (args: PlaylistDetailArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).getPlaylistSongList({ + const res = await ndApiClient(apiClientProps).getPlaylistSongList({ params: { id: query.id, }, @@ -429,20 +388,16 @@ const getPlaylistSongList = async ( } return { - items: res.body.data.map((item) => ndNormalize.song(item, server, '')), + items: res.body.data.map((item) => ndNormalize.song(item, apiClientProps.server, '')), startIndex: query?.startIndex || 0, totalRecordCount: Number(res.body.headers.get('x-total-count') || 0), }; }; const addToPlaylist = async (args: AddToPlaylistArgs): Promise => { - const { body, query, server } = args; + const { body, query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server }).addToPlaylist({ + const res = await ndApiClient(apiClientProps).addToPlaylist({ body: { ids: body.songId, }, @@ -461,13 +416,9 @@ const addToPlaylist = async (args: AddToPlaylistArgs): Promise => { - const { query, server, signal } = args; + const { query, apiClientProps } = args; - if (!server) { - throw new Error('No server'); - } - - const res = await ndApiClient({ server, signal }).removeFromPlaylist({ + const res = await ndApiClient(apiClientProps).removeFromPlaylist({ body: null, params: { id: query.id, diff --git a/src/renderer/api/navidrome/navidrome-normalize.ts b/src/renderer/api/navidrome/navidrome-normalize.ts index 9012ed62..db3d63c5 100644 --- a/src/renderer/api/navidrome/navidrome-normalize.ts +++ b/src/renderer/api/navidrome/navidrome-normalize.ts @@ -157,7 +157,7 @@ const normalizeAlbumArtist = ( lastPlayedAt: item.playDate.includes('0001-') ? null : item.playDate, name: item.name, playCount: item.playCount, - serverId: server?.id || '', + serverId: server.id, serverType: ServerType.NAVIDROME, similarArtists: null, // similarArtists: diff --git a/src/renderer/api/navidrome/navidrome-types.ts b/src/renderer/api/navidrome/navidrome-types.ts index 0434d086..b4ed6d35 100644 --- a/src/renderer/api/navidrome/navidrome-types.ts +++ b/src/renderer/api/navidrome/navidrome-types.ts @@ -2,6 +2,8 @@ import { z } from 'zod'; const sortOrderValues = ['ASC', 'DESC'] as const; +const error = z.string(); + const paginationParameters = z.object({ _end: z.number().optional(), _order: z.enum(sortOrderValues), @@ -339,6 +341,7 @@ export const ndType = { authenticate, createPlaylist, deletePlaylist, + error, genre, genreList, playlist, diff --git a/src/renderer/api/subsonic/subsonic-api.ts b/src/renderer/api/subsonic/subsonic-api.ts index 7642310b..09b7adb0 100644 --- a/src/renderer/api/subsonic/subsonic-api.ts +++ b/src/renderer/api/subsonic/subsonic-api.ts @@ -1,8 +1,8 @@ import { initClient, initContract } from '@ts-rest/core'; import axios, { Method, AxiosError, isAxiosError, AxiosResponse } from 'axios'; import { ssType } from '/@/renderer/api/subsonic/subsonic-types'; +import { ServerListItem } from '/@/renderer/api/types'; import { toast } from '/@/renderer/components'; -import { useAuthStore } from '/@/renderer/store'; const c = initContract(); @@ -95,29 +95,24 @@ axiosClient.interceptors.response.use( }, ); -export const ssApiClient = (args: { serverId?: string; signal?: AbortSignal; url?: string }) => { - const { serverId, url, signal } = args; +export const ssApiClient = (args: { + server?: ServerListItem; + signal?: AbortSignal; + url?: string; +}) => { + const { server, url, signal } = args; return initClient(contract, { api: async ({ path, method, headers, body }) => { let baseUrl: string | undefined; const authParams: Record = {}; - if (serverId) { - const selectedServer = useAuthStore.getState().actions.getServer(serverId); - - if (!selectedServer) { - return { - body: { data: null, headers: null }, - status: 500, - }; - } - - baseUrl = `${selectedServer?.url}/rest`; - const token = selectedServer.credential; + if (server) { + baseUrl = `${server.url}/rest`; + const token = server.credential; const params = token.split(/&?\w=/gm); - authParams.u = selectedServer.username; + authParams.u = server.username; if (params?.length === 4) { authParams.s = params[2]; authParams.t = params[3]; diff --git a/src/renderer/api/subsonic/subsonic-controller.ts b/src/renderer/api/subsonic/subsonic-controller.ts index 0aeb6011..5e89992b 100644 --- a/src/renderer/api/subsonic/subsonic-controller.ts +++ b/src/renderer/api/subsonic/subsonic-controller.ts @@ -72,13 +72,9 @@ const authenticate = async ( }; const getMusicFolderList = async (args: MusicFolderListArgs): Promise => { - const { signal, serverId } = args; + const { apiClientProps } = args; - if (!serverId) { - throw new Error('No server id'); - } - - const res = await ssApiClient({ serverId, signal }).getMusicFolderList({}); + const res = await ssApiClient(apiClientProps).getMusicFolderList({}); if (res.status !== 200) { throw new Error('Failed to get music folder list'); @@ -198,13 +194,9 @@ const getMusicFolderList = async (args: MusicFolderListArgs): Promise => { - const { serverId, query, signal } = args; + const { query, apiClientProps } = args; - if (!serverId) { - throw new Error('No server id'); - } - - const res = await ssApiClient({ serverId, signal }).createFavorite({ + const res = await ssApiClient(apiClientProps).createFavorite({ query: { albumId: query.type === LibraryItem.ALBUM ? query.id : undefined, artistId: query.type === LibraryItem.ALBUM_ARTIST ? query.id : undefined, @@ -223,13 +215,9 @@ const createFavorite = async (args: FavoriteArgs): Promise => }; const removeFavorite = async (args: FavoriteArgs): Promise => { - const { serverId, query, signal } = args; + const { query, apiClientProps } = args; - if (!serverId) { - throw new Error('No server id'); - } - - const res = await ssApiClient({ serverId, signal }).removeFavorite({ + const res = await ssApiClient(apiClientProps).removeFavorite({ query: { albumId: query.type === LibraryItem.ALBUM ? query.id : undefined, artistId: query.type === LibraryItem.ALBUM_ARTIST ? query.id : undefined, @@ -248,16 +236,12 @@ const removeFavorite = async (args: FavoriteArgs): Promise => }; const setRating = async (args: RatingArgs): Promise => { - const { serverId, query, signal } = args; - - if (!serverId) { - throw new Error('No server id'); - } + const { query, apiClientProps } = args; const itemIds = query.item.map((item) => item.id); for (const id of itemIds) { - await ssApiClient({ serverId, signal }).setRating({ + await ssApiClient(apiClientProps).setRating({ query: { id, rating: query.rating, @@ -269,13 +253,9 @@ const setRating = async (args: RatingArgs): Promise => { }; const getTopSongList = async (args: TopSongListArgs): Promise => { - const { signal, serverId, query, server } = args; + const { query, apiClientProps } = args; - if (!serverId || !server) { - throw new Error('No server id'); - } - - const res = await ssApiClient({ serverId, signal }).getTopSongsList({ + const res = await ssApiClient(apiClientProps).getTopSongsList({ query: { artist: query.artist, count: query.limit, @@ -287,7 +267,7 @@ const getTopSongList = async (args: TopSongListArgs): Promise } return { - items: res.body.topSongs.song.map((song) => ssNormalize.song(song, server, '')), + items: res.body.topSongs.song.map((song) => ssNormalize.song(song, apiClientProps.server, '')), startIndex: 0, totalRecordCount: res.body.topSongs.song.length || 0, }; @@ -296,13 +276,9 @@ const getTopSongList = async (args: TopSongListArgs): Promise const getArtistInfo = async ( args: ArtistInfoArgs, ): Promise> => { - const { signal, serverId, query } = args; + const { query, apiClientProps } = args; - if (!serverId) { - throw new Error('No server id'); - } - - const res = await ssApiClient({ serverId, signal }).getArtistInfo({ + const res = await ssApiClient(apiClientProps).getArtistInfo({ query: { count: query.limit, id: query.artistId, @@ -317,13 +293,9 @@ const getArtistInfo = async ( }; const scrobble = async (args: ScrobbleArgs): Promise => { - const { signal, serverId, query } = args; + const { query, apiClientProps } = args; - if (!serverId) { - throw new Error('No server id'); - } - - const res = await ssApiClient({ serverId, signal }).scrobble({ + const res = await ssApiClient(apiClientProps).scrobble({ query: { id: query.id, submission: query.submission,