All files / src/common/filters gql-exception.filter.ts

87.5% Statements 14/16
50% Branches 5/10
100% Functions 1/1
85.71% Lines 12/14

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 401x     1x             1x     1x 1x       1x 1x 1x 1x     1x           1x 1x                
import { ArgumentsHost, Catch, HttpException } from '@nestjs/common';
import type { GqlContextType } from '@nestjs/graphql';
import { GqlExceptionFilter } from '@nestjs/graphql';
import { GraphQLError } from 'graphql';
 
/**
 * Translates boring Nest HttpExceptions into sexy ApolloErrors so the frontend
 * can actually understand what the hell went wrong.
 */
@Catch()
export class GqlHttpExceptionFilter implements GqlExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    // Only handle GraphQL context; otherwise let Nest's default HTTP filter handle it
    const ctxType = host.getType<GqlContextType>();
    Iif (ctxType !== 'graphql') {
      throw exception;
    }
 
    if (exception instanceof HttpException) {
      const response = exception.getResponse() as any;
      const message = (response && response.message) || response || 'Unexpected error';
      const status = exception.getStatus();
 
      // Map status → GraphQL error code (Apollo style)
      const codeMap: Record<number, string> = {
        400: 'BAD_REQUEST',
        401: 'UNAUTHENTICATED',
        403: 'FORBIDDEN',
        404: 'NOT_FOUND',
      };
      const gqlCode = codeMap[status] ?? 'INTERNAL_SERVER_ERROR';
      return new GraphQLError(Array.isArray(message) ? message.join(', ') : message, {
        extensions: { code: gqlCode, http: { status } },
      });
    }
 
    // Fallback for unknown throwables in GraphQL context
    return new GraphQLError('Something went terribly wrong', { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
  }
}