<commit_before>{Promise} = require 'es6-promise'
_ = require 'lodash'
interpolate = require 'interpolate'
{METHODS_TO_ACTIONS} = require './collections'

makeRequestHandlers = (Actions, options) ->
  {onSuccess, onFail} = options
  onFail ?= 'FAILED'

  handlers =
    onSuccess: (response, args...) ->
      Actions[onSuccess](response.data, args...)
      response

  if options.handleError?
    handlers.onFail = (error, args...) ->
      {response} = error
      isErrorHandled = options.handleError(response, args...)

      Promise.reject(error) unless isErrorHandled

  if options.errorHandlers?
    handlers.onFail = (error, args...) ->
      {response} = error
      {errors} = response.data

      unhandledErrors = _.reject(errors, (error) ->
        if options.errorHandlers[error.code]?
          Actions[options.errorHandlers[error.code]]?(args..., error)
      )

      unless _.isEmpty(unhandledErrors)
        error.response.data.errors = unhandledErrors
        Promise.reject(error)

  handlers.onFail ?= (error, args...) ->
    {response} = error
    {status, statusMessage} = response

    Actions[onFail](status, statusMessage, args...)
    Promise.reject(error)

  handlers

resolveOption = (option, key, args...) ->
  if _.isFunction(option) and key isnt 'handleError'
    option(args...)
  else
    option

resolveAndMergeHandlerOptions = (options, makeRequestOptions, args...) ->
  resolvedAndMergedOptions = _.mapValues(options, _.partial(resolveOption, _, _, args...))
  additionalRequestOptions = _.map(makeRequestOptions, _.partial(resolveOption, _, _, args...))
  _.merge(resolvedAndMergedOptions, additionalRequestOptions...)
  resolvedAndMergedOptions

# convenient aliases
makeIdRouteData = (id) -> {id} if id?

ACTIONS =
  create:
    trigger: 'create'
    onSuccess: 'created'
  read:
    trigger: 'load'
    onSuccess: 'loaded'
  update:
    trigger: 'save'
    onSuccess: 'saved'
  'delete':
    trigger: 'delete'
    onSuccess: 'deleted'

METHODS = _.invert(METHODS_TO_ACTIONS)

connectHandler = (apiHandler, Actions, allOptions...) ->
  [objectOptions, makeRequestOptions] = _.partition(allOptions, _.isObject)
  options = _.merge({}, objectOptions...)
  {trigger} = options

  Actions[trigger].addListener 'trigger', (args...) ->
    request = resolveAndMergeHandlerOptions(options, makeRequestOptions, args...)

    handlers = makeRequestHandlers(Actions, options)

    requestConfig = _.pick(request, 'url', 'method', 'data', 'params')
    requestConfig.url ?= interpolate(options.pattern, options.route or makeIdRouteData(args...))

    requestOptions = _.merge(_.pick(request, 'delay'), handlers)

    apiHandler.send(requestConfig, requestOptions, args...)

connectAction = (action, apiHandler, Actions, allOptions...) ->
  actionOptions = _.merge(method: METHODS[action], ACTIONS[action] or {})
  connectHandler(apiHandler, Actions, actionOptions, allOptions...)

adaptHandler = (apiHandler) ->
  connectHandler: _.partial(connectHandler, apiHandler)
  connectCreate:  _.partial(connectAction, 'create', apiHandler)
  connectRead:    _.partial(connectAction, 'read', apiHandler)
  connectUpdate:  _.partial(connectAction, 'update', apiHandler)
  connectDelete:  _.partial(connectAction, 'delete', apiHandler)
  connectModify:  _.partial(connectAction, 'modify', apiHandler)

module.exports = adaptHandler
<commit_msg>adapter was doing weird things with options<commit_after>{Promise} = require 'es6-promise'
_ = require 'lodash'
interpolate = require 'interpolate'
{METHODS_TO_ACTIONS} = require './collections'

makeRequestHandlers = (Actions, options) ->
  {onSuccess, onFail} = options
  onFail ?= 'FAILED'

  handlers =
    onSuccess: (response, args...) ->
      Actions[onSuccess](response.data, args...)
      response

  if options.handleError?
    handlers.onFail = (error, args...) ->
      {response} = error
      isErrorHandled = options.handleError(response, args...)

      Promise.reject(error) unless isErrorHandled

  if options.errorHandlers?
    handlers.onFail = (error, args...) ->
      {response} = error
      {errors} = response.data

      unhandledErrors = _.reject(errors, (error) ->
        if options.errorHandlers[error.code]?
          Actions[options.errorHandlers[error.code]]?(args..., error)
      )

      unless _.isEmpty(unhandledErrors)
        error.response.data.errors = unhandledErrors
        Promise.reject(error)

  handlers.onFail ?= (error, args...) ->
    {response} = error
    {status, statusMessage} = response

    Actions[onFail](status, statusMessage, args...)
    Promise.reject(error)

  handlers

resolveOptions = (args...) ->
  (option, key) ->
    if _.isFunction(option) and key isnt 'handleError'
      console.info(args...)
      option(args...)
    else
      option

resolveAndMergeHandlerOptions = (options, makeRequestOptions, args...) ->
  resolvedAndMergedOptions = _.mapValues(options, resolveOptions(args...))
  additionalRequestOptions = _.map(makeRequestOptions, resolveOptions(args...))
  _.merge(resolvedAndMergedOptions, additionalRequestOptions...)
  resolvedAndMergedOptions

# convenient aliases
makeIdRouteData = (id) -> {id} if id?

ACTIONS =
  create:
    trigger: 'create'
    onSuccess: 'created'
  read:
    trigger: 'load'
    onSuccess: 'loaded'
  update:
    trigger: 'save'
    onSuccess: 'saved'
  'delete':
    trigger: 'delete'
    onSuccess: 'deleted'

METHODS = _.invert(METHODS_TO_ACTIONS)

connectHandler = (apiHandler, Actions, allOptions...) ->
  [objectOptions, makeRequestOptions] = _.partition(allOptions, _.isObjectLike)
  options = _.merge({}, objectOptions...)
  {trigger} = options

  Actions[trigger].addListener 'trigger', (args...) ->
    request = resolveAndMergeHandlerOptions(options, makeRequestOptions, args...)

    handlers = makeRequestHandlers(Actions, options)

    requestConfig = _.pick(request, 'url', 'method', 'data', 'params')
    requestConfig.url ?= interpolate(options.pattern, options.route or makeIdRouteData(args...))

    requestOptions = _.merge(_.pick(request, 'delay'), handlers)

    apiHandler.send(requestConfig, requestOptions, args...)

connectAction = (action, apiHandler, Actions, allOptions...) ->
  actionOptions = _.merge(method: METHODS[action], ACTIONS[action] or {})
  connectHandler(apiHandler, Actions, actionOptions, allOptions...)

adaptHandler = (apiHandler) ->
  connectHandler: _.partial(connectHandler, apiHandler)
  connectCreate:  _.partial(connectAction, 'create', apiHandler)
  connectRead:    _.partial(connectAction, 'read', apiHandler)
  connectUpdate:  _.partial(connectAction, 'update', apiHandler)
  connectDelete:  _.partial(connectAction, 'delete', apiHandler)
  connectModify:  _.partial(connectAction, 'modify', apiHandler)

module.exports = adaptHandler

{'fraction_non_alphanumeric': 0.13716226192233869, 'fraction_numerical': 0.0002952901225454009, 'mean_word_length': 3.930131004366812, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 30, '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': '5661107', 'n_tokens_mistral': 2012, 'n_tokens_neox': 1971, 'n_words': 431}