- Updated pagination-response and read-write-controllers documentation to include `orderBy` and `orderType` parameters for sorting results. - Introduced new `order-clause` module to handle ordering logic, including validation for order types and columns. - Enhanced `PaginationQueryDto` to support ordering fields in API requests. - Updated various repository and service classes to implement ordering in database queries. - Added unit tests for new ordering functionality and ensured existing tests cover the updated behavior. - Refactored related DTOs to include user and code relations for better data representation in responses.
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`) plus `orderBy`/`orderType` (`ASC` | `DESC`, default `ASC`)
|
|
- 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`.
|