|
11 | 11 | from importlib.metadata import PackageNotFoundError, version |
12 | 12 | from pathlib import Path |
13 | 13 |
|
14 | | -import httpx |
15 | 14 | import uvicorn |
16 | 15 | from dotenv import load_dotenv |
17 | 16 | from faker import Faker |
18 | | -from fastapi import FastAPI, Request |
19 | | -from fastapi.responses import FileResponse, Response |
| 17 | +from fastapi import FastAPI |
| 18 | +from fastapi.responses import FileResponse |
20 | 19 | from fastapi.staticfiles import StaticFiles |
21 | 20 | from rich.console import Console |
22 | 21 | from rich.text import Text |
@@ -49,19 +48,14 @@ def main(): |
49 | 48 | server.set_defaults(func=run_server) |
50 | 49 |
|
51 | 50 | dashboard = subparsers.add_parser( |
52 | | - "dashboard", help="Launch the AlphaTrion web dashboard" |
| 51 | + "dashboard", |
| 52 | + help="Serve pre-built dashboard (for testing production builds locally)", |
53 | 53 | ) |
54 | 54 | dashboard.add_argument( |
55 | 55 | "--port", |
56 | 56 | type=int, |
57 | 57 | default=5173, |
58 | | - help="Port to run the dashboard on (default: 5173)", |
59 | | - ) |
60 | | - dashboard.add_argument( |
61 | | - "--backend-url", |
62 | | - type=str, |
63 | | - default="http://localhost:8000", |
64 | | - help="Backend server URL to proxy requests to (default: http://localhost:8000)", |
| 58 | + help="Port to serve the dashboard on (default: 5173)", |
65 | 59 | ) |
66 | 60 | dashboard.set_defaults(func=start_dashboard) |
67 | 61 |
|
@@ -560,99 +554,29 @@ def start_dashboard(args): |
560 | 554 | ) |
561 | 555 | console.print(msg) |
562 | 556 | console.print(Text(f"📂 Serving static files from: {static_path}", style="dim")) |
563 | | - |
564 | | - console.print( |
565 | | - Text(f"🔗 Proxying backend requests to: {args.backend_url}", style="dim") |
566 | | - ) |
567 | 557 | console.print() |
568 | 558 | console.print( |
569 | | - Text("💡 Note: Make sure the backend server is running:", style="bold yellow") |
| 559 | + Text( |
| 560 | + "💡 Note: Make sure the backend server is running at http://localhost:8000", |
| 561 | + style="bold yellow", |
| 562 | + ) |
570 | 563 | ) |
571 | | - console.print(Text(" alphatrion server", style="cyan")) |
| 564 | + console.print(Text(" Run: alphatrion server", style="cyan")) |
572 | 565 | console.print() |
573 | 566 |
|
574 | 567 | app = FastAPI() |
575 | 568 |
|
576 | | - # Create HTTP client for proxying requests to backend |
577 | | - http_client = httpx.AsyncClient(base_url=args.backend_url, timeout=30.0) |
578 | | - |
579 | | - # Proxy /graphql requests to backend (MUST be before catch-all route) |
580 | | - @app.api_route("/graphql", methods=["GET", "POST"]) |
581 | | - async def proxy_graphql(request: Request): |
582 | | - headers = dict(request.headers) |
583 | | - headers.pop("host", None) # Remove host header |
584 | | - |
585 | | - try: |
586 | | - response = await http_client.request( |
587 | | - method=request.method, |
588 | | - url="/graphql", |
589 | | - content=await request.body(), |
590 | | - headers=headers, |
591 | | - ) |
592 | | - return Response( |
593 | | - content=response.content, |
594 | | - status_code=response.status_code, |
595 | | - headers=dict(response.headers), |
596 | | - ) |
597 | | - except Exception as e: |
598 | | - console.print(Text(f"❌ Error connecting to backend: {e}", style="red")) |
599 | | - return Response( |
600 | | - content=f'{{"error": "Backend server not available. Make sure it\'s running at {args.backend_url}"}}', |
601 | | - status_code=503, |
602 | | - media_type="application/json", |
603 | | - ) |
604 | | - |
605 | | - # Proxy /api requests to backend (MUST be before catch-all route) |
606 | | - @app.api_route("/api/{path:path}", methods=["GET", "POST", "PUT", "DELETE"]) |
607 | | - async def proxy_api(path: str, request: Request): |
608 | | - headers = dict(request.headers) |
609 | | - headers.pop("host", None) |
610 | | - |
611 | | - try: |
612 | | - response = await http_client.request( |
613 | | - method=request.method, |
614 | | - url=f"/api/{path}", |
615 | | - content=await request.body(), |
616 | | - headers=headers, |
617 | | - ) |
618 | | - return Response( |
619 | | - content=response.content, |
620 | | - status_code=response.status_code, |
621 | | - headers=dict(response.headers), |
622 | | - ) |
623 | | - except Exception as e: |
624 | | - console.print(Text(f"❌ Error connecting to backend: {e}", style="red")) |
625 | | - return Response( |
626 | | - content='{"error": "Backend server not available"}', |
627 | | - status_code=503, |
628 | | - media_type="application/json", |
629 | | - ) |
630 | | - |
631 | 569 | # Mount the entire static directory at /static |
632 | 570 | app.mount("/static", StaticFiles(directory=static_path, html=True), name="static") |
633 | 571 |
|
634 | | - @app.get("/") |
635 | | - def serve_root(): |
636 | | - # Serve index.html at root |
637 | | - index_file = static_path / "index.html" |
638 | | - if index_file.exists(): |
639 | | - return FileResponse(index_file) |
640 | | - return {"error": "index.html not found"} |
641 | | - |
| 572 | + # SPA fallback: serve index.html for all routes (enables client-side routing) |
642 | 573 | @app.get("/{full_path:path}") |
643 | 574 | def spa_fallback(full_path: str): |
644 | | - # Serve index.html for all routes (SPA fallback) |
645 | | - # This enables client-side routing |
646 | 575 | index_file = static_path / "index.html" |
647 | 576 | if index_file.exists(): |
648 | 577 | return FileResponse(index_file) |
649 | 578 | return {"error": "index.html not found"} |
650 | 579 |
|
651 | | - # Register cleanup handler for HTTP client |
652 | | - @app.on_event("shutdown") |
653 | | - async def shutdown_event(): |
654 | | - await http_client.aclose() |
655 | | - |
656 | 580 | url = f"http://127.0.0.1:{args.port}" |
657 | 581 |
|
658 | 582 | console.print(Text(f"🌐 Dashboard URL: {url}", style="bold cyan")) |
|
0 commit comments