api.py 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. """FastAPI:把 ck_post / ck_knowledge_item 暴露给 web 可视化,并托管单页前端。
  2. 启动:
  3. CK_ENV_FILE=/path/.env uvicorn creation_knowledge.api:app --host 0.0.0.0 --port 8900
  4. API 在 /api/*,前端单页在 /。
  5. """
  6. from __future__ import annotations
  7. import os
  8. from functools import lru_cache
  9. from pathlib import Path
  10. from fastapi import FastAPI, HTTPException
  11. from fastapi.middleware.cors import CORSMiddleware
  12. from fastapi.staticfiles import StaticFiles
  13. from creation_knowledge.config import PgConfig
  14. from creation_knowledge.integrations.db import CkStore
  15. WEB_DIR = Path(__file__).resolve().parent.parent / "web"
  16. @lru_cache(maxsize=1)
  17. def _store() -> CkStore:
  18. env_file = os.getenv("CK_ENV_FILE", ".env")
  19. return CkStore(PgConfig.from_env(env_file))
  20. app = FastAPI(title="创作知识")
  21. app.add_middleware(
  22. CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]
  23. )
  24. @app.get("/api/posts")
  25. def list_posts() -> list[dict]:
  26. return _store().posts_overview()
  27. @app.get("/api/posts/{post_id}")
  28. def get_post(post_id: str) -> dict:
  29. post = _store().read_post(post_id)
  30. if not post:
  31. raise HTTPException(status_code=404, detail="post not found")
  32. return post
  33. @app.get("/api/posts/{post_id}/items")
  34. def get_items(post_id: str) -> list[dict]:
  35. return _store().read_items(post_id)
  36. # 单页前端挂在最后(catch-all),不影响上面的 /api 路由
  37. if WEB_DIR.exists():
  38. app.mount("/", StaticFiles(directory=str(WEB_DIR), html=True), name="web")