This PR addresses issue #236 by implementing consistent pagination defaults and maximum limit enforcement across all list endpoints in the callora-backend repository. This improves API consistency, performance, and protects against unbounded queries that could be used for DoS attacks.
- Core Pagination Helper: Updated
src/lib/pagination.tsto support bothoffset/limitandpage/limitpagination. - Default Limits: Enforced a
DEFAULT_LIMITof 20 and aMAX_LIMITof 100. - Input Normalization: Parsed and clamped invalid inputs (NaN, negative, zero) to safe defaults.
- Refactoring: Updated
src/app.ts,src/routes/admin.ts, andsrc/routes/developerRoutes.tsto use the sharedparsePaginationandpaginatedResponsehelpers consistently. - Repository Updates: Extended
UsageEventsRepository(both In-Memory and PG implementations) to support pagination (limitandoffset). - Endpoint Improvements: Implemented full public API listing in
GET /api/apisand standardized response formats.
MAX_LIMIT of 100, we prevent potentially expensive database queries that could return thousands of rows, which could be used as an application-layer DoS vector.
- Input Sanitization: All pagination parameters are parsed as integers and clamped to safe ranges (limit 1-100, offset >= 0). This prevents unexpected behavior or SQL injection through pagination parameters.
- Consistency: Using a single source of truth (
parsePagination) ensures that all list endpoints behave identically, reducing developer error when adding new endpoints. - Default Behavior: If no pagination parameters are provided, the system defaults to the first page (offset 0) with a limit of 20, ensuring stable and predictable API responses without overwhelming the backend or client.
src/lib/pagination.ts- Core pagination logicsrc/lib/__tests__/pagination.test.ts- Unit testssrc/app.ts- Refactored endpointssrc/repositories/usageEventsRepository.ts- Interface updatessrc/repositories/usageEventsRepository.pg.ts- PostgreSQL implementation updatessrc/routes/admin.ts- Admin routessrc/routes/developerRoutes.ts- Developer analytics routes
βΆ parsePagination
β returns defaults when no query params given
β parses valid limit and offset
β clamps limit to max 100
β clamps limit to min 1
β clamps offset to min 0
β handles non-numeric strings gracefully
β truncates floating-point limit via parseInt
β clamps a huge limit (Number.MAX_SAFE_INTEGER) to 100
β calculates offset based on page and limit
β uses default limit when only page is provided
β prefers page over offset when both are provided
β handles invalid page values gracefully
...
β parsePagination (2.98ms)
βΆ paginatedResponse
β wraps data and meta into the envelope
β works without total in meta
β returns exactly "data" and "meta" top-level keys
...
β paginatedResponse (1.05ms)
βΉ tests 32
βΉ suites 2
βΉ pass 32
βΉ fail 0
- Total Test Cases: 32 unit tests
- Result: All passing
npm run lint- Success (0 errors)npx tsx --test src/lib/__tests__/pagination.test.ts- Success (32/32 tests passed)git checkout -b feature/pagination-defaults-max- Success