"""FastAPI app factory. Run with: `uvicorn mist.api.app:app --host 0.0.0.0 --port 8000` """ from __future__ import annotations import logging from contextlib import asynccontextmanager from collections.abc import AsyncIterator from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from mist.api import admin, auth, builds, catalog, downloads from mist.config import settings from mist.core import paths as core_paths log = logging.getLogger(__name__) @asynccontextmanager async def lifespan(_: FastAPI) -> AsyncIterator[None]: logging.basicConfig(level=settings.log_level) log.info("Mist API starting; environment=%s", settings.environment) core_paths.ensure_dirs() yield log.info("Mist API stopping") def create_app() -> FastAPI: app = FastAPI(title="Mist API", version="0.1.0", lifespan=lifespan) app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins or ["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(auth.router, prefix="/auth", tags=["auth"]) app.include_router(catalog.router, prefix="/catalog", tags=["catalog"]) app.include_router(admin.router, prefix="/admin", tags=["admin"]) app.include_router(builds.router, prefix="/builds", tags=["builds"]) app.include_router(downloads.router, prefix="/download", tags=["downloads"]) @app.get("/healthz", tags=["health"]) def healthz() -> dict[str, bool]: return {"ok": True} @app.get("/readyz", tags=["health"]) def readyz() -> dict[str, bool]: # TODO: actually check db / redis / rabbitmq reachability return {"ok": True} return app app = create_app()