<commit_before>'use strict'

const ExecInfo = require('./ExecInfo')
const Promise = require('bluebird')
const _ = require('lodash')
const { execHook, logError, possiblyCallback, resultsTransform } =
        require('./utils')

// Implements command implementation functions binding and wrapping.
class CommandBinder {

  constructor (server, transport, userName) {
    this.server = server
    this.transport = transport
    this.userName = userName
  }

  commandWatcher (id, name) {
    this.server.runningCommands++
    return Promise.resolve().disposer(() => {
      this.server.runningCommands--
      if (this.transport.closed && this.server.runningCommands <= 0) {
        this.server.emit('commandsFinished')
      }
    })
  }

  makeCommand (name, fn) {
    let { validator } = this.server
    let beforeHook = this.server.hooks[`${name}Before`]
    let afterHook = this.server.hooks[`${name}After`]
    return (args, info) => {
      let execInfo = new ExecInfo()
      _.assign(execInfo, { server: this.server, userName: this.userName })
      _.assign(execInfo, info)
      _.assign(execInfo, validator.splitArguments(name, args))
      return Promise.using(
        this.commandWatcher(info.id, name),
        () => validator.checkArguments(name, ...execInfo.args)
          .then(() => {
            if (beforeHook && !execInfo.bypassHooks) {
              return execHook(beforeHook, execInfo)
            } else {
              return Promise.resolve()
            } })
          .then(results => {
            if (results && results.length) { return results }
            return fn(...execInfo.args, execInfo)
              .then(result => { execInfo.results = [result] },
                    error => { execInfo.error = error })
              .then(() => {
                if (afterHook && !execInfo.bypassHooks) {
                  return execHook(afterHook, execInfo)
                } else {
                  return Promise.resolve()
                } })
              .then(results => {
                if (results && results.length) {
                  return results
                } else if (execInfo.error) {
                  return Promise.reject(execInfo.error)
                } else {
                  return execInfo.results
                }
              })
          }))
        .catch(error => logError(error))
    }
  }

  bindDisconnect (id, fn) {
    let server = this.server
    let hook = this.server.hooks.onDisconnect
    this.transport.bindHandler(id, 'disconnect', () => {
      return Promise.using(
        this.commandWatcher(id, 'disconnect'),
        () => fn(id).then(() => execHook(hook, server, id)).catchReturn())
    })
  }

  bindCommand (id, name, fn) {
    let cmd = this.makeCommand(name, fn)
    let useErrorObjects = this.server.useRawErrorObjects
    let info = {id}
    return this.transport.bindHandler(id, name, function () {
      let [args, cb] = possiblyCallback(arguments)
      let ack = resultsTransform(useErrorObjects, cb)
      return cmd(args, info).asCallback(ack, { spread: true })
    })
  }

}

module.exports = CommandBinder<commit_msg>fix: add disconnection errors logging<commit_after>'use strict'

const ExecInfo = require('./ExecInfo')
const Promise = require('bluebird')
const _ = require('lodash')
const { execHook, logError, possiblyCallback, resultsTransform } =
        require('./utils')

// Implements command functions binding and wrapping.
class CommandBinder {

  constructor (server, transport, userName) {
    this.server = server
    this.transport = transport
    this.userName = userName
  }

  commandWatcher (id, name) {
    this.server.runningCommands++
    return Promise.resolve().disposer(() => {
      this.server.runningCommands--
      if (this.transport.closed && this.server.runningCommands <= 0) {
        this.server.emit('commandsFinished')
      }
    })
  }

  makeCommand (name, fn) {
    let { validator } = this.server
    let beforeHook = this.server.hooks[`${name}Before`]
    let afterHook = this.server.hooks[`${name}After`]
    return (args, info) => {
      let execInfo = new ExecInfo()
      _.assign(execInfo, { server: this.server, userName: this.userName })
      _.assign(execInfo, info)
      _.assign(execInfo, validator.splitArguments(name, args))
      return Promise.using(
        this.commandWatcher(info.id, name),
        () => validator.checkArguments(name, ...execInfo.args)
          .then(() => {
            if (beforeHook && !execInfo.bypassHooks) {
              return execHook(beforeHook, execInfo)
            } else {
              return Promise.resolve()
            } })
          .then(results => {
            if (results && results.length) { return results }
            return fn(...execInfo.args, execInfo)
              .then(result => { execInfo.results = [result] },
                    error => { execInfo.error = error })
              .then(() => {
                if (afterHook && !execInfo.bypassHooks) {
                  return execHook(afterHook, execInfo)
                } else {
                  return Promise.resolve()
                } })
              .then(results => {
                if (results && results.length) {
                  return results
                } else if (execInfo.error) {
                  return Promise.reject(execInfo.error)
                } else {
                  return execInfo.results
                }
              })
          }))
        .catch(error => logError(error))
    }
  }

  bindDisconnect (id, fn) {
    let server = this.server
    let hook = this.server.hooks.onDisconnect
    this.transport.bindHandler(id, 'disconnect', () => {
      return Promise.using(
        this.commandWatcher(id, 'disconnect'),
        () => fn(id)
          .catch(error => logError(error))
          .catchReturn()
          .then(() => execHook(hook, server, id))
          .catch(error => logError(error))
          .catchReturn())
    })
  }

  bindCommand (id, name, fn) {
    let cmd = this.makeCommand(name, fn)
    let useErrorObjects = this.server.useRawErrorObjects
    let info = {id}
    return this.transport.bindHandler(id, name, function () {
      let [args, cb] = possiblyCallback(arguments)
      let ack = resultsTransform(useErrorObjects, cb)
      return cmd(args, info).asCallback(ack, { spread: true })
    })
  }

}

module.exports = CommandBinder
{'fraction_non_alphanumeric': 0.1291131306800376, 'fraction_numerical': 0.00031338138514572234, 'mean_word_length': 2.0805984555984556, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 31, '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': '1737418', 'n_tokens_mistral': 1804, 'n_tokens_neox': 1767, 'n_words': 379}