All files / module/actions saveAction.js

0% Statements 0/38
0% Branches 0/31
0% Functions 0/4
0% Lines 0/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94                                                                                                                                                                                           
import { diff } from 'deep-object-diff'
import { processResponseData } from '../helpers/processResponseData'
import { getExpectedResponse } from '../helpers/getExpectedResponse'
import { saveOptions as applySaveOptions } from './options/saveOptions'
import { deref, hasOwn } from '../../shared/utils'
 
/**
 * Update an existing resource
 *
 * @param {ResourcefulApi} api
 * @param {Boolean} isCollection
 * @param {String} moduleName
 * @param {Object} defaultQuery
 */
export function saveAction (api, isCollection, moduleName, defaultQuery = {}) {
  return new Proxy(() => {}, {
    apply (target, thisArg, [vuexFns, params]) {
      const id = (typeof params === 'object') ? params.id : params
      const options = hasOwn(params, 'options') ? params.options : null
 
      if (typeof id === 'undefined') {
        throw new Error('You must pass an object id to this action')
      }
 
      let currentItemState = null
      let initialItemState = null
 
      if (hasOwn(defaultQuery, 'group')) {
        if (isCollection) {
          currentItemState = thisArg.state[moduleName][defaultQuery.group].items[id]
          initialItemState = deref(thisArg.state[moduleName][defaultQuery.group].initial[id])
        } else {
          currentItemState = thisArg.state[moduleName][defaultQuery.group].item
          initialItemState = deref(thisArg.state[moduleName][defaultQuery.group].initial)
        }
      } else {
        if (isCollection) {
          currentItemState = thisArg.state[moduleName].items[id]
          initialItemState = deref(thisArg.state[moduleName].initial[id])
        } else {
          currentItemState = thisArg.state[moduleName].item
          initialItemState = deref(thisArg.state[moduleName].initial)
        }
      }
 
      let changedItemState = diff(initialItemState, currentItemState)
 
      if (hasOwn(changedItemState, 'relationships')) {
        for (const relationship in changedItemState.relationships) {
          changedItemState.relationships[relationship] = currentItemState.relationships[relationship]
        }
      }
 
      if (options) {
        changedItemState = applySaveOptions({ currentItemState, changedItemState, options })
      }
 
      vuexFns.commit('startLoading', null)
 
      return api[moduleName].update(
        { id },
        {
          data: Object.assign(
            changedItemState, {
              id: id,
              type: currentItemState.type
            })
        }
      ).then(response => {
        const { data, status } = response
 
        if (status === 204) {
          vuexFns.commit('set', getExpectedResponse(currentItemState))
        }
 
        if (status === 200) {
          const isEmptyArray = Array.isArray(data) === true && data.length === 0
          const isEmptyObject = typeof data === 'object' && data !== null && Object.keys(data).length === 0
          const isNull = data === null
          if (isEmptyArray || isEmptyObject || isNull) {
            vuexFns.commit('set', getExpectedResponse(currentItemState))
          }
        }
 
        processResponseData(vuexFns, api, moduleName, data, 'update')
 
        vuexFns.commit('endLoading', null)
 
        return response
      })
    }
  })
}