Skip to content

Instantly share code, notes, and snippets.

@rjhilgefort
Created October 20, 2019 19:47
Show Gist options
  • Save rjhilgefort/261bb26bfc6d3a5074dc0bbeeea4e3fc to your computer and use it in GitHub Desktop.
Save rjhilgefort/261bb26bfc6d3a5074dc0bbeeea4e3fc to your computer and use it in GitHub Desktop.
import { isArray, curry, isPlainObject, isFunction, isNil } from 'lodash/fp'
import { mapValuesWithKey } from './mapValuesWithKey'
import { mapWithKey } from './mapWithKey'
const iteratee = (spec, full) => (val, key) => fn(spec[key], val, full)
const fn = (spec, data, full) => {
if (isNil(spec)) return data
if (isFunction(spec)) return spec(full)
if (isPlainObject(spec)) return mapValuesWithKey(iteratee(spec, full), data)
if (isArray(spec)) return mapWithKey(iteratee(spec, full), data)
return data
}
/**
* @name evolveSpec
*
* @description
* Like `evolve`, but useful when you need to modify a prop on an object/array,
* but need the entire object/array context (instead of just the prop value).
*
* @see ramda.evolve
*
* @example
* evolveSpec(
* { name: ({ _key, name }) => `${name} (${_key})` },
* { _key: 'k_1', name: 'Some name' },
* ) // -> { _key: 'k_1', name: 'Some name (k_1)' }
*
* @signature
* { [String]: a -> Any } -> Object a -> Object b
*/
export const evolveSpec = curry((spec, data) => fn(spec, data, data))
import { evolveSpec } from './'
it.each([
['`null` spec', null, { foo: 'foo' }, { foo: 'foo' }],
[
'simple object',
{ name: ({ _key, name }) => `${name} (${_key})` },
{ _key: 'k_1', name: 'Some name' },
{ _key: 'k_1', name: 'Some name (k_1)' },
],
[
'nested object',
{ foo: { name: ({ foo: { _key, name } }) => `${name} (${_key})` } },
{ foo: { _key: 'k_1', name: 'Some name' }, bar: 5 },
{ foo: { _key: 'k_1', name: 'Some name (k_1)' }, bar: 5 },
],
[
'simple array',
[null, ([_key, name]) => `${name} (${_key})`],
['k_1', 'Some name'],
['k_1', 'Some name (k_1)'],
],
[
// Probably don't do this, but it's supported
'nested array',
[null, [null, ([, [_key, name]]) => `${name} (${_key})`]],
[5, ['k_1', 'Some name'], 6],
[5, ['k_1', 'Some name (k_1)'], 6],
],
])('%p', (_label, spec, data, expected) => {
expect(evolveSpec(spec, data)).toEqual(expected)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment