import { BadRequestException, ExecutionContext, Logger, createParamDecorator, HttpStatus, Type, applyDecorators } from '@nestjs/common'; import { Request } from 'express'; import { Pagination as NestPagination } from 'nestjs-typeorm-paginate'; import { ApiExtraModels, ApiOkResponse, ApiProperty, getSchemaPath, } from '@nestjs/swagger'; export interface Pagination { page: number; limit: number; } export const PaginationParams = createParamDecorator( (data, ctx: ExecutionContext): Pagination => { const req: Request = ctx.switchToHttp().getRequest(); const page = parseInt(req.query.page as string); const limit = parseInt(req.query.limit as string); Logger.log(`page: ${page}, limit: ${limit}`); if (isNaN(page) || page < 0 || isNaN(limit) || limit < 0) { throw new BadRequestException('Invalid pagination params'); } if (limit > 100) { throw new BadRequestException( 'Invalid pagination params: Max size is 100', ); } return { page, limit }; }, ); export class HttpBaseResponse { @ApiProperty({ enum: HttpStatus, }) public code: HttpStatus; @ApiProperty() public data: T; @ApiProperty({ type: String }) public message: string; constructor( code: number = HttpStatus.INTERNAL_SERVER_ERROR, data: T, message = '', ) { this.code = code; this.data = data; this.message = message; } } export class HttpSuccessResponse extends HttpBaseResponse { constructor(data: T, message = '') { super(HttpStatus.OK, data, message); } } export const ApiOkResponseCommon = >( dataDto: DataDto, description?: string, ) => applyDecorators( ApiExtraModels(HttpSuccessResponse, dataDto), ApiOkResponse({ schema: { allOf: [ { $ref: getSchemaPath(HttpSuccessResponse) }, { properties: { data: { $ref: getSchemaPath(dataDto) }, }, }, ], }, description, }), ); export const ApiOkResponsePaginated = >( dataDto: DataDto, description?: string, ) => applyDecorators( ApiExtraModels(NestPagination, dataDto), ApiOkResponse({ schema: { allOf: [ { $ref: getSchemaPath(HttpSuccessResponse) }, { properties: { data: { type: 'object', properties: { items: { type: 'array', items: { $ref: getSchemaPath(dataDto) }, }, meta: { type: 'object', properties: { totalItems: { type: 'number' }, itemCount: { type: 'number' }, itemsPerPage: { type: 'number' }, totalPages: { type: 'number' }, currentPage: { type: 'number' }, }, }, }, }, }, }, ], }, description, }), );