OpenAPI(Swagger) Codegenで出力したAPIクライアント（typescript-fetch）を Nuxt に組み込む

Nuxt に OpenAPI(Swagger) Codegen で出力した APIクライアントのコードを組み込む際のメモ。

# Codegen で typescript-fetch のコードを出力する
まずは、API Client のコードを取得する。
Spec の書き方とか、Codegen の使い方は省略。
特に強い理由がないのであれば、SwaggerHub を使うのが賢いと思う。

Export から、Client SDK > typescript-fetch を選択して zip をダウンロード。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134740/c859799c-0388-867c-391d-420d8e880b73.png)

# API Client ファイルを配置する
設置場所はどこでもいいが、ここでは `/api` 以下に、ダウンロードしてきた API Client のファイルを配置する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134740/82eaaffc-4cd8-24fb-2449-e65c4c21b63c.png)

# Nuxt 内のコードから、API Client を読み込む

APIクラスは、Specの `tag` に対応して作成されている。
次のSpecでは `tags` が `user` となっているため、出力されたクライアントには、**UserApi** というAPIクラスが定義されている。

なお、下記の Spec は OpenAPI3 での記述です。

```yaml:openapi.yaml
/user/{userId}:
  get:
    tags:
      - user
    summary: ユーザー情報参照
    operationId: getUserById
    parameters:
      - name: userId
        in: path
        required: true
        schema:
          type: string
    responses:
      200:
        description: successful operation
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
```

vue側では、まず使用するAPIクラスと、設定用のConfigurationをインポートする。
各メソッドは、Spec の `operationId` と対応している

```js:index.vue
import { UserApi, Configuration } from '@/api'
```
```js:index.vue
mounted () {
  // Specの記述と同じであれば、BasePathを指定する必要はない
  const conf = new Configuration({
    basePath: 'http://localhost:3000'
  })

  // APIインスタンスを作成
  const userApi = new UserApi(conf)

  // 実行
  // 各メソッドは、Spec の operationId と対応している
  userApi.getUserById('userid').then((value:User) => {
    // Success
    console.log('success', value)

    // 〜取得成功の処理〜

  }).catch((error:unknown) => {
    // Error
    if (error instanceof Response) {
      // エラーレスポンス
      console.error('Error Status', (error as Response).status)
    } else {
      // 接続エラー
      console.error('Error', error)
    }
  })
}
```

# ESLintのエラーが出る場合
まあ、大量に出る。
これはもう、`/api` を丸ごと ignore しておく。

```text:.eslintignore
static/js/*
static/
api/   <--追加
```

#TypeScriptのエラーが出る場合
## api_test.spec.ts のエラー

`api_test.spec.ts` の中で、
**Cannot find name 'describe'**
**Cannot find name 'expect'**
などのエラーが出る場合は、@types/jest をインストールする。

```
npm install -D @types/jest
```

そして、インストール後に、tsconfig で読み込んでおく。

```js:tsconfig.json
  "compilerOptions": {
    "types": [
      "@types/node",
      "@nuxt/types",
      "@types/jest"  // <--追記
    ]
  }
```

## api.ts のエラー

**Property 'configuration' has no initializer and is not definitely assigned in the constructor.**

どうしても、`protected configuration: Configuration` と `name: "RequiredError"` の2箇所で TypeScript エラーが出てしまう。

どうやら、本家のリポジトリでは解決されているらしいが（[修正コミット](https://github.com/OpenAPITools/openapi-generator/pull/145/files#diff-100ea6c31db06688893ce887c86f6741327edb9534a2745f44228867887a910e)）、SwaggerHubには反映されていないようだ。

該当する2箇所を次のように書き換えれば解決する。

```js
export class BaseAPI {
    protected configuration: Configuration | undefined;  // <--ここ
```

```js
export class RequiredError extends Error {
    name: "RequiredError" = "RequiredError";  // <--ここ
```

ただ、面倒くさければ api.ts の先頭で、`@ts-nocheck` してもいいと思う。