All files / validation baseValidation.ts

100% Statements 98/98
88% Branches 22/25
100% Functions 6/6
100% Lines 98/98

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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 991x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 13x 4x 1x 1x 3x 3x 3x 4x 4x 4x 1x 1x 1x 67x 2x 4x 4x 4x 1x 1x 1x 1x 1x 1x 13x 13x 13x 3x 3x 3x 1x 1x 1x 2x 2x 2x 1x 1x 1x 21x 1x 1x 4x 4x 4x 1x 1x 1x 1x 1x 8x 8x 8x 8x 8x 8x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 3x 3x 3x 3x 3x 3x 3x 9x 1x 1x 1x 1x 1x 1x 1x 9x 8x 8x 8x  
import { AppType } from '@constants/enum/appType';
import { makeArrayOrDefault } from '@helpers/arrayHelper';
import { getAppType } from '@services/internal/configService';
import { getLog } from '@services/internal/logService';
import { FormDtoMeta } from '@contracts/dto/forms/baseFormDto';
import { ValidationResult } from '@contracts/validationResult';
 
export const noValidation = <T>(_: T): ValidationResult => ({ isValid: true });
 
export const notNull =
  (customErrMsg?: string) =>
  <T>(value: T): ValidationResult => {
    if (value != null) {
      return { isValid: true };
    }
 
    return {
      isValid: false,
      errorMessage: customErrMsg ?? `Field shouldn't be empty`,
    };
  };
 
export const multiValidation =
  <T>(...validations: Array<(validationVal: T) => ValidationResult>) =>
  (value: T): ValidationResult => {
    for (const validation of validations) {
      const result = validation(value);
      if (result.isValid === false) return result;
    }
 
    return { isValid: true };
  };
 
export const separateValidation =
  <T>(validators: {
    [key in keyof typeof AppType]?: (validationVal: T) => ValidationResult;
  }) =>
  (value: T): ValidationResult => {
    const appType = getAppType()?.toString?.() as keyof typeof AppType;
    const validatorForAppType = validators[AppType[appType]];
    if (validatorForAppType == null) {
      getLog().w(`separateValidation - ${appType} validator not found`);
      return { isValid: true };
    }
 
    return validatorForAppType(value);
  };
 
export const validateForEach =
  <T>(validation: (item: T) => ValidationResult) =>
  (values: Array<T>): ValidationResult => {
    const safeArr = makeArrayOrDefault(values);
    for (const value of safeArr) {
      const result = validation(value);
      if (result.isValid === false) return result;
    }
 
    return { isValid: true };
  };
 
export const validateObj = <T>(props: {
  data: T;
  validationObj: FormDtoMeta<T>;
  includeLabelInErrMsgs?: boolean;
}): Array<ValidationResult> => {
  const validationMessages: Array<ValidationResult> = [];
  for (const mappedBodyParam in props.validationObj) {
    const validatorHasProp = Object.prototype.hasOwnProperty.call(
      props.validationObj,
      mappedBodyParam,
    );
    if (validatorHasProp === false) continue;
 
    try {
      const propValue = props.data[mappedBodyParam];
      const { label, validationLabel, validator } = props.validationObj[mappedBodyParam];
      const validationResult = validator(propValue);
 
      if (validationResult.isValid === false) {
        const errMsg = validationResult.errorMessage ?? `Validation failed for ${mappedBodyParam}`;
        const propLabel = validationLabel ?? label;
        validationMessages.push({
          isValid: validationResult.isValid,
          errorMessage: props.includeLabelInErrMsgs ? `${propLabel}: ${errMsg}` : errMsg,
        });
      }
    } catch (ex) {
      const errMsg = `exception while processing ${mappedBodyParam}`;
      getLog().e(errMsg, ex);
      validationMessages.push({
        isValid: false,
        errorMessage: errMsg,
      });
    }
  }
 
  return validationMessages;
};