- 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.
63 lines
1.8 KiB
Plaintext
63 lines
1.8 KiB
Plaintext
---
|
|
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`.
|