koa-typescript
Koa.jsとTypeScriptを使用したモダンなAPI構築のガイドラインで、オニオンモデルのミドルウェア設計とasync/awaitパターンを活用した開発をサポートします。
description の原文を見る
Guidelines for building modern APIs with Koa.js and TypeScript, featuring the onion middleware model and async/await patterns
SKILL.md 本文
Koa TypeScript 開発
Koa.js と TypeScript 開発の専門家として、Koa の独特なオニオンモデルを使用した優雅なミドルウェアベースの API 構築に関する深い知識を持っています。
TypeScript 一般ガイドライン
基本原則
- コードとドキュメントはすべて英語で記述する
- 変数と関数に対して常に型を宣言する
any型の使用を避ける。必要な型を作成する- 公開クラスとメソッドに JSDoc を使用して文書化する
- 簡潔で保守性の高い、技術的に正確なコードを書く
- 関数型および宣言型プログラミングパターンを使用する
- DRY 原則に従うために、反復処理とモジュール化を優先する
命名規則
- 型とインターフェースには PascalCase を使用する
- 変数、関数、メソッドには camelCase を使用する
- ファイルとディレクトリ名には kebab-case を使用する
- 環境変数には UPPERCASE を使用する
- 補助動詞を含む説明的な変数名を使用する
関数
- 単一の目的を持つ短い関数を書く
- ミドルウェアには矢印関数を使用する
- コードベース全体で async/await を一貫して使用する
- 複数のパラメータには RO-RO パターンを使用する
Koa 固有ガイドライン
プロジェクト構造
src/
routes/
{resource}/
index.ts
controller.ts
validators.ts
middleware/
auth.ts
errorHandler.ts
requestId.ts
logger.ts
services/
{domain}Service.ts
models/
{entity}.ts
utils/
config/
app.ts
server.ts
ミドルウェアパターン
Koa は独特の「オニオン」ミドルウェアモデルを使用しています。ミドルウェア関数はスタック状の方法で構成・実行されます。
import { Middleware } from 'koa';
// async/await を用いたミドルウェアパターン
const responseTime: Middleware = async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
};
- ミドルウェアには常に
async/awaitを使用する - 制御を下流のミドルウェアに渡すために
await next()を呼び出す await next()の後のコードは「上流」フェーズ中に実行される- リクエスト/レスポンス変換にはこのパターンを使用する
コンテキスト (ctx) のベストプラクティス
- ミドルウェア間でデータを渡すために
ctx.stateを使用する - より強い型安全性のためにコンテキストに型を付ける
- コンテキストを直接変更することを避ける
- リクエスト/レスポンスアクセスにはコンテキストを使用する
import { ParameterizedContext, Middleware } from 'koa';
interface AppState {
user?: User;
requestId: string;
}
type AppContext = ParameterizedContext<AppState>;
const authMiddleware: Middleware<AppState> = async (ctx, next) => {
ctx.state.user = await validateToken(ctx.headers.authorization);
await next();
};
アプリケーションセットアップ
import Koa from 'koa';
import Router from '@koa/router';
import bodyParser from 'koa-bodyparser';
import cors from '@koa/cors';
import helmet from 'koa-helmet';
import { errorHandler } from './middleware/errorHandler';
import { requestLogger } from './middleware/logger';
const app = new Koa();
// エラーハンドリング (チェーンの最初)
app.use(errorHandler);
// セキュリティ
app.use(helmet());
app.use(cors());
// ボディパース
app.use(bodyParser());
// ロギング
app.use(requestLogger);
// ルート
app.use(router.routes());
app.use(router.allowedMethods());
export default app;
koa-router によるルーティング
- 宣言的ルーティングに koa-router を使用する
- リソースごとにルートを整理する
- ルートハンドラを簡潔に保つ
- 横断的な関心事にはミドルウェアを使用する
import Router from '@koa/router';
import * as controller from './controller';
import { validateUserInput } from './validators';
const router = new Router({ prefix: '/api/users' });
router.get('/', controller.listUsers);
router.get('/:id', controller.getUser);
router.post('/', validateUserInput, controller.createUser);
router.put('/:id', validateUserInput, controller.updateUser);
router.delete('/:id', controller.deleteUser);
export default router;
エラーハンドリング
- 集中型エラーハンドリングミドルウェアを作成する
- ミドルウェアスタックの最上部にエラーハンドラを配置する
- 異なるエラータイプに対してカスタムエラークラスを使用する
- 本番環境では内部エラーの詳細を公開しない
import { Middleware } from 'koa';
class AppError extends Error {
constructor(
public status: number,
message: string,
public expose: boolean = true
) {
super(message);
}
}
const errorHandler: Middleware = async (ctx, next) => {
try {
await next();
} catch (err) {
const error = err as Error & { status?: number; expose?: boolean };
ctx.status = error.status || 500;
ctx.body = {
error: {
message: error.expose ? error.message : 'Internal Server Error',
...(process.env.NODE_ENV === 'development' && { stack: error.stack })
}
};
ctx.app.emit('error', err, ctx);
}
};
リクエスト検証
- 検証に koa-joi-router または Zod を使用する
- ボディ、クエリ、パラメータを検証する
- 明確な検証エラーメッセージを返す
- 再利用可能な検証ミドルウェアを作成する
import { z } from 'zod';
import { Middleware } from 'koa';
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
});
const validate = (schema: z.ZodSchema): Middleware => {
return async (ctx, next) => {
try {
ctx.request.body = schema.parse(ctx.request.body);
await next();
} catch (error) {
if (error instanceof z.ZodError) {
ctx.status = 400;
ctx.body = { errors: error.errors };
return;
}
throw error;
}
};
};
認証
- koa-jwt で JWT 認証を実装する
- 認証されたユーザを
ctx.state.userに保存する - ロールベースのアクセス用に認可ミドルウェアを作成する
import jwt from 'koa-jwt';
app.use(jwt({ secret: process.env.JWT_SECRET }).unless({ path: [/^\/public/] }));
const requireRole = (role: string): Middleware => {
return async (ctx, next) => {
if (ctx.state.user?.role !== role) {
ctx.throw(403, 'Forbidden');
}
await next();
};
};
セキュリティ
- セキュリティヘッダに koa-helmet を使用する
- koa-ratelimit でレート制限を実装する
- @koa/cors で CORS を有効にする
- すべての入力を検証・サニタイズする
- 本番環境では HTTPS を使用する
テスト
- テストに Jest または Mocha を使用する
- app.callback() を使用した統合テストに supertest を使用する
- ミドルウェアを分離してテストする
- ユニットテストではコンテキストをモックする
import request from 'supertest';
import app from '../app';
describe('GET /api/users', () => {
it('should return users list', async () => {
const response = await request(app.callback())
.get('/api/users')
.expect(200);
expect(response.body).toBeInstanceOf(Array);
});
});
パフォーマンス
- レスポンス圧縮に koa-compress を使用する
- koa-redis-cache でキャッシングを実装する
- データベースにはコネクションプーリングを使用する
- リストエンドポイントにはページネーションを実装する
- 静的ファイルの配信には koa-static を検討する
環境構成
- 環境変数に dotenv を使用する
- スタートアップ時に必須の環境変数を検証する
- 異なる環境ごとに個別の設定を作成する
- シークレットを絶対にバージョン管理にコミットしない
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- mindrally
- リポジトリ
- mindrally/skills
- ライセンス
- Apache-2.0
- 最終更新
- 不明
Source: https://github.com/mindrally/skills / ライセンス: Apache-2.0
関連スキル
agent-browser
AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。
anyskill
AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。
engram
AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。
skyvern
AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。
pinchbench
PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。
openui
OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。