Pass full server to controller
This commit is contained in:
parent
1cbd61888f
commit
8f042ad448
6 changed files with 144 additions and 181 deletions
|
@ -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,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -49,7 +49,7 @@ const authenticate = async (
|
|||
): Promise<AuthenticationResponse> => {
|
||||
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<UserListResponse> => {
|
||||
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<UserListResponse> => {
|
|||
};
|
||||
|
||||
const getGenreList = async (args: GenreListArgs): Promise<GenreListResponse> => {
|
||||
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<GenreListResponse> =>
|
|||
const getAlbumArtistDetail = async (
|
||||
args: AlbumArtistDetailArgs,
|
||||
): Promise<AlbumArtistDetailResponse> => {
|
||||
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<AlbumArtistListResponse> => {
|
||||
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<AlbumArtis
|
|||
throw new Error('Failed to get album artist list');
|
||||
}
|
||||
|
||||
if (!apiClientProps.server) {
|
||||
throw new Error('Server is required');
|
||||
}
|
||||
|
||||
return {
|
||||
items: res.body.data.map((albumArtist) => 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<AlbumDetailResponse> => {
|
||||
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<AlbumDetailRespons
|
|||
throw new Error('Failed to get album detail');
|
||||
}
|
||||
|
||||
return ndNormalize.album({ ...albumRes.body.data, songs: songsData.body.data }, server);
|
||||
return ndNormalize.album(
|
||||
{ ...albumRes.body.data, songs: songsData.body.data },
|
||||
apiClientProps.server,
|
||||
);
|
||||
};
|
||||
|
||||
const getAlbumList = async (args: AlbumListArgs): Promise<AlbumListResponse> => {
|
||||
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<AlbumListResponse> =>
|
|||
}
|
||||
|
||||
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<SongListResponse> => {
|
||||
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<SongListResponse> => {
|
|||
}
|
||||
|
||||
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<SongDetailResponse> => {
|
||||
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<SongDetailResponse>
|
|||
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<CreatePlaylistResponse> => {
|
||||
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<CreatePlaylistR
|
|||
};
|
||||
|
||||
const updatePlaylist = async (args: UpdatePlaylistArgs): Promise<UpdatePlaylistResponse> => {
|
||||
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<UpdatePlaylistR
|
|||
};
|
||||
|
||||
const deletePlaylist = async (args: DeletePlaylistArgs): Promise<DeletePlaylistResponse> => {
|
||||
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<DeletePlaylistR
|
|||
};
|
||||
|
||||
const getPlaylistList = async (args: PlaylistListArgs): Promise<PlaylistListResponse> => {
|
||||
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<PlaylistListResp
|
|||
}
|
||||
|
||||
return {
|
||||
items: res.body.data.map((item) => 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<PlaylistDetailResponse> => {
|
||||
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<PlaylistDeta
|
|||
throw new Error('Failed to get playlist detail');
|
||||
}
|
||||
|
||||
return ndNormalize.playlist(res.body.data, server);
|
||||
return ndNormalize.playlist(res.body.data, apiClientProps.server);
|
||||
};
|
||||
|
||||
const getPlaylistSongList = async (
|
||||
args: PlaylistSongListArgs,
|
||||
): Promise<PlaylistSongListResponse> => {
|
||||
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<AddToPlaylistResponse> => {
|
||||
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<AddToPlaylistResp
|
|||
const removeFromPlaylist = async (
|
||||
args: RemoveFromPlaylistArgs,
|
||||
): Promise<RemoveFromPlaylistResponse> => {
|
||||
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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<string, any> = {};
|
||||
|
||||
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];
|
||||
|
|
|
@ -72,13 +72,9 @@ const authenticate = async (
|
|||
};
|
||||
|
||||
const getMusicFolderList = async (args: MusicFolderListArgs): Promise<MusicFolderListResponse> => {
|
||||
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<MusicFolde
|
|||
// };
|
||||
|
||||
const createFavorite = async (args: FavoriteArgs): Promise<FavoriteResponse> => {
|
||||
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<FavoriteResponse> =>
|
|||
};
|
||||
|
||||
const removeFavorite = async (args: FavoriteArgs): Promise<FavoriteResponse> => {
|
||||
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<FavoriteResponse> =>
|
|||
};
|
||||
|
||||
const setRating = async (args: RatingArgs): Promise<RatingResponse> => {
|
||||
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<RatingResponse> => {
|
|||
};
|
||||
|
||||
const getTopSongList = async (args: TopSongListArgs): Promise<SongListResponse> => {
|
||||
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<SongListResponse>
|
|||
}
|
||||
|
||||
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<SongListResponse>
|
|||
const getArtistInfo = async (
|
||||
args: ArtistInfoArgs,
|
||||
): Promise<z.infer<typeof ssType._response.artistInfo>> => {
|
||||
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<ScrobbleResponse> => {
|
||||
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,
|
||||
|
|
Reference in a new issue