Bin
2025-12-16 9e0b2ba2c317b1a86212f24cbae3195ad1f3dbfa
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
import { types } from "mobx-state-tree";
import { ConfigValidator } from "./ConfigValidator";
 
/**@typedef {(errors: any[]) => void} ErrorCallback */
 
const DATA_VALIDATORS = {
  CONFIG: ConfigValidator,
  RESULT: {
    validate() {
      return [];
    },
  },
};
 
/** @type {{[key: string]: keyof typeof DATA_VALIDATORS}} */
export const VALIDATORS = Object.keys(DATA_VALIDATORS).reduce((res, k) => ({ ...res, [k]: k }), {});
 
const ValidType = types.union(types.string, types.array(types.string));
 
export const ValidationError = types
  .model({
    modelName: types.string,
    field: types.string,
    error: types.string,
    value: types.maybeNull(types.string),
    validType: types.maybeNull(ValidType),
  })
  .views((self) => ({
    get identifier() {
      return [self.modelName, self.field, self.error, self.value]
        .concat(...[self.validType])
        .filter((el) => el !== null)
        .join("-");
    },
  }));
 
export class DataValidator {
  /**@type {Set<ErrorCallback>} */
  callbacks = new Set();
 
  addErrorCallback(callback) {
    if (!this.callbacks.has(callback)) {
      this.callbacks.add(callback);
      return true;
    }
    return false;
  }
 
  removeErrorCallback(callback) {
    if (this.callbacks.has(callback)) {
      this.callbacks.delete(callback);
      return true;
    }
    return false;
  }
 
  /**
   * Perform validation and return errors in a form of an array
   * @param {keyof typeof DATA_VALIDATORS} validatorName
   * @param {Object} data
   */
  validate(validatorName, data) {
    const validator = DATA_VALIDATORS[validatorName];
    let errors = [];
 
    if (validator) {
      errors = (validator.validate(data) ?? []).map((compiledError) => {
        try {
          return ValidationError.create(compiledError);
        } catch (err) {
          console.log({ compiledError });
          throw err;
        }
      });
    } else {
      console.error(`Unknown validator: ${validatorName}`);
    }
 
    setTimeout(() => {
      if (errors.length) {
        for (const callback of this.callbacks) {
          callback(errors);
        }
      }
    }, 0);
  }
}