Source: form-validate/modules/validation-function.js

/**
 * @summary validation-function
 *
 * @version 3.0.0
 * @since 1.0.0
 * @author Arian Khosravi <arian.khosravi@aofl.com>
 */

/**
 * ValidationFunction implementation
 *
 * @memberof module:@aofl/form-validate
 */
class ValidationFunction {
  /**
   * Creates an instance of ValidationFunction.
   *
   * @param {Object} target
   * @param {Object} validatorFn
   * @param {String} path
   */
  constructor(target, validatorFn, path) {
    Object.defineProperties(this, {
      target: {
        value: target
      },
      propName: {
        value: path
      },
      resolve: {
        writable: true
      },
      cachedPromise: {
        writable: true
      },
      validateCompletePromise: {
        writable: true
      },
      valid: {
        writable: true
      },
      observed: {
        writable: true
      },
      pending: {
        writable: true
      },
      validatorFn: {
        value: validatorFn
      }
    });

    this.reset();
  }

  /**
   *
   */
  reset() {
    this.cachedPromise = null;
    this.resolve = null;
    this.valid = true;
    this.observed = false;
    this.pending = false;
    this.validateCompletePromise = null;
  }

  /**
   *
   *
   */
  validate() {
    this.observed = true;
    let target = this.target; // @todo: move to object utils
    const propChain = this.propName.split('.');

    for (let i = 0; i < propChain.length - 1; i++) {
      target = target[propChain[i]];
    }

    const promise = Promise.resolve(this.validatorFn(target));

    this.cachedPromise = promise;

    if (this.pending === false) {
      this.validateCompletePromise = new Promise((resolve) => {
        this.resolve = resolve;
      });
    }

    this.pending = true;
    promise
      .then((valid) => {
        if (this.cachedPromise === promise) { // latest update
          this.valid = valid;
          this.pending = false;
          this.resolve();
          this.target.requestUpdate();
        }
      });
  }

  /**
   * @type {Promise}
   */
  get validateComplete() {
    return this.validateCompletePromise;
  }

  /* istanbul ignore next */
  /**
   *
   * @return {Array}
   */
  getKeys() {
    const keys = ['valid', 'pending', 'observed'];
    for (const key in this) {
      if (!Object.prototype.hasOwnProperty.call(this, key)) continue;
      keys.push(key);
    }
    return keys;
  }

  /* istanbul ignore next */
  /**
   * @return {String}
   */
  toString() {
    const keys = this.getKeys();
    return JSON.stringify(this, keys, 2);
  }
}

export {
  ValidationFunction
};