mcpField
K
koa-typescript

koa-typescript

github.com/mindrally開発287708 回インストール3 週間前に更新
リポジトリ

koa-typescript について

Koa.js と TypeScript で API を開発する人向けのコーディングスキルです。ミドルウェアの設計、型安全、検証、セキュリティ、テストの指針を扱います。

主な機能

  1. 01Koa の onion ミドルウェアパターン
  2. 02TypeScript の型安全ガイダンス
  3. 03ルーティングとプロジェクト構成
  4. 04エラー処理とリクエスト検証
  5. 05認証、セキュリティ、テスト

活用シーン

  1. 01Koa API のプロジェクト構成の設計
  2. 02非同期ミドルウェアとルートの実装
  3. 03エンドポイントへの検証と認証の追加
  4. 04テストとセキュリティ対策の計画

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mindrally/skills --skill koa-typescript

インストール後、Claude Code で/koa-typescriptを入力して読み込まれたか確認します。

詳細

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';

// Middleware pattern with 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();

// Error handling (first in chain)
app.use(errorHandler);

// Security
app.use(helmet());
app.use(cors());

// Body parsing
app.use(bodyParser());

// Logging
app.use(requestLogger);

// Routes
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 を使用します
  • body、query、params を検証します
  • 明確な検証エラーメッセージを返します
  • 再利用可能な検証ミドルウェアを作成します
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 を使用します
  • 起動時に必須の環境変数を検証します
  • 環境ごとに個別の設定を作成します
  • シークレットをバージョン管理にコミットしないでください

コメント