mirror of
https://github.com/curlconverter/curlconverter.git
synced 2022-05-22 02:35:29 +03:00
report Bash parsing errors (#399)
* allow passing warnings list to *Warn() functions that way if there's an error, we can catch the error, look at the warnings that happened while parsing and show them to users.
This commit is contained in:
committed by
GitHub
parent
a29f9bc259
commit
39f01a5a47
@@ -8,7 +8,8 @@
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"no-empty": ["error", { "allowEmptyCatch": true }]
|
||||
"no-empty": ["error", { "allowEmptyCatch": true }],
|
||||
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }]
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
|
||||
46
src/cli.ts
46
src/cli.ts
@@ -54,8 +54,8 @@ const defaultLanguage = "python";
|
||||
// NOTE: make sure to update this when adding language support
|
||||
const translate: {
|
||||
[key: string]: [
|
||||
(request: Request, warnings?: Warnings) => [string, Warnings],
|
||||
(curlCommand: string | string[]) => [string, [string, string][]]
|
||||
(request: Request, warnings?: Warnings) => string,
|
||||
(curlCommand: string | string[], warnings?: Warnings) => [string, Warnings]
|
||||
];
|
||||
} = {
|
||||
ansible: [_toAnsible, toAnsibleWarn],
|
||||
@@ -120,6 +120,17 @@ const curlConverterShortOpts: ShortOpts = {
|
||||
const longOpts: LongOpts = { ...curlLongOpts, ...curlConverterLongOpts };
|
||||
const shortOpts: ShortOpts = { ...curlShortOpts, ...curlConverterShortOpts };
|
||||
|
||||
function printWarnings(warnings: Warnings, verbose: boolean): Warnings {
|
||||
if (!verbose) {
|
||||
return warnings;
|
||||
}
|
||||
for (const w of warnings) {
|
||||
for (const line of w[1].trim().split("\n")) {
|
||||
console.error("warning: " + line);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
function exitWithError(error: unknown, verbose = false): never {
|
||||
let errMsg: Error | string | unknown = error;
|
||||
if (!verbose) {
|
||||
@@ -139,9 +150,10 @@ function exitWithError(error: unknown, verbose = false): never {
|
||||
}
|
||||
|
||||
const argv = process.argv.slice(2);
|
||||
let parsedArguments, warnings;
|
||||
let parsedArguments;
|
||||
let warnings: Warnings = [];
|
||||
try {
|
||||
[parsedArguments, warnings] = parseArgs(argv, longOpts, shortOpts);
|
||||
parsedArguments = parseArgs(argv, longOpts, shortOpts, undefined, warnings);
|
||||
} catch (e) {
|
||||
exitWithError(e);
|
||||
}
|
||||
@@ -153,6 +165,7 @@ if (parsedArguments.version) {
|
||||
console.log("curlconverter " + VERSION);
|
||||
process.exit(0);
|
||||
}
|
||||
const verbose = parsedArguments.verbose;
|
||||
|
||||
const argc = Object.keys(parsedArguments).length;
|
||||
const language = parsedArguments.language || defaultLanguage;
|
||||
@@ -166,7 +179,7 @@ if (!has(translate, language)) {
|
||||
"must be one of: " +
|
||||
Object.keys(translate).join(", ")
|
||||
),
|
||||
parsedArguments.verbose
|
||||
verbose
|
||||
);
|
||||
}
|
||||
for (const opt of Object.keys(curlConverterLongOpts)) {
|
||||
@@ -192,22 +205,26 @@ if (stdin) {
|
||||
new CCError(
|
||||
"if you pass --stdin or -, you can't also pass " + extraArgsStr
|
||||
),
|
||||
parsedArguments.verbose
|
||||
verbose
|
||||
);
|
||||
}
|
||||
const input = fs.readFileSync(0, "utf8");
|
||||
try {
|
||||
[code, warnings] = warnGenerator(input);
|
||||
[code, warnings] = warnGenerator(input, warnings);
|
||||
} catch (e) {
|
||||
exitWithError(e, parsedArguments.verbose);
|
||||
printWarnings(warnings, true); // print warnings to help figure out the error
|
||||
exitWithError(e, verbose);
|
||||
}
|
||||
warnings = printWarnings(warnings, verbose);
|
||||
} else {
|
||||
warnings = printWarnings(warnings, verbose);
|
||||
let request;
|
||||
try {
|
||||
request = buildRequest(parsedArguments, warnings);
|
||||
} catch (e) {
|
||||
exitWithError(e, parsedArguments.verbose);
|
||||
exitWithError(e, verbose);
|
||||
}
|
||||
warnings = printWarnings(warnings, verbose);
|
||||
// Warning for users using the pre-4.0 CLI
|
||||
if (request.url?.startsWith("curl ")) {
|
||||
console.error(
|
||||
@@ -221,15 +238,12 @@ if (stdin) {
|
||||
);
|
||||
}
|
||||
try {
|
||||
[code, warnings] = generator(request, warnings);
|
||||
code = generator(request, warnings);
|
||||
} catch (e) {
|
||||
exitWithError(e, parsedArguments.verbose);
|
||||
exitWithError(e, verbose);
|
||||
}
|
||||
warnings = printWarnings(warnings, verbose);
|
||||
}
|
||||
|
||||
if (warnings && parsedArguments.verbose) {
|
||||
for (const w of warnings) {
|
||||
console.error("warning: " + w[1]);
|
||||
}
|
||||
}
|
||||
printWarnings(warnings, verbose);
|
||||
process.stdout.write(code);
|
||||
|
||||
@@ -48,9 +48,8 @@ function getDataString(request: Request): string | object {
|
||||
|
||||
export const _toAnsible = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
warnings: Warnings = [] // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
): string => {
|
||||
let convertedData;
|
||||
if (request.data && typeof request.data === "string") {
|
||||
convertedData = getDataString(request);
|
||||
@@ -59,13 +58,15 @@ export const _toAnsible = (
|
||||
request,
|
||||
data: convertedData,
|
||||
});
|
||||
return [result, warnings];
|
||||
return result;
|
||||
};
|
||||
export const toAnsibleWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toAnsible(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const ansible = _toAnsible(request, warnings);
|
||||
return [ansible, warnings];
|
||||
};
|
||||
export const toAnsible = (curlCommand: string | string[]): string => {
|
||||
return toAnsibleWarn(curlCommand)[0];
|
||||
|
||||
@@ -31,11 +31,7 @@ const quote = (str: string): string => {
|
||||
return jsesc(str, { quotes: "single" }).replace(/"/g, '""');
|
||||
};
|
||||
|
||||
export const _toCFML = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
export const _toCFML = (request: Request, warnings: Warnings = []): string => {
|
||||
let cfmlCode = "";
|
||||
|
||||
cfmlCode += "httpService = new http();\n";
|
||||
@@ -137,14 +133,16 @@ export const _toCFML = (
|
||||
cfmlCode += "\nresult = httpService.send().getPrefix();\n";
|
||||
cfmlCode += "writeDump(result);\n";
|
||||
|
||||
return [cfmlCode, warnings];
|
||||
return cfmlCode;
|
||||
};
|
||||
|
||||
export const toCFMLWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toCFML(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const cfml = _toCFML(request, warnings);
|
||||
return [cfml, warnings];
|
||||
};
|
||||
|
||||
export const toCFML = (curlCommand: string | string[]): string => {
|
||||
|
||||
@@ -34,11 +34,7 @@ function repr(value: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
export const _toDart = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
export const _toDart = (request: Request, warnings: Warnings = []): string => {
|
||||
let s = "";
|
||||
|
||||
if (request.auth || request.isDataBinary) s += "import 'dart:convert';\n";
|
||||
@@ -144,13 +140,15 @@ export const _toDart = (
|
||||
" print(res.body);\n" +
|
||||
"}";
|
||||
|
||||
return [s + "\n", warnings];
|
||||
return s + "\n";
|
||||
};
|
||||
export const toDartWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toDart(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const dart = _toDart(request, warnings);
|
||||
return [dart, warnings];
|
||||
};
|
||||
export const toDart = (curlCommand: string | string[]): string => {
|
||||
return toDartWarn(curlCommand)[0];
|
||||
|
||||
@@ -229,10 +229,8 @@ ${data.join(",\n")}
|
||||
|
||||
export const _toElixir = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
if (request.cookies) {
|
||||
util.deleteHeader(request, "cookie");
|
||||
}
|
||||
@@ -249,13 +247,15 @@ export const _toElixir = (
|
||||
response = HTTPoison.request(request)
|
||||
`;
|
||||
|
||||
return [template, warnings];
|
||||
return template;
|
||||
};
|
||||
export const toElixirWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toElixir(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const elixir = _toElixir(request, warnings);
|
||||
return [elixir, warnings];
|
||||
};
|
||||
|
||||
export const toElixir = (curlCommand: string | string[]): string => {
|
||||
|
||||
@@ -35,10 +35,7 @@ const repr = (s: string): string => {
|
||||
return '"' + jsesc(s, { quotes: "double", minimal: true }) + '"';
|
||||
};
|
||||
|
||||
export const _toGo = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
export const _toGo = (request: Request, warnings: Warnings = []): string => {
|
||||
warnings = warnings || [];
|
||||
let goCode = "package main\n\n";
|
||||
goCode += "import (\n";
|
||||
@@ -94,13 +91,15 @@ export const _toGo = (
|
||||
goCode += '\tfmt.Printf("%s\\n", bodyText)\n';
|
||||
goCode += "}";
|
||||
|
||||
return [goCode + "\n", warnings];
|
||||
return goCode + "\n";
|
||||
};
|
||||
export const toGoWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toGo(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const go = _toGo(request, warnings);
|
||||
return [go, warnings];
|
||||
};
|
||||
export const toGo = (curlCommand: string | string[]): string => {
|
||||
return toGoWarn(curlCommand)[0];
|
||||
|
||||
@@ -27,11 +27,7 @@ const supportedArgs = new Set([
|
||||
|
||||
const doubleQuotes = (str: string): string => jsesc(str, { quotes: "double" });
|
||||
|
||||
export const _toJava = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
export const _toJava = (request: Request, warnings: Warnings = []): string => {
|
||||
let javaCode = "";
|
||||
|
||||
if (request.auth) {
|
||||
@@ -116,13 +112,15 @@ export const _toJava = (
|
||||
javaCode += "\t}\n";
|
||||
javaCode += "}";
|
||||
|
||||
return [javaCode + "\n", warnings];
|
||||
return javaCode + "\n";
|
||||
};
|
||||
export const toJavaWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toJava(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const java = _toJava(request, warnings);
|
||||
return [java, warnings];
|
||||
};
|
||||
|
||||
export const toJava = (curlCommand: string | string[]): string => {
|
||||
|
||||
@@ -234,10 +234,8 @@ const buildConfigObject = (
|
||||
|
||||
export const _toNodeAxios = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
let importCode = "const axios = require('axios');\n";
|
||||
const imports: Set<[string, string]> = new Set();
|
||||
|
||||
@@ -377,13 +375,15 @@ export const _toNodeAxios = (
|
||||
importCode += "const " + varName + " = require(" + repr(imp) + ");\n";
|
||||
}
|
||||
|
||||
return [importCode + "\n" + code, warnings];
|
||||
return importCode + "\n" + code;
|
||||
};
|
||||
export const toNodeAxiosWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toNodeAxios(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const nodeAxios = _toNodeAxios(request, warnings);
|
||||
return [nodeAxios, warnings];
|
||||
};
|
||||
export const toNodeAxios = (curlCommand: string | string[]): string => {
|
||||
return toNodeAxiosWarn(curlCommand)[0];
|
||||
|
||||
@@ -123,7 +123,7 @@ export const _toJavaScriptOrNode = (
|
||||
request: Request,
|
||||
warnings: Warnings,
|
||||
isNode: boolean
|
||||
): [string, Warnings] => {
|
||||
): string => {
|
||||
const fetchImports: Set<string> = new Set();
|
||||
const imports: Set<[string, string]> = new Set();
|
||||
|
||||
@@ -307,47 +307,44 @@ export const _toJavaScriptOrNode = (
|
||||
if (importCode) {
|
||||
code = importCode + "\n" + code;
|
||||
}
|
||||
return [code + "\n", warnings];
|
||||
return code + "\n";
|
||||
};
|
||||
|
||||
export const _toJavaScript = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
return _toJavaScriptOrNode(request, warnings, false);
|
||||
};
|
||||
export const _toNode = (request: Request, warnings: Warnings = []): string => {
|
||||
return _toJavaScriptOrNode(request, warnings, true);
|
||||
};
|
||||
|
||||
export const toJavaScriptWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(
|
||||
const request = util.parseCurlCommand(
|
||||
curlCommand,
|
||||
javaScriptSupportedArgs
|
||||
javaScriptSupportedArgs,
|
||||
warnings
|
||||
);
|
||||
return _toJavaScript(request, warnings);
|
||||
return [_toJavaScript(request, warnings), warnings];
|
||||
};
|
||||
|
||||
export const toJavaScript = (curlCommand: string | string[]): string => {
|
||||
return toJavaScriptWarn(curlCommand)[0];
|
||||
};
|
||||
|
||||
export const _toNode = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
return _toJavaScriptOrNode(request, warnings, true);
|
||||
};
|
||||
|
||||
export const toNodeWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(
|
||||
const request = util.parseCurlCommand(
|
||||
curlCommand,
|
||||
nodeSupportedArgs
|
||||
nodeSupportedArgs,
|
||||
warnings
|
||||
);
|
||||
return _toNode(request, warnings);
|
||||
return [_toNode(request, warnings), warnings];
|
||||
};
|
||||
export const toNode = (curlCommand: string | string[]): string => {
|
||||
return toNodeWarn(curlCommand)[0];
|
||||
|
||||
@@ -26,9 +26,8 @@ const supportedArgs = new Set([
|
||||
|
||||
export const _toNodeRequest = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
let nodeRequestCode = "var request = require('request');\n\n";
|
||||
if (request.headers) {
|
||||
nodeRequestCode += "var headers = {\n";
|
||||
@@ -87,14 +86,17 @@ export const _toNodeRequest = (
|
||||
nodeRequestCode += "}\n\n";
|
||||
nodeRequestCode += "request(options, callback);";
|
||||
|
||||
return [nodeRequestCode + "\n", warnings];
|
||||
return nodeRequestCode + "\n";
|
||||
};
|
||||
export const toNodeRequestWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
warnings.unshift(["node-request", "the request package is deprecated"]);
|
||||
return _toNodeRequest(request, warnings);
|
||||
|
||||
const nodeRequests = _toNodeRequest(request, warnings);
|
||||
return [nodeRequests, warnings];
|
||||
};
|
||||
export const toNodeRequest = (curlCommand: string | string[]): string => {
|
||||
return toNodeRequestWarn(curlCommand)[0];
|
||||
|
||||
@@ -122,10 +122,8 @@ function getFilesString(
|
||||
|
||||
export const _toJsonString = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
const requestJson: JSONOutput = {
|
||||
url: (request.queryDict ? request.urlWithoutQuery : request.url).replace(
|
||||
/\/$/,
|
||||
@@ -177,20 +175,21 @@ export const _toJsonString = (
|
||||
};
|
||||
}
|
||||
|
||||
return [
|
||||
return (
|
||||
JSON.stringify(
|
||||
Object.keys(requestJson).length ? requestJson : "{}",
|
||||
null,
|
||||
4
|
||||
) + "\n",
|
||||
warnings,
|
||||
];
|
||||
) + "\n"
|
||||
);
|
||||
};
|
||||
export const toJsonStringWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toJsonString(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const json = _toJsonString(request, warnings);
|
||||
return [json, warnings];
|
||||
};
|
||||
export const toJsonString = (curlCommand: string | string[]): string => {
|
||||
return toJsonStringWarn(curlCommand)[0];
|
||||
|
||||
@@ -29,26 +29,24 @@ const supportedArgs = new Set([
|
||||
|
||||
export const _toMATLAB = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
let webServicesLines, httpInterfaceLines;
|
||||
[webServicesLines, warnings] = toWebServices(request, warnings);
|
||||
[httpInterfaceLines, warnings] = toHTTPInterface(request, warnings);
|
||||
const lines = webServicesLines.concat("", httpInterfaceLines);
|
||||
return [
|
||||
lines
|
||||
.flat()
|
||||
.filter((line) => line !== null)
|
||||
.join("\n"),
|
||||
warnings,
|
||||
];
|
||||
return lines
|
||||
.flat()
|
||||
.filter((line) => line !== null)
|
||||
.join("\n");
|
||||
};
|
||||
export const toMATLABWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toMATLAB(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const matlab = _toMATLAB(request, warnings);
|
||||
return [matlab, warnings];
|
||||
};
|
||||
export const toMATLAB = (curlCommand: string | string[]): string => {
|
||||
return toMATLABWarn(curlCommand)[0];
|
||||
|
||||
@@ -31,9 +31,8 @@ const quote = (str: string | null | (string | null)[]): string =>
|
||||
|
||||
export const _toPhpRequests = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
let headerString: string;
|
||||
if (request.headers) {
|
||||
headerString = "$headers = array(\n";
|
||||
@@ -113,13 +112,15 @@ export const _toPhpRequests = (
|
||||
|
||||
phpCode += requestLine;
|
||||
|
||||
return [phpCode + "\n", warnings];
|
||||
return phpCode + "\n";
|
||||
};
|
||||
export const toPhpRequestsWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toPhpRequests(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const php = _toPhpRequests(request, warnings);
|
||||
return [php, warnings];
|
||||
};
|
||||
export const toPhpRequests = (curlCommand: string | string[]): string => {
|
||||
return toPhpRequestsWarn(curlCommand)[0];
|
||||
|
||||
@@ -36,11 +36,7 @@ const supportedArgs = new Set([
|
||||
|
||||
const quote = (str: string): string => jsesc(str, { quotes: "single" });
|
||||
|
||||
export const _toPhp = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
export const _toPhp = (request: Request, warnings: Warnings = []): string => {
|
||||
let cookieString;
|
||||
if (util.hasHeader(request, "cookie")) {
|
||||
cookieString = util.getHeader(request, "cookie");
|
||||
@@ -157,14 +153,16 @@ export const _toPhp = (
|
||||
phpCode += "\n$response = curl_exec($ch);\n\n";
|
||||
|
||||
phpCode += "curl_close($ch);\n";
|
||||
return [phpCode, warnings];
|
||||
return phpCode;
|
||||
};
|
||||
|
||||
export const toPhpWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toPhp(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const php = _toPhp(request, warnings);
|
||||
return [php, warnings];
|
||||
};
|
||||
export const toPhp = (curlCommand: string | string[]): string => {
|
||||
return toPhpWarn(curlCommand)[0];
|
||||
|
||||
@@ -667,9 +667,8 @@ function detectEnvVar(inputString: string): [Set<string>, string] {
|
||||
|
||||
export const _toPython = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
const imports: Set<string> = new Set();
|
||||
// Currently, only assuming that the env-var only used in
|
||||
// the value part of cookies, params, or body
|
||||
@@ -1024,17 +1023,18 @@ export const _toPython = (
|
||||
]);
|
||||
}
|
||||
|
||||
return [pythonCode + "\n", warnings];
|
||||
return pythonCode + "\n";
|
||||
};
|
||||
|
||||
export const toPythonWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toPython(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const python = _toPython(request, warnings);
|
||||
return [python, warnings];
|
||||
};
|
||||
|
||||
export const toPython = (curlCommand: string | string[]): string => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand);
|
||||
return _toPython(request, warnings)[0];
|
||||
return toPythonWarn(curlCommand)[0];
|
||||
};
|
||||
|
||||
@@ -92,11 +92,7 @@ function getFilesString(request: Request): string | undefined {
|
||||
return filesString;
|
||||
}
|
||||
|
||||
export const _toR = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
export const _toR = (request: Request, warnings: Warnings = []): string => {
|
||||
let cookieDict;
|
||||
if (request.cookies) {
|
||||
cookieDict = "cookies = c(\n";
|
||||
@@ -223,11 +219,15 @@ export const _toR = (
|
||||
}
|
||||
rstatsCode += requestLine;
|
||||
|
||||
return [rstatsCode + "\n", warnings];
|
||||
return rstatsCode + "\n";
|
||||
};
|
||||
export const toRWarn = (curlCommand: string | string[]): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toR(request, warnings);
|
||||
export const toRWarn = (
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const r = _toR(request, warnings);
|
||||
return [r, warnings];
|
||||
};
|
||||
export const toR = (curlCommand: string | string[]): string => {
|
||||
return toRWarn(curlCommand)[0];
|
||||
|
||||
@@ -29,11 +29,7 @@ const indent = (line: string, level = 1): string =>
|
||||
INDENTATION.repeat(level) + line;
|
||||
const quote = (str: string): string => jsesc(str, { quotes: "double" });
|
||||
|
||||
export const _toRust = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
export const _toRust = (request: Request, warnings: Warnings = []): string => {
|
||||
const lines = ["extern crate reqwest;"];
|
||||
{
|
||||
// Generate imports.
|
||||
@@ -121,13 +117,15 @@ export const _toRust = (
|
||||
"}"
|
||||
);
|
||||
|
||||
return [lines.join("\n") + "\n", warnings];
|
||||
return lines.join("\n") + "\n";
|
||||
};
|
||||
export const toRustWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toRust(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const rust = _toRust(request, warnings);
|
||||
return [rust, warnings];
|
||||
};
|
||||
export const toRust = (curlCommand: string | string[]): string => {
|
||||
return toRustWarn(curlCommand)[0];
|
||||
|
||||
@@ -94,9 +94,8 @@ type StrestOutput = {
|
||||
|
||||
export const _toStrest = (
|
||||
request: Request,
|
||||
warnings?: Warnings
|
||||
): [string, Warnings] => {
|
||||
warnings = warnings || [];
|
||||
warnings: Warnings = []
|
||||
): string => {
|
||||
const response: StrestOutput = { version: 2 };
|
||||
if (request.insecure) {
|
||||
response.allowInsecure = true;
|
||||
@@ -139,14 +138,15 @@ export const _toStrest = (
|
||||
response.requests.curl_converter.request.queryString = queryList;
|
||||
}
|
||||
|
||||
const yamlString = yaml.stringify(response, 100, 2);
|
||||
return [yamlString, warnings];
|
||||
return yaml.stringify(response, 100, 2);
|
||||
};
|
||||
export const toStrestWarn = (
|
||||
curlCommand: string | string[]
|
||||
curlCommand: string | string[],
|
||||
warnings: Warnings = []
|
||||
): [string, Warnings] => {
|
||||
const [request, warnings] = util.parseCurlCommand(curlCommand, supportedArgs);
|
||||
return _toStrest(request, warnings);
|
||||
const request = util.parseCurlCommand(curlCommand, supportedArgs, warnings);
|
||||
const strest = _toStrest(request, warnings);
|
||||
return [strest, warnings];
|
||||
};
|
||||
export const toStrest = (curlCommand: string | string[]): string => {
|
||||
return toStrestWarn(curlCommand)[0];
|
||||
|
||||
96
src/util.ts
96
src/util.ts
@@ -63,12 +63,6 @@ interface ShortOpts {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
interface PossibleArgs {
|
||||
supported: string[];
|
||||
unsupported: string[];
|
||||
ignored: string[];
|
||||
}
|
||||
|
||||
type Query = Array<[string, string | null]>;
|
||||
interface QueryDict {
|
||||
[key: string]: string | null | Array<string | null>;
|
||||
@@ -966,13 +960,34 @@ function toVal(node: any): string {
|
||||
}
|
||||
}
|
||||
|
||||
const reportError = (
|
||||
curlCommand: string,
|
||||
startCol: number,
|
||||
startRow: number,
|
||||
endCol: number,
|
||||
endRow: number
|
||||
): string => {
|
||||
// TODO: is this exactly how tree-sitter splits lines?
|
||||
const line = curlCommand.split("\n")[startRow];
|
||||
const end = endRow === startRow ? endCol : line.length;
|
||||
return (
|
||||
`Bash parsing error on line ${startRow + 1}:\n` +
|
||||
`${line}\n` +
|
||||
" ".repeat(startCol) +
|
||||
"^".repeat(end - startCol)
|
||||
);
|
||||
};
|
||||
|
||||
interface TokenizeResult {
|
||||
cmdName: string;
|
||||
args: string[];
|
||||
stdin?: string;
|
||||
input?: string;
|
||||
}
|
||||
const tokenize = (curlCommand: string): TokenizeResult => {
|
||||
const tokenize = (
|
||||
curlCommand: string,
|
||||
warnings: Warnings = []
|
||||
): TokenizeResult => {
|
||||
const curlArgs = parser.parse(curlCommand);
|
||||
// The AST must be in a nice format, i.e.
|
||||
// (program
|
||||
@@ -1004,20 +1019,20 @@ const tokenize = (curlCommand: string): TokenizeResult => {
|
||||
|
||||
// Get the curl call AST node. Skip comments
|
||||
let command, stdin, input;
|
||||
for (const programChildNode of curlArgs.rootNode.children) {
|
||||
if (programChildNode.type === "comment") {
|
||||
for (const n of curlArgs.rootNode.children) {
|
||||
if (n.type === "comment") {
|
||||
continue;
|
||||
} else if (programChildNode.type === "command") {
|
||||
command = programChildNode;
|
||||
} else if (n.type === "command") {
|
||||
command = n;
|
||||
// TODO: if there are more `command` nodes,
|
||||
// warn that everything after the first one is ignored
|
||||
break;
|
||||
} else if (programChildNode.type === "redirected_statement") {
|
||||
if (!programChildNode.childCount) {
|
||||
} else if (n.type === "redirected_statement") {
|
||||
if (!n.childCount) {
|
||||
throw new CCError("got empty 'redirected_statement' AST node");
|
||||
}
|
||||
let redirect;
|
||||
[command, redirect] = programChildNode.children;
|
||||
[command, redirect] = n.children;
|
||||
if (command.type !== "command") {
|
||||
throw new CCError(
|
||||
"got 'redirected_statement' AST node whose first child is not a 'command', got " +
|
||||
@@ -1025,7 +1040,7 @@ const tokenize = (curlCommand: string): TokenizeResult => {
|
||||
" instead"
|
||||
);
|
||||
}
|
||||
if (programChildNode.childCount < 2) {
|
||||
if (n.childCount < 2) {
|
||||
throw new CCError(
|
||||
"got 'redirected_statement' AST node with only one child - no redirect"
|
||||
);
|
||||
@@ -1041,7 +1056,7 @@ const tokenize = (curlCommand: string): TokenizeResult => {
|
||||
);
|
||||
}
|
||||
const heredocStart = redirect.namedChildren[0].text;
|
||||
const heredocBody = programChildNode.nextNamedSibling;
|
||||
const heredocBody = n.nextNamedSibling;
|
||||
if (!heredocBody) {
|
||||
throw new CCError(
|
||||
"got 'redirected_statement' AST node with no heredoc body"
|
||||
@@ -1081,6 +1096,16 @@ const tokenize = (curlCommand: string): TokenizeResult => {
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (n.type === "ERROR") {
|
||||
throw new CCError(
|
||||
reportError(
|
||||
curlCommand,
|
||||
n.startPosition.column,
|
||||
n.startPosition.row,
|
||||
n.endPosition.column,
|
||||
n.endPosition.row
|
||||
)
|
||||
);
|
||||
} else {
|
||||
// TODO: better error message.
|
||||
throw new CCError(
|
||||
@@ -1096,6 +1121,20 @@ const tokenize = (curlCommand: string): TokenizeResult => {
|
||||
"expected a 'command' or 'redirected_statement' AST node, only found 'comment' nodes"
|
||||
);
|
||||
}
|
||||
for (const n of curlArgs.rootNode.children) {
|
||||
if (n.type === "ERROR") {
|
||||
warnings.push([
|
||||
"bash",
|
||||
reportError(
|
||||
curlCommand,
|
||||
n.startPosition.column,
|
||||
n.startPosition.row,
|
||||
n.endPosition.column,
|
||||
n.endPosition.row
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (command.childCount < 1) {
|
||||
// TODO: better error message.
|
||||
@@ -1149,9 +1188,9 @@ const parseArgs = (
|
||||
args: string[],
|
||||
longOpts: LongOpts,
|
||||
shortOpts: ShortOpts,
|
||||
supportedOpts?: Set<string>
|
||||
): [ParsedArguments, Warnings] => {
|
||||
const warnings: Warnings = [];
|
||||
supportedOpts?: Set<string>,
|
||||
warnings: Warnings = []
|
||||
): ParsedArguments => {
|
||||
const parsedArguments: ParsedArguments = {};
|
||||
for (let i = 0, stillflags = true; i < args.length; i++) {
|
||||
let arg: string | string[] = args[i];
|
||||
@@ -1257,7 +1296,7 @@ const parseArgs = (
|
||||
parsedArguments[arg] = values[values.length - 1];
|
||||
}
|
||||
}
|
||||
return [parsedArguments, warnings];
|
||||
return parsedArguments;
|
||||
};
|
||||
|
||||
export function parseQueryString(
|
||||
@@ -1352,9 +1391,8 @@ export function parseQueryString(
|
||||
|
||||
function buildRequest(
|
||||
parsedArguments: ParsedArguments,
|
||||
warnings?: Warnings
|
||||
warnings: Warnings = []
|
||||
): Request {
|
||||
warnings = warnings || [];
|
||||
// TODO: handle multiple URLs
|
||||
if (!parsedArguments.url || !parsedArguments.url.length) {
|
||||
// TODO: better error message (could be parsing fail)
|
||||
@@ -1699,8 +1737,9 @@ function buildRequest(
|
||||
|
||||
function parseCurlCommand(
|
||||
curlCommand: string | string[],
|
||||
supportedArgs?: Set<string>
|
||||
): [Request, Warnings] {
|
||||
supportedArgs?: Set<string>,
|
||||
warnings: Warnings = []
|
||||
): Request {
|
||||
let cmdName: string,
|
||||
args: string[],
|
||||
stdin: undefined | string,
|
||||
@@ -1711,7 +1750,7 @@ function parseCurlCommand(
|
||||
throw new CCError("no arguments provided");
|
||||
}
|
||||
} else {
|
||||
({ cmdName, args, stdin, input } = tokenize(curlCommand));
|
||||
({ cmdName, args, stdin, input } = tokenize(curlCommand, warnings));
|
||||
if (typeof cmdName === "undefined") {
|
||||
throw new CCError("failed to parse input");
|
||||
}
|
||||
@@ -1732,11 +1771,12 @@ function parseCurlCommand(
|
||||
}
|
||||
}
|
||||
|
||||
const [parsedArguments, warnings] = parseArgs(
|
||||
const parsedArguments = parseArgs(
|
||||
args,
|
||||
curlLongOpts,
|
||||
curlShortOpts,
|
||||
supportedArgs
|
||||
supportedArgs,
|
||||
warnings
|
||||
);
|
||||
const request = buildRequest(parsedArguments, warnings);
|
||||
if (stdin) {
|
||||
@@ -1745,7 +1785,7 @@ function parseCurlCommand(
|
||||
if (input) {
|
||||
request.input = input;
|
||||
}
|
||||
return [request, warnings];
|
||||
return request;
|
||||
}
|
||||
|
||||
// Gets the first header, matching case-insensitively
|
||||
|
||||
@@ -10,7 +10,7 @@ export const fixturesDir = path.resolve(__dirname, "../../test/fixtures");
|
||||
|
||||
// Special case that returns the parsed argument object
|
||||
const toParser = (curl: string | string[]): string => {
|
||||
const [parserOutput, warnings] = utils.parseCurlCommand(curl);
|
||||
const parserOutput = utils.parseCurlCommand(curl);
|
||||
const code = JSON.stringify(parserOutput, null, 2);
|
||||
return code + "\n";
|
||||
};
|
||||
|
||||
@@ -129,7 +129,7 @@ const testFile = async (testFilename: string): Promise<void> => {
|
||||
throw new Error("input file doesn't exist: " + inputFile);
|
||||
}
|
||||
const curlCommand = fs.readFileSync(inputFile, "utf8");
|
||||
const requestedUrl = utils.parseCurlCommand(curlCommand)[0].url;
|
||||
const requestedUrl = utils.parseCurlCommand(curlCommand).url;
|
||||
if (!requestedUrl.replace("http://", "").startsWith(EXPECTED_URL)) {
|
||||
throw new Error(
|
||||
inputFile +
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"module": "es2022",
|
||||
"esModuleInterop": true,
|
||||
"strictNullChecks": true,
|
||||
"noUnusedParameters": false,
|
||||
"noUnusedLocals": false,
|
||||
"noImplicitReturns": true
|
||||
},
|
||||
"include": ["src/**/*", "test/**/*", "tools/**/*", "index.d.ts"],
|
||||
|
||||
Reference in New Issue
Block a user