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