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:
shancheas
2026-08-21 15:56:54 +07:00
parent d01fd6e2ef
commit 0550cbe764
28 changed files with 1177 additions and 19 deletions
+28 -14
View File
@@ -8,36 +8,50 @@ alwaysApply: false
## API Response Format
Paginated lists (after `@Pagination()` + `TransformInterceptor`):
```typescript
interface ApiResponse<T> {
success: boolean
data?: T
error?: string
meta?: {
total: number
page: number
limit: number
}
interface PaginationMeta {
currentPage: number
itemCount: number
itemsPerPage: number
totalItems: number
totalPages: number
}
interface SuccessResponse<T> {
data: T
meta?: PaginationMeta
}
// Handler return for @Pagination() routes only
interface PaginationResponse<T> {
data: T[]
total: number
}
```
Detail / create / update / delete responses are the resource DTO (unwrapped). See `.cursor/rules/pagination-response.mdc`.
## Feature Module
```typescript
@Module({
imports: [],
controllers: [UsersController],
providers: [UsersService, UsersRepository],
exports: [UsersService],
controllers: [ShipmentsReadController, ShipmentsWriteController],
providers: [ShipmentsService, ShipmentsRepository],
exports: [ShipmentsService],
})
export class UsersModule {}
export class ShipmentsModule {}
```
Auth-style modules may register a single controller.
## Repository Pattern (Drizzle)
```typescript
interface Repository<T> {
findAll(filters?: Filters): Promise<T[]>
findAll(filters?: Filters): Promise<{ data: T[]; total: number }>
findById(id: string): Promise<T | null>
create(data: CreateDto): Promise<T>
update(id: string, data: UpdateDto): Promise<T>