fix(client): Fix CI configuration, prevent socket hangs with auto-drain, and apply various client/core TypeScript fixes and test updates
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
import { type CoreResponse } from '../../core/index.js';
|
||||
import type { ICoreResponse } from '../../core_base/types.js';
|
||||
import { type TPaginationConfig, PaginationStrategy, type TPaginatedResponse } from '../types/pagination.js';
|
||||
import {
|
||||
type TPaginationConfig,
|
||||
PaginationStrategy,
|
||||
type TPaginatedResponse,
|
||||
} from '../types/pagination.js';
|
||||
|
||||
/**
|
||||
* Creates a paginated response from a regular response
|
||||
@@ -9,15 +13,17 @@ export async function createPaginatedResponse<T>(
|
||||
response: ICoreResponse<any>,
|
||||
paginationConfig: TPaginationConfig,
|
||||
queryParams: Record<string, string>,
|
||||
fetchNextPage: (params: Record<string, string>) => Promise<TPaginatedResponse<T>>
|
||||
fetchNextPage: (
|
||||
params: Record<string, string>,
|
||||
) => Promise<TPaginatedResponse<T>>,
|
||||
): Promise<TPaginatedResponse<T>> {
|
||||
// Parse response body first
|
||||
const body = await response.json() as any;
|
||||
|
||||
const body = (await response.json()) as any;
|
||||
|
||||
// Default to response.body for items if response is JSON
|
||||
let items: T[] = Array.isArray(body)
|
||||
? body
|
||||
: (body?.items || body?.data || body?.results || []);
|
||||
: body?.items || body?.data || body?.results || [];
|
||||
|
||||
let hasNextPage = false;
|
||||
let nextPageParams: Record<string, string> = {};
|
||||
@@ -26,8 +32,14 @@ export async function createPaginatedResponse<T>(
|
||||
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 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;
|
||||
@@ -35,7 +47,7 @@ export async function createPaginatedResponse<T>(
|
||||
if (hasNextPage) {
|
||||
nextPageParams = {
|
||||
...queryParams,
|
||||
[config.pageParam || 'page']: String(currentPage + 1)
|
||||
[config.pageParam || 'page']: String(currentPage + 1),
|
||||
};
|
||||
}
|
||||
break;
|
||||
@@ -43,7 +55,10 @@ export async function createPaginatedResponse<T>(
|
||||
|
||||
case PaginationStrategy.CURSOR: {
|
||||
const config = paginationConfig;
|
||||
const nextCursor = getValueByPath(body, config.cursorPath || 'nextCursor');
|
||||
const nextCursor = getValueByPath(
|
||||
body,
|
||||
config.cursorPath || 'nextCursor',
|
||||
);
|
||||
const hasMore = getValueByPath(body, config.hasMorePath || 'hasMore');
|
||||
|
||||
hasNextPage = !!nextCursor || !!hasMore;
|
||||
@@ -51,7 +66,7 @@ export async function createPaginatedResponse<T>(
|
||||
if (hasNextPage && nextCursor) {
|
||||
nextPageParams = {
|
||||
...queryParams,
|
||||
[config.cursorParam || 'cursor']: nextCursor
|
||||
[config.cursorParam || 'cursor']: nextCursor,
|
||||
};
|
||||
}
|
||||
break;
|
||||
@@ -60,7 +75,9 @@ export async function createPaginatedResponse<T>(
|
||||
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 headerValue = Array.isArray(linkHeader)
|
||||
? linkHeader[0]
|
||||
: linkHeader;
|
||||
const links = parseLinkHeader(headerValue);
|
||||
|
||||
hasNextPage = !!links.next;
|
||||
@@ -100,7 +117,13 @@ export async function createPaginatedResponse<T>(
|
||||
// Create a function to fetch all remaining pages
|
||||
const getAllPages = async (): Promise<T[]> => {
|
||||
const allItems = [...items];
|
||||
let currentPage: TPaginatedResponse<T> = { items, hasNextPage, getNextPage, getAllPages, response };
|
||||
let currentPage: TPaginatedResponse<T> = {
|
||||
items,
|
||||
hasNextPage,
|
||||
getNextPage,
|
||||
getAllPages,
|
||||
response,
|
||||
};
|
||||
|
||||
while (currentPage.hasNextPage) {
|
||||
try {
|
||||
@@ -119,7 +142,7 @@ export async function createPaginatedResponse<T>(
|
||||
hasNextPage,
|
||||
getNextPage,
|
||||
getAllPages,
|
||||
response
|
||||
response,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -166,11 +189,15 @@ export function getValueByPath(obj: any, path?: string): any {
|
||||
let current = obj;
|
||||
|
||||
for (const key of keys) {
|
||||
if (current === null || current === undefined || typeof current !== 'object') {
|
||||
if (
|
||||
current === null ||
|
||||
current === undefined ||
|
||||
typeof current !== 'object'
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
current = current[key];
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user