Files
curlconverter/bin/cli.js
Boris Verkhovskiy 01f2538e59 bump version (#343)
and readme update
2022-03-16 15:08:19 -07:00

183 lines
5.1 KiB
JavaScript
Executable File

#!/usr/bin/env node
import { curlLongOpts, curlShortOpts, parseArgs, buildRequest, parseCurlCommand, CCError } from '../util.js'
import { _toAnsible } from '../generators/ansible.js'
import { _toDart } from '../generators/dart.js'
import { _toElixir } from '../generators/elixir.js'
import { _toGo } from '../generators/go.js'
import { _toJava } from '../generators/java.js'
import { _toJavaScript } from '../generators/javascript/javascript.js'
import { _toJsonString } from '../generators/json.js'
import { _toMATLAB } from '../generators/matlab/matlab.js'
import { _toNode } from '../generators/javascript/node-fetch.js'
import { _toNodeRequest } from '../generators/javascript/node-request.js'
import { _toPhp } from '../generators/php/php.js'
import { _toPhpRequests } from '../generators/php/php-requests.js'
import { _toPython } from '../generators/python.js'
import { _toR } from '../generators/r.js'
import { _toRust } from '../generators/rust.js'
import { _toStrest } from '../generators/strest.js'
import fs from 'fs'
// This line is generated by extract_curl_args.py. Do not modify it.
const VERSION = '4.0.0-alpha.10 (curl 7.79.1)'
// sets a default in case --language isn't passed
const defaultLanguage = 'python'
// Maps options for --language to functions
// NOTE: make sure to update this when adding language support
const translate = {
ansible: _toAnsible,
browser: _toJavaScript, // backwards compatibility, undocumented
dart: _toDart,
elixir: _toElixir,
go: _toGo,
java: _toJava,
javascript: _toJavaScript,
json: _toJsonString,
matlab: _toMATLAB,
node: _toNode,
'node-request': _toNodeRequest,
php: _toPhp,
'php-requests': _toPhpRequests,
python: _toPython,
r: _toR,
rust: _toRust,
strest: _toStrest
}
const USAGE = `Usage: curlconverter [--language <language>] [-] [curl_options...]
language: the language to convert the curl command to. The choices are
ansible
dart
elixir
go
java
javascript
json
matlab
node
node-request
php
php-requests
python (the default)
r
rust
strest
-: read curl command from stdin
curl_options: these should be passed exactly as they would be passed to curl.
see 'curl --help' or 'curl --manual' for which options are allowed here`
const curlConverterLongOpts = {
language: { type: 'string', name: 'language' },
stdin: { type: 'boolean', name: 'stdin' }
}
const curlConverterShortOpts = {
// a single - (dash) tells curlconverter to read input from stdin
'': 'stdin'
}
const opts = [
{ ...curlLongOpts, ...curlConverterLongOpts },
{ ...curlConverterShortOpts, ...curlShortOpts }
]
const exitWithError = (error, verbose = false) => {
let errMsg = error
if (!verbose) {
if (error instanceof CCError) {
errMsg = ''
for (const line of error.message.toString().split('\n')) {
errMsg += 'error: ' + line + '\n'
}
errMsg = errMsg.trimEnd()
} else {
// .toString() removes the traceback
errMsg = error.toString()
}
}
console.error(errMsg)
process.exit(2) // curl exits with 2 so we do too
}
const argv = process.argv.slice(2)
let parsedArguments
try {
parsedArguments = parseArgs(argv, opts)
} catch (e) {
exitWithError(e)
}
if (parsedArguments.help) {
console.log(USAGE.trim())
process.exit(0)
}
if (parsedArguments.version) {
console.log('curlconverter ' + VERSION)
process.exit(0)
}
const argc = Object.keys(parsedArguments).length
const language = parsedArguments.language || defaultLanguage
const stdin = parsedArguments.stdin
if (!Object.prototype.hasOwnProperty.call(translate, language)) {
exitWithError(
new CCError('unexpected --language: ' + JSON.stringify(language) + '\n' +
'must be one of: ' + Object.keys(translate).join(', ')),
parsedArguments.verbose
)
}
for (const opt of Object.keys(curlConverterLongOpts)) {
delete parsedArguments[opt]
}
let request
if (argc === 0) {
console.log(USAGE.trim())
process.exit(2)
} else if (stdin) {
if (Object.keys(parsedArguments).length > 0) {
// Throw an error so that if user typos something like
// curlconverter - -data
// they aren't stuck with what looks like a hung terminal.
// TODO: some options like --verbose are understandable
const args = Object.keys(parsedArguments).map(a => '--' + a).join(', ')
exitWithError(
new CCError('if you pass --stdin or -, you can\'t also pass ' + args),
parsedArguments.verbose
)
}
const input = fs.readFileSync(0, 'utf8')
try {
request = parseCurlCommand(input)
} catch (e) {
exitWithError(e, parsedArguments.verbose)
}
} else {
try {
request = buildRequest(parsedArguments)
} catch (e) {
exitWithError(e, parsedArguments.verbose)
}
}
// Warning for users using the pre-4.0 CLI
if (request.url && request.url.startsWith('curl ')) {
console.error('warning: Passing a whole curl command as a single argument?')
console.error('warning: Pass options to curlconverter as if it was curl instead:')
console.error("warning: curlconverter 'curl example.com' -> curlconverter example.com")
}
const generator = translate[language]
let code
try {
code = generator(request)
} catch (e) {
exitWithError(e, parsedArguments.verbose)
}
process.stdout.write(code)