From ee8278bedc6b1d172c3f64f7419ec92f892e0f84 Mon Sep 17 00:00:00 2001 From: Kohtaroh Sakaue Date: Wed, 24 Dec 2025 14:31:07 +0000 Subject: [PATCH 01/11] refactor: add type hints for better clarity and maintainability --- server/app/routers/blocks.py | 2 +- server/app/routers/pages.py | 2 +- server/app/routers/trips.py | 2 +- server/tests/conftest.py | 4 ++-- server/tests/cruds/test_blocks.py | 17 +++++++++-------- server/tests/routers/test_pages_router.py | 2 +- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/server/app/routers/blocks.py b/server/app/routers/blocks.py index 4e4aa2e..2af7fd7 100644 --- a/server/app/routers/blocks.py +++ b/server/app/routers/blocks.py @@ -44,7 +44,7 @@ async def get_blocks( - 特定のページに関連するすべてのブロックを取得する """ - return await blocks_cruds.find_blocks(db=db, page_id=page_id) + return await blocks_cruds.find_blocks(db=db, page_id=page_id) # type: ignore @router.get( diff --git a/server/app/routers/pages.py b/server/app/routers/pages.py index 5c6b34f..2e54978 100644 --- a/server/app/routers/pages.py +++ b/server/app/routers/pages.py @@ -44,7 +44,7 @@ async def get_pages(trip_id: int, db: Session = Depends(get_db_session)) -> list - 特定の旅行プランに関連するすべてのページを取得する """ - return await pages_cruds.get_pages(db=db, trip_id=trip_id) + return await pages_cruds.get_pages(db=db, trip_id=trip_id) # type: ignore @router.get( diff --git a/server/app/routers/trips.py b/server/app/routers/trips.py index f2f7c03..692a16a 100644 --- a/server/app/routers/trips.py +++ b/server/app/routers/trips.py @@ -44,7 +44,7 @@ async def list_trips(db: Session = Depends(get_db_session)) -> list[Trip]: - すべての旅行プランを取得する """ - return await trips_cruds.list_trips(db=db) + return await trips_cruds.list_trips(db=db) # type: ignore @router.get( diff --git a/server/tests/conftest.py b/server/tests/conftest.py index 9bca679..0165f60 100644 --- a/server/tests/conftest.py +++ b/server/tests/conftest.py @@ -68,7 +68,7 @@ async def test_create_trip(db_session: Session) -> Trip: trip_id = await trips_cruds.create_trip( db=db_session, trip=trip_in, url_id="test_url_id_fixture" ) - return await trips_cruds.get_trip(db=db_session, trip_id=trip_id) + return await trips_cruds.get_trip(db=db_session, trip_id=trip_id) # type: ignore @pytest_asyncio.fixture @@ -78,4 +78,4 @@ async def test_create_page(db_session: Session, test_create_trip: Trip) -> Page: db_page = await pages_cruds.create_page( db=db_session, page=page_in, trip_id=test_create_trip.id ) - return await pages_cruds.get_page(db=db_session, page_id=db_page.id) + return await pages_cruds.get_page(db=db_session, page_id=db_page.id) # type: ignore diff --git a/server/tests/cruds/test_blocks.py b/server/tests/cruds/test_blocks.py index 99f6d38..8dc295c 100644 --- a/server/tests/cruds/test_blocks.py +++ b/server/tests/cruds/test_blocks.py @@ -1,3 +1,4 @@ +from app.schemas.block import BlockType from datetime import datetime import pytest @@ -20,7 +21,7 @@ async def test_create_block(db_session: Session, test_create_page: Page): start_time=datetime(2023, 1, 1, 10, 0), end_time=datetime(2023, 1, 1, 12, 0), detail="test detail", - block_type="event", + block_type=BlockType.EVENT, transportation_type="car", ) @@ -53,7 +54,7 @@ async def test_create_block_non_existent_page_id(db_session: Session): start_time=datetime(2023, 1, 1, 10, 0), end_time=datetime(2023, 1, 1, 12, 0), detail="test detail", - block_type="event", + block_type=BlockType.EVENT, ) non_existent_page_id = 999 @@ -75,7 +76,7 @@ async def test_get_block(db_session: Session, test_create_page: Page): start_time=datetime(2023, 1, 1, 10, 0), end_time=datetime(2023, 1, 1, 12, 0), detail="test detail", - block_type="event", + block_type=BlockType.EVENT, transportation_type="car", ) created_block = await blocks_cruds.create_block( @@ -118,7 +119,7 @@ async def test_find_blocks(db_session: Session, test_create_page: Page): title="b1", start_time=datetime(2023, 1, 1, 10, 0), detail="d", - block_type="event", + block_type=BlockType.EVENT, ), page_id=test_create_page.id, ) @@ -128,7 +129,7 @@ async def test_find_blocks(db_session: Session, test_create_page: Page): title="b2", start_time=datetime(2023, 1, 1, 11, 0), detail="d", - block_type="event", + block_type=BlockType.EVENT, ), page_id=test_create_page.id, ) @@ -152,7 +153,7 @@ async def test_update_block(db_session: Session, test_create_page: Page): title="before", start_time=datetime(2023, 1, 1, 10, 0), detail="d", - block_type="event", + block_type=BlockType.EVENT, ) created_block = await blocks_cruds.create_block( db=db_session, block=block_in, page_id=test_create_page.id @@ -161,7 +162,7 @@ async def test_update_block(db_session: Session, test_create_page: Page): title="after", start_time=datetime(2023, 1, 1, 10, 0), detail="d", - block_type="event", + block_type=BlockType.EVENT, ) # act @@ -192,7 +193,7 @@ async def test_delete_block(db_session: Session, test_create_page: Page): title="delete", start_time=datetime(2023, 1, 1, 10, 0), detail="d", - block_type="event", + block_type=BlockType.EVENT, ) created_block = await blocks_cruds.create_block( db=db_session, block=block_in, page_id=test_create_page.id diff --git a/server/tests/routers/test_pages_router.py b/server/tests/routers/test_pages_router.py index 19cdef2..fed2770 100644 --- a/server/tests/routers/test_pages_router.py +++ b/server/tests/routers/test_pages_router.py @@ -38,7 +38,7 @@ async def test_create_page_invalid_input( POST /trips/{trip_id}/pages で不正な入力が与えられた場合に 422 が返ることを検証 """ # title が欠落している不正なデータ - invalid_page_data = {} + invalid_page_data: dict = {} response = client.post( f"/trips/{test_create_trip.id}/pages", json=invalid_page_data ) From 9537c670164317c8081bb6f9b6af1ee01a36179d Mon Sep 17 00:00:00 2001 From: Kohtaroh Sakaue Date: Wed, 24 Dec 2025 14:31:40 +0000 Subject: [PATCH 02/11] refactor: update VSCode settings and add type hints for types-nanoid dependency --- .devcontainer/devcontainer.json | 3 ++- .vscode/settings.json | 13 +++++++++++-- server/pyproject.toml | 1 + server/uv.lock | 11 +++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9d83a16..cc1d049 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -28,7 +28,8 @@ "dotenv.dotenvx-vscode", "ms-vsliveshare.vsliveshare", "corschenzi.mermaid-graphical-editor", - "anthropic.claude-code" + "anthropic.claude-code", + "ms-python.mypy-type-checker" ], "settings": { "[python]": { diff --git a/.vscode/settings.json b/.vscode/settings.json index fa38051..b8223d4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -34,7 +34,9 @@ "editor.defaultFormatter": "vscode.html-language-features" }, "[markdown]": { - "editor.defaultFormatter": "vscode.markdown-language-features" + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "editor.defaultFormatter": "DavidAnson.vscode-markdownlint" }, "biome.lsp.bin": "frontend/node_modules/@biomejs/biome/bin/biome", "tailwindCSS.experimental.classRegex": [ @@ -53,5 +55,12 @@ "python.testing.pytestEnabled": true, "python.testing.pytestArgs": ["./server/tests", "-svvv"], "python.testing.autoTestDiscoverOnSaveEnabled": true, - "python.defaultInterpreterPath": "${workspaceFolder}/server/.venv/bin/python" + "python.defaultInterpreterPath": "${workspaceFolder}/server/.venv/bin/python", + "mypy-type-checker.reportingScope": "workspace", + "mypy-type-checker.importStrategy": "fromEnvironment", + "mypy-type-checker.args": [ + "--ignore-missing-imports", + "--follow-imports=silent" + ], + "python.analysis.typeCheckingMode": "off" } diff --git a/server/pyproject.toml b/server/pyproject.toml index 8560b5b..d556f12 100644 --- a/server/pyproject.toml +++ b/server/pyproject.toml @@ -24,6 +24,7 @@ dev = [ "pytest>=8.4.1", "pytest-asyncio>=1.1.0", "ruff>=0.12.7", + "types-nanoid>=2.0.0.20240601", "types-passlib>=1.7.7.20250602", ] [tool.ruff] diff --git a/server/uv.lock b/server/uv.lock index f584ecf..b4503bc 100644 --- a/server/uv.lock +++ b/server/uv.lock @@ -519,6 +519,7 @@ dev = [ { name = "pytest" }, { name = "pytest-asyncio" }, { name = "ruff" }, + { name = "types-nanoid" }, { name = "types-passlib" }, ] @@ -543,6 +544,7 @@ dev = [ { name = "pytest", specifier = ">=8.4.1" }, { name = "pytest-asyncio", specifier = ">=1.1.0" }, { name = "ruff", specifier = ">=0.12.7" }, + { name = "types-nanoid", specifier = ">=2.0.0.20240601" }, { name = "types-passlib", specifier = ">=1.7.7.20250602" }, ] @@ -588,6 +590,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f7/1f/b876b1f83aef204198a42dc101613fefccb32258e5428b5f9259677864b4/starlette-0.47.2-py3-none-any.whl", hash = "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b", size = 72984, upload-time = "2025-07-20T17:31:56.738Z" }, ] +[[package]] +name = "types-nanoid" +version = "2.0.0.20240601" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/f2/b42b17bf27e90aa8dd9a06721b35804842ca72afac294b700b4fa23ffc92/types-nanoid-2.0.0.20240601.tar.gz", hash = "sha256:7246ee685ed55a367fc160d87cde75a550296ecca26e0602619552dae72efda0", size = 2614, upload-time = "2024-06-01T02:27:23.985Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/2c/a584a285447ecb1997cda73477550068f461885e1676a4ac271ad16f8078/types_nanoid-2.0.0.20240601-py3-none-any.whl", hash = "sha256:5219f721b80748d82b14edd5429cc888d32eb816966d2a4719730ef3f2e3a417", size = 3862, upload-time = "2024-06-01T02:27:22.949Z" }, +] + [[package]] name = "types-passlib" version = "1.7.7.20250602" From 913fbe06618ddea5346e070b51a215bc2b729321 Mon Sep 17 00:00:00 2001 From: Kohtaroh Sakaue Date: Wed, 24 Dec 2025 14:32:42 +0000 Subject: [PATCH 03/11] refactor: update application setup script for improved clarity and organization --- .devcontainer/postCreateCommand.sh | 2 +- scripts/{setup.sh => setup_application.sh} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename scripts/{setup.sh => setup_application.sh} (100%) diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh index 0dbdd9a..67b709a 100755 --- a/.devcontainer/postCreateCommand.sh +++ b/.devcontainer/postCreateCommand.sh @@ -31,7 +31,7 @@ fi # --- アプリケーションのセットアップ --- # アプリケーション固有のセットアップ(依存関係のインストール、マイグレーションなど)を実行する echo "🚀 Starting application setup..." -./scripts/setup.sh +sh ./scripts/setup_application.sh # --- データベースのセットアップ --- diff --git a/scripts/setup.sh b/scripts/setup_application.sh similarity index 100% rename from scripts/setup.sh rename to scripts/setup_application.sh From 700d6854f81ded1bd52e55b88dc9111a7199cadb Mon Sep 17 00:00:00 2001 From: Kohtaroh Sakaue Date: Wed, 24 Dec 2025 14:32:50 +0000 Subject: [PATCH 04/11] refactor: reorganize and update words list in cspell configuration for consistency --- cspell.json | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/cspell.json b/cspell.json index ac9c202..c261480 100644 --- a/cspell.json +++ b/cspell.json @@ -2,18 +2,28 @@ "version": "0.2", "language": "en,ja", "words": [ - "Tabishare", - "devcontainers", - "itsmechlark", "anthropics", - "pylance", - "dbaeumer", + "autodocs", "bradlc", + "dbaeumer", + "devcontainers", + "devdb", + "dotenvx", "eamodio", - "uvicorn", + "fastapi", + "itsmechlark", + "mypy", "Nonoctal", + "NOPASSWD", + "psql", + "pylance", + "pytest", + "rolname", "Tabi", - "autodocs" + "Tabishare", + "tablename", + "testdb", + "uvicorn" ], "ignoreWords": [], "import": [] From 2ad54a8f66d6013a9b7c933c6bfe64b21a2a8df2 Mon Sep 17 00:00:00 2001 From: Kohtaroh Sakaue Date: Wed, 24 Dec 2025 14:32:55 +0000 Subject: [PATCH 05/11] refactor: enhance script organization and add section headers in package.json --- package.json | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 0edd3ba..df8beca 100644 --- a/package.json +++ b/package.json @@ -3,18 +3,34 @@ "private": true, "version": "0.0.0", "scripts": { - "dev": "concurrently --names \"FRONT,SERVER,STORYBOOK\" --prefix-colors \"cyan,yellow\" \"npm run dev:front\" \"npm run dev:server\" \"npm run dev:storybook\"", + "// --- ALL --- //": "", + "dev": "concurrently --names \"FRONT,SERVER,STORYBOOK\" --prefix-colors \"cyan,yellow,magenta\" \"npm run dev:front\" \"npm run dev:server\" \"npm run dev:storybook\"", + "install:all": "npm ci && cd frontend && npm ci", + + "// --- FRONTEND --- //": "", "dev:front": "cd frontend && npm run dev", - "dev:server": "cd server && python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload", "dev:storybook": "cd frontend && npm run storybook", - "install:all": "npm ci && cd frontend && npm ci", - "build": "cd frontend && npm run build", - "lint:check": "cd frontend && npm run lint:check", - "lint:fix": "cd frontend && npm run lint:fix", - "format:check": "cd frontend && npm run format:check", - "format:fix": "cd frontend && npm run format:fix", - "preview": "cd frontend && npm run preview", - "db:connect": "npx dotenvx run -- sh -c 'psql -U $POSTGRES_USER -h $POSTGRES_HOST -d $POSTGRES_DB'" + "build:front": "cd frontend && npm run build", + "lint:check:front": "cd frontend && npm run lint:check", + "lint:fix:front": "cd frontend && npm run lint:fix", + "format:check:front": "cd frontend && npm run format:check", + "format:fix:front": "cd frontend && npm run format:fix", + "preview:front": "cd frontend && npm run preview", + + "// --- SERVER --- //": "", + "dev:server": "cd server && npx dotenvx run --env-file ../.env -- uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload", + "test:server": "cd server && npx dotenvx run --env-file ../.env -- uv run pytest", + "type-check:server": "cd server && uv run mypy .", + "lint:check:server": "cd server && uv run ruff check .", + "lint:fix:server": "cd server && uv run ruff check --fix .", + "format:check:server": "cd server && uv run ruff format --check .", + "format:fix:server": "cd server && uv run ruff format .", + + "// --- DATABASE --- //": "", + "connect:db": "npx dotenvx run -- sh -c 'psql -U $POSTGRES_USER -h $POSTGRES_HOST -d $POSTGRES_DB'", + "migrate:db": "cd server && npx dotenvx run --env-file ../.env -- alembic -n devdb upgrade head", + "status:db": "cd server && npx dotenvx run --env-file ../.env -- alembic -n devdb current", + "rollback:db": "cd server && npx dotenvx run --env-file ../.env -- alembic -n devdb downgrade -1" }, "devDependencies": { "@dotenvx/dotenvx": "^1.48.4", From 312d693b05ab3cc446fa9b67c2181d43577eda80 Mon Sep 17 00:00:00 2001 From: Kohtaroh Sakaue Date: Wed, 24 Dec 2025 14:33:00 +0000 Subject: [PATCH 06/11] refactor: add Ruff linter and type check steps to CI workflow --- .github/workflows/ci_server.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci_server.yml b/.github/workflows/ci_server.yml index 4c11c7f..ecc39ec 100644 --- a/.github/workflows/ci_server.yml +++ b/.github/workflows/ci_server.yml @@ -89,6 +89,18 @@ jobs: working-directory: ./server run: uv sync + - name: Run Ruff check (Linter) + working-directory: ./server + run: uv run ruff check . + + - name: Run Ruff format check (Formatter) + working-directory: ./server + run: uv run ruff format --check . + + - name: Run mypy (Type check) + working-directory: ./server + run: uv run mypy . + - name: Run Alembic migrations working-directory: ./server run: dotenvx run --env-file ../.env -- uv run alembic -n testdb upgrade head From f020d94fc50a1532ee9a0c39bb6ab1cdf4d5709d Mon Sep 17 00:00:00 2001 From: Kohtaroh Sakaue Date: Wed, 24 Dec 2025 14:33:06 +0000 Subject: [PATCH 07/11] refactor: improve README structure and clarity for development setup --- server/README.md | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/server/README.md b/server/README.md index 7fca2f5..0e8114b 100644 --- a/server/README.md +++ b/server/README.md @@ -5,12 +5,14 @@ FastAPI + PostgreSQL + Alembicを使用したバックエンドAPI ## 開発環境手順 ### 前提条件 + - Docker Desktopがインストールされている - VS Code + Dev Containers拡張機能がインストールされている ### devcontainer環境でのセットアップ 1. **devcontainer起動** + ```bash cd tabi-share # VS Codeでプロジェクトを開く @@ -18,6 +20,7 @@ FastAPI + PostgreSQL + Alembicを使用したバックエンドAPI ``` 2. **データベースマイグレーション** + ```bash cd server @@ -26,22 +29,24 @@ FastAPI + PostgreSQL + Alembicを使用したバックエンドAPI ``` 3. **開発サーバー起動** + ```bash npm run dev ``` - ### アクセス先 -- フロントエンド: http://localhost:3000 (または5173) -- バックエンドAPI: http://localhost:8000 -- API自動ドキュメント: http://localhost:8000/docs -- 代替ドキュメント: http://localhost:8000/redoc + +- フロントエンド: (または5173) +- バックエンドAPI: +- API自動ドキュメント: +- 代替ドキュメント: ## 開発ワークフロー(devcontainer環境) ### 環境変数の変更手順 1. **環境変数の復号化** + ```bash cd tabi-share @@ -51,11 +56,13 @@ FastAPI + PostgreSQL + Alembicを使用したバックエンドAPI 2. **.envファイルをIDEで編集する** 3. **環境変数の暗号化** + ```bash - npx detenvx encrypt + npx dotenvx encrypt ``` ### パッケージの追加手順 + ```bash cd server @@ -71,12 +78,14 @@ uv add --dev pytest 1. **server/app/models.pyにモデルを追加する** 2. **マイグレーションファイルを生成する** + ```bash cd server npx dotenvx run --env-file ../.env -- alembic -n devdb revision --autogenerate -m "file_name" ``` 3. **マイグレーションファイルをDBに適用する** + ```bash # 現在のバージョンを確認する npx dotenvx run --env-file ../.env -- alembic -n devdb current @@ -98,13 +107,17 @@ uv add --dev pytest ``` ### DBに直接アクセスする方法 + - 環境変数の値を使ってアクセスする + ```bash cd tabi-share npx dotenvx run -- sh -c 'psql -U $POSTGRES_USER -h $POSTGRES_HOST -d $POSTGRES_DB' ``` + - よく使用するコマンド + ```bash \l # List Databases \dt # List Tables @@ -114,12 +127,15 @@ uv add --dev pytest ``` ### 新機能開発 + 1. **機能ブランチ作成** + ```bash git switch -c feature/your-feature-name ``` 2. **モデル定義** (`app/models.py`) + ```python class YourModel(Base): __tablename__ = "your_table" @@ -128,6 +144,7 @@ uv add --dev pytest ``` 3. **マイグレーション生成・適用** + ```bash cd server npx dotenvx run --env-file ../.env -- alembic -n devdb revision --autogenerate -m "file_name" @@ -135,6 +152,7 @@ uv add --dev pytest ``` 4. **スキーマ定義** (`app/schemas.py`) + ```python class YourModelCreate(BaseModel): # 作成用スキーマ @@ -146,12 +164,14 @@ uv add --dev pytest ``` 5. **CRUD操作実装** (`app/cruds/your_model.py`) + ```python async def create_your_model(db: Session, model_data: YourModelCreate): # CRUD実装 ``` 6. **APIルーター実装** (`app/routers/your_model.py`) + ```python @router.post("/", response_model=YourModelResponse) async def create_endpoint( @@ -162,9 +182,12 @@ uv add --dev pytest ``` ### テスト実行 + #### VScodeのテスト機能を使った実行方法 + - アクティビティバーのテストを押し、対象のテストファイルを実行する場合 - Terminalから実行する場合 + ```bash cd server # 全テスト実行 @@ -192,11 +215,11 @@ uv add --dev pytest ## よく使用するコマンド(devcontainer環境) - ## API設計パターン ### 標準的なCRUDエンドポイント -``` + +```text GET /api/v1/users/ # ユーザー一覧取得 POST /api/v1/users/ # ユーザー作成 GET /api/v1/users/{id} # 特定ユーザー取得 @@ -205,6 +228,7 @@ DELETE /api/v1/users/{id} # ユーザー削除 ``` ### レスポンス形式 + ```json { "data": {...}, @@ -222,6 +246,7 @@ DELETE /api/v1/users/{id} # ユーザー削除 ## 開発ツール設定 ### mypy設定 + - 設定内容を整理して記述する プロジェクトルートに`mypy.ini`または`pyproject.toml`で型チェック設定: @@ -244,6 +269,7 @@ ignore_errors = true ``` --> ### pytest設定 + - 設定内容を整理して記述する