<commit_before>const transformSchema = require('./transformSchema.js')
const { Schema, Value } = require('./exceptions')

class Validator {
  /**
   * Create a new instance of the Validator
   * @param  {Mixed} data
   * @param  {Object|Array} schema
   * @return {Validator}
   */
  constructor (data, schema) {
    this.errors = {}
    this.mutated = {}
    this.compare(data, transformSchema(schema))
    this.mutateData(data)
  }

  /**
   * Compare data agains a schema
   * @param  {Mixed} data
   * @param  {Object|Array|Function} schema can be a validator function or a schema
   * @param  {Array}  context
   * @private
   */
  compare (data, schema, context = []) {
    if (Array.isArray(schema)) {
      return this.compareArray(data, schema, context)
    }

    if (typeof schema === 'object') {
      return this.compareObject(data, schema, context)
    }

    return this.validate(data, schema, context)
  }

  /**
   * Compare a schema against an array
   * @param  {Mixed} data
   * @param  {Array} schema
   * @param  {Array}  context
   * @private
   */
  compareArray (data, [ schema ], context = []) {
    for (let index = 0; index < data.length; index++) {
      this.compare(data[index], schema, context.concat(index))
    }
  }

  /**
   * Compare a schema against an object
   * @param  {Mixed} data
   * @param  {Object} schema
   * @param  {Array}  context
   * @private
   */
  compareObject (data, schema, context = []) {
    for (let key in schema) {
      this.compare(data[key], schema[key], context.concat(key))
    }
  }

  /**
   * Validate the value with the validator function
   * @param  {Mixed} value
   * @param  {Function} validator
   * @param  {Array}  context
   * @private
   */
  validate (value, validator, context) {
    try {
      if (!validator(value)) throw new Error('value is invalid')
    } catch (err) {
      if (err instanceof Schema) {
        return this.compare(value, transformSchema(err.schema), context)
      }

      if (err instanceof Value) {
        return (this.mutated[context.join('.')] = err.value)
      }

      this.errors[context.join('.')] = err.message
    }
  }

  /**
   * Check if any data is marked as mutated and transform the data object with
   * the mutated data
   * I know its bad practice to mutate function arguments but i have to be
   * able to set default values or e.g mutate date strings to Date objects on
   * the fly.
   * @param {Mixed} data
   * @private
   */
  mutateData (data) {
    if (Object.keys(this.mutated).length === 0) {
      return
    }

    for (const key in this.mutated) {
      key.split('.').reduce((data, context, index, path) => {
        if (index < path.length - 1) {
          return (data[context])
        }

        return (data[context] = this.mutated[key])
      }, data)
    }
  }

  /**
   * Check if the validator has failed.
   * @return {Boolean}
   * @public
   */
  fails () {
    if (Object.keys(this.errors).length > 0) {
      return true
    }

    return false
  }
}

module.exports = Validator<commit_msg>Simplified failed function<commit_after>const transformSchema = require('./transformSchema.js')
const { Schema, Value } = require('./exceptions')

class Validator {
  /**
   * Create a new instance of the Validator
   * @param  {Mixed} data
   * @param  {Object|Array} schema
   * @return {Validator}
   */
  constructor (data, schema) {
    this.errors = {}
    this.mutated = {}
    this.compare(data, transformSchema(schema))
    this.mutateData(data)
  }

  /**
   * Compare data agains a schema
   * @param  {Mixed} data
   * @param  {Object|Array|Function} schema can be a validator function or a schema
   * @param  {Array}  context
   * @private
   */
  compare (data, schema, context = []) {
    if (Array.isArray(schema)) {
      return this.compareArray(data, schema, context)
    }

    if (typeof schema === 'object') {
      return this.compareObject(data, schema, context)
    }

    return this.validate(data, schema, context)
  }

  /**
   * Compare a schema against an array
   * @param  {Mixed} data
   * @param  {Array} schema
   * @param  {Array}  context
   * @private
   */
  compareArray (data, [ schema ], context = []) {
    for (let index = 0; index < data.length; index++) {
      this.compare(data[index], schema, context.concat(index))
    }
  }

  /**
   * Compare a schema against an object
   * @param  {Mixed} data
   * @param  {Object} schema
   * @param  {Array}  context
   * @private
   */
  compareObject (data, schema, context = []) {
    for (let key in schema) {
      this.compare(data[key], schema[key], context.concat(key))
    }
  }

  /**
   * Validate the value with the validator function
   * @param  {Mixed} value
   * @param  {Function} validator
   * @param  {Array}  context
   * @private
   */
  validate (value, validator, context) {
    try {
      if (!validator(value)) throw new Error('value is invalid')
    } catch (err) {
      if (err instanceof Schema) {
        return this.compare(value, transformSchema(err.schema), context)
      }

      if (err instanceof Value) {
        return (this.mutated[context.join('.')] = err.value)
      }

      this.errors[context.join('.')] = err.message
    }
  }

  /**
   * Check if any data is marked as mutated and transform the data object with
   * the mutated data
   * I know its bad practice to mutate function arguments but i have to be
   * able to set default values or e.g mutate date strings to Date objects on
   * the fly.
   * @param {Mixed} data
   * @private
   */
  mutateData (data) {
    if (Object.keys(this.mutated).length === 0) {
      return
    }

    for (const key in this.mutated) {
      key.split('.').reduce((data, context, index, path) => {
        if (index < path.length - 1) {
          return (data[context])
        }

        return (data[context] = this.mutated[key])
      }, data)
    }
  }

  /**
   * Check if the validator has failed.
   * @return {Boolean}
   * @public
   */
  fails () {
    return Object.keys(this.errors).length > 0
  }
}

module.exports = Validator
{'fraction_non_alphanumeric': 0.13445378151260504, 'fraction_numerical': 0.0013181743285549513, 'mean_word_length': 2.4885057471264367, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '300062', 'n_tokens_mistral': 1948, 'n_tokens_neox': 1912, 'n_words': 553}