From b98368bb25bb0720e97cd04133dc1c437dfb62a2 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Sun, 22 Mar 2026 10:44:36 +0000 Subject: [PATCH] Initial upload: curl-converter-cli with CI/CD workflow --- curlconverter/generators/javascript.py | 103 +++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 curlconverter/generators/javascript.py diff --git a/curlconverter/generators/javascript.py b/curlconverter/generators/javascript.py new file mode 100644 index 0000000..4ccfafb --- /dev/null +++ b/curlconverter/generators/javascript.py @@ -0,0 +1,103 @@ +"""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 }"