Files
trackgo-be/src/common/http/response/transform.interceptor.ts
T
shancheas 0550cbe764 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.
2026-08-21 15:56:54 +07:00

59 lines
1.6 KiB
TypeScript

import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
StreamableFile,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { PAGINATION_RESPONSE, RAW_RESPONSE } from './constants';
import {
createPaginationResponse,
resolvePaginationQuery,
} from './pagination-meta.helper';
/**
* Applies pagination enveloping when a handler is marked with `@Pagination()`.
*
* Non-paginated handlers pass through unchanged. `@RawResponse()`, empty
* bodies, and `StreamableFile` downloads are never wrapped.
*/
@Injectable()
export class TransformInterceptor implements NestInterceptor {
constructor(private readonly reflector: Reflector) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
const isRaw = this.reflector.getAllAndOverride<boolean>(RAW_RESPONSE, [
context.getHandler(),
context.getClass(),
]);
if (isRaw) {
return next.handle();
}
const isPagination = this.reflector.getAllAndOverride<boolean>(
PAGINATION_RESPONSE,
[context.getHandler(), context.getClass()],
);
if (!isPagination) {
return next.handle();
}
const request = context.switchToHttp().getRequest<{
query: Record<string, unknown>;
}>();
const { page, limit } = resolvePaginationQuery(request.query);
return next.handle().pipe(
map((payload: unknown): unknown => {
if (payload == null || payload instanceof StreamableFile) {
return payload;
}
return createPaginationResponse(payload, page, limit);
}),
);
}
}