Socket
Socket
Sign inDemoInstall

flat

Package Overview
Dependencies
Maintainers
2
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

flat - npm Package Compare versions

Comparing version 4.1.0 to 5.0.0

17

cli.js
#!/usr/bin/env node
const flat = require('.')
const fs = require('fs')

@@ -8,8 +7,12 @@ const path = require('path')

if (process.stdin.isTTY) {
const flat = require('./index')
const filepath = process.argv.slice(2)[0]
if (filepath) {
// Read from file
const file = path.resolve(process.cwd(), process.argv.slice(2)[0])
if (!file) usage()
if (!fs.existsSync(file)) usage()
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 {

@@ -31,3 +34,3 @@ // Read from newline-delimited STDIN

function usage () {
function usage (code) {
console.log(`

@@ -40,3 +43,3 @@ Usage:

process.exit()
process.exit(code || 0)
}

@@ -7,8 +7,13 @@ var isBuffer = require('is-buffer')

function keyIdentity (key) {
return key
}
function flatten (target, opts) {
opts = opts || {}
var delimiter = opts.delimiter || '.'
var maxDepth = opts.maxDepth
var output = {}
const delimiter = opts.delimiter || '.'
const maxDepth = opts.maxDepth
const transformKey = opts.transformKey || keyIdentity
const output = {}

@@ -18,7 +23,7 @@ function step (object, prev, currentDepth) {

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 = (
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]' ||

@@ -28,5 +33,5 @@ type === '[object Array]'

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

@@ -50,7 +55,8 @@ if (!isarray && !isbuffer && isobject && Object.keys(value).length &&

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]') {

@@ -63,3 +69,3 @@ return target

function getkey (key) {
var parsedKey = Number(key)
const parsedKey = Number(key)

@@ -74,15 +80,48 @@ return (

var sortedKeys = Object.keys(target).sort(function (keyA, keyB) {
return keyA.length - keyB.length
})
function addKeys (keyPrefix, recipient, target) {
return Object.keys(target).reduce(function (result, key) {
result[keyPrefix + delimiter + key] = target[key]
sortedKeys.forEach(function (key) {
var split = key.split(delimiter)
var key1 = getkey(split.shift())
var key2 = getkey(split[0])
var recipient = result
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((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 = (
const type = Object.prototype.toString.call(recipient[key1])
const isobject = (
type === '[object Object]' ||

@@ -89,0 +128,0 @@ type === '[object Array]'

{
"name": "flat",
"version": "4.1.0",
"version": "5.0.0",
"main": "index.js",
"bin": "cli.js",
"scripts": {
"test": "mocha -u tdd --reporter spec && standard index.js test/index.js"
"test": "mocha -u tdd --reporter spec && standard cli.js index.js test/index.js"
},

@@ -12,4 +12,4 @@ "license": "BSD-3-Clause",

"devDependencies": {
"mocha": "~5.2.0",
"standard": "^11.0.1"
"mocha": "~6.2.2",
"standard": "^14.3.1"
},

@@ -20,3 +20,3 @@ "directories": {

"dependencies": {
"is-buffer": "~2.0.3"
"is-buffer": "~2.0.4"
},

@@ -23,0 +23,0 @@ "repository": {

@@ -125,3 +125,3 @@ # flat [![Build Status](https://secure.travis-ci.org/hughsk/flat.png?branch=master)](http://travis-ci.org/hughsk/flat)

'TRAVIS': 'true',
'TRAVIS_DIR': '/home/travis/build/kvz/environmental'
'TRAVIS.DIR': '/home/travis/build/kvz/environmental'
}, { overwrite: true })

@@ -163,2 +163,51 @@

### 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

@@ -189,2 +238,2 @@

cat foo.json | flat
```
```
/* globals suite test */
var assert = require('assert')
var flat = require('../index')
var flatten = flat.flatten
var unflatten = flat.unflatten
const assert = require('assert')
const path = require('path')
const { exec } = require('child_process')
const pkg = require('../package.json')
const flat = require('../index')
var primitives = {
const flatten = flat.flatten
const unflatten = flat.unflatten
const primitives = {
String: 'good morning',

@@ -19,6 +23,6 @@ Number: 1234.99,

Object.keys(primitives).forEach(function (key) {
var value = primitives[key]
const value = primitives[key]
test(key, function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -36,6 +40,6 @@ world: value

Object.keys(primitives).forEach(function (key) {
var value = primitives[key]
const value = primitives[key]
test(key, function () {
assert.deepEqual(unflatten({
assert.deepStrictEqual(unflatten({
'hello.world': value

@@ -53,3 +57,3 @@ }), {

test('Nested once', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -64,3 +68,3 @@ world: 'good morning'

test('Nested twice', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -77,3 +81,3 @@ world: {

test('Multiple Keys', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -100,3 +104,3 @@ lorem: {

test('Custom Delimiter', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -115,10 +119,10 @@ world: {

test('Empty Objects', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {
empty: {
nested: { }
nested: {}
}
}
}), {
'hello.empty.nested': { }
'hello.empty.nested': {}
})

@@ -129,3 +133,3 @@ })

test('Buffer', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -144,3 +148,3 @@ empty: {

test('typed arrays', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -158,3 +162,3 @@ empty: {

test('Custom Depth', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -182,4 +186,26 @@ world: {

test('Transformed Keys', function () {
assert.deepStrictEqual(flatten({
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
}, {
transformKey: function (key) {
return '__' + key + '__'
}
}), {
'__hello__.__world__.__again__': 'good morning',
'__lorem__.__ipsum__.__dolor__': 'good evening'
})
})
test('Should keep number in the left when object', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: {

@@ -198,3 +224,3 @@ '0200': 'world',

test('Nested once', function () {
assert.deepEqual({
assert.deepStrictEqual({
hello: {

@@ -209,3 +235,3 @@ world: 'good morning'

test('Nested twice', function () {
assert.deepEqual({
assert.deepStrictEqual({
hello: {

@@ -222,3 +248,3 @@ world: {

test('Multiple Keys', function () {
assert.deepEqual({
assert.deepStrictEqual({
hello: {

@@ -242,3 +268,3 @@ lorem: {

'world.lorem.dolor': 'sit',
'world': {greet: 'hello'}
world: { greet: 'hello' }
}))

@@ -248,6 +274,6 @@ })

test('nested objects do not clobber each other when a.b inserted before a', function () {
var x = {}
x['foo.bar'] = {t: 123}
x['foo'] = {p: 333}
assert.deepEqual(unflatten(x), {
const x = {}
x['foo.bar'] = { t: 123 }
x.foo = { p: 333 }
assert.deepStrictEqual(unflatten(x), {
foo: {

@@ -263,3 +289,3 @@ bar: {

test('Custom Delimiter', function () {
assert.deepEqual({
assert.deepStrictEqual({
hello: {

@@ -278,3 +304,3 @@ world: {

test('Overwrite', function () {
assert.deepEqual({
assert.deepStrictEqual({
travis: {

@@ -294,4 +320,26 @@ build: {

test('Transformed Keys', function () {
assert.deepStrictEqual(unflatten({
'__hello__.__world__.__again__': 'good morning',
'__lorem__.__ipsum__.__dolor__': 'good evening'
}, {
transformKey: function (key) {
return key.substring(2, key.length - 2)
}
}), {
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
})
})
test('Messy', function () {
assert.deepEqual({
assert.deepStrictEqual({
hello: { world: 'again' },

@@ -302,9 +350,15 @@ lorem: { ipsum: 'another' },

hash: {
key: { nested: {
deep: { and: { even: {
deeper: { still: 'hello' }
} } }
} }
key: {
nested: {
deep: {
and: {
even: {
deeper: { still: 'hello' }
}
}
}
}
}
},
again: { testing: { 'this': 'out' } }
again: { testing: { this: 'out' } }
}

@@ -330,18 +384,18 @@ }

test('non-object keys + overwrite should be overwritten', function () {
assert.deepEqual(flat.unflatten({ a: null, 'a.b': 'c' }, {overwrite: true}), { a: { b: 'c' } })
assert.deepEqual(flat.unflatten({ a: 0, 'a.b': 'c' }, {overwrite: true}), { a: { b: 'c' } })
assert.deepEqual(flat.unflatten({ a: 1, 'a.b': 'c' }, {overwrite: true}), { a: { b: 'c' } })
assert.deepEqual(flat.unflatten({ a: '', 'a.b': 'c' }, {overwrite: true}), { a: { b: 'c' } })
assert.deepStrictEqual(flat.unflatten({ a: null, 'a.b': 'c' }, { overwrite: true }), { a: { b: 'c' } })
assert.deepStrictEqual(flat.unflatten({ a: 0, 'a.b': 'c' }, { overwrite: true }), { a: { b: 'c' } })
assert.deepStrictEqual(flat.unflatten({ a: 1, 'a.b': 'c' }, { overwrite: true }), { a: { b: 'c' } })
assert.deepStrictEqual(flat.unflatten({ a: '', 'a.b': 'c' }, { overwrite: true }), { a: { b: 'c' } })
})
test('overwrite value should not affect undefined keys', function () {
assert.deepEqual(flat.unflatten({ a: undefined, 'a.b': 'c' }, {overwrite: true}), { a: { b: 'c' } })
assert.deepEqual(flat.unflatten({ a: undefined, 'a.b': 'c' }, {overwrite: false}), { a: { b: 'c' } })
assert.deepStrictEqual(flat.unflatten({ a: undefined, 'a.b': 'c' }, { overwrite: true }), { a: { b: 'c' } })
assert.deepStrictEqual(flat.unflatten({ a: undefined, 'a.b': 'c' }, { overwrite: false }), { a: { b: 'c' } })
})
test('if no overwrite, should ignore nested values under non-object key', function () {
assert.deepEqual(flat.unflatten({ a: null, 'a.b': 'c' }), { a: null })
assert.deepEqual(flat.unflatten({ a: 0, 'a.b': 'c' }), { a: 0 })
assert.deepEqual(flat.unflatten({ a: 1, 'a.b': 'c' }), { a: 1 })
assert.deepEqual(flat.unflatten({ a: '', 'a.b': 'c' }), { a: '' })
assert.deepStrictEqual(flat.unflatten({ a: null, 'a.b': 'c' }), { a: null })
assert.deepStrictEqual(flat.unflatten({ a: 0, 'a.b': 'c' }), { a: 0 })
assert.deepStrictEqual(flat.unflatten({ a: 1, 'a.b': 'c' }), { a: 1 })
assert.deepStrictEqual(flat.unflatten({ a: '', 'a.b': 'c' }), { a: '' })
})

@@ -352,6 +406,6 @@ })

test('Should protect arrays when true', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: [
{ world: { again: 'foo' } },
{ lorem: 'ipsum' }
{ world: { again: 'foo' } },
{ lorem: 'ipsum' }
],

@@ -368,4 +422,4 @@ another: {

hello: [
{ world: { again: 'foo' } },
{ lorem: 'ipsum' }
{ world: { again: 'foo' } },
{ lorem: 'ipsum' }
],

@@ -378,6 +432,6 @@ 'lorem.ipsum': 'whoop',

test('Should not protect arrays when false', function () {
assert.deepEqual(flatten({
assert.deepStrictEqual(flatten({
hello: [
{ world: { again: 'foo' } },
{ lorem: 'ipsum' }
{ world: { again: 'foo' } },
{ lorem: 'ipsum' }
]

@@ -391,2 +445,9 @@ }, {

})
test('Empty objects should not be removed', function () {
assert.deepStrictEqual(unflatten({
foo: [],
bar: {}
}), { foo: [], bar: {} })
})
})

@@ -396,3 +457,3 @@

test('Should create object instead of array when true', function () {
var unflattened = unflatten({
const unflattened = unflatten({
'hello.you.0': 'ipsum',

@@ -404,3 +465,3 @@ 'hello.you.1': 'lorem',

})
assert.deepEqual({
assert.deepStrictEqual({
hello: {

@@ -418,4 +479,4 @@ you: {

test('Should create object instead of array when nested', function () {
var unflattened = unflatten({
'hello': {
const unflattened = unflatten({
hello: {
'you.0': 'ipsum',

@@ -428,3 +489,3 @@ 'you.1': 'lorem',

})
assert.deepEqual({
assert.deepStrictEqual({
hello: {

@@ -442,3 +503,3 @@ you: {

test('Should keep the zero in the left when object is true', function () {
var unflattened = unflatten({
const unflattened = unflatten({
'hello.0200': 'world',

@@ -450,3 +511,3 @@ 'hello.0500': 'darkness my old friend'

assert.deepEqual({
assert.deepStrictEqual({
hello: {

@@ -460,3 +521,3 @@ '0200': 'world',

test('Should not create object when false', function () {
var unflattened = unflatten({
const unflattened = unflatten({
'hello.you.0': 'ipsum',

@@ -468,3 +529,3 @@ 'hello.you.1': 'lorem',

})
assert.deepEqual({
assert.deepStrictEqual({
hello: {

@@ -481,3 +542,3 @@ you: ['ipsum', 'lorem'],

test('Buffer', function () {
assert.deepEqual(unflatten({
assert.deepStrictEqual(unflatten({
'hello.empty.nested': Buffer.from('test')

@@ -496,3 +557,3 @@ }), {

test('typed arrays', function () {
assert.deepEqual(unflatten({
assert.deepStrictEqual(unflatten({
'hello.empty.nested': new Uint8Array([1, 2, 3, 4])

@@ -512,3 +573,3 @@ }), {

test('Should be able to flatten arrays properly', function () {
assert.deepEqual({
assert.deepStrictEqual({
'a.0': 'foo',

@@ -522,3 +583,3 @@ 'a.1': 'bar'

test('Should be able to revert and reverse array serialization via unflatten', function () {
assert.deepEqual({
assert.deepStrictEqual({
a: ['foo', 'bar']

@@ -532,4 +593,4 @@ }, unflatten({

test('Array typed objects should be restored by unflatten', function () {
assert.equal(
Object.prototype.toString.call(['foo', 'bar'])
assert.strictEqual(
Object.prototype.toString.call(['foo', 'bar'])
, Object.prototype.toString.call(unflatten({

@@ -543,3 +604,3 @@ 'a.0': 'foo',

test('Do not include keys with numbers inside them', function () {
assert.deepEqual(unflatten({
assert.deepStrictEqual(unflatten({
'1key.2_key': 'ok'

@@ -553,1 +614,56 @@ }), {

})
suite('Order of Keys', function () {
test('Order of keys should not be changed after round trip flatten/unflatten', function () {
const obj = {
b: 1,
abc: {
c: [{
d: 1,
bca: 1,
a: 1
}]
},
a: 1
}
const result = unflatten(
flatten(obj)
)
assert.deepStrictEqual(Object.keys(obj), Object.keys(result))
assert.deepStrictEqual(Object.keys(obj.abc), Object.keys(result.abc))
assert.deepStrictEqual(Object.keys(obj.abc.c[0]), Object.keys(result.abc.c[0]))
})
})
suite('CLI', function () {
test('can take filename', function (done) {
const cli = path.resolve(__dirname, '..', pkg.bin)
const pkgJSON = path.resolve(__dirname, '..', 'package.json')
exec(`${cli} ${pkgJSON}`, (err, stdout, stderr) => {
assert.ifError(err)
assert.strictEqual(stdout.trim(), JSON.stringify(flatten(pkg), null, 2))
done()
})
})
test('exits with usage if no file', function (done) {
const cli = path.resolve(__dirname, '..', pkg.bin)
const pkgJSON = path.resolve(__dirname, '..', 'package.json')
exec(`${cli} ${pkgJSON}`, (err, stdout, stderr) => {
assert.ifError(err)
assert.strictEqual(stdout.trim(), JSON.stringify(flatten(pkg), null, 2))
done()
})
})
test('can take piped file', function (done) {
const cli = path.resolve(__dirname, '..', pkg.bin)
const pkgJSON = path.resolve(__dirname, '..', 'package.json')
exec(`cat ${pkgJSON} | ${cli}`, (err, stdout, stderr) => {
assert.ifError(err)
assert.strictEqual(stdout.trim(), JSON.stringify(flatten(pkg), null, 2))
done()
})
})
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc