<commit_before>import { prompt } from 'inquirer'

// ===================================================================

const forArray = (array, iteratee) => {
  for (let i = 0, n = array.length; i < n; ++i) {
    iteratee(array[i], i, array)
  }
}

const { hasOwnProperty } = Object.prototype
const forOwn = (object, iteratee) => {
  for (const key in object) {
    if (hasOwnProperty.call(object, key)) {
      iteratee(object[key], key, object)
    }
  }
}

// -------------------------------------------------------------------

const _makeAsyncIterator = iterator => (promises, cb) => {
  let mainPromise = Promise.resolve()

  iterator(promises, (promise, key) => {
    mainPromise = mainPromise

      // Waits the current promise.
      .then(() => promise)

      // Executes the callback.
      .then(value => cb(value, key))
  })

  return mainPromise
}

const forOwnAsync = _makeAsyncIterator(forOwn)

// -------------------------------------------------------------------

const _isNaN = (
  Number.isNaN ||
  (value => value !== value) // eslint-disable-line no-self-compare
)

const isNumber = value => !_isNaN(value) && typeof value === 'number'

const isInteger = (
  Number.isInteger ||
  (value => (
    isNumber(value) &&
    value > -Infinity && value < Infinity &&
    Math.floor(value) === value
  ))
)

// ===================================================================

const EMPTY_OBJECT = Object.freeze({ __proto__: null })

const _extractValue = ({ value }) => value

export const confirm = (message, {
  default: defaultValue = null
} = EMPTY_OBJECT) => prompt({
  default: defaultValue,
  message,
  name: 'value',
  type: 'confirm'
}).then(_extractValue)

export const input = (message, {
  default: defaultValue = null,
  filter = undefined,
  validate = undefined
} = EMPTY_OBJECT) => prompt({
  default: defaultValue,
  message,
  name: 'value',
  type: 'input',
  validate
}).then(_extractValue)

export const list = (message, choices, {
  default: defaultValue = null
} = EMPTY_OBJECT) => prompt({
  default: defaultValue,
  choices,
  message,
  name: 'value',
  type: 'list'
}).then(_extractValue)

export const password = (message, {
  default: defaultValue = null,
  filter = undefined,
  validate = undefined
} = EMPTY_OBJECT) => prompt({
  default: defaultValue,
  message,
  name: 'value',
  type: 'password',
  validate
}).then(_extractValue)

// ===================================================================

const promptByType = {
  __proto__: null,

  array: async (schema, defaultValue, path) => {
    const items = []
    if (defaultValue == null) {
      defaultValue = items
    }

    let i = 0

    const itemSchema = schema.items
    const promptItem = async () => {
      items[i] = await promptGeneric(
        itemSchema,
        defaultValue[i],
        path
          ? `${path} [${i}]`
          : `[${i}]`
      )

      ++i
    }

    let n = schema.minItems || 0
    while (i < n) { // eslint-disable-line no-unmodified-loop-condition
      await promptItem()
    }

    n = schema.maxItems || Infinity
    while (
      i < n && // eslint-disable-line no-unmodified-loop-condition
      await confirm('additional item?', {
        default: false
      })
    ) {
      await promptItem()
    }

    return items
  },

  boolean: (schema, defaultValue, path) => confirm(path, {
    default: defaultValue || schema.default
  }),

  enum: (schema, defaultValue, path) => list(path, schema.enum, {
    defaultValue: defaultValue || schema.defaultValue
  }),

  integer: (schema, defaultValue, path) => input(path, {
    default: defaultValue || schema.default,
    filter: input => +input,
    validate: input => isInteger(+input)
  }),

  number: (schema, defaultValue, path) => input(path, {
    default: defaultValue || schema.default,
    filter: input => +input,
    validate: input => isNumber(+input)
  }),

  object: async (schema, defaultValue, path) => {
    const value = {}

    const required = {}
    schema.required && forArray(schema.required, name => {
      required[name] = true
    })

    const promptProperty = async (schema, name) => {
      const subpath = path
        ? `${path} > ${schema.title || name}`
        : schema.title || name

      if (
        required[name] ||
        await confirm(`fill optional ${subpath}?`, {
          default: Boolean(defaultValue && name in defaultValue)
        })
      ) {
        value[name] = await promptGeneric(
          schema,
          defaultValue && defaultValue[name],
          subpath
        )
      }
    }

    await forOwnAsync(schema.properties || {}, promptProperty)

    return value
  },
<commit_msg>chore(xo-server-auth-ldap): use lodash and promise-toolbox utils<commit_after>import { forEach, isFinite, isInteger } from 'lodash'
import { forOwn as forOwnAsync } from 'promise-toolbox'
import { prompt } from 'inquirer'

// ===================================================================

const EMPTY_OBJECT = Object.freeze({ __proto__: null })

const _extractValue = ({ value }) => value

export const confirm = (message, {
  default: defaultValue = null
} = EMPTY_OBJECT) => prompt({
  default: defaultValue,
  message,
  name: 'value',
  type: 'confirm'
}).then(_extractValue)

export const input = (message, {
  default: defaultValue = null,
  filter = undefined,
  validate = undefined
} = EMPTY_OBJECT) => prompt({
  default: defaultValue,
  message,
  name: 'value',
  type: 'input',
  validate
}).then(_extractValue)

export const list = (message, choices, {
  default: defaultValue = null
} = EMPTY_OBJECT) => prompt({
  default: defaultValue,
  choices,
  message,
  name: 'value',
  type: 'list'
}).then(_extractValue)

export const password = (message, {
  default: defaultValue = null,
  filter = undefined,
  validate = undefined
} = EMPTY_OBJECT) => prompt({
  default: defaultValue,
  message,
  name: 'value',
  type: 'password',
  validate
}).then(_extractValue)

// ===================================================================

const promptByType = {
  __proto__: null,

  array: async (schema, defaultValue, path) => {
    const items = []
    if (defaultValue == null) {
      defaultValue = items
    }

    let i = 0

    const itemSchema = schema.items
    const promptItem = async () => {
      items[i] = await promptGeneric(
        itemSchema,
        defaultValue[i],
        path
          ? `${path} [${i}]`
          : `[${i}]`
      )

      ++i
    }

    let n = schema.minItems || 0
    while (i < n) { // eslint-disable-line no-unmodified-loop-condition
      await promptItem()
    }

    n = schema.maxItems || Infinity
    while (
      i < n && // eslint-disable-line no-unmodified-loop-condition
      await confirm('additional item?', {
        default: false
      })
    ) {
      await promptItem()
    }

    return items
  },

  boolean: (schema, defaultValue, path) => confirm(path, {
    default: defaultValue || schema.default
  }),

  enum: (schema, defaultValue, path) => list(path, schema.enum, {
    defaultValue: defaultValue || schema.defaultValue
  }),

  integer: (schema, defaultValue, path) => input(path, {
    default: defaultValue || schema.default,
    filter: input => +input,
    validate: input => isInteger(+input)
  }),

  number: (schema, defaultValue, path) => input(path, {
    default: defaultValue || schema.default,
    filter: input => +input,
    validate: input => isFinite(+input)
  }),

  object: async (schema, defaultValue, path) => {
    const value = {}

    const required = {}
    schema.required && forEach(schema.required, name => {
      required[name] = true
    })

    const promptProperty = async (schema, name) => {
      const subpath = path
        ? `${path} > ${schema.title || name}`
        : schema.title || name

      if (
        required[name] ||
        await confirm(`fill optional ${subpath}?`, {
          default: Boolean(defaultValue && name in defaultValue)
        })
      ) {
        value[name] = await promptGeneric(
          schema,
          defaultValue && defaultValue[name],
          subpath
        )
      }
    }

    await forOwnAsync.call(schema.properties || {}, promptProperty)

    return value
  },

{'fraction_non_alphanumeric': 0.1909578357299537, 'fraction_numerical': 0.0006093102607847916, 'mean_word_length': 2.715255771842463, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 52, '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': '365108', 'n_tokens_mistral': 2451, 'n_tokens_neox': 2395, 'n_words': 609}