from fastapi import FastAPI, Request, WebSocket from fastapi.middleware.cors import CORSMiddleware from .core.config import settings from .db.database import async_engine as engine, Base from .api import auth, products, orders, users, analytics, files, notifications, calendar, scheduler, maintenance from .utils.rate_limiter import rate_limiter from .utils.logger import log_api_request from .utils.tasks import run_periodic_tasks from .services.websocket import connect, disconnect import time import logging import asyncio from typing import List # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) app = FastAPI(title=settings.PROJECT_NAME, version=settings.VERSION) # Store background tasks background_tasks = set() # Configure CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], # Configure appropriately for production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # WebSocket endpoint @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await connect(websocket) try: while True: data = await websocket.receive_text() except: await disconnect(websocket) # Request logging and rate limiting middleware @app.middleware("http") async def middleware(request: Request, call_next): await rate_limiter.check_rate_limit(request) start_time = time.time() response = await call_next(request) end_time = time.time() duration = end_time - start_time log_api_request( method=request.method, path=request.url.path, status_code=response.status_code, duration=duration ) return response # Application startup and shutdown events @app.on_event("startup") async def startup_event(): # Create all database tables async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) # Start background tasks task = asyncio.create_task(run_periodic_tasks()) background_tasks.add(task) task.add_done_callback(background_tasks.discard) @app.on_event("shutdown") async def shutdown_event(): # Cancel background tasks for task in background_tasks: task.cancel() # Include routers app.include_router(auth.router, prefix=f"{settings.API_V1_STR}/auth", tags=["auth"]) app.include_router(users.router, prefix=f"{settings.API_V1_STR}/users", tags=["users"]) app.include_router(products.router, prefix=f"{settings.API_V1_STR}/products", tags=["products"]) app.include_router(orders.router, prefix=f"{settings.API_V1_STR}/orders", tags=["orders"]) app.include_router(analytics.router, prefix=f"{settings.API_V1_STR}/analytics", tags=["analytics"]) app.include_router(files.router, prefix=f"{settings.API_V1_STR}/files", tags=["files"]) app.include_router(notifications.router, prefix=f"{settings.API_V1_STR}/notifications", tags=["notifications"]) app.include_router(calendar.router, prefix=f"{settings.API_V1_STR}/calendar", tags=["calendar"]) app.include_router(scheduler.router, prefix=f"{settings.API_V1_STR}/scheduler", tags=["scheduler"]) app.include_router(maintenance.router, prefix=f"{settings.API_V1_STR}/maintenance", tags=["maintenance"]) @app.get("/") async def root(): return { "message": f"Welcome to {settings.PROJECT_NAME} v{settings.VERSION}", "docs_url": "/docs", "openapi_url": "/openapi.json" }