🐡

Next.js で OpenAPI を使う

2023/12/01に公開

この記事は mob Advent Calendar 1日目の記事になります。

今回は openapi.yaml から ApiClient を生成して、Next.js 上で API通信を実装するところまで説明しようと思います。

ジェネレータの設定

まずは openapi-typescrip をインストールします。

yarn add -D openapi-typescript

インストールできたら、下記のコマンドで諸々の型定義を生成することができます。

生成

yarn run openapi-typescript {openapi.yaml の path} --output {output file}

自動生成することが確認できたら、 package.json の scripts に下記のように追記しておくと、また生成する際に楽です。

package.json
{
  "private": true,
  "scripts": {
    "dev": "next",
    ...
+    "openapi": "yarn run openapi-typescript ../path/to/openapi.yml --output api/api.ts "
  },
  ...
  "devDependencies": {
    ...
    "openapi-typescript": "^6.7.1",
  }
}

生成したものを使う

下記のようにリクエストやレスポンスの型を扱うことができます。

import { paths, components } from "./path/to/my/schema"; // <- generated by openapi-typescript

// Schema Obj
type MyType = components["schemas"]["MyType"];

// Path params
type EndpointParams = paths["/my/endpoint"]["parameters"];

// Response obj
type SuccessResponse = paths["/my/endpoint"]["get"]["responses"][200]["content"]["application/json"]["schema"];
type ErrorResponse = paths["/my/endpoint"]["get"]["responses"][500]["content"]["application/json"]["schema"];

https://github.com/drwpow/openapi-typescript/tree/main/packages/openapi-typescript

また、 openapi-fetch というものがあります。

こんな感じで apiClient をつくって、

client.ts
import createClient from "openapi-fetch";
import { paths } from "./api";

const apiClient = createClient<paths>({
  baseUrl: "https://myapi.dev/v1/",
});

export default apiClient;

https://github.com/drwpow/openapi-typescript/tree/main/packages/openapi-fetch

こんな感じで簡単に API通信の実装ができます。

const { data, error, response } = await apiClient.GET("/api/someone/{id}", {
    params: {
      path: {
        id: id,
      },
    },
  });

...

const { data, error, response } = await apiClient.POST("/api/someone/{id}", {
  params: {
    path: {
      id: id,
    },
  },
  body: {
    param1: param1,
    param2: param2,
  },
});

自分の場合は、 GET の場合は useSwr を使用しているので、こんな感じで書いています。

const { data, isLoading, mutate } = useSwr(`/api/someone/${id}`, () =>
  apiClient.GET("/api/someone/{id}", {
    params: {
      path: {
        id: id,
      },
    },
  })
);

とっても簡単!

Discussion