from fastapi import FastAPI from fastapi.responses import FileResponse from fastapi.middleware.cors import CORSMiddleware from pathlib import Path from app.routers import ( actions as actions_router, alerts, emulated_session as emulated_session_router, logs as logs_router, network, query as query_router, ) from app.services import log_ingest app = FastAPI(title="P5G Marvis", version="1.0.0", docs_url="/api/docs") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) app.include_router(network.router, prefix="/api") app.include_router(alerts.router, prefix="/api") app.include_router(query_router.router, prefix="/api") app.include_router(actions_router.router, prefix="/api") app.include_router(logs_router.router, prefix="/api") app.include_router(emulated_session_router.router, prefix="/api") UI = Path(__file__).parent / "ui" / "index.html" OVERVIEW_UI = Path(__file__).parent / "ui" / "overview.html" TASKS_UI = Path(__file__).parent / "ui" / "tasks.html" ACTIONS_UI = Path(__file__).parent / "ui" / "actions.html" @app.get("/health") async def health(): return {"status": "ok"} @app.get("/overview") async def overview_page(): return FileResponse(str(OVERVIEW_UI)) @app.get("/minis") async def minis_page(): return FileResponse(str(TASKS_UI)) @app.get("/tasks") async def tasks_page(): return FileResponse(str(TASKS_UI)) @app.get("/actions") async def actions_page(): return FileResponse(str(ACTIONS_UI)) @app.on_event("startup") async def _startup() -> None: await log_ingest.startup() @app.on_event("shutdown") async def _shutdown() -> None: await log_ingest.shutdown() # Catch-all: serve the SPA for any unmatched path (supports deep-linking) @app.get("/{full_path:path}") async def spa(full_path: str): return FileResponse(str(UI))