discovery-by-llm/backend/app/main.py
Justin Visser e171dd6d80
Some checks are pending
ci / backend (push) Waiting to run
ci / frontend (push) Waiting to run
feat: add Spotify client and auth routes
2026-08-10 10:53:14 +02:00

57 lines
1.8 KiB
Python

"""Application factory and wiring. No logic lives here."""
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from pathlib import Path
import httpx2
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from app.adapters.spotify.session import PendingLogins, SessionStore
from app.api.routes import router
from app.config import AppMode, Settings, settings
FRONTEND_DIST = Path(__file__).parent / "static"
def create_app(
application_settings: Settings | None = None,
http_transport: httpx2.AsyncBaseTransport | None = None,
) -> FastAPI:
"""Build the FastAPI app: API routes plus the built SPA on one port."""
active_settings = application_settings or settings
@asynccontextmanager
async def lifespan(application: FastAPI) -> AsyncIterator[None]:
if active_settings.app_mode is AppMode.LIVE and not active_settings.spotify_client_id:
raise RuntimeError("SPOTIFY_CLIENT_ID is required in live mode")
async with httpx2.AsyncClient(
timeout=active_settings.spotify_timeout_seconds,
transport=http_transport,
) as http:
application.state.http = http
application.state.session_store = SessionStore()
application.state.pending_logins = PendingLogins()
application.state.settings = active_settings
yield
app = FastAPI(
title="discovery-by-llm",
docs_url=None,
redoc_url=None,
lifespan=lifespan,
)
@app.get("/api/health")
def health() -> dict[str, str]:
return {"status": "ok", "mode": active_settings.app_mode}
app.include_router(router)
if FRONTEND_DIST.is_dir():
app.mount("/", StaticFiles(directory=FRONTEND_DIST, html=True), name="spa")
return app
app = create_app()