OpenAPIの使い方（NestJS + Next.js連携編）

## 🎯 目的

* **NestJSでREST APIを定義**
* **OpenAPI (Swagger) 仕様を自動生成**
* **Next.jsでOpenAPI仕様から型とAPIクライアントを自動生成**
* **フロントとバックで安全＆効率的な連携を実現**

---

## 🧱 ステップ全体の流れ

1. \[NestJS] APIを作る（Swagger導入）
2. \[NestJS] Swagger UIで仕様を確認
3. \[Next.js] OpenAPIから型/クライアントを自動生成（`openapi-typescript` など）
4. \[Next.js] 安全にAPIを呼び出す

---

## 🧪 ステップ①：NestJSでAPI作成＆Swagger導入

### 🔧 インストール

```bash
npm install @nestjs/swagger swagger-ui-express
```

### 📝 コントローラ定義（例）

```ts
// user.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';

@Controller('users')
@ApiTags('Users')
export class UserController {
  @Get(':id')
  @ApiOperation({ summary: 'Get user by ID' })
  @ApiResponse({ status: 200, description: 'User found.' })
  getUser(@Param('id') id: string) {
    return { id, name: 'John Doe' };
  }
}
```

### 🧰 Swaggerの設定（main.ts）

```ts
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const config = new DocumentBuilder()
    .setTitle('My API')
    .setDescription('User API documentation')
    .setVersion('1.0')
    .build();

  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);

  await app.listen(3000);
}
```

### 🌐 実行して確認

ブラウザで `http://localhost:3000/api` にアクセスすると、
**Swagger UI** でAPIドキュメントが見れます（＝OpenAPIのビジュアル版）

---

## 📦 ステップ②：OpenAPI仕様をJSONとしてエクスポート

```ts
import * as fs from 'fs';

const document = SwaggerModule.createDocument(app, config);
fs.writeFileSync('./openapi.json', JSON.stringify(document, null, 2));
```

このファイル（`openapi.json`）を Next.js 側にコピーして使います。

---

## 💡 ステップ③：Next.jsで型とAPIクライアントを自動生成

### 方法①：型だけ生成する（`openapi-typescript`）

#### 🔧 インストール

```bash
npm install -D openapi-typescript
```

#### 🔁 実行

```bash
npx openapi-typescript ./openapi.json -o types/api.d.ts
```

#### ✅ 使用例（Next.js）

```ts
import type { paths } from './types/api';

type GetUserResponse = paths['/users/{id}']['get']['responses']['200']['content']['application/json'];

const res = await fetch('/users/123');
const user: GetUserResponse = await res.json();

console.log(user.name); // 型補完される！
```

---

### 方法②：型 + APIクライアントも自動生成（例：`orval`）

#### 🔧 インストール

```bash
npm install -D orval
```

#### 📄 orval.config.ts

```ts
export default {
  api: {
    input: './openapi.json',
    output: {
      mode: 'split',
      target: './api/',
      schemas: './api/schemas',
    },
  },
};
```

#### 🔁 実行

```bash
npx orval
```

#### ✅ 使用例

```ts
import { getUser } from './api/users';

const { data } = await getUser({ id: '123' });
console.log(data.name); // 型付きで安全
```

---

## ✅ OpenAPI導入のメリットまとめ

| 項目               | メリット                   |
| ---------------- | ---------------------- |
| 🔧 フロントとバックの型が一致 | 自動生成されるのでズレなし          |
| 📖 APIドキュメント自動化  | Swagger UIで可視化         |
| 🤝 チーム連携         | 仕様が明文化されて共有しやすい        |
| 🔄 モックやテストも自動化可  | Prism, Mockoon などで活用可能 |

---

## 🎓 まとめ

| ステップ | 内容                       |
| ---- | ------------------------ |
| 1    | NestJSでAPIとSwagger UIを構築 |
| 2    | OpenAPI仕様（JSON）を出力       |
| 3    | Next.jsで型やクライアントを自動生成    |
| 4    | フロントから安全にAPIを叩けるようになる    |

---

## 🧰 もしNext.jsとNestJSが同じリポジトリなら？

* **OpenAPIでの連携**はもちろん便利
* Turborepoなどで**共通型ファイル（DTO）を共有**する構成でもOK
* でも**外部公開APIやフロント分離型構成なら OpenAPIはベストチョイス**

---

## 🙋 もっと知りたい方へ

* ✅ `openapi-typescript-codegen` を使ってAxiosクライアントを生成する方法
* ✅ `Prism` や `Stoplight` でOpenAPIのモックサーバーを立てる方法
* ✅ OpenAPIとZodやTypeBoxを併用する構成



---

# 📘 OpenAPI（Swagger）仕様の `openapi.json` を NestJS で生成する方法

---

## 🔍 目的：何のために生成するの？

`openapi.json` は、「このAPIは何を受け取り、何を返すのか」という**APIの設計図**です。これがあると：

* **Swagger UI** や **Postman** でドキュメント化できる
* **Next.js などのフロント**で、型やAPIクライアントを自動生成できる
* 外部開発者と**API仕様を共有**できる

つまり「**コードからAPIの仕様を機械的に取り出せる**」ようになります。

---

## ✅ ステップ①：必要なパッケージをインストール

```bash
npm install @nestjs/swagger swagger-ui-express
```

これで Swagger（OpenAPI）を扱う準備はOK。

---

## ✅ ステップ②：Swaggerを `main.ts` に組み込む

```ts
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const config = new DocumentBuilder()
    .setTitle('My API')
    .setDescription('API docs powered by Swagger')
    .setVersion('1.0')
    .build();

  const document = SwaggerModule.createDocument(app, config);

  // Swagger UI 表示（任意）
  SwaggerModule.setup('api', app, document);

  await app.listen(3000);
}
bootstrap();
```

この時点で `http://localhost:3000/api` にアクセスすれば、Swagger UI が見られます。

---

## ✅ ステップ③：`openapi.json` をファイルとして保存する

### ✏️ コード追加（`main.ts`）

```ts
import * as fs from 'fs'; // Node.js のファイル操作用

const document = SwaggerModule.createDocument(app, config);

// ファイル出力
fs.writeFileSync('./openapi.json', JSON.stringify(document, null, 2));
```

### 🏁 実行すると：

プロジェクトルートに `openapi.json` というファイルが生成されます。

---

## 📦 出力された `openapi.json` はこんな内容

```json
{
  "openapi": "3.0.0",
  "info": {
    "title": "My API",
    "description": "API docs powered by Swagger",
    "version": "1.0"
  },
  "paths": {
    "/users/{id}": {
      "get": {
        "summary": "Get user by ID",
        "parameters": [ ... ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "User": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" }
        }
      }
    }
  }
}
```

> これはまさに「APIの仕様書」。この内容を使って型生成やクライアント生成ができます。

---

## 💡 よくある注意点

| 注意点                                       | 内容                            |
| ----------------------------------------- | ----------------------------- |
| `@ApiTags` や `@ApiResponse` を書かないと中身が空になる | Swagger用のデコレータが必要             |
| 自動出力したいなら CLI やスクリプト化もできる                 | `npm run generate:openapi` など |
| DTO にも `@ApiProperty()` を書こう              | 型情報が詳細に反映される                  |

---

## ✅ 最小限のセットアップ例まとめ

```ts
// user.dto.ts
import { ApiProperty } from '@nestjs/swagger';

export class UserDto {
  @ApiProperty()
  id: string;

  @ApiProperty()
  name: string;
}
```

```ts
// user.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { ApiTags, ApiResponse } from '@nestjs/swagger';
import { UserDto } from './user.dto';

@Controller('users')
@ApiTags('Users')
export class UserController {
  @Get(':id')
  @ApiResponse({ status: 200, type: UserDto })
  getUser(@Param('id') id: string): UserDto {
    return { id, name: 'Taro' };
  }
}
```

---

## 🔚 まとめ：NestJSで openapi.json を生成するには？

| ステップ                                  | 内容                                       |
| ------------------------------------- | ---------------------------------------- |
| ① パッケージ導入                             | `@nestjs/swagger` + `swagger-ui-express` |
| ② `main.ts` にSwagger設定を書く             | `DocumentBuilder + createDocument`       |
| ③ `fs.writeFileSync` で JSON 出力        | 任意の場所に `openapi.json` 保存                 |
| ④ DTO や Controller に Swagger用デコレータを記述 | `@ApiProperty()`, `@ApiResponse()` など    |