All files / src/utils EntityValidator.ts

83.33% Statements 30/36
76.19% Branches 32/42
100% Functions 9/9
83.87% Lines 26/31

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 99 100 101 102 103                              2x 2x 2x     2x               235x           235x 235x   235x 1648x 1594x             235x 1592x         235x 1582x 1594x                       1594x   1592x 1592x   1592x   1319x           229x       668x   2x   207x             208x   5x            
import type { IDataBase } from '../lib';
import type { ColumnPropMap } from '../classes';
 
export type ValidationInterface = {
  valid: boolean;
  invalidKey: string[];
};
 
export class EntityValidator {
  static validateManualObj(
    db: IDataBase<any, any>,
    entity: string,
    value: any,
    update: boolean,
  ): ValidationInterface {
    const meta = db.getEntityMeta();
    const ent = meta.find((e) => e.key === entity);
    Iif (!ent || typeof value !== 'object') {
      throw new Error('Validation failed');
    }
    return this.validateObj(ent.meta, value, update);
  }
 
  static validateObj(
    meta: ColumnPropMap<any>,
    value: any,
    update: boolean,
  ): ValidationInterface {
    Iif (typeof value !== 'object' || !value || Array.isArray(value)) {
      return {
        valid: false,
        invalidKey: ['value is not an object'],
      };
    }
    try {
      const fields: { valid: boolean; key: string }[] = [];
 
      meta.forEach((el, key) => {
        if (!update || value[key] !== undefined) {
          fields.push({
            valid: this.validateObjKey(meta, key as string, value[key]),
            key: key as string,
          });
        }
      });
 
      Object.keys(value).forEach((key) => {
        Iif (!meta.has(key)) {
          fields.push({ key, valid: false });
        }
      });
 
      return {
        valid: !fields.some((el) => !el.valid),
        invalidKey: fields.filter((el) => !el.valid).map((el) => el.key),
      };
    } catch (e) {
      return { valid: false, invalidKey: ['unknown'] };
    }
  }
 
  static validateObjKey(
    metaContainer: ColumnPropMap<any>,
    key: string,
    value: unknown,
  ): boolean {
    if (value === undefined) return false;
 
    const meta = metaContainer.get(key);
    Iif (!meta) return false;
 
    if (meta.canBeNull && value === null) return true;
 
    switch (meta.dataType) {
      case 'serial':
      case 'int':
      case 'long':
      case 'double':
      case 'float':
        return typeof value === 'number';
      case 'string':
      case 'text':
      case 'uuid':
        return typeof value === 'string';
      case 'boolean':
        return typeof value === 'boolean' || value === 0 || value === 1;
      case 'date':
        return (
          value instanceof Date ||
          (typeof value === 'string' &&
            !Number.isNaN(new Date(value).getTime()))
        );
 
      case 'json':
        return typeof value === 'object';
      case 'blob':
        return value instanceof Buffer;
      default:
        return false;
    }
  }
}