From 152d5ca52a7f8f29aedd4c65cea1901a1719e194 Mon Sep 17 00:00:00 2001 From: Sumit Kolhe <35036894+sumitkolhe@users.noreply.github.com> Date: Sat, 30 Mar 2024 11:02:35 +0530 Subject: [PATCH] feat: add pagination support for get playlist --- .../controllers/playlist.controller.ts | 30 ++++++++++++++++--- .../playlists/services/playlist.service.ts | 15 ++++++---- .../get-playlist-by-id.use-case.spec.ts | 13 +++++--- .../get-playlist-by-id.use-case.ts | 23 +++++++++++--- .../get-playlist-by-link.use-case.ts | 20 +++++++++++-- 5 files changed, 81 insertions(+), 20 deletions(-) diff --git a/src/modules/playlists/controllers/playlist.controller.ts b/src/modules/playlists/controllers/playlist.controller.ts index 57b14e99..45afbc95 100644 --- a/src/modules/playlists/controllers/playlist.controller.ts +++ b/src/modules/playlists/controllers/playlist.controller.ts @@ -41,7 +41,21 @@ export class PlaylistController implements Routes { type: 'string', example: 'https://www.jiosaavn.com/featured/its-indie-english/AMoxtXyKHoU_', default: 'https://www.jiosaavn.com/featured/its-indie-english/AMoxtXyKHoU_' - }) + }), + page: z.string().pipe(z.coerce.number()).optional().openapi({ + title: 'Page Number', + description: 'The page number of the songs to retrieve from the playlist', + type: 'integer', + example: 0, + default: 0 + }), + limit: z.string().pipe(z.coerce.number()).optional().openapi({ + title: 'Limit', + description: 'Number of songs to retrieve per page', + type: 'integer', + example: 10, + default: 10 + }) }) }, responses: { @@ -68,15 +82,23 @@ export class PlaylistController implements Routes { } }), async (ctx) => { - const { id, link } = ctx.req.valid('query') + const { id, link, page, limit } = ctx.req.valid('query') if (!link && !id) { return ctx.json({ success: false, message: 'Either playlist ID or link is required' }, 400) } const response = link - ? await this.playlistService.getPlaylistByLink(link) - : await this.playlistService.getPlaylistById(id!) + ? await this.playlistService.getPlaylistByLink({ + token: link, + page: page || 0, + limit: limit || 10 + }) + : await this.playlistService.getPlaylistById({ + id: id!, + page: page || 0, + limit: limit || 10 + }) return ctx.json({ success: true, data: response }) } diff --git a/src/modules/playlists/services/playlist.service.ts b/src/modules/playlists/services/playlist.service.ts index 05eaef08..fbaa7bc8 100644 --- a/src/modules/playlists/services/playlist.service.ts +++ b/src/modules/playlists/services/playlist.service.ts @@ -1,4 +1,9 @@ -import { GetPlaylistByIdUseCase, GetPlaylistByLinkUseCase } from '#modules/playlists/use-cases' +import { + type GetPlaylistByIdArgs, + GetPlaylistByIdUseCase, + type GetPlaylistByLinkArgs, + GetPlaylistByLinkUseCase +} from '#modules/playlists/use-cases' export class PlaylistService { private readonly getPlaylistByIdUseCase: GetPlaylistByIdUseCase @@ -9,11 +14,11 @@ export class PlaylistService { this.getPlaylistByLinkUseCase = new GetPlaylistByLinkUseCase() } - getPlaylistById = (playlistId: string) => { - return this.getPlaylistByIdUseCase.execute(playlistId) + getPlaylistById = (args: GetPlaylistByIdArgs) => { + return this.getPlaylistByIdUseCase.execute(args) } - getPlaylistByLink = (token: string) => { - return this.getPlaylistByLinkUseCase.execute(token) + getPlaylistByLink = (args: GetPlaylistByLinkArgs) => { + return this.getPlaylistByLinkUseCase.execute(args) } } diff --git a/src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.spec.ts b/src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.spec.ts index f2a315bd..34bd5008 100644 --- a/src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.spec.ts +++ b/src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.spec.ts @@ -1,18 +1,23 @@ import { beforeAll, describe, expect, test } from 'vitest' -import { GetAlbumByIdUseCase } from '#modules/albums/use-cases' +import { GetPlaylistByIdUseCase } from '#modules/playlists/use-cases' describe('GetAlbumById', () => { - let getAlbumByIdUseCase: GetAlbumByIdUseCase + let getPlaylistByIdUseCase: GetPlaylistByIdUseCase beforeAll(() => { - getAlbumByIdUseCase = new GetAlbumByIdUseCase() + getPlaylistByIdUseCase = new GetPlaylistByIdUseCase() }) test('should get album by id and return an album', async () => { - const album = await getAlbumByIdUseCase.execute('23241654') + const album = await getPlaylistByIdUseCase.execute({ + id: '159470188', + page: 1, + limit: 5 + }) expect(album).toMatchSnapshot({ playCount: expect.any(Number), + songCount: expect.any(Number), songs: album.songs.map((song) => ({ ...song, playCount: expect.any(Number) diff --git a/src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.ts b/src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.ts index da60b244..dafa6206 100644 --- a/src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.ts +++ b/src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.ts @@ -6,14 +6,29 @@ import { useFetch } from '#common/helpers' import { Endpoints } from '#common/constants' import { createPlaylistPayload } from '#modules/playlists/helpers' -export class GetPlaylistByIdUseCase implements IUseCase> { +export interface GetPlaylistByIdArgs { + id: string + limit: number + page: number +} + +export class GetPlaylistByIdUseCase implements IUseCase> { constructor() {} - async execute(id: string) { - const response = await useFetch>(Endpoints.playlists.id, { listid: id }) + async execute({ id, limit, page }: GetPlaylistByIdArgs) { + const response = await useFetch>(Endpoints.playlists.id, { + listid: id, + n: limit, + p: page + }) if (!response) throw new HTTPException(404, { message: 'playlist not found' }) - return createPlaylistPayload(response) + const playlist = createPlaylistPayload(response) + return { + ...playlist, + songCount: playlist.songs?.length || 0, + songs: playlist.songs?.slice(0, limit) || [] + } } } diff --git a/src/modules/playlists/use-cases/get-playlist-by-link/get-playlist-by-link.use-case.ts b/src/modules/playlists/use-cases/get-playlist-by-link/get-playlist-by-link.use-case.ts index 35de39f1..d3b6c52f 100644 --- a/src/modules/playlists/use-cases/get-playlist-by-link/get-playlist-by-link.use-case.ts +++ b/src/modules/playlists/use-cases/get-playlist-by-link/get-playlist-by-link.use-case.ts @@ -6,17 +6,31 @@ import { useFetch } from '#common/helpers' import { Endpoints } from '#common/constants' import { createPlaylistPayload } from '#modules/playlists/helpers' -export class GetPlaylistByLinkUseCase implements IUseCase> { +export interface GetPlaylistByLinkArgs { + token: string + limit: number + page: number +} + +export class GetPlaylistByLinkUseCase implements IUseCase> { constructor() {} - async execute(token: string) { + async execute({ token, limit, page }: GetPlaylistByLinkArgs) { const response = await useFetch>(Endpoints.albums.link, { token, + n: limit, + p: page, type: 'playlist' }) if (!response) throw new HTTPException(404, { message: 'playlist not found' }) - return createPlaylistPayload(response) + const playlist = createPlaylistPayload(response) + + return { + ...playlist, + songCount: playlist.songs?.length, + songs: playlist.songs?.slice(0, limit) || [] + } } }