UNPKG

@dbs-portal/tool-mock

Version:

API mocking toolkit using MSW for DBS Portal development workflows

230 lines 6.89 kB
/** * Pagination utilities for mock responses */ /** * Create a paginated response from items */ export function createPaginatedResponse(options) { const { items, page, pageSize, total } = options; const totalItems = total ?? items.length; const totalPages = Math.ceil(totalItems / pageSize); const startIndex = (page - 1) * pageSize; const endIndex = startIndex + pageSize; const paginatedItems = items.slice(startIndex, endIndex); const paginatedResponse = { data: paginatedItems, meta: { page, pageSize, total: totalItems, totalPages, hasNextPage: page < totalPages, hasPreviousPage: page > 1, }, }; return { data: paginatedResponse, items: paginatedItems, }; } /** * Create pagination metadata only */ export function createPaginationMeta(page, pageSize, total) { const totalPages = Math.ceil(total / pageSize); return { page, pageSize, total, totalPages, hasNextPage: page < totalPages, hasPreviousPage: page > 1, }; } /** * Parse pagination parameters from URL search params */ export function parsePaginationParams(searchParams, defaults = { page: 1, pageSize: 10, maxPageSize: 100, }) { const page = Math.max(1, parseInt(searchParams.get('page') || '1', 10)); const pageSize = Math.min(defaults.maxPageSize, Math.max(1, parseInt(searchParams.get('pageSize') || String(defaults.pageSize), 10))); return { page, pageSize }; } /** * Create cursor-based pagination response */ export function createCursorPaginatedResponse(items, cursor, limit, getCursor) { let startIndex = 0; // Find start index based on cursor if (cursor) { const cursorIndex = items.findIndex(item => getCursor(item) === cursor); if (cursorIndex !== -1) { startIndex = cursorIndex + 1; } } const endIndex = startIndex + limit; const paginatedItems = items.slice(startIndex, endIndex); const hasNextPage = endIndex < items.length; const hasPreviousPage = startIndex > 0; const lastItem = paginatedItems[paginatedItems.length - 1]; const nextCursor = hasNextPage && paginatedItems.length > 0 && lastItem ? getCursor(lastItem) : null; const prevItem = items[startIndex - 1]; const previousCursor = hasPreviousPage && startIndex > 0 && prevItem ? getCursor(prevItem) : null; return { data: paginatedItems, meta: { hasNextPage, hasPreviousPage, nextCursor, previousCursor, limit, }, }; } /** * Create offset-based pagination response */ export function createOffsetPaginatedResponse(items, offset, limit) { const startIndex = Math.max(0, offset); const endIndex = startIndex + limit; const paginatedItems = items.slice(startIndex, endIndex); const hasMore = endIndex < items.length; return { data: paginatedItems, meta: { offset: startIndex, limit, total: items.length, hasMore, }, }; } /** * Create infinite scroll pagination response */ export function createInfiniteScrollResponse(items, page, pageSize) { const startIndex = (page - 1) * pageSize; const endIndex = startIndex + pageSize; const paginatedItems = items.slice(startIndex, endIndex); const hasMore = endIndex < items.length; return { data: paginatedItems, meta: { page, pageSize, hasMore, nextPage: hasMore ? page + 1 : null, }, }; } /** * Validate pagination parameters */ export function validatePaginationParams(page, pageSize, maxPageSize = 100) { const errors = []; if (page < 1) { errors.push('Page must be greater than 0'); } if (pageSize < 1) { errors.push('Page size must be greater than 0'); } if (pageSize > maxPageSize) { errors.push(`Page size cannot exceed ${maxPageSize}`); } return { valid: errors.length === 0, errors, }; } /** * Calculate pagination ranges for UI */ export function calculatePaginationRanges(currentPage, totalPages, maxVisible = 5) { const pages = []; const half = Math.floor(maxVisible / 2); let start = Math.max(1, currentPage - half); let end = Math.min(totalPages, currentPage + half); // Adjust if we're near the beginning or end if (end - start + 1 < maxVisible) { if (start === 1) { end = Math.min(totalPages, start + maxVisible - 1); } else if (end === totalPages) { start = Math.max(1, end - maxVisible + 1); } } for (let i = start; i <= end; i++) { pages.push(i); } return { pages, showFirst: start > 1, showLast: end < totalPages, showPrevious: currentPage > 1, showNext: currentPage < totalPages, }; } /** * Create pagination links for API responses */ export function createPaginationLinks(baseUrl, page, pageSize, totalPages) { const links = {}; const createUrl = (p) => { const url = new URL(baseUrl); url.searchParams.set('page', p.toString()); url.searchParams.set('pageSize', pageSize.toString()); return url.toString(); }; if (page > 1) { links['first'] = createUrl(1); links['previous'] = createUrl(page - 1); } if (page < totalPages) { links['next'] = createUrl(page + 1); links['last'] = createUrl(totalPages); } return links; } /** * Create search and filter pagination */ export function createSearchPaginatedResponse(items, searchQuery, searchFields, filters, page, pageSize) { let filteredItems = items; // Apply search if (searchQuery) { const query = searchQuery.toLowerCase(); filteredItems = filteredItems.filter(item => searchFields.some(field => { const value = item[field]; return value && String(value).toLowerCase().includes(query); })); } // Apply filters if (Object.keys(filters).length > 0) { filteredItems = filteredItems.filter(item => Object.entries(filters).every(([key, value]) => { const itemValue = item[key]; if (Array.isArray(value)) { return value.includes(itemValue); } return itemValue === value; })); } const filteredCount = filteredItems.length; const paginatedResponse = createPaginatedResponse({ items: filteredItems, page, pageSize, }); return { data: paginatedResponse.data, filteredCount, totalCount: items.length, }; } //# sourceMappingURL=pagination.js.map