Skip to content

Instantly share code, notes, and snippets.

@nyteshade
Last active November 2, 2022 20:47
Show Gist options
  • Save nyteshade/f3217864e8abec939599a1a4623e2080 to your computer and use it in GitHub Desktop.
Save nyteshade/f3217864e8abec939599a1a4623e2080 to your computer and use it in GitHub Desktop.
json cli tool
#!/usr/bin/env node
const FS = require('fs')
const { inspect } = require('util')
const { EOL } = require('os')
const { dirname, basename } = require('path')
const version = {
major: 1,
minor: 1,
patch: 0,
toString() { return `${this.major}.${this.minor}.${this.patch}` },
compare(to) {
if (this.major < to.major) return -1
if (this.major > to.major) return 1
if (this.minor < to.minor) return -1
if (this.minor > to.minor) return 1
if (this.patch < to.patch) return -1
if (this.patch > to.patch) return 1
return 0;
},
}
let truthy = (o) => /Yes|Y|True|T|[123456789]+/i.test(String(o))
let arguments = Array.from(process.argv)
let nodeBinary = arguments.shift()
let progBinary = arguments.shift()
let progPath = dirname(progBinary)
let progName = basename(progBinary)
let separator = process.env['SEPARATOR'] || ' '
let noline = truthy(process.env['NOLINE']) || false
let asJson = truthy(process.env['ASJSON']) || false
let noColor = truthy(process.env['NOCOLOR']) || false
let indentation = Number(process.env['INDENT']) || 2
let compact = truthy(process.env['COMPACT']) || false
let breakLength = Number(process.env['BREAKLENGTH']) || 80
let printf = (...args) => process.stdout.write(...args)
let endl = `${noline ? separator : EOL}`
if (!arguments.length) {
console.log([
`Usage: ${progName} <json-file-or-string> <key1> [keyN]`,
'where',
' json-file-or-string - either a path to a file or a string of JSON',
' key1 - any JSON key path (ex: user?.name?.first)',
' checks for user then user.name then user.name.first',
' keyN - n-number of keys to specified separated by space',
'',
'environment variables',
` NOLINE - print without a newline (cur: ${noline})`,
` SEPARATOR - defaults to a space (cur: "${separator}")`,
` ASJSON - defaults to formal JSON output instead of hilighted code (cur: ${asJson})`,
` INDENT - indicates indentation for JSON output, ignored otherwise (cur: ${indentation})`,
` NOCOLOR - indicates colorized output should not be shown (cur: ${noColor})`,
` COMPACT - truncates values to the column width (${breakLength}) (cur: ${compact})`,
` BREAKLENGTH - shows the column width when using COMPACT (cur: ${breakLength})`,
'',
`Version ${version}`,
`\x1b[3mRun using NodeJS ${nodeBinary},\n binary in ${progPath}\x1b[23m\n`
].join('\n'))
process.exit(0)
}
let json = arguments.shift()
try {
json = FS.existsSync(json)
? JSON.parse(FS.readFileSync(json).toString())
: JSON.parse(json)
}
catch (error) {
console.log([
'Do not understand the value provided for json or file. It must be either',
'a string of JSON text or a file containing JSON data'
].join('\n'))
process.exit(5)
}
if (!arguments.length) {
if (asJson) {
printf(`${JSON.stringify(json, null, indentation)}${endl}`)
}
else {
let inspected = inspect(
json,
{
showHidden: true,
depth: 100,
colors: !noColor,
compact,
breakLength
}
)
printf(`${inspected}${endl}`)
}
}
else {
for (let arg of arguments) {
let input = `json?.${arg}`
let output = eval(`(${input})`)
if (asJson) {
printf(`${JSON.stringify(output, null, indentation)}${endl}`)
}
else {
let inspected = inspect(
output,
{
showHidden: true,
depth: 100,
colors: !noColor,
compact,
breakLength
}
)
printf(`${inspected}${endl}`)
}
}
}
@nyteshade
Copy link
Author

Example usage

json package.json scripts

Which might show

{
  start: 'node index.js',
  build: 'tsc'
}

There are quite a few help options

Usage: json json-file-or-string key1 [keyN]
where
  json-file-or-string - either a path to a file or a string of JSON
  key1                - any JSON key path (ex: user?.name?.first)
                        checks for user then user.name then user.name.first
  keyN                - n-number of keys to specified separated by space

environment variables
  NOLINE              - print without a newline
    (cur: false)
  SEPARATOR           - defaults to a space
    (cur: " ")
  ASJSON              - defaults to formal JSON output instead of hilighted code
    (cur: false)
  INDENT              - indicates indentation for JSON output, ignored otherwise
    (cur: 2)
  NOCOLOR             - indicates colorized output should not be shown
    (cur: false)
  COMPACT             - truncates values to the column width (80)
    (cur: false)
  BREAKLENGTH         - shows the column width when using COMPACT
    (cur: 80)

Version 1.0.0
Run using NodeJS /opt/homebrew/Cellar/node/18.11.0/bin/node,
  binary in /Users/brie/bin

Using the env value ASJSON=true can change the output to something like this

$ ASJSON=true json package.json scripts

{
  "start": "node index.js",
  "build": "tsc"
}

@nyteshade
Copy link
Author

Easy install to local ~/bin directory.

curl -o /tmp/json https://gist.githubusercontent.com/nyteshade/f3217864e8abec939599a1a4623e2080/raw/b21018f393575deea03b515138fcf85cfb628700/json.js && chmod +x /tmp/json; [ ! -d ~/bin ] && mkdir ~/bin; mv /tmp/json ~/bin; printf "\nMake sure ${HOME}/bin is in your path\n"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment