Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: hughsk/flat
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.0.1
Choose a base ref
...
head repository: hughsk/flat
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5.0.2
Choose a head ref

Commits on Jul 13, 2017

  1. Copy the full SHA
    7dd970d View commit details
  2. Copy the full SHA
    1a06751 View commit details

Commits on Jul 23, 2017

  1. Update dependencies.

    timoxley committed Jul 23, 2017
    Copy the full SHA
    c35c195 View commit details
  2. Release 3.0.0

    timoxley committed Jul 23, 2017
    Copy the full SHA
    91211e8 View commit details

Commits on Jul 25, 2017

  1. Upgrade Node.js on CI (#58)

    sugarshin authored and timoxley committed Jul 25, 2017
    Copy the full SHA
    2859120 View commit details
  2. let unflatten iterate over sorted object keys (#44)

    * let unflatten iterate over sorted object keys
    
    * simplify key length predicate
    lipp authored and timoxley committed Jul 25, 2017
    Copy the full SHA
    c20048c View commit details
  3. Format code using standard.

    timoxley committed Jul 25, 2017
    Copy the full SHA
    36d0f98 View commit details
  4. Copy the full SHA
    83f49fe View commit details
  5. Release 4.0.0

    timoxley committed Jul 25, 2017
    Copy the full SHA
    b6633d0 View commit details

Commits on Jun 20, 2018

  1. feat: add command line interface

    zeke committed Jun 20, 2018
    Copy the full SHA
    6fb1bf6 View commit details

Commits on Jul 2, 2018

  1. Copy the full SHA
    eab457c View commit details
  2. Merge branch 'zeke-add-cli'

    * zeke-add-cli:
      Support cli file.json in addition to cli ./file.json
      feat: add command line interface
    timoxley committed Jul 2, 2018
    Copy the full SHA
    b4e89b6 View commit details
  3. Update dependencies.

    timoxley committed Jul 2, 2018
    Copy the full SHA
    059d970 View commit details
  4. Release 4.1.0

    timoxley committed Jul 2, 2018
    Copy the full SHA
    32432dd View commit details

Commits on Oct 22, 2019

  1. Copy the full SHA
    2b99901 View commit details
  2. Fix issue in overwrite example code

    Example now actually works as documented.
    silverwind authored and timoxley committed Oct 22, 2019
    Copy the full SHA
    3b3cd0a View commit details
  3. Fix losing order of keys after unflatten an object

    commit 6c46e143953460bfc3e00b8696803f02b71849df
    Author: Lench Volodymyr <volodymyr.lench@binary-studio.com>
    Date:   Tue May 28 19:39:37 2019 +0300
    
        hotfix: remove console.lo
    
    commit 0ecbcc026987f8d45fc112f51d3c3820978a947d
    Author: Lench Volodymyr <volodymyr.lench@binary-studio.com>
    Date:   Tue May 28 19:37:14 2019 +0300
    
        unflatten: fix removing empty objects
    
    commit 6f538e98360be5e280e434aa33957130b21b10d0
    Author: Lench Volodymyr <volodymyr.lench@binary-studio.com>
    Date:   Tue May 28 16:22:46 2019 +0300
    
        unflatten: fix losing an order of keys
    lenchvolodymyr authored and timoxley committed Oct 22, 2019
    Copy the full SHA
    2ac1b4d View commit details
  4. Update dependencies.

    timoxley committed Oct 22, 2019
    Copy the full SHA
    74f83ab View commit details
  5. Copy the full SHA
    a3909c5 View commit details
  6. Copy the full SHA
    f9f0788 View commit details
  7. Exit 1 on usage.

    timoxley committed Oct 22, 2019
    Copy the full SHA
    369b206 View commit details
  8. Copy the full SHA
    fdfd095 View commit details
  9. Copy the full SHA
    533ac93 View commit details
  10. Add tests around cli. Only show usage if on TTY & no argument, allow …

    …eaccess error if file not readable.
    timoxley committed Oct 22, 2019
    Copy the full SHA
    beaea9d View commit details
  11. Release 5.0.0

    timoxley committed Oct 22, 2019
    Copy the full SHA
    38239cc View commit details
  12. Copy the full SHA
    6e95c43 View commit details

Commits on Aug 6, 2020

  1. Copy the full SHA
    e8fb281 View commit details
  2. Fix prototype pollution on unflatten

    Fixes #105.
    MatthiasKunnen authored and timoxley committed Aug 6, 2020
    Copy the full SHA
    20ef0ef View commit details
  3. Bump acorn from 7.1.0 to 7.4.0

    Bumps [acorn](https://github.com/acornjs/acorn) from 7.1.0 to 7.4.0.
    - [Release notes](https://github.com/acornjs/acorn/releases)
    - [Commits](acornjs/acorn@7.1.0...7.4.0)
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored and timoxley committed Aug 6, 2020
    Copy the full SHA
    a61a554 View commit details
  4. Bump lodash from 4.17.15 to 4.17.19

    Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
    - [Release notes](https://github.com/lodash/lodash/releases)
    - [Commits](lodash/lodash@4.17.15...4.17.19)
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored and timoxley committed Aug 6, 2020
    Copy the full SHA
    2eea6d3 View commit details
  5. drop dependencies

    43081j authored and timoxley committed Aug 6, 2020
    Copy the full SHA
    779816e View commit details
  6. use standard formatting

    43081j authored and timoxley committed Aug 6, 2020
    Copy the full SHA
    54cc7ad View commit details
  7. Release 5.0.1

    timoxley committed Aug 6, 2020
    Copy the full SHA
    f25d3a1 View commit details
  8. Avoid arrow function syntax.

    andornaut authored and timoxley committed Aug 6, 2020
    Copy the full SHA
    0189cb1 View commit details
  9. Test against node 14 in CI.

    timoxley committed Aug 6, 2020
    Copy the full SHA
    e52185d View commit details
  10. Copy the full SHA
    fdb79d5 View commit details
  11. Release 5.0.2

    timoxley committed Aug 6, 2020
    Copy the full SHA
    e5ffd66 View commit details
Showing with 3,297 additions and 216 deletions.
  1. +1 −0 .gitignore
  2. +6 −2 .travis.yml
  3. +77 −1 README.md
  4. +42 −0 cli.js
  5. +91 −38 index.js
  6. +2,722 −0 package-lock.json
  7. +6 −6 package.json
  8. +352 −169 test/test.js
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
.idea
8 changes: 6 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
language: node_js
node_js:
- 0.6
- 0.8
- "6"
- "7"
- "8"
- "10"
- "12"
- "14"
78 changes: 77 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -122,7 +122,7 @@ When enabled, existing keys in the unflattened object may be overwritten if they
```javascript
unflatten({
'TRAVIS': 'true',
'TRAVIS_DIR': '/home/travis/build/kvz/environmental'
'TRAVIS.DIR': '/home/travis/build/kvz/environmental'
}, { overwrite: true })

// TRAVIS: {
@@ -158,3 +158,79 @@ flatten({
// 'key3.a': { b: { c: 2 } }
// }
```

### transformKey

Transform each part of a flat key before and after flattening.

```javascript
var flatten = require('flat')
var unflatten = require('flat').unflatten

flatten({
key1: {
keyA: 'valueI'
},
key2: {
keyB: 'valueII'
},
key3: { a: { b: { c: 2 } } }
}, {
transformKey: function(key){
return '__' + key + '__';
}
})

// {
// '__key1__.__keyA__': 'valueI',
// '__key2__.__keyB__': 'valueII',
// '__key3__.__a__.__b__.__c__': 2
// }

unflatten({
'__key1__.__keyA__': 'valueI',
'__key2__.__keyB__': 'valueII',
'__key3__.__a__.__b__.__c__': 2
}, {
transformKey: function(key){
return key.substring(2, key.length - 2)
}
})

// {
// key1: {
// keyA: 'valueI'
// },
// key2: {
// keyB: 'valueII'
// },
// key3: { a: { b: { c: 2 } } }
// }
```

## Command Line Usage

`flat` is also available as a command line tool. You can run it with
[`npx`](https://ghub.io/npx):

```sh
npx flat foo.json
```

Or install the `flat` command globally:

```sh
npm i -g flat && flat foo.json
```

Accepts a filename as an argument:

```sh
flat foo.json
```

Also accepts JSON on stdin:

```sh
cat foo.json | flat
```
42 changes: 42 additions & 0 deletions cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env node

const fs = require('fs')
const path = require('path')
const readline = require('readline')

const flat = require('./index')

const filepath = process.argv.slice(2)[0]
if (filepath) {
// Read from file
const file = path.resolve(process.cwd(), filepath)
fs.accessSync(file, fs.constants.R_OK) // allow to throw if not readable
out(require(file))
} else if (process.stdin.isTTY) {
usage(0)
} else {
// Read from newline-delimited STDIN
const lines = []
readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
})
.on('line', line => lines.push(line))
.on('close', () => out(JSON.parse(lines.join('\n'))))
}

function out (data) {
process.stdout.write(JSON.stringify(flat(data), null, 2))
}

function usage (code) {
console.log(`
Usage:
flat foo.json
cat foo.json | flat
`)

process.exit(code || 0)
}
129 changes: 91 additions & 38 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
var isBuffer = require('is-buffer')

var flat = module.exports = flatten
module.exports = flatten
flatten.flatten = flatten
flatten.unflatten = unflatten

function flatten(target, opts) {
function isBuffer (obj) {
return obj &&
obj.constructor &&
(typeof obj.constructor.isBuffer === 'function') &&
obj.constructor.isBuffer(obj)
}

function keyIdentity (key) {
return key
}

function flatten (target, opts) {
opts = opts || {}

var delimiter = opts.delimiter || '.'
var maxDepth = opts.maxDepth
var output = {}

function step(object, prev, currentDepth) {
currentDepth = currentDepth ? currentDepth : 1
Object.keys(object).forEach(function(key) {
var value = object[key]
var isarray = opts.safe && Array.isArray(value)
var type = Object.prototype.toString.call(value)
var isbuffer = isBuffer(value)
var isobject = (
type === "[object Object]" ||
type === "[object Array]"
const delimiter = opts.delimiter || '.'
const maxDepth = opts.maxDepth
const transformKey = opts.transformKey || keyIdentity
const output = {}

function step (object, prev, currentDepth) {
currentDepth = currentDepth || 1
Object.keys(object).forEach(function (key) {
const value = object[key]
const isarray = opts.safe && Array.isArray(value)
const type = Object.prototype.toString.call(value)
const isbuffer = isBuffer(value)
const isobject = (
type === '[object Object]' ||
type === '[object Array]'
)

var newKey = prev
? prev + delimiter + key
: key
const newKey = prev
? prev + delimiter + transformKey(key)
: transformKey(key)

if (!isarray && !isbuffer && isobject && Object.keys(value).length &&
(!opts.maxDepth || currentDepth < maxDepth)) {
@@ -41,41 +51,84 @@ function flatten(target, opts) {
return output
}

function unflatten(target, opts) {
function unflatten (target, opts) {
opts = opts || {}

var delimiter = opts.delimiter || '.'
var overwrite = opts.overwrite || false
var result = {}
const delimiter = opts.delimiter || '.'
const overwrite = opts.overwrite || false
const transformKey = opts.transformKey || keyIdentity
const result = {}

var isbuffer = isBuffer(target)
const isbuffer = isBuffer(target)
if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') {
return target
}

// safely ensure that the key is
// an integer.
function getkey(key) {
var parsedKey = Number(key)
function getkey (key) {
const parsedKey = Number(key)

return (
isNaN(parsedKey) ||
key.indexOf('.') !== -1
key.indexOf('.') !== -1 ||
opts.object
) ? key
: parsedKey
}

Object.keys(target).forEach(function(key) {
var split = key.split(delimiter)
var key1 = getkey(split.shift())
var key2 = getkey(split[0])
var recipient = result
function addKeys (keyPrefix, recipient, target) {
return Object.keys(target).reduce(function (result, key) {
result[keyPrefix + delimiter + key] = target[key]

return result
}, recipient)
}

function isEmpty (val) {
const type = Object.prototype.toString.call(val)
const isArray = type === '[object Array]'
const isObject = type === '[object Object]'

if (!val) {
return true
} else if (isArray) {
return !val.length
} else if (isObject) {
return !Object.keys(val).length
}
}

target = Object.keys(target).reduce(function (result, key) {
const type = Object.prototype.toString.call(target[key])
const isObject = (type === '[object Object]' || type === '[object Array]')
if (!isObject || isEmpty(target[key])) {
result[key] = target[key]
return result
} else {
return addKeys(
key,
result,
flatten(target[key], opts)
)
}
}, {})

Object.keys(target).forEach(function (key) {
const split = key.split(delimiter).map(transformKey)
let key1 = getkey(split.shift())
let key2 = getkey(split[0])
let recipient = result

while (key2 !== undefined) {
var type = Object.prototype.toString.call(recipient[key1])
var isobject = (
type === "[object Object]" ||
type === "[object Array]"
if (key1 === '__proto__') {
return
}

const type = Object.prototype.toString.call(recipient[key1])
const isobject = (
type === '[object Object]' ||
type === '[object Array]'
)

// do not write over falsey, non-undefined values if overwrite is false
Loading