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 をダウンロード。

API Client ファイルを配置する

設置場所はどこでもいいが、ここでは /api 以下に、ダウンロードしてきた API Client のファイルを配置する。

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

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

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

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 と対応している

index.vue
import { UserApi, Configuration } from '@/api'
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 しておく。

.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 で読み込んでおく。

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: Configurationname: "RequiredError" の2箇所で TypeScript エラーが出てしまう。

どうやら、本家のリポジトリでは解決されているらしいが(修正コミット)、SwaggerHubには反映されていないようだ。

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

export class BaseAPI {
    protected configuration: Configuration | undefined;  // <--ここ
export class RequiredError extends Error {
    name: "RequiredError" = "RequiredError";  // <--ここ

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