Implement pagination response handling and related enhancements
- Introduced `@Pagination()` decorator to mark list endpoints for pagination.
- Added `TransformInterceptor` to wrap responses in a standardized format `{ data, meta }`.
- Created pagination-related utility functions and constants for managing pagination logic.
- Defined `PaginationQueryDto` for handling pagination query parameters.
- Established `PaginationMetaDto` for OpenAPI documentation of pagination metadata.
- Updated existing controller and service structures to support pagination in responses.
- Added unit tests for pagination utilities and interceptor to ensure correct functionality.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
---
|
||||
description: List endpoints use @Pagination() and return { data, total }; interceptor emits { data, meta }
|
||||
globs: "src/**/*.controller.ts,src/common/http/**/*.ts,src/common/configure-app.ts"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Pagination Response Envelope
|
||||
|
||||
Canonical list HTTP shape (TrackGo-compatible). Shared code lives in `src/common/http/response/`.
|
||||
|
||||
## Handler vs public response
|
||||
|
||||
```typescript
|
||||
// Handler return when marked @Pagination()
|
||||
interface PaginationResponse<T> {
|
||||
data: T[]
|
||||
total: number
|
||||
}
|
||||
|
||||
// Public response after TransformInterceptor
|
||||
interface SuccessResponse<T> {
|
||||
data: T
|
||||
meta?: PaginationMeta
|
||||
}
|
||||
|
||||
interface PaginationMeta {
|
||||
currentPage: number
|
||||
itemCount: number
|
||||
itemsPerPage: number
|
||||
totalItems: number
|
||||
totalPages: number
|
||||
}
|
||||
```
|
||||
|
||||
## Mandatory
|
||||
|
||||
- Mark every list endpoint with `@Pagination()`
|
||||
- Return `{ data, total }` from the handler — **never** build `meta` in the service or controller
|
||||
- Query: `page`/`limit` or `offset`/`limit` (defaults `page=1`, `limit=10`; max limit `200`)
|
||||
- Use `@RawResponse()` for file downloads / health probes that must skip wrapping
|
||||
- Non-list handlers (detail, create, update, delete, status, import) pass through **unwrapped**
|
||||
|
||||
```typescript
|
||||
// BAD — hand-rolled meta / success wrapper
|
||||
return { success: true, data: items, meta: { total, page, limit } }
|
||||
|
||||
// GOOD
|
||||
@Get()
|
||||
@Pagination()
|
||||
list(@Query() query: ListQueryDto): Promise<PaginationResponse<ItemDto>> {
|
||||
return this.service.list(query) // { data, total }
|
||||
}
|
||||
```
|
||||
|
||||
## Forbidden
|
||||
|
||||
- `success: boolean` response wrappers for lists
|
||||
- Putting `total` on `meta` instead of `totalItems`
|
||||
- Computing `PaginationMeta` in feature services
|
||||
- Documenting the internal `{ data, total }` shape in OpenAPI — document `{ data, meta }` instead
|
||||
|
||||
`TransformInterceptor` is registered globally in `configureApp`.
|
||||
Reference in New Issue
Block a user