hirens15 / hs73

MIT License
0 stars 0 forks source link

test #1

Closed hirens15 closed 1 month ago

hirens15 commented 1 month ago

import os import yaml import anthropic import re import claudeapi_key

CLAUDE_PROMPT_TEMPLATE = """ You are a backend software engineer. Given the following OpenAPI 3.0 YAML specification, generate a complete C# .NET 8.0 Web API microservice project.

The project should be production-ready and must include:

The final output should be structured as clearly labeled code blocks with file names. For example:

// Program.cs

// Models/User.cs """

INPUT_DIR = "C:/Users/hiren/DotNetAPIGenerator/" OUTPUT_DIR = "C:/Users/hiren/DotNetAPIGenerator/GeneratedApi/Claude_generated_services_v3" CLAUDE_API_KEY = claudeapi_key.apikey

client = anthropic.Anthropic(api_key=CLAUDE_API_KEY)

def read_yaml_file(filepath): with open(filepath, "r", encoding="utf-8") as file: return file.read()

def call_claude_api(prompt): response = client.messages.create( model="claude-3-opus-20240229", # Change model as per availability max_tokens=4000, temperature=0.2, system="You are a senior .NET backend engineer.", messages=[{"role": "user", "content": prompt}] ) return response.content[0].text

def clean_filename(raw_filename):

Extract only the first line and strip extra characters

cleaned = raw_filename.split('\n')[0].split('```')[0].strip()

# Keep forward slashes for subfolders, clean all other invalid characters
cleaned = re.sub(r'[<>:"\\|?*]', '_', cleaned)  # Note: we don't replace `/`

return cleaned

def save_code_blocks(output_text, service_name): service_dir = os.path.join(OUTPUT_DIR, service_name) os.makedirs(service_dir, exist_ok=True)

# Extract code blocks: // Filename\n```csharp\n<code>```
code_blocks = re.findall(r'//\s*(.+?)\n```(?:csharp|json|xml)?\n(.*?)```', output_text, re.DOTALL)

for raw_filename, code in code_blocks:
    filename = clean_filename(raw_filename)  # 'Models/User.cs'
    relative_path = filename.replace("/", os.sep)  # 'Models\User.cs' on Windows
    full_path = os.path.normpath(os.path.join(service_dir, relative_path))  # Final full path

    os.makedirs(os.path.dirname(full_path), exist_ok=True)
    with open(full_path, "w", encoding="utf-8") as f:
        f.write(code.strip())

    print(f"āœ… Saved: {full_path}")

return len(code_blocks)

def enhance_generated_code(service_dir):

=== Inject Swagger support into Program.cs ===

program_cs_path = os.path.join(service_dir, "Program.cs")
if os.path.exists(program_cs_path):
    with open(program_cs_path, "r+", encoding="utf-8") as f:
        content = f.read()
        changed = False

        # Inject Swagger services
        if "AddSwaggerGen" not in content:
            content = content.replace(
                "builder.Services.AddControllers();",
                "builder.Services.AddControllers();\n"
                "builder.Services.AddEndpointsApiExplorer();\n"
                "builder.Services.AddSwaggerGen();"
            )
            changed = True

        # Inject Swagger middleware
        if "app.UseSwagger();" not in content:
            content = content.replace(
                "app.MapControllers();",
                "if (app.Environment.IsDevelopment())\n"
                "{\n"
                "    app.UseSwagger();\n"
                "    app.UseSwaggerUI(c =>\n"
                "    {\n"
                "        c.SwaggerEndpoint(\"/swagger/v1/swagger.json\", \"Generated API v1\");\n"
                "        c.RoutePrefix = \"\";\n"
                "    });\n"
                "}\n\n"
                "app.MapControllers();"
            )
            changed = True

        if changed:
            f.seek(0)
            f.write(content)
            f.truncate()
            print("āœ… Enhanced Program.cs with Swagger support")

# === Inject root GET / route ===
controller_dir = os.path.join(service_dir, "Controllers")
if os.path.exists(controller_dir):
    for fname in os.listdir(controller_dir):
        if fname.endswith(".cs"):
            controller_path = os.path.join(controller_dir, fname)
            with open(controller_path, "r+", encoding="utf-8") as f:
                content = f.read()

                if '[Route("/")' not in content and 'GET /' not in content:
                    index_method = (
                        "\n    [HttpGet]\n"
                        "    [Route(\"/\")]\n"
                        "    public IActionResult Index()\n"
                        "    {\n"
                        "        return Ok(\"API is running\");\n"
                        "    }\n"
                    )

                    # Insert before final closing brace
                    if content.strip().endswith("}"):
                        content = content.rstrip("}").rstrip() + index_method + "\n}"

                        f.seek(0)
                        f.write(content)
                        f.truncate()
                        print(f"āœ… Added root route to {fname}")
                    break  # only update one controller

                # === Inject launchSettings.json to auto-open Swagger in browser ===
                    properties_dir = os.path.join(service_dir, "Properties")
                    os.makedirs(properties_dir, exist_ok=True)

                    launch_settings = {
                        "profiles": {
                            "GeneratedApi": {
                                "commandName": "Project",
                                "launchBrowser": True,
                                "launchUrl": "",
                                "applicationUrl": "https://localhost:5001;http://localhost:5000",
                                "environmentVariables": {
                                    "ASPNETCORE_ENVIRONMENT": "Development"
                                }
                            }
                        }
                    }

                    launch_path = os.path.join(properties_dir, "launchSettings.json")
                    with open(launch_path, "w", encoding="utf-8") as f:
                        json.dump(launch_settings, f, indent=4)
                        print("āœ… Added launchSettings.json for Visual Studio Swagger launch")                    

def main(): os.makedirs(OUTPUT_DIR, exist_ok=True)

for filename in os.listdir(INPUT_DIR):
    if filename.endswith(".yaml") or filename.endswith(".yml"):
        yaml_path = os.path.join(INPUT_DIR, filename)
        service_name = os.path.splitext(filename)[0]

        print(f"\nšŸš€ Processing {filename}...")

        yaml_content = read_yaml_file(yaml_path)
        prompt = CLAUDE_PROMPT_TEMPLATE + "\n\n" + yaml_content

        try:
            response_text = call_claude_api(prompt)
            count = save_code_blocks(response_text, service_name)
            print(f"āœ… Generated {count} files for: {service_name}")

            #service_path = os.path.join(OUTPUT_DIR, service_name)
            #enhance_generated_code(service_path)

            #run_dotnet_project(service_path)       # Optional
            #open_swagger_ui("56562")                # Adjust port as needed

        except Exception as e:
            print(f"āŒ Error generating project for {filename}: {e}")

import webbrowser

def open_swagger_ui(port="5001"): url = f"https://localhost:{port}/swagger" print(f"🌐 Launching Swagger UI: {url}") webbrowser.open(url)

import subprocess

def run_dotnet_project(project_dir): print(f"šŸš€ Running project at: {project_dir}") subprocess.Popen(["dotnet", "run"], cwd=project_dir, shell=True)

if name == "main": main()