Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
exotic-core / src / coerce / toShape.ts
Size: Mime:
import {
  filterWhere,
  toUniverseView,
  forOwn,
  identity,
  get,
  has,
  set,
  merge,
  curry3,
  curry2,
} from '../../deps'
import { toEmpty } from '../../types'
import Typed from '../Typed'

/**
 * @NOTE this is `filterObj`
 * @desc dereferences obj, deletes property
 * @param  {string} path
 * @param  {Object} obj
 * @return {Object}
 */
const withoutProp = (path, obj) => {
  const predicate = (value, key) => key !== path
  return filterWhere(obj, predicate)
}

/**
 * @TODO we may not use flat paths the whole way through, but it reduces recursion
 *
 * @param {Object} data convert primitives to their correct type
 * @return {Object} autofixed data
 */
const toFlatAutoCoercedPrimitives = data => {
  const primitives = [Typed(Boolean), Typed(Number), Typed(String)]
  const find = (value, path) => {
    return primitives.find(Type => Type.is(value, path)) || { coerce: identity }
  }

  const flat = toUniverseView(data, true)

  // @TODO for history, ON THE ACTUAL OBJECT
  // defineFinal(flat, 'original', original)

  forOwn(flat, (value, path) => {
    // which primitive wants this one
    const Type = find(value, path)

    // upgrade it
    flat[path] = Type.coerce(value, path)
  })

  return flat
}

const fromFlatToNested = flat => {
  const target = {}
  forOwn(flat, (value, path) => {
    set(target, path, value)
  })
  return target
}

const thereAndFlatAgain = data => {
  console.log('thereAndFlatAgain')
  const defaulted = toEmpty(data)
  const flattened = toFlatAutoCoercedPrimitives(data)
  const nested = fromFlatToNested(flattened)
  return nested
}

/**
 * @NOTE @TODO handle mapping of paths IN SCHEMA OR MAP
 *
 * @param {Object} schema type definitions for data
 * @param {Object<string, string>} pathMap paths to remap & lift
 * @return {Object} lifted & merged
 *
 * @see lift
 */
function mapDataWith(schema, pathMap, data) {
  const target = {}
  const simple = lift(data, 'children')

  // value, key, obj
  forOwn(pathMap, (sourcePath, destinationPath) => {
    // when we have this path in our data
    if (has(simple, sourcePath)) {
      // then set it on our target
      const value = get(simple, sourcePath)
      set(target, destinationPath, value)
    } else {
      // @TODO otherwise, default, or...
    }
  })
}

/**
 * @param {Object} data object to lift on
 * @param {String|Array<string>} property paths
 * @return {Object} lifted & merged
 */
function lift(data, property) {
  const value = get(data, property)
  if (!value) {return data}

  const merged = merge(data, value, { clone: true })
  const selected = withoutProp(property, merged)
  return selected
}

const liftCurried = curry2(lift)
const mapDataWithCurried = curry3(mapDataWith)
const withoutPropCurried = curry2(withoutProp)

export { lift, mapDataWith, withoutProp, thereAndFlatAgain }