erikras/redux-form

View on GitHub
src/deleteInWithCleanUp.js

Summary

Maintainability
A
0 mins
Test Coverage
// @flow
import { toPath } from 'lodash'
import type { Structure } from './types'

type ShouldDelete<SDM, SDL> = (
  structure: Structure<SDM, SDL>
) => (state: SDM | SDL, path: string) => boolean

type DeleteInWithCleanup<DIM, DIL> = (DIM | DIL, string) => DIM | DIL

function createDeleteInWithCleanUp<DIM, DIL>(structure: Structure<DIM, DIL>) {
  const shouldDeleteDefault: ShouldDelete<DIM, DIL> = structure => (
    state,
    path
  ) => structure.getIn(state, path) !== undefined

  const { deepEqual, empty, getIn, deleteIn, setIn } = structure

  return (
    shouldDelete: ShouldDelete<DIM, DIL> = shouldDeleteDefault
  ): DeleteInWithCleanup<DIM, DIL> => {
    const deleteInWithCleanUp = (state: DIM | DIL, path: string): DIM | DIL => {
      if (path[path.length - 1] === ']') {
        // array path
        const pathTokens = toPath(path)
        pathTokens.pop()
        const parent = getIn(state, pathTokens.join('.'))
        return parent ? setIn(state, path) : state
      }

      let result: DIM | DIL = state

      if (shouldDelete(structure)(state, path)) {
        result = deleteIn(state, path)
      }

      const dotIndex = path.lastIndexOf('.')
      if (dotIndex > 0) {
        const parentPath = path.substring(0, dotIndex)
        if (parentPath[parentPath.length - 1] !== ']') {
          const parent = getIn(result, parentPath)
          if (deepEqual(parent, empty)) {
            return deleteInWithCleanUp(result, parentPath)
          }
        }
      }
      return result
    }

    return deleteInWithCleanUp
  }
}

export default createDeleteInWithCleanUp