from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
import uvicorn
import time
import json
from api_routes import router
app = FastAPI(title="Faulkner DB Visualization API")
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Add timing middleware for monitoring
@app.middleware("http")
async def add_process_time_header(request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
# Mount static files
app.mount("/static", StaticFiles(directory="static"), name="static")
# Include API routes
app.include_router(router, prefix="/api")
@app.get("/")
async def root():
return {"message": "Faulkner DB Visualization API", "docs": "/docs"}
@app.get("/health")
async def health():
return {"status": "healthy"}
# WebSocket endpoint for real-time updates
class ConnectionManager:
def __init__(self):
self.active_connections: list[WebSocket] = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)
def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)
async def broadcast(self, message: dict):
for connection in self.active_connections:
try:
await connection.send_text(json.dumps(message))
except:
pass
manager = ConnectionManager()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
try:
while True:
# Keep connection alive and listen for messages
data = await websocket.receive_text()
# Echo back for now (can be extended for bidirectional communication)
await websocket.send_text(json.dumps({"type": "pong", "data": data}))
except WebSocketDisconnect:
manager.disconnect(websocket)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8082, reload=True)