diff --git a/src/renderer/api/navidrome/navidrome-api.ts b/src/renderer/api/navidrome/navidrome-api.ts index 09f2d37f..3eccfaff 100644 --- a/src/renderer/api/navidrome/navidrome-api.ts +++ b/src/renderer/api/navidrome/navidrome-api.ts @@ -66,6 +66,7 @@ export const contract = c.router({ getAlbumList: { method: 'GET', path: 'album', + query: ndType._parameters.albumList, responses: { 200: resultWithHeaders(ndType._response.albumList), }, @@ -87,10 +88,19 @@ export const contract = c.router({ getPlaylistList: { method: 'GET', path: 'playlist', + query: ndType._parameters.playlistList, responses: { 200: resultWithHeaders(ndType._response.playlistList), }, }, + getPlaylistSongList: { + method: 'GET', + path: 'playlist/:id/tracks', + query: ndType._parameters.songList, + responses: { + 200: resultWithHeaders(ndType._response.playlistSongList), + }, + }, getSongDetail: { method: 'GET', path: 'song/:id', @@ -109,6 +119,7 @@ export const contract = c.router({ getUserList: { method: 'GET', path: 'user', + query: ndType._parameters.userList, responses: { 200: resultWithHeaders(ndType._response.userList), }, @@ -164,7 +175,9 @@ axiosClient.interceptors.response.use( }, ); -export const ndApiClient = (server: ServerListItem | string) => { +export const ndApiClient = (args: { server: ServerListItem | string; signal?: AbortSignal }) => { + const { server, signal } = args; + return initClient(contract, { api: async ({ path, method, headers, body }) => { let baseUrl: string | undefined; @@ -186,6 +199,7 @@ export const ndApiClient = (server: ServerListItem | string) => { ...(token && { 'x-nd-authorization': `Bearer ${token}` }), }, method: method as Method, + signal, url: `${baseUrl}/${path}`, }); return { diff --git a/src/renderer/api/navidrome/navidrome-types.ts b/src/renderer/api/navidrome/navidrome-types.ts index 3412576e..0434d086 100644 --- a/src/renderer/api/navidrome/navidrome-types.ts +++ b/src/renderer/api/navidrome/navidrome-types.ts @@ -1,4 +1,4 @@ -import z from 'zod'; +import { z } from 'zod'; const sortOrderValues = ['ASC', 'DESC'] as const; @@ -37,6 +37,14 @@ const user = z.object({ const userList = z.array(user); +const ndUserListSort = { + NAME: 'name', +} as const; + +const userListParameters = paginationParameters.extend({ + _sort: z.nativeEnum(ndUserListSort).optional(), +}); + const genre = z.object({ id: z.string(), name: z.string(), @@ -221,8 +229,8 @@ const ndSongListSort = { const songListParameters = paginationParameters.extend({ _sort: z.nativeEnum(ndSongListSort).optional(), - album_id: z.string().optional(), - artist_id: z.string().optional(), + album_id: z.array(z.string()).optional(), + artist_id: z.array(z.string()).optional(), genre_id: z.string().optional(), starred: z.boolean().optional(), }); @@ -238,7 +246,7 @@ const playlist = z.object({ ownerName: z.string(), path: z.string(), public: z.boolean(), - rules: z.string(), + rules: z.record(z.string(), z.any()), size: z.number(), songCount: z.number(), sync: z.boolean(), @@ -247,11 +255,27 @@ const playlist = z.object({ const playlistList = z.array(playlist); -const playlistSong = playlist.extend({ +const ndPlaylistListSort = { + DURATION: 'duration', + NAME: 'name', + OWNER: 'ownerName', + PUBLIC: 'public', + SONG_COUNT: 'songCount', + UPDATED_AT: 'updatedAt', +} as const; + +const playlistListParameters = paginationParameters.extend({ + _sort: z.nativeEnum(ndPlaylistListSort).optional(), + owner_id: z.string().optional(), +}); + +const playlistSong = song.extend({ mediaFileId: z.string(), playlistId: z.string(), }); +const playlistSongList = z.array(playlistSong); + const createPlaylist = playlist.pick({ id: true, }); @@ -287,15 +311,24 @@ const removeFromPlaylistParameters = z.object({ }); export const ndType = { + _enum: { + albumArtistList: ndAlbumArtistListSort, + albumList: ndAlbumListSort, + playlistList: ndPlaylistListSort, + songList: ndSongListSort, + userList: ndUserListSort, + }, _parameters: { addToPlaylist: addToPlaylistParameters, albumArtistList: albumArtistListParameters, albumList: albumListParameters, authenticate: authenticateParameters, createPlaylist: createPlaylistParameters, + playlistList: playlistListParameters, removeFromPlaylist: removeFromPlaylistParameters, songList: songListParameters, updatePlaylist: updatePlaylistParameters, + userList: userListParameters, }, _response: { addToPlaylist, @@ -311,6 +344,7 @@ export const ndType = { playlist, playlistList, playlistSong, + playlistSongList, removeFromPlaylist, song, songList,