Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#1.20.0
- feat: add transformKeysToSnake

#1.19.1
- fix: fix isPlainObject to check that the constructor is an object

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Currently supported utils:
- `snakeCase` - convert camel case and string/dash separated strings to snake case
- `sum` - calculate sum of array items
- `sumBy` - calculate sum of array items using iteratee function or string shortcut
- `transformKeysToSnake` - transform every object key to snake case
- `union` - Returns the union of the given arrays
- `uniqBy` - get unique values of array by the iteratee function or property path
- `uniqWith` - Returns a new array with unique values, using a comparator function
Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function shuffle<T> (array: Array<T>): Array<T>
export function snakeCase (str: string): string
export function sum (values: Array<string>): number
export function sumBy (values: Array, iteratee: Function | string): number
export function transformKeysToSnake (obj: Object) : Object
export function union (...arrays: Array[]): Array
export function uniqBy (array: Array, iteratee: Function | string): Array
export function uniqWith (array: Array, comparator: Function): Array
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const shuffle = require('./src/shuffle')
const snakeCase = require('./src/snakeCase')
const sum = require('./src/sum')
const sumBy = require('./src/sumBy')
const transformKeysToSnake = require('./src/transformKeysToSnake')
const union = require('./src/union')
const uniqBy = require('./src/uniqBy')
const uniqWith = require('./src/uniqWith')
Expand Down Expand Up @@ -93,6 +94,7 @@ module.exports = {
snakeCase,
sum,
sumBy,
transformKeysToSnake,
union,
uniqBy,
uniqWith,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bitfinexcom/lib-js-util-base",
"version": "1.19.1",
"version": "1.20.0",
"description": "general utils",
"main": "index.js",
"scripts": {
Expand Down
29 changes: 29 additions & 0 deletions src/transformKeysToSnake.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict'

const isPlainObject = require('./isPlainObject')
const snakeCase = require('./snakeCase')

/**
* Transform object keys to snake case
* e.g. { fooBar: 1 } => { foo_bar: 1 }
* @param {Object} obj
* @returns {Object}
*/
const transformKeysToSnakeCase = (obj) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we have a deep/recursive flag to inform that nested objects should also be applied?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you propose, the following?

const transformKeysToSnakeCase = (obj, { recursive } = {}) => {
  if (Array.isArray(obj)) {
    return obj.map(item => transformKeysToSnakeCase(item))
  }

  if (!isPlainObject(obj)) {
    return obj
  }

  return Object.fromEntries(
    Object.entries(obj).map(([k, v]) => [
      snakeCase(k),
      recursive ? transformKeysToSnakeCase(v) : v
    ])
  )
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I give the consumer more control

if (Array.isArray(obj)) {
return obj.map(item => transformKeysToSnakeCase(item))
}

if (!isPlainObject(obj)) {
return obj
}

return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [
snakeCase(k),
transformKeysToSnakeCase(v)
])
)
}

module.exports = transformKeysToSnakeCase
51 changes: 51 additions & 0 deletions test/transformKeystoSnake.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict'

/* eslint-env mocha */

const assert = require('assert')
const { transformKeysToSnake } = require('../index')
const { itEach } = require('mocha-it-each')

describe('transformKeysToSnake', () => {
itEach('should return input when it is not an object', [new Date(), null, false], (input) => {
assert.equal(transformKeysToSnake(input), input)
})

it('should return input with snake case props recursively', () => {
const input = {
camelProp: 'true',
nestedProp: {
first_name: 'john',
lastName: 'doe',
tags: ['keepCamel']
},
someObjs: [
{ someProp: 'value' },
{ foo_bar: 'value', foo: 'value' }
]
}
const output = {
camel_prop: 'true',
nested_prop: {
first_name: 'john',
last_name: 'doe',
tags: ['keepCamel']
},
some_objs: [
{ some_prop: 'value' },
{ foo_bar: 'value', foo: 'value' }
]
}
assert.deepEqual(transformKeysToSnake(input), output)
})

it('should work with', () => {
const input = {
mixedArray: [123, { someKey: 'value' }, [{ nestedArrayItem: 'test' }]]
}
const output = {
mixed_array: [123, { some_key: 'value' }, [{ nested_array_item: 'test' }]]
}
assert.deepEqual(transformKeysToSnake(input), output)
})
})