hono-typescript について
TypeScript で Hono アプリケーションを構築するための開発ガイドスキルです。型付きルーティング、検証、ミドルウェア、テストと、複数ランタイム向けの設定を扱います。
主な機能
- 01TypeScript の型付け規約
- 02Hono のルーティングとミドルウェア
- 03Zod によるリクエスト検証
- 04コンテキストとエラー処理
- 05複数ランタイムの設定
- 06テストとパフォーマンスの実践
活用シーン
- 01型付き Hono API の設計
- 02Zod によるリクエストデータの検証
- 03異なるランタイム向けのアプリ設定
- 04ハンドラーとミドルウェアのテスト
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mindrally/ skills --skill hono-typescriptインストール後、Claude Code で/hono-typescriptを入力して読み込まれたか確認します。
詳細
Hono TypeScript 開発
Cloudflare Workers、Deno、Bun、Node.js で動作する超高速なエッジファースト API の構築に関する深い知識を持つ、Hono と TypeScript 開発のエキスパートです。
TypeScript の一般的なガイドライン
基本原則
- コードとドキュメントにはすべて英語を使用します
- 変数と関数(引数と戻り値)には必ず型を宣言します
any型の使用を避け、必要な型を作成します- 公開クラスとメソッドのドキュメントには JSDoc を使用します
- 簡潔で保守しやすく、技術的に正確なコードを書きます
- 関数型および宣言型のプログラミングパターンを使用し、クラスは避けます
- DRY 原則に従うため、反復とモジュール化を優先します
命名規則
- 型とインターフェースには PascalCase を使用します
- 変数、関数、メソッドには camelCase を使用します
- ファイル名とディレクトリ名には kebab-case を使用します
- 環境変数には UPPERCASE を使用します
- 補助動詞を使った説明的な変数名を使用します:
isLoading、hasError、canDelete - 各関数名は動詞で始めます
関数
- 単一の目的を持つ短い関数を書きます
- ハンドラーとミドルウェアにはアロー関数を使用します
- RO-RO パターン(オブジェクトを受け取り、オブジェクトを返す)を優先します
- null チェックの代わりにデフォルト引数を使用します
型とインターフェース
- オブジェクトの形状には型よりインターフェースを優先します
- enum は避け、型安全性を高めるためにマップまたは const オブジェクトを使用します
- 実行時のバリデーションには Zod を使用し、型を推論します
- 不変のプロパティには
readonlyを使用します - 型のみのインポートには
import typeを使用します
Hono 固有のガイドライン
プロジェクト構成
src/
routes/
{resource}/
index.ts
handlers.ts
validators.ts
middleware/
auth.ts
cors.ts
logger.ts
services/
{domain}Service.ts
types/
index.ts
utils/
config/
index.ts
アプリケーションの初期化
import { Hono } from 'hono';
// Type your environment bindings
type Bindings = {
DB: D1Database;
KV: KVNamespace;
JWT_SECRET: string;
};
type Variables = {
user: User;
};
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>();
ルーティング
- すっきりとしたルート定義にはメソッドチェーンを使用します
- 関連するルートを
app.route()でグループ化します - 適切な型指定でルートパラメーターを使用します
const users = new Hono<{ Bindings: Bindings }>();
users.get('/', listUsers);
users.get('/:id', getUser);
users.post('/', zValidator('json', createUserSchema), createUser);
users.put('/:id', zValidator('json', updateUserSchema), updateUser);
users.delete('/:id', deleteUser);
app.route('/api/users', users);
ミドルウェア
- 利用可能な場合は Hono 組み込みのミドルウェアを使用します
- 独自のロジックには型付きミドルウェアを作成します
- 再利用しやすいようにミドルウェアを連結します
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
import { jwt } from 'hono/jwt';
app.use('*', logger());
app.use('/api/*', cors());
app.use('/api/*', jwt({ secret: 'your-secret' }));
// Custom middleware
const authMiddleware = async (c: Context, next: Next) => {
const user = await validateUser(c);
c.set('user', user);
await next();
};
Zod によるリクエストのバリデーション
- リクエストのバリデーションには
@hono/zod-validatorを使用します - すべてのリクエスト入力にスキーマを定義します
- Zod スキーマから型を推論します
import { z } from 'zod';
import { zValidator } from '@hono/zod-validator';
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
role: z.enum(['user', 'admin']).default('user'),
});
type CreateUserInput = z.infer<typeof createUserSchema>;
app.post('/users', zValidator('json', createUserSchema), async (c) => {
const data = c.req.valid('json');
// data is typed as CreateUserInput
});
コンテキストとレスポンスの処理
- 型安全性を高めるために型付きコンテキストを使用します
- レスポンスにはヘルパーメソッドを使用します:
c.json()、c.text()、c.html() - 環境バインディングにはコンテキスト経由でアクセスします
app.get('/users/:id', async (c) => {
const id = c.req.param('id');
const db = c.env.DB;
const user = await db.prepare('SELECT * FROM users WHERE id = ?')
.bind(id)
.first();
if (!user) {
return c.json({ error: 'User not found' }, 404);
}
return c.json(user);
});
エラー処理
- 想定されるエラーには Hono の
HTTPExceptionを使用します - グローバルエラーハンドラーミドルウェアを作成します
- 一貫性のあるエラーレスポンスを返します
import { HTTPException } from 'hono/http-exception';
// Throwing errors
if (!user) {
throw new HTTPException(404, { message: 'User not found' });
}
// Global error handler
app.onError((err, c) => {
if (err instanceof HTTPException) {
return c.json({ error: err.message }, err.status);
}
console.error(err);
return c.json({ error: 'Internal Server Error' }, 500);
});
Cloudflare Workers との統合
- キーと値のストレージには Workers KV を使用します
- SQL データベースには D1 を使用します
- オブジェクトストレージには R2 を使用します
- ステートフルなアプリケーションには Durable Objects を使用します
// D1 Database
const result = await c.env.DB.prepare('SELECT * FROM users').all();
// KV Storage
await c.env.KV.put('key', 'value');
const value = await c.env.KV.get('key');
// R2 Storage
await c.env.BUCKET.put('file.txt', content);
テスト
- 統合テストには Hono のテストクライアントを使用します
- テストランナーには Vitest または Jest を使用します
- ハンドラーとミドルウェアは個別にテストします
import { testClient } from 'hono/testing';
import { describe, it, expect } from 'vitest';
describe('User API', () => {
const client = testClient(app);
it('should list users', async () => {
const res = await client.api.users.$get();
expect(res.status).toBe(200);
const data = await res.json();
expect(Array.isArray(data)).toBe(true);
});
});
パフォーマンス
- Hono はオーバーヘッドが最小限の超高速フレームワークです
- 大きなデータにはストリーミングレスポンスを使用します
- Cache API によるエッジキャッシュを活用します
- バンドルサイズを最小限にするには
hono/tinyプリセットを使用します
セキュリティ
hono/secure-headersミドルウェアを使用します- レート制限を実装します
- すべての入力を Zod で検証します
- 認証には JWT を使用します
- 適切に CORS を有効にします
マルチランタイム対応
Hono は複数のランタイムで動作します。適切に設定してください:
// Cloudflare Workers
export default app;
// Node.js
import { serve } from '@hono/node-server';
serve(app);
// Bun
export default app;
// Deno
Deno.serve(app.fetch);
コメント
Markdown 対応