hono-typescript
Cloudflare Workers、Deno、Bun、Node.js 向けに、Hono と TypeScript を使ってエッジファーストな高パフォーマンス API を構築するためのガイドライン。
description の原文を見る
Guidelines for building edge-first, high-performance APIs with Hono and TypeScript for Cloudflare Workers, Deno, Bun, and Node.js
SKILL.md 本文
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 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' }));
// カスタムミドルウェア
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 は 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';
// エラーをスロー
if (!user) {
throw new HTTPException(404, { message: 'User not found' });
}
// グローバルエラーハンドラ
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 データベース
const result = await c.env.DB.prepare('SELECT * FROM users').all();
// KV ストレージ
await c.env.KV.put('key', 'value');
const value = await c.env.KV.get('key');
// R2 ストレージ
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);
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- mindrally
- リポジトリ
- mindrally/skills
- ライセンス
- Apache-2.0
- 最終更新
- 不明
Source: https://github.com/mindrally/skills / ライセンス: Apache-2.0
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。