Files
curl-converter-cli/curlconverter/generators/javascript.py

104 lines
3.6 KiB
Python

"""JavaScript code generator."""
import json
from curlconverter.parser import ParsedCurl
from curlconverter.generators import register_generator
def _detect_content_type(headers: dict, data: str) -> str:
"""Detect content type from headers or data."""
if "Content-Type" in headers:
return headers["Content-Type"]
if "content-type" in headers:
return headers["content-type"]
if data:
try:
json.loads(data)
return "application/json"
except (json.JSONDecodeError, TypeError):
pass
return "application/x-www-form-urlencoded"
@register_generator("javascript")
def generate_javascript(parsed: ParsedCurl) -> str:
"""Generate JavaScript fetch code from parsed curl data."""
lines = []
lines.append("const url = " + repr(parsed.url) + ";")
lines.append("")
options = {"method": parsed.method}
headers = dict(parsed.headers) if parsed.headers else {}
if parsed.user_agent and "User-Agent" not in headers and "user-agent" not in headers:
headers["User-Agent"] = parsed.user_agent
if parsed.data:
content_type = _detect_content_type(headers, parsed.data)
if content_type == "application/json":
try:
json_data = json.loads(parsed.data)
lines.append("const jsonData = " + json.dumps(json_data, indent=2) + ";")
options["body"] = "JSON.stringify(jsonData)"
if "Content-Type" not in headers and "content-type" not in headers:
headers["Content-Type"] = "application/json"
except (json.JSONDecodeError, TypeError):
lines.append("const data = " + repr(parsed.data) + ";")
options["body"] = "data"
else:
lines.append("const data = " + repr(parsed.data) + ";")
options["body"] = "data"
if parsed.cookies:
if "Cookie" not in headers and "cookie" not in headers:
headers["Cookie"] = parsed.cookies
if headers:
lines.append("const headers = " + _format_object(headers) + ";")
options["headers"] = "headers"
if parsed.auth:
auth_str = f"{parsed.auth[0]}:{parsed.auth[1]}"
import base64
encoded = base64.b64encode(auth_str.encode()).decode()
lines.append("const auth = " + repr(encoded) + ";")
if "Authorization" not in headers and "content-type" not in headers:
lines.append("const headersWithAuth = {")
lines.append(" ...headers,")
lines.append(' "Authorization": `Basic ${auth}`')
lines.append("};")
options["headers"] = "headersWithAuth"
options_str = _format_options(options)
lines.append("")
lines.append(f"fetch(url, {options_str})")
lines.append(" .then(response => {")
lines.append(" console.log(response.status);")
lines.append(" return response.text();")
lines.append(" })")
lines.append(" .then(data => console.log(data))")
lines.append(" .catch(error => console.error(error));")
return "\n".join(lines)
def _format_object(obj: dict) -> str:
"""Format an object for JavaScript code."""
if not obj:
return "{}"
items = []
for k, v in obj.items():
items.append(f' {repr(k)}: {repr(v)}')
return "{\n" + ",\n".join(items) + "\n}"
def _format_options(opts: dict) -> str:
"""Format fetch options for JavaScript code."""
if not opts:
return "{}"
items = []
for k, v in opts.items():
items.append(f" {k}: {v}")
return "{\n" + ",\n".join(items) + "\n }"