66 lines
1.6 KiB
TypeScript
66 lines
1.6 KiB
TypeScript
|
|
// common/utils/pagination/pagination.service.ts
|
||
|
|
import { PaginationOptions, PaginationParams, PaginatedResponse } from './pagination.types';
|
||
|
|
|
||
|
|
export class PaginationService {
|
||
|
|
private readonly DEFAULT_PAGE = 1;
|
||
|
|
private readonly DEFAULT_LIMIT = 10;
|
||
|
|
private readonly MAX_LIMIT = 100;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Parse and validate pagination parameters
|
||
|
|
*/
|
||
|
|
parsePaginationParams(params: PaginationParams): PaginationOptions {
|
||
|
|
let page = Number(params.page) || this.DEFAULT_PAGE;
|
||
|
|
let limit = Number(params.limit) || this.DEFAULT_LIMIT;
|
||
|
|
|
||
|
|
// Validate and constrain values
|
||
|
|
page = Math.max(1, page);
|
||
|
|
limit = Math.max(1, Math.min(limit, this.MAX_LIMIT));
|
||
|
|
|
||
|
|
const skip = (page - 1) * limit;
|
||
|
|
|
||
|
|
return {
|
||
|
|
page,
|
||
|
|
limit,
|
||
|
|
skip,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Create paginated response
|
||
|
|
*/
|
||
|
|
createPaginatedResponse<T>(
|
||
|
|
data: T[],
|
||
|
|
totalCount: number,
|
||
|
|
paginationOptions: PaginationOptions,
|
||
|
|
): PaginatedResponse<T> {
|
||
|
|
const { page, limit } = paginationOptions;
|
||
|
|
const totalPages = Math.ceil(totalCount / limit);
|
||
|
|
|
||
|
|
return {
|
||
|
|
data,
|
||
|
|
pagination: {
|
||
|
|
currentPage: page,
|
||
|
|
pageSize: limit,
|
||
|
|
totalCount,
|
||
|
|
totalPages,
|
||
|
|
hasNext: page < totalPages,
|
||
|
|
hasPrevious: page > 1,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Extract pagination params from API Gateway event
|
||
|
|
*/
|
||
|
|
getPaginationFromEvent(event: any): PaginationParams {
|
||
|
|
const queryParams = event.queryStringParameters || {};
|
||
|
|
|
||
|
|
return {
|
||
|
|
page: queryParams.page,
|
||
|
|
limit: queryParams.limit,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export const paginationService = new PaginationService();
|