@push.rocks/smartrequest
Version:
A module for modern HTTP/HTTPS requests with support for form data, file uploads, JSON, binary data, streams, and more.
138 lines • 11 kB
JavaScript
import {} from '../../legacy/smartrequest.request.js';
import { PaginationStrategy } from '../types/pagination.js';
/**
* Creates a paginated response from a regular response
*/
export function createPaginatedResponse(response, paginationConfig, queryParams, fetchNextPage) {
// Default to response.body for items if response is JSON
let items = Array.isArray(response.body)
? response.body
: (response.body?.items || response.body?.data || response.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(response.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(response.body, config.cursorPath || 'nextCursor');
const hasMore = getValueByPath(response.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL21vZGVybi9mZWF0dXJlcy9wYWdpbmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBaUMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNyRixPQUFPLEVBQTBCLGtCQUFrQixFQUEyQixNQUFNLHdCQUF3QixDQUFDO0FBRTdHOztHQUVHO0FBQ0gsTUFBTSxVQUFVLHVCQUF1QixDQUNyQyxRQUF1QyxFQUN2QyxnQkFBbUMsRUFDbkMsV0FBbUMsRUFDbkMsYUFBaUY7SUFFakYseURBQXlEO0lBQ3pELElBQUksS0FBSyxHQUFRLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztRQUMzQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUk7UUFDZixDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssSUFBSSxRQUFRLENBQUMsSUFBSSxFQUFFLElBQUksSUFBSSxRQUFRLENBQUMsSUFBSSxFQUFFLE9BQU8sSUFBSSxFQUFFLENBQUMsQ0FBQztJQUVsRixJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUM7SUFDeEIsSUFBSSxjQUFjLEdBQTJCLEVBQUUsQ0FBQztJQUVoRCxnRUFBZ0U7SUFDaEUsUUFBUSxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNsQyxLQUFLLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDL0IsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUM7WUFDaEMsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkcsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxJQUFJ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