# All files / common/pipes validation.pipe.ts

97.14% Statements 34/35
85% Branches 17/20
100% Functions 6/6
96.67% Lines 29/30

    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
    701x
    1x

    1x
    1x
    1x

    1x
    1x

    1x

    7x
    7x
    7x
    7x
    7x

    14x
    7x
    7x

    10x
    10x
    1x

    9x

    9x
    9x
    1x

    8x

    9x
    9x

    9x
    45x

    9x

     import { Optional } from '../decorators';
    import { ArgumentMetadata, BadRequestException } from '../index';
    import { ValidatorOptions } from '../interfaces/external/validator-options.interface';
    import { PipeTransform } from '../interfaces/features/pipe-transform.interface';
    import { loadPackage } from '../utils/load-package.util';
    import { isNil } from '../utils/shared.utils';
    import { Injectable } from '../decorators/core/component.decorator';

    export interface ValidationPipeOptions extends ValidatorOptions {
      transform?: boolean;
      disableErrorMessages?: boolean;
    }

    let classValidator: any = {};
    let classTransformer: any = {};

    @Injectable()
    export class ValidationPipe implements PipeTransform<any> {
      protected isTransformEnabled: boolean;
      protected isDetailedOutputDisabled?: boolean;
      protected validatorOptions: ValidatorOptions;

      constructor(@Optional() options?: ValidationPipeOptions) {
        options = options || {};
        const { transform, disableErrorMessages, ...validatorOptions } = options;
        this.isTransformEnabled = !!transform;
        this.validatorOptions = validatorOptions;
        this.isDetailedOutputDisabled = disableErrorMessages;

        const loadPkg = pkg => loadPackage(pkg, 'ValidationPipe');
        classValidator = loadPkg('class-validator');
        classTransformer = loadPkg('class-transformer');
      }

      public async transform(value, metadata: ArgumentMetadata) {
        const { metatype } = metadata;
        if (!metatype || !this.toValidate(metadata)) {
          return value;
        }
        const entity = classTransformer.plainToClass(
          metatype,
          this.toEmptyIfNil(value),
        );
        const errors = await classValidator.validate(entity, this.validatorOptions);
        if (errors.length > 0) {
          throw new BadRequestException(
            this.isDetailedOutputDisabled ? undefined : errors,
          );
        }
        return this.isTransformEnabled
          ? entity
          : Object.keys(this.validatorOptions).length > 0
            ? classTransformer.classToPlain(entity)
            : value;
      }

      private toValidate(metadata: ArgumentMetadata): boolean {
        const { metatype, type } = metadata;
        Iif (type === 'custom') {
          return false;
        }
        const types = [String, Boolean, Number, Array, Object];
        return !types.some(t => metatype === t) && !isNil(metatype);
      }

      toEmptyIfNil<T = any, R = any>(value: T): R | {} {
        return isNil(value) ? {} : value;
      }
    }