Skip to content

Commit 497bf62

Browse files
authored
fix(pagination): reject fractional pagination flags (#40)
1 parent a524702 commit 497bf62

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

src/lib/pagination.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,18 @@ describe('validatePaginationFlags', () => {
4343
expect(() => validatePaginationFlags({ pageSize: Number.NaN })).toThrow(ApiError);
4444
});
4545

46+
it('rejects fractional pageSize values', () => {
47+
expect(() => validatePaginationFlags({ pageSize: 1.5 })).toThrow(ApiError);
48+
});
49+
4650
it('rejects maxItems=0', () => {
4751
expect(() => validatePaginationFlags({ maxItems: 0 })).toThrow(ApiError);
4852
});
4953

54+
it('rejects fractional maxItems values', () => {
55+
expect(() => validatePaginationFlags({ maxItems: 2.5 })).toThrow(ApiError);
56+
});
57+
5058
it('accepts pageSize=100 (the hard cap)', () => {
5159
expect(() => validatePaginationFlags({ pageSize: 100 })).not.toThrow();
5260
});

src/lib/pagination.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ const DEFAULT_PAGE_SIZE = 25;
2727
* Validates and normalizes pagination flags. Per the CLI OpenAPI spec
2828
* §components.parameters.PageSize the hard cap is 100. Values above the
2929
* cap are now rejected with exit 5 rather than silently clamped, giving
30-
* callers fast feedback that their flag value is out of range. Sub-1 /
31-
* NaN values also throw. `maxItems` is validated but not capped (it is a
32-
* client-side cursor, not a server parameter).
30+
* callers fast feedback that their flag value is out of range. Fractional,
31+
* sub-1, and NaN values also throw. `maxItems` is validated but not capped
32+
* (it is a client-side cursor, not a server parameter).
3333
*
3434
* NOTE: `runResultHistory` previously did its own silent clamp via
3535
* `Math.min(Math.max(1, n), 100)` — that was unified to this path by the
@@ -38,7 +38,7 @@ const DEFAULT_PAGE_SIZE = 25;
3838
export function validatePaginationFlags(flags: PaginationFlags): PaginationFlags {
3939
const out: PaginationFlags = { ...flags };
4040
if (out.pageSize !== undefined) {
41-
if (!Number.isFinite(out.pageSize) || out.pageSize < 1) {
41+
if (!Number.isFinite(out.pageSize) || !Number.isInteger(out.pageSize) || out.pageSize < 1) {
4242
throw localValidationError(
4343
'page-size',
4444
`must be a positive integer between 1 and ${HARD_PAGE_SIZE_CAP}`,
@@ -52,7 +52,7 @@ export function validatePaginationFlags(flags: PaginationFlags): PaginationFlags
5252
}
5353
}
5454
if (out.maxItems !== undefined) {
55-
if (!Number.isFinite(out.maxItems) || out.maxItems < 1) {
55+
if (!Number.isFinite(out.maxItems) || !Number.isInteger(out.maxItems) || out.maxItems < 1) {
5656
throw localValidationError('maxItems', 'must be a positive integer');
5757
}
5858
}

0 commit comments

Comments
 (0)