<commit_before>/* @flow */

/**
 * Forgiving check for a promise
 */
function isPromise (p: Object): boolean {
  return p && typeof p.then === 'function'
}

export default function (Vue: GlobalAPI): Object {
  const { isPlainObject, resolveAsset } = Vue.util

  function _resolveValidator (name: string): ?ValidatorAsset {
    const options = (this.child && this.child.context)
      ? this.child.context.$options
      : this.$options
    return resolveAsset(options, 'validators', name)
  }

  function _getValidateDescriptor (
    validator: string,
    field: string,
    value: any
  ): $ValidateDescriptor | null {
    const asset: ValidatorAsset = this._resolveValidator(validator)
    if (!asset) {
      // TODO: should be warned
      return null
    }

    let fn = null
    let rule = null
    let msg = null
    if (isPlainObject(asset)) {
      if (asset.check && typeof asset.check === 'function') {
        fn = asset.check
      }
      if (asset.message) {
        msg = asset.message
      }
    } else if (typeof asset === 'function') {
      fn = asset
    } else {
      // TODO: should be warned
      return null
    }

    if (!fn) {
      // TODO: should be warned
      return null
    }

    if (isPlainObject(this.validators)) {
      if (isPlainObject(this.validators[validator])) {
        if (this.validators[validator].rule) {
          rule = this.validators[validator].rule
        }
        if (this.validators[validator].message) {
          msg = this.validators[validator].message
        }
      } else {
        rule = this.validators[validator]
      }
    }

    const descriptor: $ValidateDescriptor = { fn, value, field }
    if (rule) {
      descriptor.rule = rule
    }
    if (msg) {
      descriptor.msg = msg
    }

    return descriptor
  }

  function _resolveMessage (
    field: string,
    msg: string | Function,
    override?: string
  ): string | void {
    if (override) { return override }
    return msg
      ? typeof msg === 'function'
        ? msg(field)
        : msg
      : undefined
  }

  function _invokeValidator (
    { fn, value, field, rule, msg }: $ValidateDescriptor,
    cb: Function
  ): void {
    const future: any = fn.call(this, value, rule)
    if (typeof future === 'function') { // function
      future(() => { // resolve
        cb(true)
      }, (err: string) => { // reject
        cb(false, this._resolveMessage(field, msg, err))
      })
    } else if (isPromise(future)) { // promise
      future.then(() => { // resolve
        cb(true)
      }, (err: string) => { // reject
        cb(false, this._resolveMessage(field, msg, err))
      }).catch((err: Error) => {
        cb(false, this._resolveMessage(field, msg, err.message))
      })
    } else { // sync
      cb(future, future === false ? this._resolveMessage(field, msg) : undefined)
    }
  }

  function _validate (validator: string, value: any, cb: Function): boolean {
    const descriptor = this._getValidateDescriptor(validator, this.field, value)
    if (descriptor) {
      if (this.progresses[validator]) { return false }
      this.progresses[validator] = 'running'
      this.$nextTick(() => {
        this._invokeValidator(descriptor, (ret: boolean, msg: ?string) => {
          this.progresses[validator] = ''
          this.results[validator] = msg || ret
          if (cb) {
            this.$nextTick(() => {
              cb.call(this, null, ret, msg)
            })
          } else {
            const e: Object = { result: ret }
            if (msg) {
              e['msg'] = msg
            }
            this._fireEvent('validate', validator, e)
          }
        })
      })
    } else {
      // TODO:
      const err = new Error()
      cb ? cb.call(this, err) : this._fireEvent('validate', validator, err)
    }
    return true
  }

  // TODO: should be re-design of API
  function validate (...args: Array<any>): boolean {
    let validators: Array<string>
    let value: any
    let cb: ?Function
    let ret: boolean = true

    if (args.length === 3) {
      validators = [args[0]]
      value = args[1]
      cb = args[2]
    } else if (args.length === 2) {
      if (isObject(args[0])) {
        validators = [args[0].validator]
        value = args[0].value || this.getValue()
        cb = args[1]
      } else {
        validators = this._keysCached(this._uid.toString(), this.results)
        value = args[0]
        cb = args[1]
      }
    } else if (args.length === 1) {
      validators = this._keysCached(this._uid.toString(), this.results)
      value = this.getValue()
      cb = args[0]
    } else {
      validators = this._keysCached(this._uid.toString(), this.results)
      value = this.getValue()
      cb = null
    }

    if (args.length === 3 || (args.length === 2 && isObject(args[0]))) {
      ret = this._validate(validators[0], value, cb)
    } else {
      validators.forEach((validator: string) => {
        ret = this._validate(validator, value, cb)<commit_msg>:zap: improvement(validate): change to vue context [ci skip]<commit_after>/* @flow */

/**
 * Forgiving check for a promise
 */
function isPromise (p: Object): boolean {
  return p && typeof p.then === 'function'
}

export default function (Vue: GlobalAPI): Object {
  const { isPlainObject, resolveAsset } = Vue.util

  function _resolveValidator (name: string): ?ValidatorAsset {
    const options = (this.child && this.child.context)
      ? this.child.context.$options
      : this.$options
    return resolveAsset(options, 'validators', name)
  }

  function _getValidateDescriptor (
    validator: string,
    field: string,
    value: any
  ): $ValidateDescriptor | null {
    const asset: ValidatorAsset = this._resolveValidator(validator)
    if (!asset) {
      // TODO: should be warned
      return null
    }

    let fn = null
    let rule = null
    let msg = null
    if (isPlainObject(asset)) {
      if (asset.check && typeof asset.check === 'function') {
        fn = asset.check
      }
      if (asset.message) {
        msg = asset.message
      }
    } else if (typeof asset === 'function') {
      fn = asset
    } else {
      // TODO: should be warned
      return null
    }

    if (!fn) {
      // TODO: should be warned
      return null
    }

    if (isPlainObject(this.validators)) {
      if (isPlainObject(this.validators[validator])) {
        if (this.validators[validator].rule) {
          rule = this.validators[validator].rule
        }
        if (this.validators[validator].message) {
          msg = this.validators[validator].message
        }
      } else {
        rule = this.validators[validator]
      }
    }

    const descriptor: $ValidateDescriptor = { fn, value, field }
    if (rule) {
      descriptor.rule = rule
    }
    if (msg) {
      descriptor.msg = msg
    }

    return descriptor
  }

  function _resolveMessage (
    field: string,
    msg: string | Function,
    override?: string
  ): string | void {
    if (override) { return override }
    return msg
      ? typeof msg === 'function'
        ? msg(field)
        : msg
      : undefined
  }

  function _invokeValidator (
    { fn, value, field, rule, msg }: $ValidateDescriptor,
    cb: Function
  ): void {
    const future: any = fn.call(this.child.context, value, rule)
    if (typeof future === 'function') { // function
      future(() => { // resolve
        cb(true)
      }, (err: string) => { // reject
        cb(false, this._resolveMessage(field, msg, err))
      })
    } else if (isPromise(future)) { // promise
      future.then(() => { // resolve
        cb(true)
      }, (err: string) => { // reject
        cb(false, this._resolveMessage(field, msg, err))
      }).catch((err: Error) => {
        cb(false, this._resolveMessage(field, msg, err.message))
      })
    } else { // sync
      cb(future, future === false ? this._resolveMessage(field, msg) : undefined)
    }
  }

  function _validate (validator: string, value: any, cb: Function): boolean {
    const descriptor = this._getValidateDescriptor(validator, this.field, value)
    if (descriptor) {
      if (this.progresses[validator]) { return false }
      this.progresses[validator] = 'running'
      this.$nextTick(() => {
        this._invokeValidator(descriptor, (ret: boolean, msg: ?string) => {
          this.progresses[validator] = ''
          this.results[validator] = msg || ret
          if (cb) {
            this.$nextTick(() => {
              cb.call(this, null, ret, msg)
            })
          } else {
            const e: Object = { result: ret }
            if (msg) {
              e['msg'] = msg
            }
            this._fireEvent('validate', validator, e)
          }
        })
      })
    } else {
      // TODO:
      const err = new Error()
      cb ? cb.call(this, err) : this._fireEvent('validate', validator, err)
    }
    return true
  }

  // TODO: should be re-design of API
  function validate (...args: Array<any>): boolean {
    let validators: Array<string>
    let value: any
    let cb: ?Function
    let ret: boolean = true

    if (args.length === 3) {
      validators = [args[0]]
      value = args[1]
      cb = args[2]
    } else if (args.length === 2) {
      if (isPlainObject(args[0])) {
        validators = [args[0].validator]
        value = args[0].value || this.getValue()
        cb = args[1]
      } else {
        validators = this._keysCached(this._uid.toString(), this.results)
        value = args[0]
        cb = args[1]
      }
    } else if (args.length === 1) {
      validators = this._keysCached(this._uid.toString(), this.results)
      value = this.getValue()
      cb = args[0]
    } else {
      validators = this._keysCached(this._uid.toString(), this.results)
      value = this.getValue()
      cb = null
    }

    if (args.length === 3 || (args.length === 2 && isPlainObject(args[0]))) {
      ret = this._validate(validators[0], value, cb)
    } else {
      validators.forEach((validator: string) => {
        ret = this._validate(validator, value, cb)
{'fraction_non_alphanumeric': 0.13900808302564616, 'fraction_numerical': 0.003392874962578585, 'mean_word_length': 2.124064837905237, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4253589', 'n_tokens_mistral': 3007, 'n_tokens_neox': 3009, 'n_words': 762}