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    
@skava/modules-modules / deps / indexBy.ts
Size: Mime:
/**
 * @fileoverview @todo
 *
 * @NOTE ramda's curry errors - enforces strict arity
 */
import { curry } from 'chain-able-boost'
import { indexBy, prop } from 'ramda'

// @NOTE this was a could be this way
// const key = Object.keys(keyVal)[0]
// const property = keyVal[key]
// {label: 'value'}
interface LabelValue {
  label?: any
  value?: any
  [key: string]: any
  [key: number]: any
}
type ArrayOfLabelValue = LabelValue[]
type LabelValueKeyProperty<
  Key extends string | number,
  Property extends string | number
> = LabelValue & { [key in Key]?: any } & { [key in Property]?: any }

function indexByKeyVal<
  Key extends keyof LabelValue = any,
  Property extends keyof LabelValue = any
>(key: Key, property: Property, list: ArrayOfLabelValue[]) {
  const indexed: LabelValueKeyProperty<Key, Property> = {}

  list.forEach(item => {
    const atKey = item[key]
    indexed[atKey] = item[property]
  })

  return indexed
}

const indexByKeyVals = (key: string, property: string, list: any[]) => {
  const indexed = {}
  list.forEach(item => {
    const atKey = item[key]

    indexed[atKey] = indexed[atKey] || []
    indexed[atKey].push(item[property])
  })
  return indexed
}

const indexByIdentity = indexBy(prop('identifier'))

interface ForEach<ValueType = any> extends Function {
  (
    callbackfn: (value: ValueType, index: number, array: ValueType[]) => void,
    thisArg?: any
  ): void
}
interface Map<ValueType = any, ReturnType = any> extends Function {
  (
    callbackfn: (value: ValueType, index: number, array: ValueType[]) => void,
    thisArg?: any
  ): ReturnType
}

interface Indexed<Value> {
  array: Array<Value>
  length: number
  forEach: ForEach<Value>
  map: ForEach<Value>
  [key: string]: any
  [key: number]: any
}

const indexByWithArray = <Value = any>(
  key: string,
  property: string,
  list: any[]
): Indexed<Value> => {
  const indexed = {} as any

  /**
   * @todo defineProperties?
   */
  list.forEach((item, index) => {
    const atKey = item[key]
    indexed[atKey] = item[property]

    Object.defineProperty(indexed, index, {
      enumerable: false,
      value: item,
    })
  })

  // add the original list as a hidden property to the data
  Object.defineProperty(indexed, 'array', {
    enumerable: false,
    value: list,
  })

  // array-like
  Object.defineProperty(indexed, 'length', {
    enumerable: false,
    value: list.length,
  })

  Object.defineProperty(indexed, 'forEach', {
    enumerable: false,
    value(fn: ForEach<Value>) {
      return Object.keys(indexed).forEach(name => fn(indexed[name], name))
    },
  })
  Object.defineProperty(indexed, 'map', {
    enumerable: false,
    value(fn: Map<Value>) {
      return Object.keys(indexed).map(name => fn(indexed[name], name))
    },
  })

  return indexed
}

// const curriedIndexByKeyVal = curry(3, indexByKeyVal)
// const curriedIndexByKeyVals = curry(3, indexByKeyVals)

export {
  indexByKeyVal,
  indexByKeyVals,
  indexByIdentity,
  indexByWithArray as indexBy,
}