MyDocs

AI駆動開発

コードを殆ど書かずに実装してみた。成果物は これ

使っているものは以下の通り。

実際のバックエンドの実装の流れはこんな感じ。

このやりかたであれば、スキーマ定義と、エンドポイントの定義さえやれば、domain ロジックと、application ロジックの実装にのみ集中できる。

今回は、このやりかたをスラッシュコマンドに落とし込んだ。

カスタムスラッシュコマンド 内容
api-gen-spec APIリソースのTypeSpec定義とSQL定義を生成
api-gen-domain Domain層を生成
api-gen-application Application層(DTO、Usecase、テスト)を生成
api-gen-infra Infrastructure層(Repository実装、Handler)を生成
api-check APIエンドポイントの動作確認

api-gen-spec

> /api-gen-spec comments id:INTEGER,post_id:INTEGER,body:TEXT,commented_at:TIMESTAMP

⏺ User answered Claude's questions:
  ⎿  · commentsテーブルのidはauto incrementで自動生成しますか? → はい(推奨)
     · post_idにFOREIGN KEY制約を付けますか? → いいえ
     · SELECT用クエリはどれが必要ですか? → 基本CRUDだが全件検索のキーはpost_idにして欲しい
     · APIのパスはどうしますか? → /posts/{postId}/comments

 了解しました。以下の仕様で生成します:
  - id: auto increment
  - 外部キー制約なし
  - SELECTクエリ: id指定の単一取得 + post_id指定の複数取得
  - APIパス: /posts/{postId}/comments

⏺ 生成完了

  以下のファイルを更新しました:

  1. sqlc/schema.sql

  CREATE TABLE IF NOT EXISTS comments (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      post_id INTEGER NOT NULL,
      body TEXT NOT NULL,
      commented_at TIMESTAMP NOT NULL
  );

  2. sqlc/query.sql

  - InsertComment - コメント作成
  - SelectComment - ID指定で1件取得
  - SelectCommentsByPostId - post_id指定で複数取得
  - UpdateComment - コメント更新
  - DeleteComment - コメント削除

  3. main.tsp

  - Comment, CommentList モデル
  - CreateCommentRequest, UpdateCommentRequest リクエストモデル
  - /posts/{postId}/comments エンドポイント(CRUD)

api-gen-domain

> /api-gen-domain

⏺ パターンを確認しました。schemaからcommentsテーブルのフィールドを把握しました:
  - id: INTEGER (auto increment)
  - post_id: INTEGER
  - body: TEXT
  - commented_at: TIMESTAMP

  bodyフィールドの制約について確認が必要です。

⏺ User answered Claude's questions:
  ⎿  · CommentBodyの文字数制約はどうしますか? → 1-500文字
     · RepositoryのFindAllはどのようにしますか? → FindAll + FindByPostID

⏺ 了解しました。以下の仕様で生成します:
  - body: 1-500文字
  - Repository: FindAll + FindByPostID

> Makefileに今回追加したrepositoryを追加したい

⏺ Update(Makefile)
  ⎿  Added 4 lines
       5    -source=./domain/repository/post_repository.go \
       6    -destination=./testing/mock/post_repository.go \
       7    -package=mock
       8 +  $(MOCK_GEN) \
       9 +  -source=./domain/repository/comment_repository.go \
      10 +  -destination=./testing/mock/comment_repository.go \
      11 +  -package=mock
      12
      13  test:
      14    go test ./...

⏺ Makefileに追加しました。make mockを実行すると両方のrepositoryのmockが生成されます。

! make mock
  ⎿  go run -mod=mod go.uber.org/mock/mockgen@latest \
        -source=./domain/repository/post_repository.go \
        -destination=./testing/mock/post_repository.go \
     … +5 lines (ctrl+o to expand)

api-gen-application

> /api-gen-application

⏺ パターンを確認しました。CommentのAPI設計が/posts/{postId}/commentsなので、Listの検索はFindByPostIDを使用し、postIDを引数に取る必要があります。

⏺ 生成完了

  全てのテストがパスしました。以下のファイルを生成しました:

  DTO

  - application/dto/comment_dto.go
    - CreateCommentInput/Output
    - GetCommentInput/Output
    - CommentItem, ListCommentsInput/Output
    - UpdateCommentInput/Output
    - DeleteCommentInput

  Usecase

  - application/usecase/comment/create_comment.go
  - application/usecase/comment/get_comment.go
  - application/usecase/comment/list_comments.go - FindByPostIDを使用
  - application/usecase/comment/update_comment.go
  - application/usecase/comment/delete_comment.go

  Usecase Tests

  - application/usecase/comment/create_comment_test.go
  - application/usecase/comment/get_comment_test.go
  - application/usecase/comment/list_comments_test.go
  - application/usecase/comment/update_comment_test.go
  - application/usecase/comment/delete_comment_test.go

api-gen-infra

> /api-gen-infra

⏺ sqlcとogenがComment用に生成されていません。まず以下のコマンドを実行する必要があります:

  # sqlc生成
  make sqlc.generate

  # TypeSpecコンパイル
  make tsp.compile

  # ogen生成
  make ogen

  これらを実行してから、再度 /api-gen-infra を実行してください。

  先に実行しますか?

> yes

⏺ 生成されたコードを確認しました。Infrastructure層を生成します。

⏺ 生成完了

  全てのテストがパスしました。以下のファイルを生成・更新しました:

  生成したファイル

  - infra/database/comment_repository.go - CommentRepository実装
    - Save, FindByID, FindAll, FindByPostID, Update, Delete
  - infra/handler/comment_handler.go - CommentHandler
    - CommentsCreate, CommentsRead, CommentsList, CommentsUpdate, CommentsDelete
  - infra/handler/handler_test.go - 統合Handlerのテスト

  更新したファイル

  - infra/handler/handler.go - 統合HandlerにCommentHandlerを追加
  - infra/handler/post_handler.go - 不要なインターフェース検証とNewErrorを削除
  - cmd/main.go - Comment関連の初期化コードを追加

  削除したファイル

  - infra/handler/post_handler_test.go - handler_test.goに統合

  実行したコード生成

  - make sqlc.generate - SQLCコード生成
  - make tsp.compile - TypeSpecコンパイル
  - make ogen - OpenAPIからGoコード生成

api-check

> /api-check postとcommentの動作を一通り確認して

⏺ postとcommentのAPI動作を一通り確認します。

⏺ Bash(curl -s http://localhost:8080/posts | jq .)
  ⎿  {
       "items": []
     }

⏺ 投稿一覧は空です。投稿を作成してテストを進めます。

⏺ Bash(curl -s -X POST http://localhost:8080/posts \
         -H "Content-Type: application/json" \…)
  ⎿  curl: option : blank argument where content is expected
     curl: try 'curl --help' or 'curl --manual' for more information

⏺ Bash(curl -s -X POST http://localhost:8080/posts -H "Content-Type: application/json" -d '{"title":"テスト投稿","content":"これはテスト内容です"}'
      | jq .)
  ⎿  {
       "id": 1,
       "title": "テスト投稿",
     … +3 lines (ctrl+o to expand)

⏺ 投稿作成成功。ID=1で作成されました。

⏺ Bash(curl -s http://localhost:8080/posts/1 | jq .)
  ⎿  {
       "id": 1,
       "title": "テスト投稿",
     … +3 lines (ctrl+o to expand)

⏺ 投稿詳細取得成功。

⏺ Bash(curl -s -X PUT http://localhost:8080/posts/1 -H "Content-Type: application/json" -d '{"title":"更新後タイトル","content":"更新後の内容"}' |
      jq .)
  ⎿  {
       "id": 1,
       "title": "更新後タイトル",
     … +3 lines (ctrl+o to expand)

⏺ 投稿更新成功。タイトルと内容が更新されました。

⏺ 投稿削除はコメントAPIを先にテストしてから行います(投稿を削除するとコメントテストができないため)。

⏺ Bash(curl -s -X POST http://localhost:8080/posts/1/comments -H "Content-Type: application/json" -d '{"body":"これはテストコメントです"}' | jq .)
  ⎿  {
       "id": 1,
       "postId": 1,
     … +3 lines (ctrl+o to expand)

⏺ コメント作成成功。ID=1で作成されました。

⏺ Bash(curl -s http://localhost:8080/posts/1/comments | jq .)
  ⎿  {
       "items": [
         {
     … +7 lines (ctrl+o to expand)

⏺ コメント一覧取得成功。1件のコメントが返されました。

⏺ Bash(curl -s http://localhost:8080/posts/1/comments/1 | jq .)
  ⎿  {
       "id": 1,
       "postId": 1,
     … +3 lines (ctrl+o to expand)

⏺ コメント詳細取得成功。

⏺ Bash(curl -s -X PUT http://localhost:8080/posts/1/comments/1 -H "Content-Type: application/json" -d '{"body":"更新後のコメント"}' | jq .)
  ⎿  {
       "id": 1,
       "postId": 1,
     … +3 lines (ctrl+o to expand)

⏺ コメント更新成功。

⏺ Bash(curl -s -X DELETE http://localhost:8080/posts/1/comments/1 -w "\nHTTP Status: %{http_code}\n")
  ⎿  HTTP Status: 204

⏺ コメント削除成功(204 No Content)。削除後、コメント一覧を確認します。

⏺ Bash(curl -s http://localhost:8080/posts/1/comments | jq .)
  ⎿  {
       "items": []
     }

⏺ コメントが正常に削除されました。最後に投稿削除を確認します。

⏺ Bash(curl -s -X DELETE http://localhost:8080/posts/1 -w "\nHTTP Status: %{http_code}\n")
  ⎿  HTTP Status: 204

⏺ Bash(curl -s http://localhost:8080/posts | jq .)
  ⎿  {
       "items": []
     }

⏺ API動作確認結果

  すべてのAPIエンドポイントが正常に動作しています。

  投稿API (Posts)

  | エンドポイント | メソッド | ステータス | 結果                   |
  |----------------|----------|------------|------------------------|
  | /posts         | GET      | 200        | 一覧取得成功(空配列) |
  | /posts         | POST     | 200        | 作成成功(ID=1)       |
  | /posts/1       | GET      | 200        | 詳細取得成功           |
  | /posts/1       | PUT      | 200        | 更新成功               |
  | /posts/1       | DELETE   | 204        | 削除成功               |

  コメントAPI (Comments)

  | エンドポイント      | メソッド | ステータス | 結果             |
  |---------------------|----------|------------|------------------|
  | /posts/1/comments   | POST     | 200        | 作成成功(ID=1) |
  | /posts/1/comments   | GET      | 200        | 一覧取得成功     |
  | /posts/1/comments/1 | GET      | 200        | 詳細取得成功     |
  | /posts/1/comments/1 | PUT      | 200        | 更新成功         |
  | /posts/1/comments/1 | DELETE   | 204        | 削除成功         |

  すべてのCRUD操作が期待通りに動作し、レスポンスも適切なJSON形式で返却されています。

web

web に関してはすべて AI で作った。

> @tsp-output/schema/openapi.yamlを読んで、postとcommentができるweb画面をweb配下に実装してください。
また https://github.com/orval-labs/orval を使ってください。

⏺ プランを更新しました。

  実装計画まとめ

  技術スタック:
  - Orval - OpenAPI仕様からAPIクライアント自動生成
  - TanStack Query - useQuery/useMutation hooks

  主な手順:
  1. @tanstack/react-query と orval をインストール
  2. orval.config.ts を作成してコード生成設定
  3. bun run orval でAPIクライアント・型を自動生成
  4. APIプロキシを設定(/api/* → localhost:8080/*)
  5. 生成されたhooksを使用してBBSコンポーネントを実装
  6. 既存のAPITester/ロゴを削除してBBSに置き換え

  準備ができました。

⏺ User approved Claude's plan
  ⎿  Plan saved to: ~/.claude/plans/gleaming-finding-sunrise.md · /plan to edit
     BBS Web画面 実装計画

     概要

     OpenAPI仕様に基づき、Post(投稿)とComment(コメント)機能を持つBBS画面を実装する。
     Orval + TanStack Query を使用してAPIクライアントを自動生成する。

     API仕様

     - GET /posts - 投稿一覧取得
     - POST /posts - 投稿作成 (title: 1-30文字, content: 1-255文字)
     - GET /posts/{id} - 投稿詳細取得
     - GET /posts/{postId}/comments - コメント一覧取得
     - POST /posts/{postId}/comments - コメント作成 (body: 1文字以上)

     ファイル構成

     web/
     ├── orval.config.ts       # Orval設定ファイル
     ├── src/
     │   ├── index.ts          # APIプロキシ追加
     │   ├── App.tsx           # BBSをメインに変更
     │   ├── frontend.tsx      # QueryClientProvider追加
     │   ├── index.css         # BBSスタイル追加
     │   ├── generated/        # Orval自動生成(git管理対象外)
     │   │   ├── api.ts        # APIクライアント・hooks
     │   │   └── model/        # 型定義
     │   └── components/
     │       ├── BBS.tsx           # メインBBSコンポーネント
     │       ├── PostList.tsx      # 投稿一覧
     │       ├── PostItem.tsx      # 投稿アイテム
     │       ├── PostForm.tsx      # 投稿フォーム
     │       ├── PostDetail.tsx    # 投稿詳細+コメント
     │       ├── CommentList.tsx   # コメント一覧
     │       ├── CommentItem.tsx   # コメントアイテム
     │       └── CommentForm.tsx   # コメントフォーム

     実装手順

     Step 1: 依存パッケージのインストール

     cd web
     bun add @tanstack/react-query
     bun add -D orval

     Step 2: Orval設定ファイルの作成

     web/orval.config.ts
     import { defineConfig } from 'orval';

     export default defineConfig({
       bbs: {
         input: '../tsp-output/schema/openapi.yaml',
         output: {
           mode: 'single',
           target: './src/generated/api.ts',
           schemas: './src/generated/model',
           client: 'react-query',
           baseUrl: '/api',
           override: {
             mutator: {
               path: './src/api/fetcher.ts',
               name: 'customFetch',
             },
           },
         },
       },
     });

     Step 3: カスタムfetcherの作成

     web/src/api/fetcher.ts
     - baseURLを /api に設定(プロキシ経由)

     Step 4: Orvalでコード生成

     bun run orval
     生成されるもの:
     - usePostsList() - 投稿一覧取得hook
     - usePostsCreate() - 投稿作成mutation
     - usePostsRead(id) - 投稿詳細取得hook
     - useCommentsList(postId) - コメント一覧取得hook
     - useCommentsCreate(postId) - コメント作成mutation
     - 型定義(Post, Comment, CreatePostRequest等)

     Step 5: APIプロキシの設定

     web/src/index.ts を編集
     - /api/* を http://localhost:8080/* に転送

     Step 6: QueryClientProviderの設定

     web/src/frontend.tsx を編集
     - QueryClientProviderでAppをラップ

     Step 7: コンポーネント実装

     1. PostForm.tsx - usePostsCreate()を使用
     2. PostItem.tsx - 投稿一覧の各アイテム
     3. PostList.tsx - usePostsList()を使用
     4. CommentForm.tsx - useCommentsCreate()を使用
     5. CommentItem.tsx - 各コメント表示
     6. CommentList.tsx - useCommentsList()を使用
     7. PostDetail.tsx - usePostsRead()を使用
     8. BBS.tsx - メインコンポーネント

     Step 8: 統合

     web/src/App.tsx を編集
     - BBSコンポーネントをメインに配置

     Step 9: スタイリング

     web/src/index.css に追加
     - 既存のカラースキーム(#fbf0df, #1a1a1a)を踏襲

     Step 10: package.jsonにスクリプト追加

     {
       "scripts": {
         "generate": "orval"
       }
     }

     画面レイアウト

     +------------------------------------------+
     |              BBS                         |
     +------------------------------------------+
     |  投稿一覧 (左)      |  投稿詳細 (右)      |
     |  +--------------+  |  +--------------+   |
     |  | [新規投稿]   |  |  | タイトル     |   |
     |  +--------------+  |  | 内容         |   |
     |  | Post 1       |  |  | 投稿日時     |   |
     |  | Post 2 ←選択 |  |  +--------------+   |
     |  | Post 3       |  |  | コメント一覧 |   |
     |  +--------------+  |  | [コメント追加]|   |
     +------------------------------------------+

     修正対象ファイル

     - web/src/index.ts - APIプロキシ追加
     - web/src/frontend.tsx - QueryClientProvider追加
     - web/src/App.tsx - BBSコンポーネントに置き換え(ロゴ・APITester削除)
     - web/src/index.css - BBSスタイル追加(既存の.api-testerスタイル削除)
     - web/package.json - scripts追加
     - web/.gitignore - generated/を追加

     削除対象ファイル

     - web/src/APITester.tsx - 不要になるため削除

     新規作成ファイル

     - web/orval.config.ts - Orval設定
     - web/src/api/fetcher.ts - カスタムfetcher
     - web/src/generated/ - Orval自動生成(型・hooks)
     - web/src/components/BBS.tsx
     - web/src/components/PostList.tsx
     - web/src/components/PostItem.tsx
     - web/src/components/PostForm.tsx
     - web/src/components/PostDetail.tsx
     - web/src/components/CommentList.tsx
     - web/src/components/CommentItem.tsx
     - web/src/components/CommentForm.tsx