diff --git a/documentation/docs/graphql/dtos.mdx b/documentation/docs/graphql/dtos.mdx index 1b334db73..5edb4f6f3 100644 --- a/documentation/docs/graphql/dtos.mdx +++ b/documentation/docs/graphql/dtos.mdx @@ -196,6 +196,10 @@ By default the max number records that can be returned is `50`. To override the default you can override the following options specifying the `maxResultSize` option. +:::note +You can disable `maxResultSize` by setting the option to `-1`. +::: + In this example we specify limit the max number of records an end user can request to 20. ```ts title="todo-item.dto.ts" {5} diff --git a/packages/query-graphql/__tests__/types/query/cursor-query-args-with-decorator.spec.ts b/packages/query-graphql/__tests__/types/query/cursor-query-args-with-decorator.spec.ts index 445ff9149..1b63a4774 100644 --- a/packages/query-graphql/__tests__/types/query/cursor-query-args-with-decorator.spec.ts +++ b/packages/query-graphql/__tests__/types/query/cursor-query-args-with-decorator.spec.ts @@ -94,7 +94,7 @@ describe('QueryArgsType with decorator options', (): void => { }); describe('max result size', () => { - it('allow validate a maxResultsSize for paging.first', () => { + it('should validate a maxResultsSize for paging.first', () => { const queryObj: CursorQueryOptionsArgs = { paging: { first: 10 }, }; @@ -112,7 +112,7 @@ describe('QueryArgsType with decorator options', (): void => { ]); }); - it('allow validate a maxResultsSize for paging.last', () => { + it('should validate a maxResultsSize for paging.last', () => { const queryObj: CursorQueryOptionsArgs = { paging: { last: 10, before: 'abc' }, }; diff --git a/packages/query-graphql/__tests__/types/query/cursor-query-args.type.spec.ts b/packages/query-graphql/__tests__/types/query/cursor-query-args.type.spec.ts index c05fb7648..a51782e04 100644 --- a/packages/query-graphql/__tests__/types/query/cursor-query-args.type.spec.ts +++ b/packages/query-graphql/__tests__/types/query/cursor-query-args.type.spec.ts @@ -165,7 +165,7 @@ describe('Cursor paging strategy QueryArgsType with manual options', (): void => return expectSDL([TestCursorQueryManualOptionsResolver], cursorQueryArgsOptionsTypeSDL); }); - it('allow validate a maxResultsSize for paging.first', () => { + it('should validate a maxResultsSize for paging.first', () => { const queryObj: TestCursorQuery = { paging: { first: 10 }, }; @@ -183,7 +183,7 @@ describe('Cursor paging strategy QueryArgsType with manual options', (): void => ]); }); - it('allow validate a maxResultsSize for paging.last', () => { + it('should validate a maxResultsSize for paging.last', () => { const queryObj: TestCursorQuery = { paging: { last: 10, before: 'abc' }, }; @@ -200,5 +200,19 @@ describe('Cursor paging strategy QueryArgsType with manual options', (): void => }, ]); }); + + it('should ignore a maxResultsSize for paging.first and paging.last if maxResultSize === -1', () => { + class NoMaxQueryArgsTpe extends QueryArgsType(TestDto, { maxResultsSize: -1 }) {} + const queryObjFirst: NoMaxQueryArgsTpe = { + paging: { first: 1000 }, + }; + expect(validateSync(plainToClass(NoMaxQueryArgsTpe, queryObjFirst))).toEqual([]); + + const queryObjLast: NoMaxQueryArgsTpe = { + paging: { last: 1000, before: 'abc' }, + }; + const queryInstance = plainToClass(NoMaxQueryArgsTpe, queryObjLast); + expect(validateSync(queryInstance)).toEqual([]); + }); }); }); diff --git a/packages/query-graphql/__tests__/types/query/offset-query-args-with-decorator.spec.ts b/packages/query-graphql/__tests__/types/query/offset-query-args-with-decorator.spec.ts index ee762b7e0..f8d9b446b 100644 --- a/packages/query-graphql/__tests__/types/query/offset-query-args-with-decorator.spec.ts +++ b/packages/query-graphql/__tests__/types/query/offset-query-args-with-decorator.spec.ts @@ -93,7 +93,7 @@ describe('Offset paging strategy QueryArgsType with decorator options', (): void return expectSDL([TestOffsetQueryOptionsDecoratorResolver], offsetQueryArgsDecoratorTypeSDL); }); - it('validate a maxResultsSize for paging.limit', () => { + it('should validate a maxResultsSize for paging.limit', () => { const queryObj: CursorQueryArgsType = { paging: { limit: 10 }, }; diff --git a/packages/query-graphql/__tests__/types/query/offset-query-args.type.spec.ts b/packages/query-graphql/__tests__/types/query/offset-query-args.type.spec.ts index c2d25f03d..d3ee47a9a 100644 --- a/packages/query-graphql/__tests__/types/query/offset-query-args.type.spec.ts +++ b/packages/query-graphql/__tests__/types/query/offset-query-args.type.spec.ts @@ -170,7 +170,7 @@ describe('Offset paging strategy QueryArgsType with manual options', (): void => return expectSDL([TestOffsetQueryManualOptionsResolver], offsetQueryArgsOptionsTypeSDL); }); - it('validate a maxResultsSize for paging.limit', () => { + it('should validate a maxResultsSize for paging.limit', () => { const queryObj: CursorQueryArgsType = { paging: { limit: 10 }, }; @@ -188,5 +188,16 @@ describe('Offset paging strategy QueryArgsType with manual options', (): void => }, ]); }); + + it('should ignore a maxResultsSize for paging.limit if maxResultSize === -1', () => { + class NoMaxQueryArgsTpe extends QueryArgsType(TestDto, { + pagingStrategy: PagingStrategies.OFFSET, + maxResultsSize: -1, + }) {} + const queryObj: NoMaxQueryArgsTpe = { + paging: { limit: 1000 }, + }; + expect(validateSync(plainToClass(NoMaxQueryArgsTpe, queryObj))).toEqual([]); + }); }); }); diff --git a/packages/query-graphql/src/types/validators/property-max.validator.ts b/packages/query-graphql/src/types/validators/property-max.validator.ts index 3f9689cfd..cb6bdfefa 100644 --- a/packages/query-graphql/src/types/validators/property-max.validator.ts +++ b/packages/query-graphql/src/types/validators/property-max.validator.ts @@ -5,11 +5,17 @@ import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments export class PropertyMax implements ValidatorConstraintInterface { // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types validate(value: any, args: ValidationArguments): boolean { - const object = args.object as Record>; - const field = args.constraints[0] as string; const maxVal = args.constraints[1] as number; + if (maxVal === -1) { + return true; + } + const field = args.constraints[0] as string; + const object = args.object as Record>; const prop = object[args.property] ?? {}; - return prop[field] !== undefined ? prop[field] <= maxVal : true; + if (prop[field] === undefined) { + return true; + } + return prop[field] <= maxVal; } defaultMessage(args: ValidationArguments): string {