import { applyDecorators, NotFoundException, Type } from '@nestjs/common' import { QueryPaginationDto } from '../dto/pagination-query.dto' import { ApiExtraModels, ApiOkResponse, ApiResponseNoStatusOptions, getSchemaPath } from '@nestjs/swagger' import { DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE, PaginateOutputDto } from '../dto/pagination-output.dto' export interface PrismaPaginationParams { skip: number take: number } export const paginate = ( query: QueryPaginationDto, ): PrismaPaginationParams => { const size = query.size || DEFAULT_PAGE_SIZE const page = query.page || DEFAULT_PAGE_NUMBER return { skip: size * (page - 1), take: size, } } export const paginateOutput = ( data: T[], total: number, query: QueryPaginationDto, ): PaginateOutputDto => { const page = query.page || DEFAULT_PAGE_NUMBER const size = query.size || DEFAULT_PAGE_SIZE const lastPage = Math.ceil(total / size) // if data is empty, return empty array if (!data.length) { return { data, meta: { total, lastPage, currentPage: page, totalPerPage: size, prevPage: null, nextPage: null, }, } } // if page is greater than last page, throw an error if (page > lastPage) { throw new NotFoundException( `Page ${page} not found. Last page is ${lastPage}`, ) } return { data, meta: { total, lastPage, currentPage: page, totalPerPage: size, prevPage: page > 1 ? page - 1 : null, nextPage: page < lastPage ? page + 1 : null, }, } } export const ApiOkResponsePaginated = >(dataDto: DataDto, options?: ApiResponseNoStatusOptions) => applyDecorators( ApiExtraModels(PaginateOutputDto, dataDto), ApiOkResponse({ ...options, schema: { allOf: [ { $ref: getSchemaPath(PaginateOutputDto) }, { properties: { data: { type: 'array', items: { $ref: getSchemaPath(dataDto) }, }, }, }, ], }, }), )