UNPKG

@push.rocks/smartrequest

Version:

A module for modern HTTP/HTTPS requests with support for form data, file uploads, JSON, binary data, streams, and more.

152 lines 11.2 kB
import {} from '../../core/index.js'; import { PaginationStrategy, } from '../types/pagination.js'; /** * Creates a paginated response from a regular response */ export async function createPaginatedResponse(response, paginationConfig, queryParams, fetchNextPage) { // Parse response body first const body = (await response.json()); // Default to response.body for items if response is JSON let items = Array.isArray(body) ? body : body?.items || body?.data || body?.results || []; let hasNextPage = false; let nextPageParams = {}; // Determine if there's a next page based on pagination strategy switch (paginationConfig.strategy) { case PaginationStrategy.OFFSET: { const config = paginationConfig; const currentPage = parseInt(queryParams[config.pageParam || 'page'] || String(config.startPage || 1)); const limit = parseInt(queryParams[config.limitParam || 'limit'] || String(config.pageSize || 20)); const total = getValueByPath(body, config.totalPath || 'total') || 0; hasNextPage = currentPage * limit < total; if (hasNextPage) { nextPageParams = { ...queryParams, [config.pageParam || 'page']: String(currentPage + 1), }; } break; } case PaginationStrategy.CURSOR: { const config = paginationConfig; const nextCursor = getValueByPath(body, config.cursorPath || 'nextCursor'); const hasMore = getValueByPath(body, config.hasMorePath || 'hasMore'); hasNextPage = !!nextCursor || !!hasMore; if (hasNextPage && nextCursor) { nextPageParams = { ...queryParams, [config.cursorParam || 'cursor']: nextCursor, }; } break; } case PaginationStrategy.LINK_HEADER: { const linkHeader = response.headers['link'] || ''; // Handle both string and string[] types for the link header const headerValue = Array.isArray(linkHeader) ? linkHeader[0] : linkHeader; const links = parseLinkHeader(headerValue); hasNextPage = !!links.next; if (hasNextPage && links.next) { // Extract query parameters from next link URL const url = new URL(links.next); nextPageParams = {}; url.searchParams.forEach((value, key) => { nextPageParams[key] = value; }); } break; } case PaginationStrategy.CUSTOM: { const config = paginationConfig; hasNextPage = config.hasNextPage(response); if (hasNextPage) { nextPageParams = config.getNextPageParams(response, queryParams); } break; } } // Create a function to fetch the next page const getNextPage = async () => { if (!hasNextPage) { throw new Error('No more pages available'); } return fetchNextPage(nextPageParams); }; // Create a function to fetch all remaining pages const getAllPages = async () => { const allItems = [...items]; let currentPage = { items, hasNextPage, getNextPage, getAllPages, response, }; while (currentPage.hasNextPage) { try { currentPage = await currentPage.getNextPage(); allItems.push(...currentPage.items); } catch (error) { break; } } return allItems; }; return { items, hasNextPage, getNextPage, getAllPages, response, }; } /** * Parse Link header for pagination * Link: <https://api.example.com/users?page=2>; rel="next", <https://api.example.com/users?page=5>; rel="last" */ export function parseLinkHeader(header) { const links = {}; if (!header) { return links; } // Split parts by comma const parts = header.split(','); // Parse each part into a name:value pair for (const part of parts) { const section = part.split(';'); if (section.length < 2) { continue; } const url = section[0].replace(/<(.*)>/, '$1').trim(); const name = section[1].replace(/rel="(.*)"/, '$1').trim(); links[name] = url; } return links; } /** * Get a nested value from an object using dot notation path * e.g., getValueByPath(obj, "data.pagination.nextCursor") */ export function getValueByPath(obj, path) { if (!path || !obj) { return undefined; } const keys = path.split('.'); let current = obj; for (const key of keys) { if (current === null || current === undefined || typeof current !== 'object') { return undefined; } current = current[key]; } return current; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2NsaWVudC9mZWF0dXJlcy9wYWdpbmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBcUIsTUFBTSxxQkFBcUIsQ0FBQztBQUV4RCxPQUFPLEVBRUwsa0JBQWtCLEdBRW5CLE1BQU0sd0JBQXdCLENBQUM7QUFFaEM7O0dBRUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLHVCQUF1QixDQUMzQyxRQUE0QixFQUM1QixnQkFBbUMsRUFDbkMsV0FBbUMsRUFDbkMsYUFFbUM7SUFFbkMsNEJBQTRCO0lBQzVCLE1BQU0sSUFBSSxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQVEsQ0FBQztJQUU1Qyx5REFBeUQ7SUFDekQsSUFBSSxLQUFLLEdBQVEsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7UUFDbEMsQ0FBQyxDQUFDLElBQUk7UUFDTixDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssSUFBSSxJQUFJLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxPQUFPLElBQUksRUFBRSxDQUFDO0lBRXJELElBQUksV0FBVyxHQUFHLEtBQUssQ0FBQztJQUN4QixJQUFJLGNBQWMsR0FBMkIsRUFBRSxDQUFDO0lBRWhELGdFQUFnRTtJQUNoRSxRQUFRLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2xDLEtBQUssa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUMvQixNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQztZQUNoQyxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQzFCLFdBQVcsQ0FBQyxNQUFNLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQztnQkFDckMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLENBQ2hDLENBQUM7WUFDRixNQUFNLEtBQUssR0FBRyxRQUFRLENBQ3BCLFdB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