feat(core): Dynamic max page size limit for pagination dto (#16100)

This commit is contained in:
Guillaume Jacquart
2025-06-10 14:00:51 +02:00
committed by GitHub
parent 09fd5c01d4
commit 5c748ca25d
4 changed files with 44 additions and 14 deletions

View File

@@ -44,6 +44,19 @@ describe('ListInsightsWorkflowQueryDto', () => {
sortBy: 'total:desc',
},
},
{
name: 'limit take to 100',
request: {
skip: '0',
take: '200',
sortBy: 'total:asc',
},
parsedResult: {
skip: 0,
take: 100,
sortBy: 'total:asc',
},
},
])('should validate $name', ({ request, parsedResult }) => {
const result = ListInsightsWorkflowQueryDto.safeParse(request);
expect(result.success).toBe(true);

View File

@@ -2,7 +2,9 @@ import { z } from 'zod';
import { Z } from 'zod-class';
import { InsightsDateFilterDto } from './date-filter.dto';
import { paginationSchema } from '../pagination/pagination.dto';
import { createTakeValidator, paginationSchema } from '../pagination/pagination.dto';
export const MAX_ITEMS_PER_PAGE = 100;
const VALID_SORT_OPTIONS = [
'total:asc',
@@ -31,6 +33,7 @@ const sortByValidator = z
export class ListInsightsWorkflowQueryDto extends Z.class({
...paginationSchema,
take: createTakeValidator(MAX_ITEMS_PER_PAGE),
dateRange: InsightsDateFilterDto.shape.dateRange,
sortBy: sortByValidator,
}) {}

View File

@@ -1,4 +1,4 @@
import { PaginationDto, MAX_ITEMS_PER_PAGE } from '../pagination.dto';
import { PaginationDto, MAX_ITEMS_PER_PAGE, createTakeValidator } from '../pagination.dto';
describe('PaginationDto', () => {
describe('valid inputs', () => {
@@ -133,4 +133,17 @@ describe('PaginationDto', () => {
}
});
});
describe('createTakeValidator', () => {
test('should create a take validator with custom maxItems', () => {
const customMaxItems = 100;
const customTakeValidator = createTakeValidator(customMaxItems);
const result = customTakeValidator.safeParse('150');
expect(result.success).toBe(true);
if (result.success) {
expect(result.data).toBe(customMaxItems);
}
});
});
});

View File

@@ -14,21 +14,22 @@ const skipValidator = z
message: 'Param `skip` must be a non-negative integer',
});
const takeValidator = z
.string()
.optional()
.transform((val) => (val ? parseInt(val, 10) : 10))
.refine((val) => !isNaN(val) && Number.isInteger(val), {
message: 'Param `take` must be a valid integer',
})
.refine((val) => val >= 0, {
message: 'Param `take` must be a non-negative integer',
})
.transform((val) => Math.min(val, MAX_ITEMS_PER_PAGE));
export const createTakeValidator = (maxItems: number) =>
z
.string()
.optional()
.transform((val) => (val ? parseInt(val, 10) : 10))
.refine((val) => !isNaN(val) && Number.isInteger(val), {
message: 'Param `take` must be a valid integer',
})
.refine((val) => val >= 0, {
message: 'Param `take` must be a non-negative integer',
})
.transform((val) => Math.min(val, maxItems));
export const paginationSchema = {
skip: skipValidator,
take: takeValidator,
take: createTakeValidator(MAX_ITEMS_PER_PAGE),
};
export class PaginationDto extends Z.class(paginationSchema) {}