fitaiProto/apps/admin/src/lib/pagination.ts
2026-03-10 04:14:03 +01:00

91 lines
1.9 KiB
TypeScript

/**
* Pagination utilities for API endpoints
*/
export interface PaginationParams {
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: "asc" | "desc";
}
export interface PaginationMetadata {
page: number;
limit: number;
total: number;
totalPages: number;
hasNextPage: boolean;
hasPrevPage: boolean;
}
export interface PaginatedResponse<T> {
data: T[];
pagination: PaginationMetadata;
}
/**
* Parse pagination parameters from URL search params
*/
export function parsePaginationParams(searchParams: URLSearchParams): {
page: number;
limit: number;
sortBy?: string;
sortOrder: "asc" | "desc";
} {
const page = Math.max(1, parseInt(searchParams.get("page") || "1", 10));
const limit = Math.min(
100,
Math.max(1, parseInt(searchParams.get("limit") || "20", 10)),
);
const sortBy = searchParams.get("sortBy") || undefined;
const sortOrder = (searchParams.get("sortOrder") || "desc") as "asc" | "desc";
return { page, limit, sortBy, sortOrder };
}
/**
* Create pagination metadata
*/
export function createPaginationMetadata(
page: number,
limit: number,
total: number,
): PaginationMetadata {
const totalPages = Math.ceil(total / limit);
return {
page,
limit,
total,
totalPages,
hasNextPage: page < totalPages,
hasPrevPage: page > 1,
};
}
/**
* Apply pagination to an array (for in-memory pagination)
* Use this sparingly - prefer database-level pagination
*/
export function paginateArray<T>(
items: T[],
page: number,
limit: number,
): PaginatedResponse<T> {
const offset = (page - 1) * limit;
const paginatedItems = items.slice(offset, offset + limit);
return {
data: paginatedItems,
pagination: createPaginationMetadata(page, limit, items.length),
};
}
/**
* Calculate SQL LIMIT and OFFSET from page and limit
*/
export function getPaginationOffsets(page: number, limit: number) {
const offset = (page - 1) * limit;
return { limit, offset };
}