diff --git a/src/music_service.ts b/src/music_service.ts index aec11ca..23da79c 100644 --- a/src/music_service.ts +++ b/src/music_service.ts @@ -38,31 +38,35 @@ export type Album = { }; export type Paging = { - _index?: number; - _count?: number; + _index: number; + _count: number; }; export type Result = { - results: T[], - total: number -} + results: T[]; + total: number; +}; export function slice2({ _index, _count }: Paging) { - const i0 = _index || 0; - const i1 = _count ? i0 + _count : undefined; - return (things: T[]): [T[], number] => [things.slice(i0, i1), things.length] + return (things: T[]): [T[], number] => [ + things.slice(_index, _index + _count), + things.length, + ]; } -export const asResult = ([results, total]: [T[], number]) => ({ results, total }) +export const asResult = ([results, total]: [T[], number]) => ({ + results, + total, +}); + +export type ArtistQuery = Paging + +export type AlbumQuery = Paging & { + artistId?: string +} export interface MusicLibrary { - artists({ _index, _count }: Paging): Promise>; + artists(q: ArtistQuery): Promise>; artist(id: string): Artist; - albums({ - artistId, - _index, - _count, - }: { - artistId?: string; - } & Paging): Promise>; + albums(q: AlbumQuery): Promise>; } diff --git a/src/navidrome.ts b/src/navidrome.ts index 984801c..fc5d7e0 100644 --- a/src/navidrome.ts +++ b/src/navidrome.ts @@ -1,5 +1,5 @@ import { Md5 } from "ts-md5/dist/md5"; -import { Credentials, MusicService, Paging, Album, Artist, Result, slice2, asResult } from "./music_service"; +import { Credentials, MusicService, Album, Artist, Result, slice2, asResult, AlbumQuery, ArtistQuery } from "./music_service"; import X2JS from "x2js"; import axios from "axios"; @@ -98,25 +98,20 @@ export class Navidrome implements MusicService { const navidrome = this; const credentials: Credentials = this.parseToken(token); return Promise.resolve({ - artists: (paging: Paging): Promise> => + artists: (q: ArtistQuery): Promise> => navidrome .get(credentials, "/rest/getArtists") .then((it) => it.artists.index.flatMap((it) => it.artist)) .then((artists) => artists.map((it) => ({ id: it._id, name: it._name })) ) - .then(slice2(paging)) + .then(slice2(q)) .then(asResult), artist: (id: string) => ({ id, name: id, }), - albums: ({ - artistId, - }: { - artistId?: string; - } & Paging): Promise> => { - console.log(artistId); + albums: (_: AlbumQuery): Promise> => { return Promise.resolve({ results: [], total: 0}); }, }); diff --git a/tests/in_memory_music_service.test.ts b/tests/in_memory_music_service.test.ts index 7d30482..b6c3b77 100644 --- a/tests/in_memory_music_service.test.ts +++ b/tests/in_memory_music_service.test.ts @@ -66,7 +66,7 @@ describe("InMemoryMusicService", () => { { id: BLONDIE.id, name: BLONDIE.name }, { id: METALLICA.id, name: METALLICA.name }, ]; - expect(await musicLibrary.artists({})).toEqual({ + expect(await musicLibrary.artists({ _index: 0, _count: 100 })).toEqual({ results: artists, total: 4, }); @@ -126,7 +126,7 @@ describe("InMemoryMusicService", () => { describe("albums", () => { describe("fetching with no filtering", () => { it("should return all the albums for all the artists", async () => { - expect(await musicLibrary.albums({})).toEqual({ + expect(await musicLibrary.albums({ _index: 0, _count: 100 })).toEqual({ results: ALL_ALBUMS, total: ALL_ALBUMS.length, }); @@ -135,56 +135,27 @@ describe("InMemoryMusicService", () => { describe("fetching for a single artist", () => { it("should return them all if the artist has some", async () => { - expect(await musicLibrary.albums({ artistId: BLONDIE.id })).toEqual({ + expect(await musicLibrary.albums({ artistId: BLONDIE.id, _index: 0, _count: 100 })).toEqual({ results: BLONDIE.albums, total: BLONDIE.albums.length, }); }); it("should return empty list of the artists does not have any", async () => { - expect(await musicLibrary.albums({ artistId: MADONNA.id })).toEqual({ + expect(await musicLibrary.albums({ artistId: MADONNA.id, _index: 0, _count: 100 })).toEqual({ results: [], total: 0, }); }); it("should return empty list if the artist id is not valid", async () => { - expect(await musicLibrary.albums({ artistId: uuid() })).toEqual({ + expect(await musicLibrary.albums({ artistId: uuid(), _index: 0, _count: 100 })).toEqual({ results: [], total: 0, }); }); }); - describe("fetching with just index", () => { - it("should return everything after", async () => { - const albums = [ - BOB_MARLEY.albums[2], - ...BLONDIE.albums, - ...MADONNA.albums, - ...METALLICA.albums, - ]; - expect(await musicLibrary.albums({ _index: 2 })).toEqual({ - results: albums, - total: ALL_ALBUMS.length, - }); - }); - }); - - describe("fetching with just count", () => { - it("should return first n items", async () => { - const albums = [ - BOB_MARLEY.albums[0], - BOB_MARLEY.albums[1], - BOB_MARLEY.albums[2], - ]; - expect(await musicLibrary.albums({ _count: 3 })).toEqual({ - results: albums, - total: ALL_ALBUMS.length, - }); - }); - }); - describe("fetching with index and count", () => { it("should be able to return the first page", async () => { const albums = [BOB_MARLEY.albums[0], BOB_MARLEY.albums[1]]; diff --git a/tests/in_memory_music_service.ts b/tests/in_memory_music_service.ts index edc6b80..00defc5 100644 --- a/tests/in_memory_music_service.ts +++ b/tests/in_memory_music_service.ts @@ -9,7 +9,8 @@ import { AuthFailure, Artist, MusicLibrary, - Paging, + ArtistQuery, + AlbumQuery, slice2, asResult, } from "../src/music_service"; @@ -57,9 +58,9 @@ export class InMemoryMusicService implements MusicService { if (this.users[credentials.username] != credentials.password) return Promise.reject("Invalid auth token"); return Promise.resolve({ - artists: (paging: Paging) => + artists: (q: ArtistQuery) => Promise.resolve(this.artists.map(artistWithAlbumsToArtist)) - .then(slice2(paging)) + .then(slice2(q)) .then(asResult), artist: (id: string) => pipe( @@ -68,26 +69,18 @@ export class InMemoryMusicService implements MusicService { O.map(artistWithAlbumsToArtist), getOrThrow(`No artist with id '${id}'`) ), - albums: ({ - artistId, - _index, - _count, - }: { - artistId?: string; - _index?: number; - _count?: number; - }) => + albums: (q: AlbumQuery) => Promise.resolve( this.artists.filter( pipe( - O.fromNullable(artistId), + O.fromNullable(q.artistId), O.map(artistWithId), O.getOrElse(() => all) ) ) ) .then((artists) => artists.flatMap((it) => it.albums)) - .then(slice2({ _index, _count })) + .then(slice2(q)) .then(asResult), }); } diff --git a/tests/navidrome.test.ts b/tests/navidrome.test.ts index a5c12f1..1bff503 100644 --- a/tests/navidrome.test.ts +++ b/tests/navidrome.test.ts @@ -101,12 +101,12 @@ describe("navidrome", () => { }); }); - describe("when no paging specified", () => { + describe("when no paging is ineffect", () => { it("should return all the artists", async () => { const artists = await navidrome .generateToken({ username, password }) .then((it) => navidrome.login(it.authToken)) - .then((it) => it.artists({})); + .then((it) => it.artists({ _index: 0, _count: 100 })); const expectedArtists = [ { id: "2911b2d67a6b11eb804dd360a6225680", name: "10 Planets" },