@activeprospect/flat
Advanced tools
Comparing version 5.0.4 to 5.1.0
@@ -15,3 +15,3 @@ ## Description of the change | ||
> Link to Clubhouse Ticket Goes Here | ||
> Link to Shortcut/Jira Ticket Goes Here | ||
@@ -34,6 +34,6 @@ ## Checklists | ||
### Tracking | ||
- [ ] Issue from Clubhouse has a link to this pull request. | ||
- [ ] This PR has a link to the issue in Clubhouse. | ||
- [ ] Issue from Shortcut/Jira has a link to this pull request. | ||
- [ ] This PR has a link to the issue in Shortcut. | ||
### QA | ||
- [ ] This branch has been deployed to staging and tested. |
27
cli.js
#!/usr/bin/env node | ||
const fs = require('node:fs') | ||
const path = require('node:path') | ||
const readline = require('node:readline') | ||
const { flatten } = require('./index.js') | ||
const flat = require('.') | ||
const fs = require('fs') | ||
const path = require('path') | ||
const readline = require('readline') | ||
if (process.stdin.isTTY) { | ||
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() | ||
out(require(file)) | ||
const file = path.resolve(process.cwd(), filepath) | ||
fs.accessSync(file, fs.constants.R_OK) // allow to throw if not readable | ||
out(JSON.parse(fs.readFileSync(file))) | ||
} else if (process.stdin.isTTY) { | ||
usage(0) | ||
} else { | ||
@@ -27,6 +28,6 @@ // Read from newline-delimited STDIN | ||
function out (data) { | ||
process.stdout.write(JSON.stringify(flat(data), null, 2)) | ||
process.stdout.write(JSON.stringify(flatten(data), null, 2)) | ||
} | ||
function usage () { | ||
function usage (code) { | ||
console.log(` | ||
@@ -39,3 +40,3 @@ Usage: | ||
process.exit() | ||
process.exit(code || 0) | ||
} |
111
index.js
@@ -1,3 +0,1 @@ | ||
var isBuffer = require('is-buffer') | ||
module.exports = flatten | ||
@@ -7,8 +5,20 @@ flatten.flatten = flatten | ||
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 = {} | ||
const delimiter = opts.delimiter || '.' | ||
const maxDepth = opts.maxDepth | ||
const transformKey = opts.transformKey || keyIdentity | ||
const output = {} | ||
@@ -18,7 +28,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 +38,5 @@ type === '[object Array]' | ||
var newKey = prev | ||
? prev + delimiter + key | ||
: key | ||
const newKey = prev | ||
? prev + delimiter + transformKey(key) | ||
: transformKey(key) | ||
@@ -50,7 +60,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 (Array.isArray(target)) { | ||
@@ -67,3 +78,3 @@ return target.map(function (item) { | ||
function getkey (key) { | ||
var parsedKey = Number(key) | ||
const parsedKey = Number(key) | ||
@@ -74,19 +85,57 @@ return ( | ||
opts.object | ||
) ? key | ||
) | ||
? key | ||
: parsedKey | ||
} | ||
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(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 = ( | ||
if (key1 === '__proto__') { | ||
return | ||
} | ||
const type = Object.prototype.toString.call(recipient[key1]) | ||
const isobject = ( | ||
type === '[object Object]' || | ||
@@ -104,3 +153,5 @@ type === '[object Array]' | ||
typeof key2 === 'number' && | ||
!opts.object ? [] : {} | ||
!opts.object | ||
? [] | ||
: {} | ||
) | ||
@@ -107,0 +158,0 @@ } |
{ | ||
"name": "@activeprospect/flat", | ||
"version": "5.0.4", | ||
"version": "5.1.0", | ||
"main": "index.js", | ||
"bin": "cli.js", | ||
"bin": { | ||
"flat": "cli.js" | ||
}, | ||
"scripts": { | ||
"test": "mocha -u tdd --reporter spec && standard index.js test/index.js" | ||
"test": "node --test && standard cli.js index.js test/test.js" | ||
}, | ||
@@ -12,14 +14,7 @@ "license": "BSD-3-Clause", | ||
"devDependencies": { | ||
"mocha": "^8.3.0", | ||
"standard": "^14.3.1" | ||
"standard": "^17.1.0" | ||
}, | ||
"directories": { | ||
"test": "test" | ||
}, | ||
"dependencies": { | ||
"is-buffer": "~2.0.4" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/hughsk/flat.git" | ||
"url": "git://github.com/activeprospect/flat.git" | ||
}, | ||
@@ -35,3 +30,3 @@ "keywords": [ | ||
], | ||
"author": "Hugh Kennedy <hughskennedy@gmail.com> (http://hughskennedy.com)", | ||
"author": "Hugh Kennedy <hughskennedy@gmail.com> (https://hughsk.io)", | ||
"bugs": { | ||
@@ -38,0 +33,0 @@ "url": "https://github.com/hughsk/flat/issues" |
@@ -1,3 +0,11 @@ | ||
# flat [![Build Status](https://secure.travis-ci.org/hughsk/flat.png?branch=master)](http://travis-ci.org/hughsk/flat) | ||
# flat | ||
> [!NOTE] | ||
> Originally forked to fix a bug where dot notation keys in a nested array were not unflattened, | ||
> see https://github.com/activeprospect/flat/commit/27b5bfaaab986028dd9d8bb8027d5dce2e5a874b. | ||
> | ||
> Fork is maintained because LeadConduit is not set up to easily consume ES modules, and the | ||
> upstream package only ships an ESM package. This lib contains equivalent code, but maintains | ||
> a CommonJS file format for compatibility with all LeadConduit integrations and applications. | ||
Take a nested Javascript object and flatten it, or unflatten an object with | ||
@@ -20,3 +28,3 @@ delimited keys. | ||
``` javascript | ||
var flatten = require('flat') | ||
const { flatten } = require('flat') | ||
@@ -42,6 +50,6 @@ flatten({ | ||
Flattening is reversible too, you can call `flatten.unflatten()` on an object: | ||
Flattening is reversible too, you can call `unflatten` on an object: | ||
``` javascript | ||
var unflatten = require('flat').unflatten | ||
const { unflatten } = require('flat') | ||
@@ -76,3 +84,3 @@ unflatten({ | ||
``` javascript | ||
var flatten = require('flat') | ||
const { flatten } = require('flat') | ||
@@ -127,3 +135,3 @@ flatten({ | ||
'TRAVIS': 'true', | ||
'TRAVIS_DIR': '/home/travis/build/kvz/environmental' | ||
'TRAVIS.DIR': '/home/travis/build/kvz/environmental' | ||
}, { overwrite: true }) | ||
@@ -146,3 +154,3 @@ | ||
``` javascript | ||
var flatten = require('flat') | ||
const { flatten } = require('flat') | ||
@@ -166,6 +174,53 @@ flatten({ | ||
### transformKey | ||
Transform each part of a flat key before and after flattening. | ||
```javascript | ||
const { flatten, unflatten } = require('flat') | ||
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): | ||
`flat` is also available as a command line tool. You can run it with [`npx`](https://docs.npmjs.com/cli/v8/commands/npx): | ||
@@ -192,2 +247,2 @@ ```sh | ||
cat foo.json | flat | ||
``` | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Unstable ownership
Supply chain riskA new collaborator has begun publishing package versions. Package stability and security risk may be elevated.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
18112
0
1
10
186
242
0
1
- Removedis-buffer@~2.0.4
- Removedis-buffer@2.0.5(transitive)