add new api controller, rework and rename types

This commit is contained in:
jeffvli
2025-07-12 16:00:26 -07:00
parent 6c360c3c19
commit a7f21db563
14 changed files with 325 additions and 317 deletions
+27
View File
@@ -0,0 +1,27 @@
import { adapter as subsonicAdapter } from './subsonic/subsonic-controller';
import i18n from '/@/i18n/i18n';
import { ApiController } from '/@/shared/types/adapter/api-controller-types';
import { ServerType } from '/@/shared/types/domain/server-domain-types';
interface ApiControllerOptions {
type: ServerType;
}
const adapters = {
[ServerType.JELLYFIN]: {},
[ServerType.NAVIDROME]: {},
[ServerType.SUBSONIC]: subsonicAdapter,
} as Record<ServerType, ApiController>;
export const apiController = (options: ApiControllerOptions): ApiController => {
const { type } = options;
const adapter = adapters[type];
if (!adapter) {
throw new Error(i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' }));
}
return adapter;
};
+121 -101
View File
@@ -1,99 +1,89 @@
import { import {
AlbumDetailArgs, AlbumDetailRequest,
AlbumDetailResponse, AlbumDetailResponse,
AlbumInfo, AlbumInfo,
AlbumListArgs, AlbumListRequest,
AlbumListResponse, AlbumListResponse,
} from '/@/shared/types/domain/album-domain-types'; } from '/@/shared/types/domain/album-domain-types';
import { BaseEndpointArgs } from '/@/shared/types/domain/api-domain-types';
import { import {
AlbumArtistDetailArgs, AlbumArtistDetailRequest,
AlbumArtistDetailResponse, AlbumArtistDetailResponse,
AlbumArtistListArgs, AlbumArtistListRequest,
AlbumArtistListResponse, AlbumArtistListResponse,
ArtistListArgs, ArtistListRequest,
ArtistListResponse, ArtistListResponse,
} from '/@/shared/types/domain/artist-domain-types'; } from '/@/shared/types/domain/artist-domain-types';
import { AuthenticationResponse } from '/@/shared/types/domain/auth-domain-types'; import { AuthenticationResponse } from '/@/shared/types/domain/auth-domain-types';
import { GenreListArgs, GenreListResponse } from '/@/shared/types/domain/genre-domain-types'; import { GenreListRequest, GenreListResponse } from '/@/shared/types/domain/genre-domain-types';
import { import {
LyricsArgs, LyricsRequest,
LyricsResponse, LyricsResponse,
StructuredLyric, StructuredLyric,
StructuredLyricsArgs, StructuredLyricsRequest,
} from '/@/shared/types/domain/lyric-domain-types'; } from '/@/shared/types/domain/lyric-domain-types';
import { TranscodingArgs } from '/@/shared/types/domain/player-domain-types'; import { TranscodingRequest } from '/@/shared/types/domain/player-domain-types';
import { import {
AddToPlaylistArgs, AddToPlaylistArgs,
AddToPlaylistResponse, AddToPlaylistResponse,
CreatePlaylistArgs, CreatePlaylistRequest,
CreatePlaylistResponse, CreatePlaylistResponse,
DeletePlaylistArgs, DeletePlaylistRequest,
DeletePlaylistResponse, DeletePlaylistResponse,
MoveItemArgs, MoveItemRequest,
PlaylistDetailArgs, PlaylistDetailRequest,
PlaylistDetailResponse, PlaylistDetailResponse,
PlaylistListArgs, PlaylistListRequest,
PlaylistListResponse, PlaylistListResponse,
PlaylistSongListArgs, PlaylistSongListRequest,
RemoveFromPlaylistArgs, RemoveFromPlaylistRequest,
RemoveFromPlaylistResponse, RemoveFromPlaylistResponse,
UpdatePlaylistArgs, UpdatePlaylistRequest,
UpdatePlaylistResponse, UpdatePlaylistResponse,
} from '/@/shared/types/domain/playlist-domain-types'; } from '/@/shared/types/domain/playlist-domain-types';
import { SearchArgs, SearchResponse } from '/@/shared/types/domain/search-domain-types'; import { SearchRequest, SearchResponse } from '/@/shared/types/domain/search-domain-types';
import { import {
ServerInfo, ServerInfo,
ServerInfoArgs, ServerInfoRequest,
ServerListItem, ServerListItem,
ServerMusicFolderListArgs, ServerMusicFolderListRequest,
ServerMusicFolderListResponse, ServerMusicFolderListResponse,
ServerType, ServerType,
} from '/@/shared/types/domain/server-domain-types'; } from '/@/shared/types/domain/server-domain-types';
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types'; import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
import { import {
RandomSongListArgs, RandomSongListRequest,
SimilarSongsArgs, SimilarSongsRequest,
Song, Song,
SongDetailArgs, SongDetailRequest,
SongDetailResponse, SongDetailResponse,
SongListArgs, SongListRequest,
SongListResponse, SongListResponse,
TopSongListArgs, TopSongListRequest,
TopSongListResponse, TopSongListResponse,
} from '/@/shared/types/domain/song-domain-types'; } from '/@/shared/types/domain/song-domain-types';
import { TagArgs, TagsResponse } from '/@/shared/types/domain/tag-domain-types'; import { TagRequest, TagsResponse } from '/@/shared/types/domain/tag-domain-types';
import { import {
DownloadArgs, DownloadRequest,
FavoriteArgs, FavoriteRequest,
FavoriteResponse, FavoriteResponse,
RatingResponse, RatingResponse,
ScrobbleArgs, ScrobbleRequest,
ScrobbleResponse, ScrobbleResponse,
SetRatingArgs, SetRatingRequest,
ShareItemArgs, ShareItemRequest,
ShareItemResponse, ShareItemResponse,
UserListArgs, UserListRequest,
UserListResponse, UserListResponse,
} from '/@/shared/types/domain/user-domain-types'; } from '/@/shared/types/domain/user-domain-types';
export interface AdapterError { export type ApiClientProps = {
code: number; baseUrl?: string;
message: string;
}
export type AdapterFn<TRequest, TResponse> = (
request: TRequest,
server: ServerListItem,
options?: AdapterRequestOptions,
) => Promise<[AdapterError, null] | [null, TResponse]>;
export interface AdapterRequestOptions {
cache?: 'default' | 'force-cache' | 'no-cache' | 'no-store' | 'only-if-cached' | 'reload'; cache?: 'default' | 'force-cache' | 'no-cache' | 'no-store' | 'only-if-cached' | 'reload';
credentials?: 'include' | 'omit' | 'same-origin'; credentials?: 'include' | 'omit' | 'same-origin';
integrity?: string; integrity?: string;
keepalive?: boolean; keepalive?: boolean;
mode?: 'cors' | 'navigate' | 'no-cors' | 'same-origin'; mode?: 'cors' | 'navigate' | 'no-cors' | 'same-origin';
parseAs?: 'arrayBuffer' | 'blob' | 'json' | 'text';
priority?: 'auto' | 'high' | 'low'; priority?: 'auto' | 'high' | 'low';
redirect?: 'error' | 'follow' | 'manual'; redirect?: 'error' | 'follow' | 'manual';
referrer?: string; referrer?: string;
@@ -108,86 +98,116 @@ export interface AdapterRequestOptions {
| 'strict-origin-when-cross-origin' | 'strict-origin-when-cross-origin'
| 'unsafe-url'; | 'unsafe-url';
signal?: AbortSignal | null; signal?: AbortSignal | null;
window?: null; };
}
export type ControllerEndpoint = { export type ApiController = {
_utility: {
getDownloadUrl: ApiControllerFn<DownloadRequest, string>;
getImageUrl: (
args: { id: string; size?: number; type: LibraryItem },
server: ServerListItem,
) => string;
getStreamUrl: (
args: { bitRate?: number; format?: string; id: string },
server: ServerListItem,
) => string;
};
album: { album: {
getDetail: (args: AlbumDetailArgs) => Promise<AlbumDetailResponse>; getDetail: ApiControllerFn<AlbumDetailRequest, AlbumDetailResponse>;
getInfo?: (args: AlbumDetailArgs) => Promise<AlbumInfo>; getInfo?: ApiControllerFn<AlbumDetailRequest, AlbumInfo>;
getList: (args: AlbumListArgs) => Promise<AlbumListResponse>; getList: ApiControllerFn<AlbumListRequest, AlbumListResponse>;
getListCount: (args: AlbumListArgs) => Promise<number>; getListCount: ApiControllerFn<AlbumListRequest, number>;
}; };
albumArtist: { albumArtist: {
getDetail: (args: AlbumArtistDetailArgs) => Promise<AlbumArtistDetailResponse>; getDetail: ApiControllerFn<AlbumArtistDetailRequest, AlbumArtistDetailResponse>;
getList: (args: AlbumArtistListArgs) => Promise<AlbumArtistListResponse>; getList: ApiControllerFn<AlbumArtistListRequest, AlbumArtistListResponse>;
getListCount: (args: AlbumArtistListArgs) => Promise<number>; getListCount: ApiControllerFn<AlbumArtistListRequest, number>;
}; };
artist: { artist: {
getList: (args: ArtistListArgs) => Promise<ArtistListResponse>; getList: ApiControllerFn<ArtistListRequest, ArtistListResponse>;
getListCount: (args: ArtistListArgs) => Promise<number>; getListCount: ApiControllerFn<ArtistListRequest, number>;
}; };
favorite: { favorite: {
create: (args: FavoriteArgs) => Promise<FavoriteResponse>; create: ApiControllerFn<FavoriteRequest, FavoriteResponse>;
delete: (args: FavoriteArgs) => Promise<FavoriteResponse>; delete: ApiControllerFn<FavoriteRequest, FavoriteResponse>;
}; };
genre: { genre: {
getList: (args: GenreListArgs) => Promise<GenreListResponse>; getList: ApiControllerFn<GenreListRequest, GenreListResponse>;
}; };
musicFolder: { musicFolder: {
getList: (args: ServerMusicFolderListArgs) => Promise<ServerMusicFolderListResponse>; getList: ApiControllerFn<ServerMusicFolderListRequest, ServerMusicFolderListResponse>;
}; };
playlist: { playlist: {
addTo: (args: AddToPlaylistArgs) => Promise<AddToPlaylistResponse>; addTo: ApiControllerFn<AddToPlaylistArgs, AddToPlaylistResponse>;
create: (args: CreatePlaylistArgs) => Promise<CreatePlaylistResponse>; create: ApiControllerFn<CreatePlaylistRequest, CreatePlaylistResponse>;
delete: (args: DeletePlaylistArgs) => Promise<DeletePlaylistResponse>; delete: ApiControllerFn<DeletePlaylistRequest, DeletePlaylistResponse>;
getDetail: (args: PlaylistDetailArgs) => Promise<PlaylistDetailResponse>; getDetail: ApiControllerFn<PlaylistDetailRequest, PlaylistDetailResponse>;
getList: (args: PlaylistListArgs) => Promise<PlaylistListResponse>; getList: ApiControllerFn<PlaylistListRequest, PlaylistListResponse>;
getListCount: (args: PlaylistListArgs) => Promise<number>; getListCount: ApiControllerFn<PlaylistListRequest, number>;
getSongList: (args: PlaylistSongListArgs) => Promise<SongListResponse>; getSongList: ApiControllerFn<PlaylistSongListRequest, SongListResponse>;
moveItem?: (args: MoveItemArgs) => Promise<void>; moveItem?: ApiControllerFn<MoveItemRequest, void>;
removeFrom: (args: RemoveFromPlaylistArgs) => Promise<RemoveFromPlaylistResponse>; removeFrom: ApiControllerFn<RemoveFromPlaylistRequest, RemoveFromPlaylistResponse>;
update: (args: UpdatePlaylistArgs) => Promise<UpdatePlaylistResponse>; update: ApiControllerFn<UpdatePlaylistRequest, UpdatePlaylistResponse>;
}; };
server: { server: {
authenticate: ( authenticate: (
url: string, url: string,
body: { legacy?: boolean; password: string; username: string }, body: { legacy?: boolean; password: string; username: string },
) => Promise<AuthenticationResponse>; ) => Promise<AuthenticationResponse>;
getCoverArtUrl: ( getRoles: ApiControllerFn<
args: { id: string; size?: number; type: LibraryItem }, BaseEndpointArgs,
server: ServerListItem, Array<string | { label: string; value: string }>
) => string; >;
getRoles: ( getServerInfo: ApiControllerFn<ServerInfoRequest, ServerInfo>;
args: BaseEndpointArgs, getTags: ApiControllerFn<TagRequest, TagsResponse>;
) => Promise<Array<string | { label: string; value: string }>>; getTranscodingUrl: ApiControllerFn<TranscodingRequest, string>;
getServerInfo: (args: ServerInfoArgs) => Promise<ServerInfo>;
getStreamUrl: (
args: { bitRate?: number; format?: string; id: string },
server: ServerListItem,
) => string;
getTags: (args: TagArgs) => Promise<TagsResponse>;
getTranscodingUrl: (args: TranscodingArgs) => string;
getType: () => ServerType; getType: () => ServerType;
scrobble: (args: ScrobbleArgs) => Promise<ScrobbleResponse>; scrobble: ApiControllerFn<ScrobbleRequest, ScrobbleResponse>;
search: (args: SearchArgs) => Promise<SearchResponse>; search: ApiControllerFn<SearchRequest, SearchResponse>;
}; };
song: { song: {
getDetail: (args: SongDetailArgs) => Promise<SongDetailResponse>; getDetail: ApiControllerFn<SongDetailRequest, SongDetailResponse>;
getDownloadUrl: (args: DownloadArgs) => string; getList: ApiControllerFn<SongListRequest, SongListResponse>;
getList: (args: SongListArgs) => Promise<SongListResponse>; getListCount: ApiControllerFn<SongListRequest, number>;
getListCount: (args: SongListArgs) => Promise<number>; getLyrics?: ApiControllerFn<LyricsRequest, LyricsResponse>;
getLyrics?: (args: LyricsArgs) => Promise<LyricsResponse>; getRandomList: ApiControllerFn<RandomSongListRequest, SongListResponse>;
getRandomList: (args: RandomSongListArgs) => Promise<SongListResponse>; getSimilar: ApiControllerFn<SimilarSongsRequest, Song[]>;
getSimilar: (args: SimilarSongsArgs) => Promise<Song[]>; getStructuredLyrics?: ApiControllerFn<StructuredLyricsRequest, StructuredLyric[]>;
getStructuredLyrics?: (args: StructuredLyricsArgs) => Promise<StructuredLyric[]>; getTopList: ApiControllerFn<TopSongListRequest, TopSongListResponse>;
getTopList: (args: TopSongListArgs) => Promise<TopSongListResponse>;
}; };
user: { user: {
getList?: (args: UserListArgs) => Promise<UserListResponse>; getList?: ApiControllerFn<UserListRequest, UserListResponse>;
setRating?: (args: SetRatingArgs) => Promise<RatingResponse>; setRating?: ApiControllerFn<SetRatingRequest, RatingResponse>;
shareItem?: (args: ShareItemArgs) => Promise<ShareItemResponse>; shareItem?: ApiControllerFn<ShareItemRequest, ShareItemResponse>;
}; };
}; };
export type ExtractAdapterResponse<T> = T extends AdapterFn<any, infer R> ? R : never; export interface ApiControllerError {
code: number;
message: string;
}
export type ApiControllerFn<TRequest, TResponse> = (
request: TRequest,
server: ServerListItem,
options?: ApiClientProps,
) => Promise<[ApiControllerError, null] | [null, TResponse]>;
export type BaseEndpointArgs = {
apiClientProps: {
signal?: AbortSignal;
};
};
export interface BasePaginatedResponse<T> {
error?: any | string;
items: T;
startIndex: number;
totalRecordCount: null | number;
}
export interface BaseQuery<T> {
sortBy: T;
sortOrder: ListSortOrder;
}
export type ExtractControllerResponse<T> = T extends ApiControllerFn<any, infer R> ? R : never;
@@ -6,11 +6,7 @@ import { JFAlbumListSort } from '/@/shared/api/jellyfin.types';
import { jfType } from '/@/shared/api/jellyfin/jellyfin-types'; import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
import { NDAlbumListSort } from '/@/shared/api/navidrome.types'; import { NDAlbumListSort } from '/@/shared/api/navidrome.types';
import { ndType } from '/@/shared/api/navidrome/navidrome-types'; import { ndType } from '/@/shared/api/navidrome/navidrome-types';
import { import { BasePaginatedResponse, BaseQuery } from '/@/shared/types/adapter/api-controller-types';
BaseEndpointArgs,
BasePaginatedResponse,
BaseQuery,
} from '/@/shared/types/domain/api-domain-types';
import { RelatedArtist } from '/@/shared/types/domain/artist-domain-types'; import { RelatedArtist } from '/@/shared/types/domain/artist-domain-types';
import { Genre } from '/@/shared/types/domain/genre-domain-types'; import { Genre } from '/@/shared/types/domain/genre-domain-types';
import { ServerType } from '/@/shared/types/domain/server-domain-types'; import { ServerType } from '/@/shared/types/domain/server-domain-types';
@@ -71,8 +67,6 @@ export enum AlbumListSort {
YEAR = 'year', YEAR = 'year',
} }
export type AlbumListArgs = BaseEndpointArgs & { query: AlbumListQuery };
export interface AlbumListQuery extends BaseQuery<AlbumListSort> { export interface AlbumListQuery extends BaseQuery<AlbumListSort> {
_custom?: { _custom?: {
jellyfin?: Partial<z.infer<typeof jfType._parameters.albumList>>; jellyfin?: Partial<z.infer<typeof jfType._parameters.albumList>>;
@@ -90,7 +84,10 @@ export interface AlbumListQuery extends BaseQuery<AlbumListSort> {
startIndex: number; startIndex: number;
} }
export type AlbumListRequest = { query: AlbumListQuery };
export type AlbumListResponse = BasePaginatedResponse<Album[]> | null | undefined; export type AlbumListResponse = BasePaginatedResponse<Album[]> | null | undefined;
type AlbumListSortMap = { type AlbumListSortMap = {
jellyfin: Record<AlbumListSort, JFAlbumListSort | undefined>; jellyfin: Record<AlbumListSort, JFAlbumListSort | undefined>;
navidrome: Record<AlbumListSort, NDAlbumListSort | undefined>; navidrome: Record<AlbumListSort, NDAlbumListSort | undefined>;
@@ -200,10 +197,10 @@ export type Album = {
userRating: null | number; userRating: null | number;
} & { songs?: Song[] }; } & { songs?: Song[] };
export type AlbumDetailArgs = BaseEndpointArgs & { query: AlbumDetailQuery };
export type AlbumDetailQuery = { id: string }; export type AlbumDetailQuery = { id: string };
export type AlbumDetailRequest = { query: AlbumDetailQuery };
export type AlbumDetailResponse = Album | null | undefined; export type AlbumDetailResponse = Album | null | undefined;
export type AlbumInfo = { export type AlbumInfo = {
+74 -96
View File
@@ -1,103 +1,79 @@
import { BaseEndpointArgs } from '/@/shared/types/adapter/api-controller-types';
import { import {
AlbumDetailArgs, AlbumDetailRequest,
AlbumDetailResponse, AlbumDetailResponse,
AlbumInfo, AlbumInfo,
AlbumListArgs, AlbumListRequest,
AlbumListResponse, AlbumListResponse,
} from '/@/shared/types/domain/album-domain-types'; } from '/@/shared/types/domain/album-domain-types';
import { import {
AlbumArtistDetailArgs, AlbumArtistDetailRequest,
AlbumArtistDetailResponse, AlbumArtistDetailResponse,
AlbumArtistListArgs, AlbumArtistListRequest,
AlbumArtistListResponse, AlbumArtistListResponse,
ArtistListArgs, ArtistListRequest,
ArtistListResponse, ArtistListResponse,
} from '/@/shared/types/domain/artist-domain-types'; } from '/@/shared/types/domain/artist-domain-types';
import { AuthenticationResponse } from '/@/shared/types/domain/auth-domain-types'; import { AuthenticationResponse } from '/@/shared/types/domain/auth-domain-types';
import { GenreListArgs, GenreListResponse } from '/@/shared/types/domain/genre-domain-types'; import { GenreListRequest, GenreListResponse } from '/@/shared/types/domain/genre-domain-types';
import { import {
LyricsArgs, LyricsRequest,
LyricsResponse, LyricsResponse,
StructuredLyric, StructuredLyric,
StructuredLyricsArgs, StructuredLyricsRequest,
} from '/@/shared/types/domain/lyric-domain-types'; } from '/@/shared/types/domain/lyric-domain-types';
import { TranscodingArgs } from '/@/shared/types/domain/player-domain-types'; import { TranscodingRequest } from '/@/shared/types/domain/player-domain-types';
import { import {
AddToPlaylistArgs, AddToPlaylistArgs,
AddToPlaylistResponse, AddToPlaylistResponse,
CreatePlaylistArgs, CreatePlaylistRequest,
CreatePlaylistResponse, CreatePlaylistResponse,
DeletePlaylistArgs, DeletePlaylistRequest,
DeletePlaylistResponse, DeletePlaylistResponse,
MoveItemArgs, MoveItemRequest,
PlaylistDetailArgs, PlaylistDetailRequest,
PlaylistDetailResponse, PlaylistDetailResponse,
PlaylistListArgs, PlaylistListRequest,
PlaylistListResponse, PlaylistListResponse,
PlaylistSongListArgs, PlaylistSongListRequest,
RemoveFromPlaylistArgs, RemoveFromPlaylistRequest,
RemoveFromPlaylistResponse, RemoveFromPlaylistResponse,
UpdatePlaylistArgs, UpdatePlaylistRequest,
UpdatePlaylistResponse, UpdatePlaylistResponse,
} from '/@/shared/types/domain/playlist-domain-types'; } from '/@/shared/types/domain/playlist-domain-types';
import { SearchArgs, SearchResponse } from '/@/shared/types/domain/search-domain-types'; import { SearchRequest, SearchResponse } from '/@/shared/types/domain/search-domain-types';
import { import {
ServerInfo, ServerInfo,
ServerInfoArgs, ServerInfoRequest,
ServerListItem, ServerMusicFolderListRequest,
ServerMusicFolderListArgs,
ServerMusicFolderListResponse, ServerMusicFolderListResponse,
} from '/@/shared/types/domain/server-domain-types'; } from '/@/shared/types/domain/server-domain-types';
import { ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
import { import {
RandomSongListArgs, RandomSongListRequest,
SimilarSongsArgs, SimilarSongsRequest,
Song, Song,
SongDetailArgs, SongDetailRequest,
SongDetailResponse, SongDetailResponse,
SongListArgs, SongListRequest,
SongListResponse, SongListResponse,
TopSongListArgs, TopSongListRequest,
TopSongListResponse, TopSongListResponse,
} from '/@/shared/types/domain/song-domain-types'; } from '/@/shared/types/domain/song-domain-types';
import { TagArgs, TagsResponse } from '/@/shared/types/domain/tag-domain-types'; import { TagRequest, TagsResponse } from '/@/shared/types/domain/tag-domain-types';
import { import {
DownloadArgs, DownloadRequest,
FavoriteArgs, FavoriteRequest,
FavoriteResponse, FavoriteResponse,
RatingResponse, RatingResponse,
ScrobbleArgs, ScrobbleRequest,
ScrobbleResponse, ScrobbleResponse,
SetRatingArgs, SetRatingRequest,
ShareItemArgs, ShareItemRequest,
ShareItemResponse, ShareItemResponse,
UserListArgs, UserListRequest,
UserListResponse, UserListResponse,
} from '/@/shared/types/domain/user-domain-types'; } from '/@/shared/types/domain/user-domain-types';
export type BaseEndpointArgs = {
apiClientProps: {
server: null | ServerListItem;
signal?: AbortSignal;
};
};
export interface BasePaginatedResponse<T> {
error?: any | string;
items: T;
startIndex: number;
totalRecordCount: null | number;
}
export interface BaseQuery<T> {
sortBy: T;
sortOrder: ListSortOrder;
}
export type EndpointDetails = {
server: ServerListItem;
};
export const instanceOfCancellationError = (error: any) => { export const instanceOfCancellationError = (error: any) => {
return 'revert' in error; return 'revert' in error;
}; };
@@ -108,44 +84,46 @@ export type ControllerEndpoint = {
url: string, url: string,
body: { legacy?: boolean; password: string; username: string }, body: { legacy?: boolean; password: string; username: string },
) => Promise<AuthenticationResponse>; ) => Promise<AuthenticationResponse>;
createFavorite: (args: FavoriteArgs) => Promise<FavoriteResponse>; createFavorite: (args: FavoriteRequest) => Promise<FavoriteResponse>;
createPlaylist: (args: CreatePlaylistArgs) => Promise<CreatePlaylistResponse>; createPlaylist: (args: CreatePlaylistRequest) => Promise<CreatePlaylistResponse>;
deleteFavorite: (args: FavoriteArgs) => Promise<FavoriteResponse>; deleteFavorite: (args: FavoriteRequest) => Promise<FavoriteResponse>;
deletePlaylist: (args: DeletePlaylistArgs) => Promise<DeletePlaylistResponse>; deletePlaylist: (args: DeletePlaylistRequest) => Promise<DeletePlaylistResponse>;
getAlbumArtistDetail: (args: AlbumArtistDetailArgs) => Promise<AlbumArtistDetailResponse>; getAlbumArtistDetail: (args: AlbumArtistDetailRequest) => Promise<AlbumArtistDetailResponse>;
getAlbumArtistList: (args: AlbumArtistListArgs) => Promise<AlbumArtistListResponse>; getAlbumArtistList: (args: AlbumArtistListRequest) => Promise<AlbumArtistListResponse>;
getAlbumArtistListCount: (args: AlbumArtistListArgs) => Promise<number>; getAlbumArtistListCount: (args: AlbumArtistListRequest) => Promise<number>;
getAlbumDetail: (args: AlbumDetailArgs) => Promise<AlbumDetailResponse>; getAlbumDetail: (args: AlbumDetailRequest) => Promise<AlbumDetailResponse>;
getAlbumInfo?: (args: AlbumDetailArgs) => Promise<AlbumInfo>; getAlbumInfo?: (args: AlbumDetailRequest) => Promise<AlbumInfo>;
getAlbumList: (args: AlbumListArgs) => Promise<AlbumListResponse>; getAlbumList: (args: AlbumListRequest) => Promise<AlbumListResponse>;
getAlbumListCount: (args: AlbumListArgs) => Promise<number>; getAlbumListCount: (args: AlbumListRequest) => Promise<number>;
getArtistList: (args: ArtistListArgs) => Promise<ArtistListResponse>; getArtistList: (args: ArtistListRequest) => Promise<ArtistListResponse>;
getArtistListCount: (args: ArtistListArgs) => Promise<number>; getArtistListCount: (args: ArtistListRequest) => Promise<number>;
getDownloadUrl: (args: DownloadArgs) => string; getDownloadUrl: (args: DownloadRequest) => string;
getGenreList: (args: GenreListArgs) => Promise<GenreListResponse>; getGenreList: (args: GenreListRequest) => Promise<GenreListResponse>;
getLyrics?: (args: LyricsArgs) => Promise<LyricsResponse>; getLyrics?: (args: LyricsRequest) => Promise<LyricsResponse>;
getMusicFolderList: (args: ServerMusicFolderListArgs) => Promise<ServerMusicFolderListResponse>; getMusicFolderList: (
getPlaylistDetail: (args: PlaylistDetailArgs) => Promise<PlaylistDetailResponse>; args: ServerMusicFolderListRequest,
getPlaylistList: (args: PlaylistListArgs) => Promise<PlaylistListResponse>; ) => Promise<ServerMusicFolderListResponse>;
getPlaylistListCount: (args: PlaylistListArgs) => Promise<number>; getPlaylistDetail: (args: PlaylistDetailRequest) => Promise<PlaylistDetailResponse>;
getPlaylistSongList: (args: PlaylistSongListArgs) => Promise<SongListResponse>; getPlaylistList: (args: PlaylistListRequest) => Promise<PlaylistListResponse>;
getRandomSongList: (args: RandomSongListArgs) => Promise<SongListResponse>; getPlaylistListCount: (args: PlaylistListRequest) => Promise<number>;
getPlaylistSongList: (args: PlaylistSongListRequest) => Promise<SongListResponse>;
getRandomSongList: (args: RandomSongListRequest) => Promise<SongListResponse>;
getRoles: (args: BaseEndpointArgs) => Promise<Array<string | { label: string; value: string }>>; getRoles: (args: BaseEndpointArgs) => Promise<Array<string | { label: string; value: string }>>;
getServerInfo: (args: ServerInfoArgs) => Promise<ServerInfo>; getServerInfo: (args: ServerInfoRequest) => Promise<ServerInfo>;
getSimilarSongs: (args: SimilarSongsArgs) => Promise<Song[]>; getSimilarSongs: (args: SimilarSongsRequest) => Promise<Song[]>;
getSongDetail: (args: SongDetailArgs) => Promise<SongDetailResponse>; getSongDetail: (args: SongDetailRequest) => Promise<SongDetailResponse>;
getSongList: (args: SongListArgs) => Promise<SongListResponse>; getSongList: (args: SongListRequest) => Promise<SongListResponse>;
getSongListCount: (args: SongListArgs) => Promise<number>; getSongListCount: (args: SongListRequest) => Promise<number>;
getStructuredLyrics?: (args: StructuredLyricsArgs) => Promise<StructuredLyric[]>; getStructuredLyrics?: (args: StructuredLyricsRequest) => Promise<StructuredLyric[]>;
getTags?: (args: TagArgs) => Promise<TagsResponse>; getTags?: (args: TagRequest) => Promise<TagsResponse>;
getTopSongs: (args: TopSongListArgs) => Promise<TopSongListResponse>; getTopSongs: (args: TopSongListRequest) => Promise<TopSongListResponse>;
getTranscodingUrl: (args: TranscodingArgs) => string; getTranscodingUrl: (args: TranscodingRequest) => string;
getUserList?: (args: UserListArgs) => Promise<UserListResponse>; getUserList?: (args: UserListRequest) => Promise<UserListResponse>;
movePlaylistItem?: (args: MoveItemArgs) => Promise<void>; movePlaylistItem?: (args: MoveItemRequest) => Promise<void>;
removeFromPlaylist: (args: RemoveFromPlaylistArgs) => Promise<RemoveFromPlaylistResponse>; removeFromPlaylist: (args: RemoveFromPlaylistRequest) => Promise<RemoveFromPlaylistResponse>;
scrobble: (args: ScrobbleArgs) => Promise<ScrobbleResponse>; scrobble: (args: ScrobbleRequest) => Promise<ScrobbleResponse>;
search: (args: SearchArgs) => Promise<SearchResponse>; search: (args: SearchRequest) => Promise<SearchResponse>;
setRating?: (args: SetRatingArgs) => Promise<RatingResponse>; setRating?: (args: SetRatingRequest) => Promise<RatingResponse>;
shareItem?: (args: ShareItemArgs) => Promise<ShareItemResponse>; shareItem?: (args: ShareItemRequest) => Promise<ShareItemResponse>;
updatePlaylist: (args: UpdatePlaylistArgs) => Promise<UpdatePlaylistResponse>; updatePlaylist: (args: UpdatePlaylistRequest) => Promise<UpdatePlaylistResponse>;
}; };
+11 -12
View File
@@ -6,11 +6,7 @@ import { JFAlbumArtistListSort, JFArtistListSort } from '/@/shared/api/jellyfin.
import { jfType } from '/@/shared/api/jellyfin/jellyfin-types'; import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
import { NDAlbumArtistListSort } from '/@/shared/api/navidrome.types'; import { NDAlbumArtistListSort } from '/@/shared/api/navidrome.types';
import { ndType } from '/@/shared/api/navidrome/navidrome-types'; import { ndType } from '/@/shared/api/navidrome/navidrome-types';
import { import { BasePaginatedResponse, BaseQuery } from '/@/shared/types/adapter/api-controller-types';
BaseEndpointArgs,
BasePaginatedResponse,
BaseQuery,
} from '/@/shared/types/domain/api-domain-types';
import { Genre } from '/@/shared/types/domain/genre-domain-types'; import { Genre } from '/@/shared/types/domain/genre-domain-types';
import { ServerType } from '/@/shared/types/domain/server-domain-types'; import { ServerType } from '/@/shared/types/domain/server-domain-types';
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types'; import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
@@ -142,13 +138,11 @@ export enum ArtistListSort {
SONG_COUNT = 'songCount', SONG_COUNT = 'songCount',
} }
export type AlbumArtistDetailArgs = BaseEndpointArgs & { query: AlbumArtistDetailQuery };
export type AlbumArtistDetailQuery = { id: string }; export type AlbumArtistDetailQuery = { id: string };
export type AlbumArtistDetailResponse = AlbumArtist | null; export type AlbumArtistDetailRequest = { query: AlbumArtistDetailQuery };
export type ArtistListArgs = BaseEndpointArgs & { query: ArtistListQuery }; export type AlbumArtistDetailResponse = AlbumArtist | null;
export interface ArtistListQuery extends BaseQuery<ArtistListSort> { export interface ArtistListQuery extends BaseQuery<ArtistListSort> {
_custom?: { _custom?: {
@@ -162,6 +156,8 @@ export interface ArtistListQuery extends BaseQuery<ArtistListSort> {
startIndex: number; startIndex: number;
} }
export type ArtistListRequest = { query: ArtistListQuery };
export type ArtistListResponse = BasePaginatedResponse<AlbumArtist[]> | null | undefined; export type ArtistListResponse = BasePaginatedResponse<AlbumArtist[]> | null | undefined;
type ArtistListSortMap = { type ArtistListSortMap = {
jellyfin: Record<ArtistListSort, JFArtistListSort | undefined>; jellyfin: Record<ArtistListSort, JFArtistListSort | undefined>;
@@ -224,8 +220,6 @@ export enum AlbumArtistListSort {
SONG_COUNT = 'songCount', SONG_COUNT = 'songCount',
} }
export type AlbumArtistListArgs = BaseEndpointArgs & { query: AlbumArtistListQuery };
export interface AlbumArtistListQuery extends BaseQuery<AlbumArtistListSort> { export interface AlbumArtistListQuery extends BaseQuery<AlbumArtistListSort> {
_custom?: { _custom?: {
jellyfin?: Partial<z.infer<typeof jfType._parameters.albumArtistList>>; jellyfin?: Partial<z.infer<typeof jfType._parameters.albumArtistList>>;
@@ -236,14 +230,19 @@ export interface AlbumArtistListQuery extends BaseQuery<AlbumArtistListSort> {
searchTerm?: string; searchTerm?: string;
startIndex: number; startIndex: number;
} }
export type AlbumArtistListRequest = { query: AlbumArtistListQuery };
export type AlbumArtistListResponse = BasePaginatedResponse<AlbumArtist[]> | null | undefined; export type AlbumArtistListResponse = BasePaginatedResponse<AlbumArtist[]> | null | undefined;
export type ArtistInfoArgs = BaseEndpointArgs & { query: ArtistInfoQuery };
export type ArtistInfoQuery = { export type ArtistInfoQuery = {
artistId: string; artistId: string;
limit: number; limit: number;
musicFolderId?: string; musicFolderId?: string;
}; };
export type ArtistInfoRequest = { query: ArtistInfoQuery };
export const sortAlbumArtistList = ( export const sortAlbumArtistList = (
artists: AlbumArtist[], artists: AlbumArtist[],
sortBy: AlbumArtistListSort | ArtistListSort, sortBy: AlbumArtistListSort | ArtistListSort,
@@ -1,11 +1,7 @@
import i18n from '/@/i18n/i18n'; import i18n from '/@/i18n/i18n';
import { JFGenreListSort } from '/@/shared/api/jellyfin.types'; import { JFGenreListSort } from '/@/shared/api/jellyfin.types';
import { NDGenreListSort } from '/@/shared/api/navidrome.types'; import { NDGenreListSort } from '/@/shared/api/navidrome.types';
import { import { BasePaginatedResponse, BaseQuery } from '/@/shared/types/adapter/api-controller-types';
BaseEndpointArgs,
BasePaginatedResponse,
BaseQuery,
} from '/@/shared/types/domain/api-domain-types';
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types'; import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
import { UserListSort } from '/@/shared/types/domain/user-domain-types'; import { UserListSort } from '/@/shared/types/domain/user-domain-types';
@@ -30,8 +26,6 @@ export type Genre = {
songCount?: number; songCount?: number;
}; };
export type GenreListArgs = BaseEndpointArgs & { query: GenreListQuery };
export interface GenreListQuery extends BaseQuery<GenreListSort> { export interface GenreListQuery extends BaseQuery<GenreListSort> {
_custom?: { _custom?: {
jellyfin?: null; jellyfin?: null;
@@ -43,9 +37,10 @@ export interface GenreListQuery extends BaseQuery<GenreListSort> {
startIndex: number; startIndex: number;
} }
export type GenreListRequest = { query: GenreListQuery };
export type GenreListResponse = BasePaginatedResponse<Genre[]> | null | undefined; export type GenreListResponse = BasePaginatedResponse<Genre[]> | null | undefined;
export type GenresResponse = Genre[];
type GenreListSortMap = { type GenreListSortMap = {
jellyfin: Record<GenreListSort, JFGenreListSort | undefined>; jellyfin: Record<GenreListSort, JFGenreListSort | undefined>;
navidrome: Record<GenreListSort, NDGenreListSort | undefined>; navidrome: Record<GenreListSort, NDGenreListSort | undefined>;
@@ -1,4 +1,3 @@
import { BaseEndpointArgs } from './api-domain-types';
import { Song } from '/@/shared/types/domain/song-domain-types'; import { Song } from '/@/shared/types/domain/song-domain-types';
export enum LyricSource { export enum LyricSource {
@@ -35,9 +34,6 @@ export type LyricGetQuery = {
export type LyricOverride = Omit<InternetProviderLyricResponse, 'lyrics'>; export type LyricOverride = Omit<InternetProviderLyricResponse, 'lyrics'>;
export type LyricsArgs = BaseEndpointArgs & {
query: LyricsQuery;
};
export type LyricSearchQuery = { export type LyricSearchQuery = {
album?: string; album?: string;
artist?: string; artist?: string;
@@ -50,22 +46,26 @@ export type LyricsQuery = {
songId: string; songId: string;
}; };
export type LyricsRequest = {
query: LyricsQuery;
};
export type LyricsResponse = string | SynchronizedLyricsArray; export type LyricsResponse = string | SynchronizedLyricsArray;
export type StructuredLyric = (StructuredSyncedLyric | StructuredUnsyncedLyric) & { export type StructuredLyric = (StructuredSyncedLyric | StructuredUnsyncedLyric) & {
lang: string; lang: string;
}; };
export type StructuredLyricsArgs = BaseEndpointArgs & { export type StructuredLyricsRequest = { query: LyricsQuery };
query: LyricsQuery;
};
export type StructuredSyncedLyric = Omit<FullLyricsMetadata, 'lyrics'> & { export type StructuredSyncedLyric = Omit<FullLyricsMetadata, 'lyrics'> & {
lyrics: SynchronizedLyricsArray; lyrics: SynchronizedLyricsArray;
synced: true; synced: true;
}; };
export type StructuredUnsyncedLyric = Omit<FullLyricsMetadata, 'lyrics'> & { export type StructuredUnsyncedLyric = Omit<FullLyricsMetadata, 'lyrics'> & {
lyrics: string; lyrics: string;
synced: false; synced: false;
}; };
export type SynchronizedLyricsArray = Array<[number, string]>; export type SynchronizedLyricsArray = Array<[number, string]>;
@@ -1,4 +1,3 @@
import { BaseEndpointArgs } from '/@/shared/types/domain/api-domain-types';
import { Song } from '/@/shared/types/domain/song-domain-types'; import { Song } from '/@/shared/types/domain/song-domain-types';
import { PlayerStatus } from '/@/shared/types/types'; import { PlayerStatus } from '/@/shared/types/types';
@@ -29,15 +28,17 @@ export interface QueueData {
next?: QueueSong; next?: QueueSong;
previous?: QueueSong; previous?: QueueSong;
} }
export type QueueSong = Song & { export type QueueSong = Song & {
uniqueId: string; uniqueId: string;
}; };
export type TranscodingArgs = BaseEndpointArgs & {
query: TranscodingQuery;
};
export type TranscodingQuery = { export type TranscodingQuery = {
base: string; base: string;
bitrate?: number; bitrate?: number;
format?: string; format?: string;
}; };
export type TranscodingRequest = {
query: TranscodingQuery;
};
@@ -9,7 +9,7 @@ import {
BaseEndpointArgs, BaseEndpointArgs,
BasePaginatedResponse, BasePaginatedResponse,
BaseQuery, BaseQuery,
} from '/@/shared/types/domain/api-domain-types'; } from '/@/shared/types/adapter/api-controller-types';
import { Genre } from '/@/shared/types/domain/genre-domain-types'; import { Genre } from '/@/shared/types/domain/genre-domain-types';
import { ServerType } from '/@/shared/types/domain/server-domain-types'; import { ServerType } from '/@/shared/types/domain/server-domain-types';
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types'; import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
@@ -58,8 +58,6 @@ export type AddToPlaylistQuery = {
export type AddToPlaylistResponse = null | undefined; export type AddToPlaylistResponse = null | undefined;
export type CreatePlaylistArgs = BaseEndpointArgs & { body: CreatePlaylistBody; serverId?: string };
export type CreatePlaylistBody = { export type CreatePlaylistBody = {
_custom?: { _custom?: {
navidrome?: { navidrome?: {
@@ -74,15 +72,20 @@ export type CreatePlaylistBody = {
public?: boolean; public?: boolean;
}; };
export type CreatePlaylistResponse = undefined | { id: string }; export type CreatePlaylistRequest = {
body: CreatePlaylistBody;
export type DeletePlaylistArgs = BaseEndpointArgs & {
query: DeletePlaylistQuery;
serverId?: string; serverId?: string;
}; };
export type CreatePlaylistResponse = undefined | { id: string };
export type DeletePlaylistQuery = { id: string }; export type DeletePlaylistQuery = { id: string };
export type DeletePlaylistRequest = {
query: DeletePlaylistQuery;
serverId?: string;
};
export type DeletePlaylistResponse = null | undefined; export type DeletePlaylistResponse = null | undefined;
export type Playlist = { export type Playlist = {
@@ -104,8 +107,6 @@ export type Playlist = {
songCount: null | number; songCount: null | number;
sync?: boolean | null; sync?: boolean | null;
}; };
export type PlaylistListArgs = BaseEndpointArgs & { query: PlaylistListQuery };
export interface PlaylistListQuery extends BaseQuery<PlaylistListSort> { export interface PlaylistListQuery extends BaseQuery<PlaylistListSort> {
_custom?: { _custom?: {
jellyfin?: Partial<z.infer<typeof jfType._parameters.playlistList>>; jellyfin?: Partial<z.infer<typeof jfType._parameters.playlistList>>;
@@ -116,26 +117,22 @@ export interface PlaylistListQuery extends BaseQuery<PlaylistListSort> {
startIndex: number; startIndex: number;
} }
export type PlaylistListResponse = BasePaginatedResponse<Playlist[]> | null | undefined; export type PlaylistListRequest = { query: PlaylistListQuery };
export type RemoveFromPlaylistArgs = BaseEndpointArgs & { export type PlaylistListResponse = BasePaginatedResponse<Playlist[]> | null | undefined;
query: RemoveFromPlaylistQuery;
serverId?: string;
};
export type RemoveFromPlaylistQuery = { export type RemoveFromPlaylistQuery = {
id: string; id: string;
songId: string[]; songId: string[];
}; };
export type RemoveFromPlaylistResponse = null | undefined; export type RemoveFromPlaylistRequest = {
query: RemoveFromPlaylistQuery;
export type UpdatePlaylistArgs = BaseEndpointArgs & {
body: UpdatePlaylistBody;
query: UpdatePlaylistQuery;
serverId?: string; serverId?: string;
}; };
export type RemoveFromPlaylistResponse = null | undefined;
export type UpdatePlaylistBody = { export type UpdatePlaylistBody = {
_custom?: { _custom?: {
navidrome?: { navidrome?: {
@@ -155,6 +152,12 @@ export type UpdatePlaylistQuery = {
id: string; id: string;
}; };
export type UpdatePlaylistRequest = {
body: UpdatePlaylistBody;
query: UpdatePlaylistQuery;
serverId?: string;
};
export type UpdatePlaylistResponse = null | undefined; export type UpdatePlaylistResponse = null | undefined;
type PlaylistListSortMap = { type PlaylistListSortMap = {
@@ -189,10 +192,6 @@ export const playlistListSortMap: PlaylistListSortMap = {
updatedAt: undefined, updatedAt: undefined,
}, },
}; };
export type MoveItemArgs = BaseEndpointArgs & {
query: MoveItemQuery;
};
export type MoveItemQuery = { export type MoveItemQuery = {
endingIndex: number; endingIndex: number;
playlistId: string; playlistId: string;
@@ -200,15 +199,18 @@ export type MoveItemQuery = {
trackId: string; trackId: string;
}; };
export type PlaylistDetailArgs = BaseEndpointArgs & { query: PlaylistDetailQuery }; export type MoveItemRequest = {
query: MoveItemQuery;
};
export type PlaylistDetailQuery = { export type PlaylistDetailQuery = {
id: string; id: string;
}; };
export type PlaylistDetailRequest = { query: PlaylistDetailQuery };
export type PlaylistDetailResponse = Playlist; export type PlaylistDetailResponse = Playlist;
export type PlaylistSongListArgs = BaseEndpointArgs & { query: PlaylistSongListQuery };
export type PlaylistSongListQuery = { export type PlaylistSongListQuery = {
id: string; id: string;
limit?: number; limit?: number;
@@ -217,4 +219,6 @@ export type PlaylistSongListQuery = {
startIndex: number; startIndex: number;
}; };
export type PlaylistSongListRequest = { query: PlaylistSongListQuery };
export type PlaylistSongListResponse = BasePaginatedResponse<Song[]> | null | undefined; export type PlaylistSongListResponse = BasePaginatedResponse<Song[]> | null | undefined;
@@ -1,5 +1,4 @@
import { Album } from '/@/shared/types/domain/album-domain-types'; import { Album } from '/@/shared/types/domain/album-domain-types';
import { BaseEndpointArgs } from '/@/shared/types/domain/api-domain-types';
import { AlbumArtist } from '/@/shared/types/domain/artist-domain-types'; import { AlbumArtist } from '/@/shared/types/domain/artist-domain-types';
import { Song } from '/@/shared/types/domain/song-domain-types'; import { Song } from '/@/shared/types/domain/song-domain-types';
@@ -17,10 +16,6 @@ export type SearchAlbumsQuery = {
query?: string; query?: string;
}; };
export type SearchArgs = BaseEndpointArgs & {
query: SearchQuery;
};
export type SearchQuery = { export type SearchQuery = {
albumArtistLimit?: number; albumArtistLimit?: number;
albumArtistStartIndex?: number; albumArtistStartIndex?: number;
@@ -32,6 +27,8 @@ export type SearchQuery = {
songStartIndex?: number; songStartIndex?: number;
}; };
export type SearchRequest = { query: SearchQuery };
export type SearchResponse = { export type SearchResponse = {
albumArtists: AlbumArtist[]; albumArtists: AlbumArtist[];
albums: Album[]; albums: Album[];
@@ -1,6 +1,6 @@
import i18n from 'src/i18n/i18n'; import i18n from 'src/i18n/i18n';
import { BaseEndpointArgs, BasePaginatedResponse } from '/@/shared/types/domain/api-domain-types'; import { BasePaginatedResponse } from '/@/shared/types/adapter/api-controller-types';
export enum ServerListSortOptions { export enum ServerListSortOptions {
CREATED_AT = 'createdAt', CREATED_AT = 'createdAt',
@@ -40,7 +40,7 @@ export type ServerInfo = {
version: string; version: string;
}; };
export type ServerInfoArgs = BaseEndpointArgs; export type ServerInfoRequest = null;
export type ServerListItem = { export type ServerListItem = {
credential: string; credential: string;
@@ -61,10 +61,10 @@ export type ServerMusicFolder = {
name: string; name: string;
}; };
export type ServerMusicFolderListArgs = BaseEndpointArgs;
export type ServerMusicFolderListQuery = null; export type ServerMusicFolderListQuery = null;
export type ServerMusicFolderListRequest = null;
export type ServerMusicFolderListResponse = export type ServerMusicFolderListResponse =
| BasePaginatedResponse<ServerMusicFolder[]> | BasePaginatedResponse<ServerMusicFolder[]>
| null | null
+19 -18
View File
@@ -6,11 +6,7 @@ import { JFSongListSort } from '/@/shared/api/jellyfin.types';
import { jfType } from '/@/shared/api/jellyfin/jellyfin-types'; import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
import { NDSongListSort } from '/@/shared/api/navidrome.types'; import { NDSongListSort } from '/@/shared/api/navidrome.types';
import { ndType } from '/@/shared/api/navidrome/navidrome-types'; import { ndType } from '/@/shared/api/navidrome/navidrome-types';
import { import { BasePaginatedResponse, BaseQuery } from '/@/shared/types/adapter/api-controller-types';
BaseEndpointArgs,
BasePaginatedResponse,
BaseQuery,
} from '/@/shared/types/domain/api-domain-types';
import { RelatedArtist } from '/@/shared/types/domain/artist-domain-types'; import { RelatedArtist } from '/@/shared/types/domain/artist-domain-types';
import { Genre } from '/@/shared/types/domain/genre-domain-types'; import { Genre } from '/@/shared/types/domain/genre-domain-types';
import { Played, QueueSong } from '/@/shared/types/domain/player-domain-types'; import { Played, QueueSong } from '/@/shared/types/domain/player-domain-types';
@@ -58,6 +54,7 @@ export const SongListSortOptionsLabels = {
[SongListSortOptions.RELEASE_DATE]: i18n.t('filter.releaseDate'), [SongListSortOptions.RELEASE_DATE]: i18n.t('filter.releaseDate'),
[SongListSortOptions.YEAR]: i18n.t('filter.year'), [SongListSortOptions.YEAR]: i18n.t('filter.year'),
}; };
export enum SongListSort { export enum SongListSort {
ALBUM = 'album', ALBUM = 'album',
ALBUM_ARTIST = 'albumArtist', ALBUM_ARTIST = 'albumArtist',
@@ -78,6 +75,7 @@ export enum SongListSort {
RELEASE_DATE = 'releaseDate', RELEASE_DATE = 'releaseDate',
YEAR = 'year', YEAR = 'year',
} }
export type Song = { export type Song = {
album: null | string; album: null | string;
albumArtists: RelatedArtist[]; albumArtists: RelatedArtist[];
@@ -121,7 +119,6 @@ export type Song = {
userFavorite: boolean; userFavorite: boolean;
userRating: null | number; userRating: null | number;
}; };
export type SongListArgs = BaseEndpointArgs & { query: SongListQuery };
export interface SongListQuery extends BaseQuery<SongListSort> { export interface SongListQuery extends BaseQuery<SongListSort> {
_custom?: { _custom?: {
@@ -143,6 +140,8 @@ export interface SongListQuery extends BaseQuery<SongListSort> {
startIndex: number; startIndex: number;
} }
export type SongListRequest = { query: SongListQuery };
export type SongListResponse = BasePaginatedResponse<Song[]> | null | undefined; export type SongListResponse = BasePaginatedResponse<Song[]> | null | undefined;
type SongListSortMap = { type SongListSortMap = {
jellyfin: Record<SongListSort, JFSongListSort | undefined>; jellyfin: Record<SongListSort, JFSongListSort | undefined>;
@@ -212,15 +211,12 @@ export const songListSortMap: SongListSortMap = {
year: undefined, year: undefined,
}, },
}; };
export type GainInfo = { export type GainInfo = {
album?: number; album?: number;
track?: number; track?: number;
}; };
export type RandomSongListArgs = BaseEndpointArgs & {
query: RandomSongListQuery;
};
export type RandomSongListQuery = { export type RandomSongListQuery = {
genre?: string; genre?: string;
limit?: number; limit?: number;
@@ -229,30 +225,35 @@ export type RandomSongListQuery = {
musicFolderId?: string; musicFolderId?: string;
played: Played; played: Played;
}; };
export type RandomSongListResponse = SongListResponse;
export type SimilarSongsArgs = BaseEndpointArgs & { export type RandomSongListRequest = { query: RandomSongListQuery };
query: SimilarSongsQuery;
}; export type RandomSongListResponse = SongListResponse;
export type SimilarSongsQuery = { export type SimilarSongsQuery = {
albumArtistIds: string[]; albumArtistIds: string[];
count?: number; count?: number;
songId: string; songId: string;
}; };
export type SongDetailArgs = BaseEndpointArgs & { query: SongDetailQuery };
export type SimilarSongsRequest = { query: SimilarSongsQuery };
export type SongDetailQuery = { id: string }; export type SongDetailQuery = { id: string };
export type SongDetailResponse = null | Song | undefined;
export type TopSongListArgs = BaseEndpointArgs & { query: TopSongListQuery }; export type SongDetailRequest = { query: SongDetailQuery };
export type SongDetailResponse = null | Song | undefined;
export type TopSongListQuery = { export type TopSongListQuery = {
artist: string; artist: string;
artistId: string; artistId: string;
limit?: number; limit?: number;
}; };
export type TopSongListRequest = { query: TopSongListQuery };
export type TopSongListResponse = BasePaginatedResponse<Song[]> | null | undefined; export type TopSongListResponse = BasePaginatedResponse<Song[]> | null | undefined;
export const sortSongList = ( export const sortSongList = (
songs: QueueSong[], songs: QueueSong[],
sortBy: SongListSort, sortBy: SongListSort,
@@ -299,7 +300,7 @@ export const sortSongList = (
results = orderBy( results = orderBy(
results, results,
[ [
(v) => v.genres?.[0].name.toLowerCase(), (v) => v.genres?.[0]?.name.toLowerCase(),
(v) => v.album?.toLowerCase(), (v) => v.album?.toLowerCase(),
'discNumber', 'discNumber',
'trackNumber', 'trackNumber',
+2 -5
View File
@@ -1,4 +1,3 @@
import { BaseEndpointArgs } from '/@/shared/types/domain/api-domain-types';
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types'; import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
export type Tag = { export type Tag = {
@@ -6,15 +5,13 @@ export type Tag = {
options: string[]; options: string[];
}; };
export type TagArgs = BaseEndpointArgs & {
query: TagQuery;
};
export type TagQuery = { export type TagQuery = {
folder?: string; folder?: string;
type: LibraryItem.ALBUM | LibraryItem.SONG; type: LibraryItem.ALBUM | LibraryItem.SONG;
}; };
export type TagRequest = { query: TagQuery };
export type TagsResponse = { export type TagsResponse = {
boolTags?: string[]; boolTags?: string[];
enumTags?: Tag[]; enumTags?: Tag[];
+15 -23
View File
@@ -1,10 +1,6 @@
import i18n from '/@/i18n/i18n'; import i18n from '/@/i18n/i18n';
import { NDUserListSort } from '/@/shared/api/navidrome.types'; import { NDUserListSort } from '/@/shared/api/navidrome.types';
import { import { BasePaginatedResponse, BaseQuery } from '/@/shared/types/adapter/api-controller-types';
BaseEndpointArgs,
BasePaginatedResponse,
BaseQuery,
} from '/@/shared/types/domain/api-domain-types';
import { AnyLibraryItems, LibraryItem } from '/@/shared/types/domain/shared-domain-types'; import { AnyLibraryItems, LibraryItem } from '/@/shared/types/domain/shared-domain-types';
export enum UserListSortOptions { export enum UserListSortOptions {
@@ -21,24 +17,23 @@ export const UserListSortOptionsLabels = {
[UserListSortOptions.UPDATED_AT]: i18n.t('filter.updatedAt'), [UserListSortOptions.UPDATED_AT]: i18n.t('filter.updatedAt'),
}; };
export type FavoriteArgs = BaseEndpointArgs & { query: FavoriteQuery; serverId?: string };
export type FavoriteQuery = { export type FavoriteQuery = {
id: string[]; id: string[];
type: LibraryItem; type: LibraryItem;
}; };
export type FavoriteResponse = null | undefined; export type FavoriteRequest = { query: FavoriteQuery; serverId?: string };
export type FavoriteResponse = null;
export type RatingQuery = { export type RatingQuery = {
item: AnyLibraryItems; item: AnyLibraryItems;
rating: number; rating: number;
}; };
export type RatingResponse = null | undefined; export type RatingResponse = null;
export type SetRatingArgs = BaseEndpointArgs & { query: RatingQuery; serverId?: string }; export type SetRatingRequest = { query: RatingQuery; serverId?: string };
export type UserListArgs = BaseEndpointArgs & { query: UserListQuery };
export interface UserListQuery extends BaseQuery<UserListSort> { export interface UserListQuery extends BaseQuery<UserListSort> {
_custom?: { _custom?: {
@@ -51,6 +46,8 @@ export interface UserListQuery extends BaseQuery<UserListSort> {
startIndex: number; startIndex: number;
} }
export type UserListRequest = { query: UserListQuery };
export type UserListResponse = BasePaginatedResponse<User[]> | null | undefined; export type UserListResponse = BasePaginatedResponse<User[]> | null | undefined;
type UserListSortMap = { type UserListSortMap = {
@@ -75,18 +72,11 @@ export enum UserListSort {
NAME = 'name', NAME = 'name',
} }
export type DownloadArgs = BaseEndpointArgs & {
query: DownloadQuery;
};
export type DownloadQuery = { export type DownloadQuery = {
id: string; id: string;
}; };
export type ScrobbleArgs = BaseEndpointArgs & { export type DownloadRequest = { query: DownloadQuery };
query: ScrobbleQuery;
serverId?: string;
};
export type ScrobbleQuery = { export type ScrobbleQuery = {
event?: 'pause' | 'start' | 'timeupdate' | 'unpause'; event?: 'pause' | 'start' | 'timeupdate' | 'unpause';
@@ -95,9 +85,9 @@ export type ScrobbleQuery = {
submission: boolean; submission: boolean;
}; };
export type ScrobbleResponse = null | undefined; export type ScrobbleRequest = { query: ScrobbleQuery; serverId?: string };
export type ShareItemArgs = BaseEndpointArgs & { body: ShareItemBody; serverId?: string }; export type ScrobbleResponse = null;
export type ShareItemBody = { export type ShareItemBody = {
description: string; description: string;
@@ -107,7 +97,9 @@ export type ShareItemBody = {
resourceType: string; resourceType: string;
}; };
export type ShareItemResponse = undefined | { id: string }; export type ShareItemRequest = { body: ShareItemBody; serverId?: string };
export type ShareItemResponse = null | { id: string };
export type User = { export type User = {
createdAt: null | string; createdAt: null | string;