from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse, HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates import os import uvicorn from loguru import logger import sys from pathlib import Path from app.core.config import settings from app.api.routes import router as api_router # Configure logging logger.remove() logger.add( sys.stdout, format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}", level="DEBUG" if settings.DEBUG else "INFO", ) # Create FastAPI app app = FastAPI( title=settings.APP_NAME, version=settings.APP_VERSION, description="A lightweight document compliance and validation tool", docs_url="/docs", redoc_url="/redoc", openapi_url="/openapi.json", ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], # In production, this should be restricted allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Create templates directory templates_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates") os.makedirs(templates_dir, exist_ok=True) templates = Jinja2Templates(directory=templates_dir) # Create static files directory if it doesn't exist static_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "static") if not os.path.exists(static_dir): os.makedirs(static_dir, exist_ok=True) # Ensure CSS and JS directories exist css_dir = os.path.join(static_dir, "css") js_dir = os.path.join(static_dir, "js") os.makedirs(css_dir, exist_ok=True) os.makedirs(js_dir, exist_ok=True) # Mount static files app.mount("/static", StaticFiles(directory=static_dir), name="static") # Include API routes app.include_router(api_router, prefix="/api") # Root endpoint - serve the frontend @app.get("/", response_class=HTMLResponse) async def root(request: Request): # Check if index.html exists in static directory index_path = os.path.join(static_dir, "index.html") if os.path.exists(index_path): with open(index_path, "r") as f: return HTMLResponse(content=f.read()) # If not found, return a simple HTML response return HTMLResponse( content=f""" {settings.APP_NAME}

{settings.APP_NAME}

Welcome to {settings.APP_NAME}, a lightweight document compliance and validation tool.

This application is currently running in API-only mode.

""" ) # Health check endpoint @app.get("/health") async def health(): return {"status": "healthy"} # Global exception handler @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): logger.error(f"Unhandled exception: {str(exc)}") return JSONResponse( status_code=500, content={"message": "An unexpected error occurred", "detail": str(exc)}, ) if __name__ == "__main__": uvicorn.run( "app.main:app", host="0.0.0.0", port=8000, reload=settings.DEBUG, log_level="debug" if settings.DEBUG else "info", )