from __future__ import annotations from collections.abc import Callable from contextlib import asynccontextmanager from fastapi import FastAPI from cloud.auth import create_auth_provider from cloud.control_config import ( CloudControlConfig, load_control_config, validate_control_config, ) from cloud.database import CloudDatabase DatabaseFactory = Callable[[CloudControlConfig], CloudDatabase] def create_app( *, config: CloudControlConfig | None = None, database_factory: DatabaseFactory | None = None, ) -> FastAPI: """Create the independently deployable cloud API application.""" control_config = config or load_control_config() validate_control_config(control_config) build_database = database_factory or _default_database_factory auth_provider = create_auth_provider( control_config.credentials, allow_insecure_anonymous=control_config.allow_insecure_anonymous, ) @asynccontextmanager async def lifespan(app: FastAPI): database = build_database(control_config) app.state.cloud_config = control_config app.state.database = database app.state.auth_provider = auth_provider try: yield finally: database.close() return FastAPI(title="Device Cloud API", lifespan=lifespan) def _default_database_factory(config: CloudControlConfig) -> CloudDatabase: return CloudDatabase( config.database_url, create_schema=config.environment != "production", )