<commit_before>import _ from 'lodash'

export const getPropType = (prop, attr) => {
  return prop.iterable
    ? recursiveValues(prop, attr)
    : prop[attr]
}

export const recursiveObject = (values, attr) => {
  return _.reduce(values, (memo, prop, key) => Object.assign({
    [key]: getPropType(prop, attr)
  }, memo), {})
}

export const recursiveArray = (values, attr) => {
  return _.map(values, (prop) => {
    return getPropType(prop, attr)
  })
}

export const selectRecursiveStrategy = (values, attr) => {
  return _.isArray(values)
    ? recursiveArray(values, attr)
    : recursiveObject(values, attr)
}

export const recursiveValues = ({ type, values }, attr) => {
  const exec = attr === 'type' ? type : _.identity
  return exec(selectRecursiveStrategy(values, attr))
}

export const createPropTypes = (definition) => {
  return recursiveObject(definition, 'type')
}

export const createDefault = (definition) => {
  return recursiveObject(definition, 'default')
}

export const filterByKeys = (definition, candidate) => {
  const keys = _.intersection(_.keys(definition), _.keys(candidate))
  return _.pick(candidate, keys)
}

export const transform = (definition, candidate, mutators) => Object.assign(
  filterByKeys(definition, candidate),
  _.reduce(mutators, (memo, value, key) => Object.assign({
    [key]: _.isFunction(value) ? value(candidate) : value,
    memo
  }), {})
)<commit_msg>feat: Add proto mutators on transform<commit_after>import _ from 'lodash'

export const getPropType = (prop, attr) => {
  return prop.iterable
    ? recursiveValues(prop, attr)
    : prop[attr]
}

export const recursiveObject = (values, attr) => {
  return _.reduce(values, (memo, prop, key) => Object.assign({
    [key]: getPropType(prop, attr)
  }, memo), {})
}

export const recursiveArray = (values, attr) => {
  return _.map(values, (prop) => {
    return getPropType(prop, attr)
  })
}

export const selectRecursiveStrategy = (values, attr) => {
  return _.isArray(values)
    ? recursiveArray(values, attr)
    : recursiveObject(values, attr)
}

export const recursiveValues = ({ type, values }, attr) => {
  const exec = attr === 'type' ? type : _.identity
  return exec(selectRecursiveStrategy(values, attr))
}

export const createPropTypes = (definition) => {
  return recursiveObject(definition, 'type')
}

export const createDefault = (definition) => {
  return recursiveObject(definition, 'default')
}

export const filterByKeys = (definition, candidate) => {
  const keys = _.intersection(_.keys(definition), _.keys(candidate))
  return _.pick(candidate, keys)
}

let protoMutators = {}

export const transform = (definition, candidate, mutators = protoMutators) => {
  return Object.assign(
    filterByKeys(definition, candidate),
    _.reduce(mutators, (memo, value, key) => Object.assign({
      [key]: _.isFunction(value) ? value(candidate) : value
    }, memo), {})
  )
}

Object.defineProperty(transform, 'mutators', {
  get: () => protoMutators,
  set: (mutators) => {
    protoMutators = mutators
  }
})
{'fraction_non_alphanumeric': 0.14765985497692816, 'fraction_numerical': 0.0, 'mean_word_length': 4.4586330935251794, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, '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': '454462', 'n_tokens_mistral': 946, 'n_tokens_neox': 933, 'n_words': 237}