"""FastAPI application factory.""" from __future__ import annotations from collections.abc import AsyncIterator from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles from app.api.routes import api_router from app.core.cache import init_cache, shutdown_cache from app.core.config import settings from app.core.middleware.cache_monitor import CacheAvailabilityMiddleware PROJECT_ROOT = Path(__file__).resolve().parent.parent FRONTEND_DIST = PROJECT_ROOT / "frontend" / "dist" FRONTEND_INDEX = FRONTEND_DIST / "index.html" def create_app() -> FastAPI: """Build FastAPI application instance.""" @asynccontextmanager async def lifespan(_: FastAPI) -> AsyncIterator[None]: await init_cache() try: yield finally: await shutdown_cache() application = FastAPI(title=settings.project_name, version=settings.version, lifespan=lifespan) application.include_router(api_router) application.add_middleware(CacheAvailabilityMiddleware) application.add_middleware( CORSMiddleware, allow_origins=[ # "https://kitchen-crm.k1nq.tech", # "http://192.168.31.51", # "http://localhost:8000", # "http://0.0.0.0:8000", # "http://127.0.0.1:8000", "*", # ! TODO: Убрать ], allow_credentials=True, allow_methods=["*"], # Разрешить все HTTP-методы allow_headers=["*"], # Разрешить все заголовки ) if FRONTEND_DIST.exists() and FRONTEND_INDEX.exists(): assets_dir = FRONTEND_DIST / "assets" if assets_dir.exists(): application.mount("/assets", StaticFiles(directory=assets_dir), name="frontend-assets") @application.get("/", include_in_schema=False) async def serve_frontend_root() -> FileResponse: # pragma: no cover - simple file response return FileResponse(FRONTEND_INDEX) @application.get("/{path:path}", include_in_schema=False) async def serve_frontend_path( path: str, ) -> FileResponse: # pragma: no cover - simple file response if path == "" or path.startswith("api"): raise HTTPException(status_code=404) candidate = FRONTEND_DIST / path if candidate.is_file(): return FileResponse(candidate) return FileResponse(FRONTEND_INDEX) return application app = create_app()