<commit_before>const _ = require('lodash')

/**
 * @param {{modelName: String}} form
 * @returns {Function}
 */
function generateInsertAction (form) {
  return async function (api, data, next) {
    try {
      let record = await api.models[ form.modelName ].build({})
      if ((!data.session.user.isAdmin && !api.forms.isModerator(data.session.user, form.modelName)) || !data.params.user) {
        data.params.user = data.session.userId
      }
      record = await record.apiUpdate(data.params)
      const hash = record.calculateHash()
      api.log('looking for %s with hash %s', 'info', form.modelName, hash)
      const existing = await api.models[ form.modelName ].findOne({ where: { hash: hash } })
      if (existing) {
        api.log('found %s with hash %s, updating', 'info', form.modelName, hash)
        data.response.existing = true
        await existing.apiUpdate(data.params)
        record = await existing.save()
      } else {
        api.log('not found %s with hash %s, creating', 'info', form.modelName, hash)
        record = await record.save()
      }
      data.response.data = await record.apiData(api)
      next()
    } catch (error) {
      console.error('insert error', error)
      api.log(error, 'error')
      next(error)
    }
  }
}

/**
 * @param {{modelName: String}} form
 * @returns {Function}
 */
function generateEditAction (form) {
  return async function (api, data, next) {
    try {
      let record = await form.retrieveRecord(api, data)
      await record.apiUpdate(data.params)
      await record.save()
      data.response.data = await record.apiData(api)
      next()
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

/**
 * @param {{modelName: String}} form
 * @returns {Function}
 */
function generateViewAction (form) {
  return async function (api, data, next) {
    try {
      let record = await form.retrieveRecord(api, data)
      data.response.data = await record.apiData(api)
      next()
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

/**
 * @param {{modelName: String}} form
 * @returns {Function}
 */
function generateDeleteAction (form) {
  return async function (api, data, next) {
    try {
      let record = await form.retrieveRecord(api, data)
      await record.destroy()
      next()
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

function generateListAction (form) {
  return async function (api, data, next) {
    try {
      let query = await form.prepareQuery(api, data)

      // fetch the results
      let result = await api.models[ form.modelName ].findAndCountAll(query)

      // prepare the output
      data.response.data = await Promise.all(result.rows.map(async (model) => model.apiData(api)))
      data.response.count = result.count

      next()
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

function generateExportAction (form) {
  return async function (api, data, next) {
    try {
      let outputType = data.params.outputType

      let query = await form.prepareQuery(api, data)

      api.tasks.enqueue('form:export', {
        query,
        outputType,
        user: data.session.user,
        formName: form.modelName
      }, 'low', (error, success) => {
        if (error) return next(error)
        data.response.success = success
        next()
      })
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

function generateFormActions (form) {
  const actions = {}

  if (!form || !form.modelName) return actions

  let insertInputs = {}
  let editInputs = {
    id: { required: true }
  }
  let listInputs = _.extend({
    user: {},
    limit: { required: false, default: 20 },
    offset: { required: false, default: 0 }
  }, form.listInputs || {})

  let exportInputs = _.extend({}, listInputs, {
    outputType: {
      required: true,
      validator: (param) => {
        if (param !== 'csv' || param !== 'zip') {
          return 'Invalid output type'
        }<commit_msg>Fix validation of form export action<commit_after>const _ = require('lodash')

/**
 * @param {{modelName: String}} form
 * @returns {Function}
 */
function generateInsertAction (form) {
  return async function (api, data, next) {
    try {
      let record = await api.models[ form.modelName ].build({})
      if ((!data.session.user.isAdmin && !api.forms.isModerator(data.session.user, form.modelName)) || !data.params.user) {
        data.params.user = data.session.userId
      }
      record = await record.apiUpdate(data.params)
      const hash = record.calculateHash()
      api.log('looking for %s with hash %s', 'info', form.modelName, hash)
      const existing = await api.models[ form.modelName ].findOne({ where: { hash: hash } })
      if (existing) {
        api.log('found %s with hash %s, updating', 'info', form.modelName, hash)
        data.response.existing = true
        await existing.apiUpdate(data.params)
        record = await existing.save()
      } else {
        api.log('not found %s with hash %s, creating', 'info', form.modelName, hash)
        record = await record.save()
      }
      data.response.data = await record.apiData(api)
      next()
    } catch (error) {
      console.error('insert error', error)
      api.log(error, 'error')
      next(error)
    }
  }
}

/**
 * @param {{modelName: String}} form
 * @returns {Function}
 */
function generateEditAction (form) {
  return async function (api, data, next) {
    try {
      let record = await form.retrieveRecord(api, data)
      await record.apiUpdate(data.params)
      await record.save()
      data.response.data = await record.apiData(api)
      next()
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

/**
 * @param {{modelName: String}} form
 * @returns {Function}
 */
function generateViewAction (form) {
  return async function (api, data, next) {
    try {
      let record = await form.retrieveRecord(api, data)
      data.response.data = await record.apiData(api)
      next()
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

/**
 * @param {{modelName: String}} form
 * @returns {Function}
 */
function generateDeleteAction (form) {
  return async function (api, data, next) {
    try {
      let record = await form.retrieveRecord(api, data)
      await record.destroy()
      next()
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

function generateListAction (form) {
  return async function (api, data, next) {
    try {
      let query = await form.prepareQuery(api, data)

      // fetch the results
      let result = await api.models[ form.modelName ].findAndCountAll(query)

      // prepare the output
      data.response.data = await Promise.all(result.rows.map(async (model) => model.apiData(api)))
      data.response.count = result.count

      next()
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

function generateExportAction (form) {
  return async function (api, data, next) {
    try {
      let outputType = data.params.outputType

      let query = await form.prepareQuery(api, data)

      api.tasks.enqueue('form:export', {
        query,
        outputType,
        user: data.session.user,
        formName: form.modelName
      }, 'low', (error, success) => {
        if (error) return next(error)
        data.response.success = success
        next()
      })
    } catch (error) {
      api.log(error, 'error')
      next(error)
    }
  }
}

function generateFormActions (form) {
  const actions = {}

  if (!form || !form.modelName) return actions

  let insertInputs = {}
  let editInputs = {
    id: { required: true }
  }
  let listInputs = _.extend({
    user: {},
    limit: { required: false, default: 20 },
    offset: { required: false, default: 0 }
  }, form.listInputs || {})

  let exportInputs = _.extend({}, listInputs, {
    outputType: {
      required: true,
      validator: (param) => {
        if (param !== 'csv' && param !== 'zip') {
          return 'Invalid output type'
        }
        return true
{'fraction_non_alphanumeric': 0.1404583895085182, 'fraction_numerical': 0.0007353842382644932, 'mean_word_length': 2.5202761000862814, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '3933261', 'n_tokens_mistral': 2532, 'n_tokens_neox': 2530, 'n_words': 651}