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.

140 lines 11 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2NsaWVudC9mZWF0dXJlcy9wYWdpbmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBcUIsTUFBTSxxQkFBcUIsQ0FBQztBQUV4RCxPQUFPLEVBQTBCLGtCQUFrQixFQUEyQixNQUFNLHdCQUF3QixDQUFDO0FBRTdHOztHQUVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSx1QkFBdUIsQ0FDM0MsUUFBNEIsRUFDNUIsZ0JBQW1DLEVBQ25DLFdBQW1DLEVBQ25DLGFBQWlGO0lBRWpGLDRCQUE0QjtJQUM1QixNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQVMsQ0FBQztJQUUxQyx5REFBeUQ7SUFDekQsSUFBSSxLQUFLLEdBQVEsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7UUFDbEMsQ0FBQyxDQUFDLElBQUk7UUFDTixDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxJQUFJLElBQUksRUFBRSxJQUFJLElBQUksSUFBSSxFQUFFLE9BQU8sSUFBSSxFQUFFLENBQUMsQ0FBQztJQUV2RCxJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUM7SUFDeEIsSUFBSSxjQUFjLEdBQTJCLEVBQUUsQ0FBQztJQUVoRCxnRUFBZ0U7SUFDaEUsUUFBUSxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNsQyxLQUFLLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDL0IsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUM7WUFDaEMsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkcsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLFdBQVcs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