"""FastAPI application entrypoint — ``create_app()`` factory + lifespan.""" from __future__ import annotations from collections.abc import AsyncIterator from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse from app.core.errors import register_exception_handlers from app.core.logging import configure_logging from app.core.settings import get_settings from app.routers import health @asynccontextmanager async def _lifespan(_: FastAPI) -> AsyncIterator[None]: configure_logging() # M2: warm the fast engine here, then flip /health readiness once weights load. yield def create_app() -> FastAPI: settings = get_settings() app = FastAPI( title=f"{settings.app_name} API", version=settings.version, description=( "Uzbek speech-to-text service. Errors follow RFC 9457 " "(application/problem+json). No authentication by design — see the README." ), lifespan=_lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins, allow_methods=["GET", "POST", "OPTIONS"], allow_headers=["*"], ) register_exception_handlers(app) app.include_router(health.router) @app.get("/", include_in_schema=False) async def _root() -> RedirectResponse: # M3 mounts the Gradio UI here; until then, send visitors to the API docs. return RedirectResponse(url="/docs") return app app = create_app()