2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HonoとRedocで始めるスキーマ駆動開発

Last updated at Posted at 2024-10-31

はじめに

前から思ってたんだけど、タイプセーフな言語で開発できて、ドキュメントの手動更新もいらなくて、しかもきれいに可視化できたらいいよなーって。

そしたら、どうやらBunHonoReDocを使えばそれができちゃうらしいです。
名称未設定ファイル.drawio.png

そもそもこいつらって何?

Bun

Bunは、最新のJavaScriptエコシステムに対応するため、ゼロから構築された新しいJavaScriptランタイムです、しかも非常に早くて、NodeJsより3倍近く速いらしいです。公式ドキュメント

A05B7BC0-AD7D-4AC0-8406-88AF4B8756C3.jpeg

この記事でBunを使うメリットは特にないんだけど、最近の流行りに乗っかりたいだけです。

Hono

高速で軽量、しかもWeb標準に基づいて作られてて、あらゆるJavaScriptランタイムをサポートしてるらしいです。
使ってみた感想としては、TypeScriptで書かれた現代のExpressって感じ。リリースされてから、NestJSを超える人気が出てるし、しかも作者は日本人。第2のRuby on Railsになることを期待してます。 公式ドキュメント
85DE1195-77E8-4137-AFD3-D2F45364CC56.jpeg

ReDoc

ReDocはOpenAPI(Swagger)仕様を基にしてAPIのドキュメントを生成するツールです。HonoでSwaggerUIを使うのも簡単なんだけど、個人的にはReDocのUIの方がきれいなので、ReDocを使います。リポジトリ
978860CC-748E-4C2D-AD45-721DB002D876.jpeg

事前準備

Bunをインストールします。

  • Homebrew
% brew install oven-sh/bun/bun
  • npm
% npm install -g bun

インストール完了後、バージョン確認できます。

% bun -v
> 1.1.33

Honoのプロジェクト作成

bunxコマンド使って初期化します。

% bunx create-hono 
create-hono version 0.14.2
? Target directory bun-hono-api
? Which template do you want to use? cloudflare-workers
? Do you want to install project dependencies? yes
? Which package manager do you want to use? bun
✔ Cloning the template
✔ Installing project dependencies
🎉 Copied project files
Get started with: cd bun-hono-api

初期化されたプロジェクトには、以下のようなエントリーファイルがあります。

src/index.ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.text('Hello Hono!')
})

export default app

このコードは、ルート / にアクセスしたときに Hello Hono! を返すシンプルなAPIを定義しています。

次に、以下のコマンドを実行し、ブラウザで http://localhost:8787 にアクセスすると、Hello Hono! というメッセージが表示されます。

% bun run dev
wrangler dev

 ⛅️ wrangler 3.83.0
-------------------

⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:8787

@hono/zod-openapiインストール

% bun add @hono/zod-openapi

@hono/zod-openapiは、HonoとZodライブラリを統合し、OpenAPIに準拠したスキーマを定義・管理するためのツールです。
これを使うと、スキーマからAPIルートやバリデーションロジックを自動生成できます :point_up_tone1:
しかも、作者のお墨付きももらってます。

実際@hono/zod-openapi使ってルート /を改造しましょう。

src/index.ts
import { OpenAPIHono as Hono, z, createRoute } from '@hono/zod-openapi';

const app = new Hono()

export const rootSchema = z.object({
  code: z.number().openapi({
    example: 200,
  }),
  message: z.string().openapi({
    example: 'Hello Hono!',
  }),
});

const rootRoute = createRoute({
  method: 'get',
  summary: 'root route',
  description: 'use health check',
  path: '/',
  request: {},
  responses: {
    200: {
      content: {
        'application/json': {
          schema: rootSchema,
        },
      },
      description: 'root router return Hello Hono',
    },
  },
  tags: ['Root'],
});

app.openapi(rootRoute, (c) => {
  return c.json({ code: 200, message: 'Hello Hono!' });
});

export default app

スキーマを追加することで、レスポンスの形式が厳密に定義されました。

再度以下のコマンドを実行し、ブラウザで http://localhost:8787 にアクセスすると、{"code":200,"message":"Hello Hono!"} というメッセージが表示されます。

% bun run dev
wrangler dev

 ⛅️ wrangler 3.83.0
-------------------

⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:8787

レスポンスからcodeを削除してみます。

src/index.ts
app.openapi(rootRoute, (c) => {
-  return c.json({  message: 'Hello Hono!' });
});

5B4F04D1-C7C9-4B24-B95F-47BADEFD8C5E_4_5005_c.jpeg
ちゃんとタイプエラーが出ました。

ReDoc追加

まず、src/index.tssrc/index.tsxに変更します。

wrangler.tomlのmainを下記のように修正。

wrangler.toml
name = "bun-hono-api"
+ main = "src/index.tsx"
compatibility_date = "2024-10-30"
...略
src/index.tsx
... 
app.openapi(rootRoute, (c) => {
  return c.json({ code: 200, message: 'Hello Hono!' });
});

+ app.doc('/openapi-spec.json', {
+   openapi: '3.0.0',
+   info: {
+     version: 'v1',
+     title: 'Sample ToDo list API',
+     description:
+     'This API exhibits how you can provide a comprehensible API documentation using [Hono](https://hono.dev), [Redoc](https://redocly.com/docs/redoc/).',
+     'x-logo': {
+      url: 'https://raw.githubusercontent.com/honojs/hono/main/docs/images/hono-title.png',
+      altText: 'Sample ToDo API logo',
+    },
+  },
+  tags: [
+     { name: 'Root', description: 'Root route' },
+   ],
+ });

+ app.get('/docs/redoc', (c) =>
+   c.html(
+     <html lang="en">
+       <head>
+         <meta charset="utf-8" />
+         <meta name="viewport" content="width=device-width, initial-scale=1" />
+         <meta name="description" content="SwaggerUI" />
+         <title>Sample API | Redoc</title>
+       </head>
+       <body>
+         <redoc spec-url="/openapi-spec.json"></redoc>
+         <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js">+ </script>
+       </body>
+    </html>,
+  ),
+ );

export default app

サーバー立ち上げて、http://localhost:8787/docs/redoc にアクセスすれば、ReDoc確認できると思います。
B6DE5ABF-5676-4370-8F46-0D5D0D72E398.jpeg

UIのカスタマイズする際には公式ドキュメントを参考してください。

また、swagger-ui使用したい場合はこちらのドキュメントを参考にしてください。

補足

本記事では、Cloudflare Workersに対応したHonoプロジェクトを初期化しました。

以下のコマンドを実行すれば、Cloudflare Workersにデプロイできます。

bun run deploy

動作検証も済みです。

AWS ECSにデプロイしたい場合、下記の修正を加えれば、対応できます。

src/index.tsx
..
- export default app;

+ export default {
+   port: 3000,
+   fetch: app.fetch,
+ };
package.json
  "scripts": {
    "dev": "wrangler dev",
    "deploy": "wrangler deploy --minify",
+   "start": "bun run src/index.tsx"
  }
Dockerfile
# build
FROM oven/bun:latest

WORKDIR /app

COPY package.json ./

RUN bun install --production
COPY . .

EXPOSE 3000

CMD ["bun", "run", "start"]

最後に

ReDocの便利なカスタマイズ方法があれば、ぜひ教えてください。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?