<commit_before>import { RequestHandler } from 'express'
import validate from './validate'
import clone from '../git/clone'
import * as path from 'path'
import * as fs from 'fs'
import * as db from '../../data'

type Body = {
  name: string
  label: string
  repository: string
  username: string
  key: string
  dockerfile: string
  credentialsId: number
}

const handler: RequestHandler = async (req, res) => {
  const { repository, name, key, label, dockerfile, username, credentialsId = 0 } = req.body as Body

  const id = await getNextId()
  const body = { id, repository, name, key, label, dockerfile, username, credentialsId }

  if (credentialsId > 0) {
    body.username = ''
    body.key = ''
  }

  const errors = validate(body)

  if (errors.length) {
    const message = errors.join(', ')
    res.status(400).json({ message })
    return
  }

  try {
    await db.applications()
      .insert(body)

    const app = { ...body }
    delete app.key

    res.json(app)
    clone(app)
  } catch (ex) {
    res.status(500)
    res.json({ message: ex.message || ex })
  }
}

function getNextId() {
  const dirs = new Promise<number>((resolve, reject) => {
    const repoPath = path.resolve(__dirname, '../../..', 'repositories')
    fs.readdir(repoPath, (err, files) => {
      if (err) {
        return reject(err)
      }

      const ids = files
        .map(file => Number(file))
        .filter(id => !isNaN(id))

      const max = Math.max(...ids)

      if (max < 1) {
        resolve(1)
        return
      }

      resolve(max + 1)
    })
  })<commit_msg>Bugfix: Include application rows when determining next id<commit_after>import { RequestHandler } from 'express'
import validate from './validate'
import clone from '../git/clone'
import * as path from 'path'
import * as fs from 'fs'
import * as db from '../../data'

type Body = {
  name: string
  label: string
  repository: string
  username: string
  key: string
  dockerfile: string
  credentialsId: number
}

const handler: RequestHandler = async (req, res) => {
  const { repository, name, key, label, dockerfile, username, credentialsId = 0 } = req.body as Body

  const id = await getNextId()
  const body = { id, repository, name, key, label, dockerfile, username, credentialsId }

  if (credentialsId > 0) {
    body.username = ''
    body.key = ''
  }

  const errors = validate(body)

  if (errors.length) {
    const message = errors.join(', ')
    res.status(400).json({ message })
    return
  }

  try {
    await db.applications()
      .insert(body)

    const app = { ...body }
    delete app.key

    res.json(app)
    clone(app)
  } catch (ex) {
    res.status(500)
    res.json({ message: ex.message || ex })
  }
}

async function getNextId() {
  const apps: Array<{ id: number }> = await db.applications().select('id')
  const dirs = new Promise<number>((resolve, reject) => {
    const repoPath = path.resolve(__dirname, '../../..', 'repositories')
    fs.readdir(repoPath, (err, files) => {
      if (err) {
        return reject(err)
      }

      const ids = files
        .map(file => Number(file))
        .filter(id => !isNaN(id))

      const max = Math.max(...ids, ...apps.map(app => app.id))

      if (max < 1) {
        resolve(1)
        return
      }

      resolve(max + 1)
    })
  })
{'fraction_non_alphanumeric': 0.14740673339399454, 'fraction_numerical': 0.006672732787382469, 'mean_word_length': 2.531049250535332, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 19, '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': '2989388', 'n_tokens_mistral': 1088, 'n_tokens_neox': 1047, 'n_words': 305}