import os import logging import sys from pathlib import Path from fastapi import FastAPI if __package__ in (None, ""): # Make `python app/main.py` behave like module execution from the project root. project_root = Path(__file__).resolve().parent.parent project_root_str = str(project_root) if project_root_str not in sys.path: sys.path.insert(0, project_root_str) from app.db import ( check_db_connection, check_shared_schema_tables, close_db_engine, init_db_tables, ) from app.logging_setup import configure_logging from app.middleware.auth import install_auth_middleware from app.middleware.request_log import install_request_logging_middleware from app.routers.auth import router as auth_router from app.routers.wechat_auth import router as wechat_auth_router from app.routers.health import router as health_router from app.routers.parents import router as parents_router from app.routers.children import router as children_router from app.routers.bindings import router as bindings_router from app.routers.devices import router as devices_router from app.routers.device_im import router as device_im_router from app.routers.device_location import router as device_location_router from app.routers.im import router as im_router from app.settings import settings configure_logging() logger = logging.getLogger("app.main") def create_app() -> FastAPI: app = FastAPI( title=settings.app_name, version=settings.app_version, description=settings.app_description, ) @app.on_event("startup") def on_startup() -> None: check_db_connection() if settings.db_auto_init_tables: init_db_tables() if settings.uses_shared_talkingq_db: logger.warning( "database auto init only creates mini-program tables; shared deployments should use the shared schema migration script", extra={ "event": "db_shared_auto_init_warning", "db_name": settings.db_name, }, ) else: check_shared_schema_tables() logger.info( "database auto init disabled", extra={ "event": "db_init_skipped", "db_name": settings.db_name, }, ) logger.info("application started", extra={"event": "app_start"}) @app.on_event("shutdown") def on_shutdown() -> None: logger.info("application shutting down", extra={"event": "app_shutdown"}) close_db_engine() install_auth_middleware(app) install_request_logging_middleware(app) app.include_router(wechat_auth_router) app.include_router(health_router) app.include_router(parents_router) app.include_router(children_router) app.include_router(bindings_router) app.include_router(devices_router) app.include_router(device_im_router) app.include_router(device_location_router) app.include_router(im_router) return app app = create_app() if __name__ == "__main__": import uvicorn uvicorn.run( app, host=os.getenv("HOST", settings.host), port=int(os.getenv("PORT", str(settings.port))), )