mcpField
N
nestjs-best-practices

nestjs-best-practices

github.com/giuseppe-trisciuoglio開発3663.8k 回インストール7 週間前に更新
リポジトリ

nestjs-best-practices について

NestJS開発者向けの実践ガイドです。公式ドキュメントを基に、モジュール境界、依存性注入、例外処理、DTO検証の方法をまとめ、Drizzle ORMの連携パターンも扱います。

主な機能

  1. 01ドメイン単位のモジュール設計
  2. 02依存性注入スコープの選択
  3. 03一貫した例外処理
  4. 04DTOと入力値の検証
  5. 05Drizzle ORMのリポジトリパターン

活用シーン

  1. 01NestJSモジュールの設計やリファクタリング
  2. 02注入とプロバイダースコープの設定
  3. 03APIへのDTO検証の追加
  4. 04例外処理やデータベースアクセスのレビュー

インストール

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

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill nestjs-best-practices

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/templates/
controller-template.ts
module-template.ts
service-template.ts
references/
api-validation-dto.md
arch-module-boundaries.md
architecture.md
db-drizzle-patterns.md
di-provider-scoping.md
error-exception-filters.md

詳細

NestJS のベストプラクティス

概要

公式の NestJS ドキュメントに基づき、モジュール型アーキテクチャ、依存性注入のスコープ、例外フィルター、class-validator による DTO 検証、Drizzle ORM の統合パターンを徹底します。

使用する場面

  • NestJS のモジュールや依存性注入を設計・リファクタリングするとき
  • 例外フィルターの作成、DTO の検証、Drizzle ORM の統合を行うとき
  • アンチパターンの有無をコードレビューするとき、または NestJS のコードベースに参加するとき

指示

1. モジュール型アーキテクチャ

厳格なモジュールのカプセル化に従います。各ドメイン機能はそれぞれ独立した @Module() にします。

  • 他のモジュールが必要とするものだけをエクスポートし、内部のプロバイダーは非公開にします
  • 循環依存に対する最後の手段としてのみ forwardRef() を使用し、可能な限り構造を見直します
  • 関連するコントローラー、サービス、リポジトリを同じモジュール内にまとめます
  • 横断的関心事(ロギング、設定、キャッシュ)には SharedModule を使用します

適用ルールについては、references/arch-module-boundaries.md を参照してください。

2. 依存性注入

ユースケースに応じて、適切なプロバイダースコープを選択します。

スコープライフサイクルユースケース
DEFAULTシングルトン(共有)ステートレスなサービス、リポジトリ
REQUESTリクエストごとのインスタンスリクエスト単位のデータ(テナント、ユーザーコンテキスト)
TRANSIENT注入ごとに新しいインスタンスステートフルなユーティリティ、利用者ごとのキャッシュ
  • DEFAULT スコープをデフォルトとし、正当な理由がある場合にのみ REQUEST または TRANSIENT を使用します
  • コンストラクター注入のみを使用し、プロパティ注入は避けます
  • useClass、useValue、useFactory、useExisting を使ってカスタムプロバイダーを登録します

適用ルールについては、references/di-provider-scoping.md を参照してください。

3. リクエストライフサイクル

NestJS のリクエスト処理パイプラインを理解し、それに従います。

Middleware → Guards → Interceptors (before) → Pipes → Route Handler → Interceptors (after) → Exception Filters
  • ミドルウェア:横断的関心事(ロギング、CORS、ボディ解析)
  • ガード:認可と認証のチェック(true/false を返します)
  • インターセプター:レスポンスデータの変換、キャッシュの追加、処理時間の計測
  • パイプ:入力パラメーターの検証と変換
  • 例外フィルター:エラーレスポンスの捕捉と整形
4. エラー処理

アプリケーション全体でエラーレスポンスを標準化します。

  • HTTP 固有のエラーには HttpException を拡張します
  • ドメイン固有の例外クラス(例:OrderNotFoundException)を作成します
  • 一貫したエラー整形のために、グローバルな ExceptionFilter を実装します
  • 想定されるビジネスロジックの失敗には Result パターンを使用します
  • 例外を黙って握りつぶしてはいけません

適用ルールについては、references/error-exception-filters.md を参照してください。

5. バリデーション

API 境界で入力検証を徹底します。

  • transform: true と whitelist: true を設定して、ValidationPipe をグローバルに有効化します
  • すべての DTO プロパティに class-validator のデコレーターを付与します
  • 型変換(@Type()、@Transform())には class-transformer を使用します
  • 作成、更新、レスポンスの操作ごとに個別の DTO を作成します
  • 生のユーザー入力を信頼せず、すべてを検証します

適用ルールについては、references/api-validation-dto.md を参照してください。

6. データベースパターン(Drizzle ORM)

NestJS のプロバイダー規約に従って Drizzle ORM を統合します。

  • Drizzle クライアントを注入可能なプロバイダーでラップします
  • データアクセスをカプセル化するためにリポジトリパターンを使用します
  • 各ドメインモジュールの専用スキーマファイルでスキーマを定義します
  • 複数ステップの操作にはトランザクションを使用します
  • コントローラーにデータベースのロジックを記述しません

適用ルールについては、references/db-drizzle-patterns.md を参照してください。

ベストプラクティス

領域実施すること避けること
モジュールドメイン機能ごとに1つのモジュールを作成するすべてをAppModuleに詰め込む
DIのスコープデフォルトでシングルトンスコープにする正当な理由なくREQUESTスコープを使う
エラー処理カスタム例外フィルターとドメインエラーを使用するconsole.logを使った単純なtry/catch
バリデーショングローバルなValidationPipeとDTOデコレーターを使うコントローラー内で手動のifチェックを行う
データベースクライアントを注入したリポジトリパターンを使うコントローラー内でDBクエリを直接実行する
テストサービスをユニットテストし、コントローラーをe2eテストするテストを省略する、または実装の詳細をテストする
設定型付きスキーマで@nestjs/configを使う値をハードコードする、またはprocess.envを使う

例

例:バリデーションを備えた新しいドメインモジュール

「Product」機能を構築する場合は、次のワークフローに従います。

1. 適切にカプセル化したモジュールを作成します:

// product/product.module.ts
@Module({
  imports: [DatabaseModule],
  controllers: [ProductController],
  providers: [ProductService, ProductRepository],
  exports: [ProductService], // Only export what others need
})
export class ProductModule {}

2. バリデーション済みのDTOを作成します:

// product/dto/create-product.dto.ts
import { IsString, IsNumber, IsPositive, MaxLength } from 'class-validator';

export class CreateProductDto {
  @IsString() @MaxLength(255) readonly name: string;
  @IsNumber() @IsPositive() readonly price: number;
}

3. エラー処理を備えたサービスを作成します:

@Injectable()
export class ProductService {
  constructor(private readonly productRepository: ProductRepository) {}

  async findById(id: string): Promise<Product> {
    const product = await this.productRepository.findById(id);
    if (!product) throw new ProductNotFoundException(id);
    return product;
  }
}

4. モジュールの登録を確認します:

# Check module is imported in AppModule
grep -r "ProductModule" src/app.module.ts

# Run e2e to confirm exports work
npx jest --testPathPattern="product"

制約と警告

  1. 正当な理由なくスコープを混在させないでください — REQUESTスコープのプロバイダーは、すべての依存先に連鎖します
  2. コントローラーからデータベースに直接アクセスしないでください — 必ずサービス層とリポジトリ層を経由します
  3. forwardRef()は避けてください — モジュールを再構成して循環依存を解消します
  4. ValidationPipeを省略しないでください — DTOを使って、APIの境界で必ずバリデーションを行います
  5. シークレットをハードコードしないでください — 環境変数を使って@nestjs/configを設定します
  6. モジュールの責務を絞ってください — 1つのモジュールにつきドメイン機能は1つとし、「巨大なモジュール」は避けます

参考資料

  • references/architecture.md — NestJSのアーキテクチャパターンを詳しく解説します
  • references/ — 正しい例と誤った例を含む、個別の適用ルール
  • assets/templates/ — 一般的なNestJSコンポーネント向けのスターターテンプレート

コメント