Socket
Socket
Sign inDemoInstall

groq-cli

Package Overview
Dependencies
83
Maintainers
14
Versions
5
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.0 to 0.2.0

readme.md

10

package.json
{
"name": "groq-cli",
"version": "0.1.0",
"version": "0.2.0",
"description": "Run GROQ in the command line",

@@ -33,8 +33,10 @@ "license": "MIT",

"chalk": "^2.4.2",
"get-it": "^5.0.0",
"get-stdin": "^7.0.0",
"groq": "0.0.9",
"groq-js": "0.0.1",
"groq-js": "0.1.3",
"json-lexer": "^1.1.1",
"meow": "^5.0.0"
"meow": "^5.0.0",
"ndjson": "^1.5.0",
"regenerator-runtime": "^0.13.3",
"stream-to-async-iterator": "^0.2.0"
},

@@ -41,0 +43,0 @@ "devDependencies": {

194

src/cli.js
#!/usr/bin/env node
/* eslint-disable id-length, no-process-exit */
require("regenerator-runtime/runtime")
const meow = require('meow')
const readFileStream = require('./readFileStream')
const { parse, evaluate } = require('groq-js')
const getStdin = require('get-stdin')
const chalk = require('chalk')
const ndjson = require('ndjson')
require('./gracefulQuit')
const colorizeJson = require('./colorizeJson')
const fromUrl = require('./fromUrl')
const S2A = require('stream-to-async-iterator').default
const cli = meow(

@@ -19,41 +20,50 @@ `

Options
${chalk.green(`--file ./path/to/file`)}
${chalk.green(`--url https://aniftyapi.dev/endpoint`)}
${chalk.green(
`--primary results | The primary element with the array you want to query`
)}
${chalk.green(`--pretty colorized JSON output [Default: false]`)}
${chalk.green(`-i, --input One of: ndjson, json, null`)}
${chalk.green(`-o, --output One of: ndjson, json, pretty`)}
${chalk.green(`-p, --pretty Shortcut for --output=pretty`)}
${chalk.green(`-n, --ndjson Shortcut for --input=ndjson --output=ndjson`)}
Input formats
${chalk.green(`json`)} Reads a JSON object from stdin.
${chalk.green(`ndjson`)} Reads a JSON stream from stdin.
${chalk.green(`null`)} Reads nothing.
Output formats
${chalk.green(`json`)} Formats the output as JSON.
${chalk.green(`pretty`)} Formats the output as pretty JSON.
${chalk.green(`ndjson`)} Streams the result as NDJSON.
Examples
${chalk.grey(`# Query data in a ndjson-file`)}
${chalk.green(`$ groq '*[_type == "post"]{title}' --file ./blog.ndjson`)}
${chalk.grey(`# Query data in a file`)}
${chalk.green(`$ cat blog.json | groq 'count(posts)' `)}
${chalk.grey(`# Query data in a NDJSON file`)}
${chalk.green(`$ cat blog.ndjson | groq --input ndjson '*[_type == "post"]{title}' `)}
${chalk.grey(`# Query JSON data from an URL`)}
${chalk.green(
`$ groq '*[completed == false]{title}' --url https://jsonplaceholder.typicode.com/todos`
`$ curl -s https://jsonplaceholder.typicode.com/todos | groq --pretty '*[completed == false]{title}'`
)}
${chalk.grey(`# Query data from stdIn`)}
${chalk.green(
`$ curl -s https://jsonplaceholder.typicode.com/todos | groq "*[completed == false]{'mainTitle': title, ...}" --pretty`
)}
`,
{
flags: {
file: {
type: 'string',
default: undefined
pretty: {
type: 'boolean',
alias: 'p',
default: false
},
primary: {
ndjson: {
type: 'boolean',
alias: 'n',
default: false
},
input: {
type: 'string',
default: undefined
alias: 'i',
default: 'json'
},
url: {
output: {
type: 'string',
default: undefined
},
pretty: {
type: 'boolean',
default: false
alias: 'o',
default: 'json'
}

@@ -69,23 +79,9 @@ }

function parseDocuments (data, primary) {
if (primary && !JSON.parse(data)[primary]) {
throw new Error(`Is the primary key correct?\n\n${primary}`)
function validateChoice(title, input, choices) {
if (!choices.includes(input)) {
throw Error(chalk.yellow(`Unknown ${title}: ${input}. Valid choices are: ${choices.join(', ')}.`))
}
try {
return primary ? JSON.parse(data)[primary] : JSON.parse(data)
} catch (err) {
try {
return data
.toString()
.trim()
.split('\n')
.map(JSON.parse)
} catch (error) {
throw new Error(`Is the input valid JSON/NDJSON?\n\n${error}`)
}
}
}
function check ({ query, file, url, stdIn }) {
function check ({ query, inputFormat, outputFormat }) {
if (!query) {

@@ -98,41 +94,91 @@ throw Error(

}
if (!file && !url && !stdIn) {
throw Error(
chalk.yellow(
'There’s no data to query. To learn more, run\n\n $ groq --help'
)
)
}
validateChoice("input format", inputFormat, ['json', 'ndjson', 'null'])
validateChoice("output format", outputFormat, ['json', 'ndjson', 'pretty'])
return true
}
async function parseQuery () {
async function* outputJSON(result) {
yield JSON.stringify(await result.get())
yield "\n"
}
async function* outputPrettyJSON(result) {
yield colorizeJson(await result.get())
yield "\n"
}
async function* outputNDJSON(result) {
if (result.getType() == 'array') {
for await (const value of result) {
yield JSON.stringify(await value.get())
yield "\n"
}
} else {
yield JSON.stringify(await result.get())
yield "\n"
}
}
const OUTPUTTERS = {
json: outputJSON,
pretty: outputPrettyJSON,
ndjson: outputNDJSON,
}
async function inputJSON() {
const dataset = JSON.parse(await getStdin())
return {dataset, root: dataset}
}
function inputNDJSON() {
const dataset = new S2A(process.stdin.pipe(ndjson()))
return {dataset}
}
const INPUTTERS = {
json: inputJSON,
ndjson: inputNDJSON,
}
async function* runQuery() {
const { flags, input } = cli
const { file, url, primary, pretty } = flags
const { pretty, ndjson: isNdjson } = flags
let { input: inputFormat, output: outputFormat } = flags
const query = input[0]
const stdIn = await getStdin()
check({ query, file, url, stdIn })
let documents = []
if (file) {
const fileContent = await readFileStream(file).catch(handleError)
documents = await parseDocuments(fileContent, primary)
} else if (url) {
const urlContent = await fromUrl(url)
documents = await parseDocuments(urlContent, primary)
} else if (stdIn) {
documents = await parseDocuments(stdIn, primary)
if (pretty) {
outputFormat = 'pretty'
}
if (isNdjson) {
outputFormat = 'ndjson'
inputFormat = 'ndjson'
}
check({ query, inputFormat, outputFormat })
// Parse query
const tree = parse(query)
const result = await evaluate(tree, { documents }).get()
if (pretty) {
return colorizeJson(result)
}
// Read input
const inputter = INPUTTERS[inputFormat]
const options = await inputter()
return JSON.stringify(result)
// Execute query
const result = await evaluate(tree, options)
// Stream output
const streamer = OUTPUTTERS[outputFormat]
yield* await streamer(result)
}
parseQuery()
.then(result => console.log(result))
.catch(handleError)
async function main() {
for await (const data of runQuery()) {
process.stdout.write(data)
}
}
main().catch(handleError)
SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc