Converts curl commands into ready-to-run VMware Orchestrator (vRO / Aria Orchestrator / VCF Orchestrator) JavaScript.
Available as an npm package or a webapp
- Parses almost any curl. The bash grammar from curlconverter replaces the Postman converter. Multi-line
\commands, trailing spaces after\, CRLF line endings, Windows cmd^(Chrome "Copy as cURL (cmd)"), PowerShell`andcurl.exe, smart quotes copied from docs, and a missingcurlkeyword all work. - Never fails on options vRO can't use.
-v,-s,--compressed,-oand similar are dropped. Unknown options,-Fuploads, proxies and other unsupported parts are listed underNotes:in the generated header. Only an unreadable command or a non-http(s) URL is an error. - No duplicated URL. The code defines
baseUrlandpathonce and uses them everywhere. - Plain ES5.1. No template literals. Multi-line bodies are built with string concatenation, so the code runs on every vRO Rhino version.
- Placeholders become inputs.
$var,${var},{{var}},{var}and<var>in URLs become camelCase inputs. - Secrets become SecureString inputs. This covers bearer tokens,
-upasswords, API-key headers and password, secret or token fields in bodies and queries. The secrets are also redacted from the curl comment. - Action or scriptable task output, an optional certificate import block and an optional log prefix.
- No runtime dependencies and no native modules.
deasyncis gone. The parser runs as WebAssembly in both Node and the browser.
Breaking change:
convertCurlToVROnow returns a Promise.
- Node.js 18 or later
- A vRO / Orchestrator 8.x or 9.x instance (with the REST plugin) to run the generated code
npm install curl2vroconst { convertCurlToVRO } = require('curl2vro');
const code = await convertCurlToVRO(`curl -k -u admin:secret https://nsx.vmw.lab/api/v1/logical-ports`, {
mode: 'action', // 'action' returns the result, 'task' sets the responseBody output
trustCertificate: true, // include the certificate import block
maskSecrets: true, // secrets become SecureString inputs
variablesAsInputs: true, // placeholders become inputs
includeCurlComment: true, // append the original curl (secrets redacted)
logPrefix: '[LAB][getLogicalPorts]',
writeToFile: false // also save <host>_<path>_<method>.js
});
console.log(code);ES modules:
import { convert } from 'curl2vro';
const { code, inputs, warnings, notes } = convert(curlCommand, { mode: 'task' });Browser (the web app uses this):
<script type="module">
import { convert } from './engine/curl2vro.browser.mjs'; // tree-sitter*.wasm must sit next to it
</script>curl --location --request POST \
'https://vra.lab/iaas/api/network-ip-ranges/{range_id}/ip-addresses/allocate?apiVersion=$api_version' \
-H "Authorization: Bearer $access_token" \
-H 'Content-Type: application/json' \
-d '{"description":"Automated IP Allocation","numberOfIps":1}'becomes
/**
* POST /iaas/api/network-ip-ranges/${range_id}/ip-addresses/allocate
* Generated by curl2vRO
*
* Action inputs:
* rangeId string // curl variable $range_id
* apiVersion string // curl variable $api_version
* accessToken SecureString // curl variable $access_token
*
* Return type: Any
*/
var baseUrl = "https://vra.lab";
var path = "/iaas/api/network-ip-ranges/" + rangeId + "/ip-addresses/allocate?apiVersion=" + apiVersion;
// Accept SSL certificate
var ld = Config.getKeystores().getImportCAFromUrlAction();
var model = ld.getModel();
model.value = baseUrl;
var error = ld.execute();
if (error) {
throw new Error("Failed to accept certificate for URL: " + baseUrl + ". Error: " + error);
}
// Transient REST host (not saved in the inventory)
var restHost = RESTHostManager.createTransientHostFrom(RESTHostManager.createHost("curl2vRO"));
restHost.url = baseUrl;
restHost.operationTimeout = 60;
restHost.connectionTimeout = 30;
var body = {
"description": "Automated IP Allocation",
"numberOfIps": 1
};
var request = restHost.createRequest("POST", path, JSON.stringify(body));
request.contentType = "application/json";
request.setHeader("Authorization", "Bearer " + accessToken);
System.log("POST " + baseUrl + path);
var response = request.execute();
var statusCode = response.statusCode;
var responseText = response.contentAsString;
System.log("Status code: " + statusCode);
if (statusCode < 200 || statusCode >= 300) {
throw new Error("POST " + path + " failed with status " + statusCode + ": " + responseText);
}
var result = responseText;
try {
result = JSON.parse(responseText);
} catch (e) {
// response is not JSON, keep it as text
}
return result;Returns the generated code. See the options above.
Returns { code, inputs: [{ name, type, source, secret }], output, warnings, notes, request }.
An alias of convertCurlToVRO, kept for 2.x callers.
| curl | vRO code |
|---|---|
-X, --request, -G, -I |
method on createRequest |
URL, query string, --url |
baseUrl + path |
-H, --header, -A, -e, -b (cookies) |
request.setHeader(...) |
-d, --data, --data-raw, --data-binary, --json |
JSON object literal, or a text/XML string |
--data-urlencode, form -d a=1&b=2 |
formParams encoded with encodeURIComponent |
-u user:pass, https://user:pass@host |
RESTAuthenticationManager Basic auth |
-k, --insecure |
certificate import block (on by default) |
-m, --max-time, --connect-timeout |
operationTimeout, connectionTimeout |
-v, -s, -L, -o, --compressed, -i … |
ignored |
-F multipart, -x proxy, digest/NTLM auth, URL globs |
skipped, explained under Notes: |
git clone https://github.com/imtrinity94/Curl2vRO.git
cd Curl2vRO
npm install
npm run build # bundles src/ into dist/ (Node + browser) and copies the wasm files
npm testThe source is in src/ (normalize.js cleans up pasted commands, parse.js builds the request model, generate.js writes the vRO code). dist/ is generated, and npm publish rebuilds it.
This project is licensed under the MIT License. See the LICENSE file for details.
Mayank Goyal
Website: cloudblogger.co.in
Email: mayankgoyalmax@gmail.com
Contributions are welcome. Feel free to open a pull request.