{"id":31698823,"url":"https://github.com/twtrubiks/graphql-python-blog","last_synced_at":"2025-10-08T19:11:22.395Z","repository":{"id":318115661,"uuid":"1070045760","full_name":"twtrubiks/graphql-python-blog","owner":"twtrubiks","description":"練習 GraphQL-First TDD tutorial","archived":false,"fork":false,"pushed_at":"2025-10-05T06:32:31.000Z","size":336,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-05T08:33:30.057Z","etag":null,"topics":["fastapi","graphql","postgresql","strawberry","tdd-python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/twtrubiks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-05T06:30:05.000Z","updated_at":"2025-10-05T06:33:43.000Z","dependencies_parsed_at":"2025-10-05T08:43:46.612Z","dependency_job_id":null,"html_url":"https://github.com/twtrubiks/graphql-python-blog","commit_stats":null,"previous_names":["twtrubiks/graphql-python-blog"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/twtrubiks/graphql-python-blog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twtrubiks%2Fgraphql-python-blog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twtrubiks%2Fgraphql-python-blog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twtrubiks%2Fgraphql-python-blog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twtrubiks%2Fgraphql-python-blog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/twtrubiks","download_url":"https://codeload.github.com/twtrubiks/graphql-python-blog/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twtrubiks%2Fgraphql-python-blog/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000701,"owners_count":26082805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","graphql","postgresql","strawberry","tdd-python"],"created_at":"2025-10-08T19:11:02.583Z","updated_at":"2025-10-08T19:11:22.383Z","avatar_url":"https://github.com/twtrubiks.png","language":"Python","readme":"# GraphQL Blog Platform\n\n本專案目標是透過 Claude 學習, GraphQL API 和 Python 後端,\n\n練習 GraphQL-First TDD 開發方法的最佳實.\n\n## 🎯 專案目標\n\n建立一個功能完整的部落格平台，作為 GraphQL + Python 的教學範例，展示：\n- GraphQL API 設計與實作\n- Test-Driven Development (TDD) 實踐\n- 現代化的前後端架構\n- 向量搜尋與 AI 功能整合 (尚未實做)\n\n## 🛠 技術棧\n\n### 後端\n- **Python 3.13** - 最新版 Python\n- **FastAPI** - 現代化 Web 框架\n- **Strawberry** - Python GraphQL 函式庫\n  - 選擇理由：原生 Type Hints 支援、與 FastAPI 完美整合、簡潔的裝飾器語法\n  - 相比 Graphene 更現代化、更 Pythonic、開發效率更高\n- **SQLAlchemy 2.0** - ORM 與資料庫操作\n- **PostgreSQL 16** - 主要資料庫\n- **pgvector** - 向量搜尋擴充套件（進階功能）(尚未實做)\n\n### 前端\n- **SvelteKit 2.41+** - 全端框架\n- **Svelte 5** - 使用最新的 Runes 系統\n- **Houdini v2.0.0-next.9** - GraphQL 客戶端（完整支援 Svelte 5）\n- **Tailwind CSS** - 樣式框架\n- **Vite 7** - 建置工具\n\n### 測試\n- **pytest** - 測試框架\n- **pytest-asyncio** - 異步測試支援\n- **httpx** - API 測試客戶端\n\n## 📋 專案文件\n\n### 核心文件\n| 文件 | 說明 | 用途 |\n|------|------|------|\n| [產品需求文件](./docs/prd.md) | 定義專案功能與需求 | 了解要做什麼 |\n| [系統架構文件](./docs/architecture.md) | C4 模型架構圖與技術決策 | 了解怎麼做 |\n| [任務清單](./docs/tasks.md) | 詳細的開發任務分解 | 追蹤執行進度 |\n\n### 開發指南\n| 文件 | 說明 | 用途 |\n|------|------|------|\n| [TDD 完整指南](./docs/tdd-guide.md) | 測試驅動開發實踐方法 | 學習 TDD 方法論 |\n| [Alembic 指南](./docs/alembic-guide.md) | 資料庫遷移管理 | 管理資料庫版本 |\n\n### GraphQL 專題\n| 文件 | 說明 | 用途 |\n|------|------|------|\n| [DataLoader 實作](./docs/dataloader-implementation.md) | N+1 查詢問題解決方案 | 效能優化指南 |\n| [Union Types 指南](./docs/union-types-guide.md) | GraphQL Union Types 完整說明 | 多型返回值處理 |\n| [Fragment 指南](./docs/fragment-guide.md) | GraphQL Fragment 重用機制 | 減少重複查詢 |\n| [權限控制指南](./docs/permissions-guide.md) | GraphQL 權限控制機制 | 實作授權與權限管理 |\n| [Relay Connection Pattern](./docs/relay-connection-pattern.md) | 標準化分頁實作 | 實現游標分頁 |\n\n### 參考資料\n| 文件 | 說明 | 用途 |\n|------|------|------|\n| [GraphQL 介紹](./docs/graphql-intro.md) | GraphQL 基礎概念 | 入門學習 |\n| [GraphQL vs REST](./docs/graphql-vs-rest.md) | API 設計比較 | 技術選型參考 |\n\n### 專案模組文件\n| 模組 | 文件連結 | 說明 |\n|------|---------|------|\n| 前端 | [Frontend README](./frontend/README.md) | SvelteKit + Houdini 前端專案 |\n| 後端 | [Backend README](./backend/README.md) | FastAPI + Strawberry 後端專案 |\n\n## 🚀 快速開始\n\n### 環境需求\n\n- Python 3.13+\n- Node.js 22+\n- Docker 和 Docker Compose\n\n### 啟動\n\ndb `blog_db`\n\n```bash\ndocker-compose up -d\n```\n\n後端\n\n```bash\ncd backend\n\n# 設定你的環境\npython -m venv venv\nsource venv/bin/activate\npip install -r requirements.txt\npip install -r requirements-test.txt # 如果要跑測試\n\n# migrate\nalembic upgrade head\n\n# 在 debug 中會自動 init_db()\nuvicorn app.main:app --host 0.0.0.0 --port 8000\n\n# 也可以使用 FastAPI CLI\n# fastapi dev app/main.py\n```\n\n後端 API [http://localhost:8000](http://localhost:8000)\n\n後端 API 文檔 [http://localhost:8000/docs](http://localhost:8000/docs)\n\nGraphQL [http://localhost:8000/graphql](http://localhost:8000/graphql)\n\n前端\n\n```bash\ncd frontend\n\nnpm install\n\n# 確保後端已經運行, 目的是要產生 schema.graphql\nnpm run codegen:pull\n\nnpm run dev\n```\n\n前端入口 [http://localhost:5173](http://localhost:5173)\n\n### 生成資料\n\n會使用 db `blog_db`\n\n```bash\ncd backend\n\n# 創建測試用戶和文章\npython3 ../scripts/seed-data.py\n```\n\n## 測試執行\n\n### 測試腳本\n\n會使用 db `test_blog`\n\n```bash\ncd backend\n\n# 建立 pytest 跑得測試 db\npython3 ../scripts/setup-test-db.py\n\n# 執行所有測試\npytest\n\n=========== 229 passed in 94.34s (0:01:34) =======================\n\n# 只執行 GraphQL 測試\npytest tests/graphql/\n\n# 執行特定測試檔案\npytest tests/graphql/queries/test_post_queries.py\n\n# 顯示覆蓋率\npytest --cov=app --cov-report=html\n\n# 執行快速測試（跳過慢速測試）\npytest -m \"not slow\"\n```\n\n### 測試標記\n\n```python\n@pytest.mark.slow  # 慢速測試（如整合測試）\n@pytest.mark.unit  # 單元測試\n@pytest.mark.integration  # 整合測試\n@pytest.mark.graphql  # GraphQL API 測試\n```\n\n## 📁 專案結構\n\n```\nGraphQL/\n├── backend/\n│   ├── app/\n│   │   ├── api/           # API 端點\n│   │   ├── graphql/       # GraphQL schema 和 resolvers\n│   │   ├── models/        # SQLAlchemy models\n│   │   ├── services/      # 業務邏輯\n│   │   ├── core/          # 核心設定\n│   │   └── utils/         # 工具函數\n│   ├── tests/             # 測試檔案\n│   ├── alembic/           # 資料庫遷移\n│   └── requirements.txt\n├── frontend/\n│   ├── src/\n│   │   ├── routes/        # SvelteKit 路由\n│   │   ├── lib/           # 共用元件\n│   │   └── $houdini/      # GraphQL 生成檔案\n│   └── package.json\n├── docker-compose.yml\n└── docs/                  # 專案文件\n    ├── prd.md\n    ├── architecture.md\n    └── tasks.md\n```\n\n## 開發流程\n\n本專案採用 **GraphQL-First TDD** 開發方法：\n\n1. **寫測試**：先寫 GraphQL API 測試\n2. **實作功能**：實作 resolver 讓測試通過\n3. **重構**：優化程式碼保持測試綠燈\n4. **文件**：更新相關文件\n\n## 核心功能\n\n### ✅ 已實現功能\n\n**後端 (90%+ 完成)**\n- ✅ 完整的 GraphQL API (Query, Mutation, Subscription)\n- ✅ JWT 認證授權系統\n- ✅ 文章 CRUD 操作\n- ✅ 評論系統（即時推送）\n- ✅ 按讚和追蹤功能\n- ✅ 標籤和搜尋系統\n- ✅ DataLoader 優化（解決 N+1）\n- ✅ WebSocket 即時通訊\n- ✅ 完整的測試覆蓋\n\n**前端 (60%+ 完成)**\n- ✅ SvelteKit + Houdini 整合\n- ✅ 用戶註冊和登入\n- ✅ 文章瀏覽和發布\n- ✅ 即時評論更新\n- ✅ Svelte 5 Runes 響應式系統\n\n### GraphQL API 範例\n\n完整的 API 查詢範例請參考：[GraphQL 範例文檔](./docs/graphql-examples.md)\n\n```graphql\n# 查詢文章列表\nquery GetPosts {\n  posts(limit: 10, status: PUBLISHED) {\n    edges {\n      node {\n        id\n        title\n        author {\n          username\n        }\n        likesCount\n        commentsCount\n      }\n    }\n  }\n}\n\n# 即時訂閱評論\nsubscription OnCommentAdded($postId: ID!) {\n  commentAdded(postId: $postId) {\n    id\n    content\n    author {\n      username\n    }\n  }\n}\n```\n\n## 系統畫面\n\nGraphQL Playground\n\n![](https://cdn.imgpile.com/f/4HsNeyL_xl.png)\n\n*互動式 GraphQL 查詢介面，支援即時文檔探索和查詢測試*\n\n前端頁面\n\n![](https://cdn.imgpile.com/f/D4UXJKz_xl.png)\n\n![](https://cdn.imgpile.com/f/kpKS9CI_xl.png)\n\n![](https://cdn.imgpile.com/f/geMcZOL_xl.png)\n\n## Donation\n\n文章都是我自己研究內化後原創，如果有幫助到您，也想鼓勵我的話，歡迎請我喝一杯咖啡 :laughing:\n\n綠界科技ECPAY ( 不需註冊會員 )\n\n![alt tag](https://payment.ecpay.com.tw/Upload/QRCode/201906/QRCode_672351b8-5ab3-42dd-9c7c-c24c3e6a10a0.png)\n\n[贊助者付款](http://bit.ly/2F7Jrha)\n\n歐付寶 ( 需註冊會員 )\n\n![alt tag](https://i.imgur.com/LRct9xa.png)\n\n[贊助者付款](https://payment.opay.tw/Broadcaster/Donate/9E47FDEF85ABE383A0F5FC6A218606F8)\n\n## 贊助名單\n\n[贊助名單](https://github.com/twtrubiks/Thank-you-for-donate)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwtrubiks%2Fgraphql-python-blog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftwtrubiks%2Fgraphql-python-blog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwtrubiks%2Fgraphql-python-blog/lists"}