All files / src/platform/gateway/interceptors api-response-envelope.interceptor.ts

0% Statements 0/15
0% Branches 0/18
0% Functions 0/2
0% Lines 0/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74                                                                                                                                                   
import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Logger,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
 
export interface ApiSuccessEnvelope<T> {
  success: true;
  data: T;
  meta: {
    requestId: string;
    correlationId: string;
    timestamp: string;
    page?: number;
    limit?: number;
    total?: number;
    totalPages?: number;
  };
}
 
@Injectable()
export class ApiResponseEnvelopeInterceptor implements NestInterceptor {
  private readonly logger = new Logger(ApiResponseEnvelopeInterceptor.name);
 
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const requestId: string = request['requestId'] || 'unknown';
    const correlationId: string = request['correlationId'] || 'unknown';
 
    return next.handle().pipe(
      map((data) => {
        // If the response is already a standard envelope (i.e., from a legacy controller that wraps itself), pass through
        if (data && typeof data === 'object' && 'success' in data) {
          return data;
        }
 
        // PaginatedResult passthrough — merge meta
        if (
          data &&
          typeof data === 'object' &&
          'data' in data &&
          'meta' in data &&
          Array.isArray(data.data)
        ) {
          return {
            success: true,
            data: data.data,
            meta: {
              ...data.meta,
              requestId,
              correlationId,
              timestamp: new Date().toISOString(),
            },
          };
        }
 
        return {
          success: true,
          data: data ?? null,
          meta: {
            requestId,
            correlationId,
            timestamp: new Date().toISOString(),
          },
        };
      }),
    );
  }
}