nestjs について
NestJS v11 と Express 5 のバックエンドコードを変更する開発者向けの規約スキルです。一方向のレイヤー構成、DTO 検証、予測可能なリクエスト処理、バージョン固有の注意点を扱います。
主な機能
- 01一方向のモジュール構成
- 02DTO 検証とレスポンス整形
- 03ドメインエラー処理
- 04グローバルエンハンサーの登録
- 05Express 5 と NestJS の注意点
活用シーン
- 01バックエンド機能の追加や変更
- 02リクエストライフサイクルの挙動確認
- 03NestJS v11 移行時のコード確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ alexander-danilenko/ cortex-claude-code-plugins --skill nestjsインストール後、Claude Code で/nestjsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/architecture.mdconfiguration-and-logging.mddependency-injection.mddto-validation-openapi.mdecosystem-packages.mderrors.mdnestjs-11-migration.mdrequest-lifecycle.md詳細
NestJS
v11/Express 5 の NestJS バックエンドに関する慣例です。作成または変更するコードに適用してください。依頼されていない限り、変更しないモジュールの構成は変更しないでください。
以下の例では、構造を具体的に示すためだけに、架空の配送ドメインを使用しています。名前ではなく構造を見てください。
レイヤー構成
レイヤーは2つだけで、依存の矢印は一方向にのみ向きます。
core/ domain + infrastructure. No controllers, no HTTP. → core only
app/ features. Controllers, DTOs, guards, middleware, CQRS. → app + core
コアモジュールが機能モジュールの内部にアクセスする必要があるなら、それは、そのコアモジュールが所有する概念が間違ったレイヤーにあるということです。上位レイヤーからインポートするのではなく、その概念を下位レイヤーに移してください。依存の矢印を正しく保つことで、コントローラーを巻き込まずに、HTTP リクエスト、cron ジョブ、CLI、キューコンシューマーのいずれからでもコアモジュールを駆動できます。
常に適用すること
ほとんどすべての変更に当てはまるため、リファレンスに委ねず、ここに記載します。
- 1つのモジュールが1つのドメインを所有し、ルートのバレルからエクスポートするのは
.module.tsのみです。 エクスポートされていないプロバイダーは自由にリファクタリングできます。エクスポートされると公開 API になります。 - コントローラーは HTTP を変換して処理を委譲し、サービスはロジックを担います。 ビジネスルールに基づいて分岐するコントローラーは、ジョブ、CLI、キューコンシューマーでは再利用できません。また、そのテストで何かを確認するには HTTP レイヤーが必要になります。
- すべてのリクエストボディ、クエリ、パラメーターは、
class-validatorを使用した DTO を通し、whitelist: true、forbidNonWhitelisted: true、transform: trueを指定したValidationPipeを適用します。 ホワイトリストがなければ、想定外のプロパティが永続化レイヤーまでそのまま渡ります。 - プロセスから返すのはレスポンス DTO です。 エンティティを返すと、将来のマイグレーションでテーブルに追加された内容(パスワードハッシュ、内部フラグ、論理削除用カラムなど)が、コードを変更しなくても漏えいします。
- ドメインエラーは1つの基底クラスを継承し、1つのグローバルフィルターで処理します。 裸の
Errorは 500 になるため、正当な「見つかりません」エラーで担当者にページャー通知が飛んでしまいます。 - グローバルエンハンサーは
APP_GUARD/APP_PIPE/APP_INTERCEPTOR/APP_FILTERで登録します。app.useGlobal*()はどのモジュールの外側にもバインドされるため、それらのインスタンスは何も注入できません。 - ドメインサービスからベンダー SDK をインポートしません。 決済ゲートウェイ、データベースクライアント、メールプロバイダーには、それぞれラッパーモジュールを用意します。SDK の大規模なバージョンアップの影響を1つのモジュール内に留められます。
デフォルトでは誤り
API 名が示唆する動作とは異なる6つの挙動です。問題に気づいたときだけ開くリファレンスではなく、ここに記載します。いずれも問題なくコンパイルされますが、実行時に失敗します。
- Express 5 のワイルドカードには名前が必要です。
@Get("files/*")とforRoutes("*")はマッチしなくなりました。@Get("files/*splat")とforRoutes("{*splat}")を記述してください。:param?も廃止されています。 - 例外フィルターはルート → コントローラー → グローバルの順で解決されます。 ガードやパイプとは逆で、インターセプターは先入れ後出しで巻き戻されます。ルートスコープのフィルターはグローバルフィルターより優先されます。
@Res()を使うと、ハンドラーはフレームワークのレスポンス処理から除外されます。@HttpCode、@Header、シリアライズ、すべてのレスポンスインターセプターが適用されなくなります。レスポンスを自分で送信するのでなければ、{ passthrough: true }を追加してください。ClassSerializerInterceptorが変換するのはクラスインスタンスのみです。{ user: new UserEntity() }を返すと、@Exclude()は警告なく無視され、除外対象のフィールドが送信されます。@nestjs/cache-managerと@nestjs/throttlerではttlの単位はミリ秒です。また、キャッシュのttl: 0は有効期限なしを意味し、「キャッシュしない」ではありません。ClientProxy.send()はコールド Observable を返し、HttpServiceも同様に Observable を返します。 購読するまでは何も起こりません。
1つ目と5つ目はバージョン固有です。このスキルで v11 と記載された内容を適用する前に、package.json の @nestjs/core を確認してください。プロジェクトが古い場合は、references/nestjs-11-migration.md を読んでください。
リファレンスマップ
変更内容に該当するファイルを読み、すべてを事前に読み込まないでください。
| 作業内容 | 読むファイル |
|---|---|
| ディレクトリ構成、ファイル名、バレル、CQRS とサービスの比較、永続化 | references/architecture.md |
プロバイダー、トークン、スコープ、ModuleRef、循環依存、ライフサイクルフック | references/dependency-injection.md |
| ガード、インターセプター、パイプ、ミドルウェア、デコレーター、レスポンス、バージョニング | references/request-lifecycle.md |
| DTO、class-validator、シリアライゼーション、Swagger/OpenAPI | references/dto-validation-openapi.md |
| 例外、例外フィルター、エラーメッセージ | references/errors.md |
ConfigModule、ConfigService、ロギング | references/configuration-and-logging.md |
@nestjs/axios、event-emitter、bullmq、throttler、cache-manager、schedule、マイクロサービス | references/ecosystem-packages.md |
| v10 からのアップグレード、または Express 5 より前のコード | references/nestjs-11-migration.md |
| テスト | cortex-testing:conventions スキルの NestJS Jest リファレンス |
レビューを行う場合は、references/request-lifecycle.md と references/nestjs-11-migration.md を読むと、1 行あたりで最も多くの不具合を見つけられます。エンハンサーの順序と Express 5 のルート構文は、どちらも型チェックを通過しても問題が発生するためです。