nestjs
NestJSは、Angularに影響を受けた構造で、Node.js上で拡張性の高いサーバーサイドアプリケーションを構築するための、TypeScriptで記述された先進的なフレームワークであり、効率的な開発を支援するSkill。
📜 元の英語説明(参考)
NestJS is a progressive TypeScript framework for building scalable server-side applications on Node.js. It uses decorators, modules, dependency injection, and an opinionated architecture inspired by Angular.
🇯🇵 日本人クリエイター向け解説
NestJSは、Angularに影響を受けた構造で、Node.js上で拡張性の高いサーバーサイドアプリケーションを構築するための、TypeScriptで記述された先進的なフレームワークであり、効率的な開発を支援するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o nestjs.zip https://jpskill.com/download/15162.zip && unzip -o nestjs.zip && rm nestjs.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15162.zip -OutFile "$d\nestjs.zip"; Expand-Archive "$d\nestjs.zip" -DestinationPath $d -Force; ri "$d\nestjs.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
nestjs.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
nestjsフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
NestJS
NestJS は、依存性注入を備えたモジュールアーキテクチャ、ルーティングとバリデーションのためのデコレータ、認証のためのガード、および横断的な関心事のためのインターセプターを提供します。
インストール
# 新しい NestJS プロジェクトを作成
npm i -g @nestjs/cli
nest new my-api
cd my-api
npm i @nestjs/typeorm typeorm pg class-validator class-transformer
プロジェクト構造
# 標準的な NestJS プロジェクトのレイアウト
src/
├── main.ts # Bootstrap
├── app.module.ts # ルートモジュール
├── articles/
│ ├── articles.module.ts # 機能モジュール
│ ├── articles.controller.ts
│ ├── articles.service.ts
│ ├── entities/article.entity.ts
│ └── dto/
│ ├── create-article.dto.ts
│ └── update-article.dto.ts
├── auth/
│ ├── auth.module.ts
│ ├── auth.guard.ts
│ └── auth.service.ts
└── common/
├── filters/
└── interceptors/
モジュール
// src/articles/articles.module.ts — 機能モジュール
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ArticlesController } from './articles.controller';
import { ArticlesService } from './articles.service';
import { Article } from './entities/article.entity';
@Module({
imports: [TypeOrmModule.forFeature([Article])],
controllers: [ArticlesController],
providers: [ArticlesService],
exports: [ArticlesService],
})
export class ArticlesModule {}
エンティティ
// src/articles/entities/article.entity.ts — TypeORM エンティティ
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne } from 'typeorm';
import { User } from '../../users/entities/user.entity';
@Entity()
export class Article {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 200 })
title: string;
@Column('text')
body: string;
@ManyToOne(() => User, (user) => user.articles)
author: User;
@CreateDateColumn()
createdAt: Date;
}
バリデーション付き DTO
// src/articles/dto/create-article.dto.ts — バリデーションされた DTO
import { IsString, IsNotEmpty, MaxLength } from 'class-validator';
export class CreateArticleDto {
@IsString()
@IsNotEmpty()
@MaxLength(200)
title: string;
@IsString()
@IsNotEmpty()
body: string;
}
コントローラ
// src/articles/articles.controller.ts — REST コントローラ
import {
Controller, Get, Post, Body, Param, Delete,
ParseIntPipe, UseGuards, Query, HttpCode, HttpStatus,
} from '@nestjs/common';
import { ArticlesService } from './articles.service';
import { CreateArticleDto } from './dto/create-article.dto';
import { AuthGuard } from '../auth/auth.guard';
@Controller('articles')
export class ArticlesController {
constructor(private readonly articlesService: ArticlesService) {}
@Get()
findAll(@Query('page') page = 1, @Query('limit') limit = 20) {
return this.articlesService.findAll(+page, +limit);
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.articlesService.findOne(id);
}
@Post()
@UseGuards(AuthGuard)
@HttpCode(HttpStatus.CREATED)
create(@Body() dto: CreateArticleDto) {
return this.articlesService.create(dto);
}
@Delete(':id')
@UseGuards(AuthGuard)
@HttpCode(HttpStatus.NO_CONTENT)
remove(@Param('id', ParseIntPipe) id: number) {
return this.articlesService.remove(id);
}
}
サービス
// src/articles/articles.service.ts — DI を使用したビジネスロジック
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Article } from './entities/article.entity';
import { CreateArticleDto } from './dto/create-article.dto';
@Injectable()
export class ArticlesService {
constructor(
@InjectRepository(Article)
private readonly repo: Repository<Article>,
) {}
async findAll(page: number, limit: number) {
return this.repo.find({
skip: (page - 1) * limit,
take: limit,
order: { createdAt: 'DESC' },
relations: ['author'],
});
}
async findOne(id: number) {
const article = await this.repo.findOne({ where: { id }, relations: ['author'] });
if (!article) throw new NotFoundException(`Article #${id} not found`);
return article;
}
async create(dto: CreateArticleDto) {
const article = this.repo.create(dto);
return this.repo.save(article);
}
async remove(id: number) {
const result = await this.repo.delete(id);
if (result.affected === 0) throw new NotFoundException();
}
}
ガード
// src/auth/auth.guard.ts — JWT 認証ガード
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Request } from 'express';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest<Request>();
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) throw new UnauthorizedException();
try {
request['user'] = await this.jwtService.verifyAsync(token);
return true;
} catch {
throw new UnauthorizedException();
}
}
}
アプリモジュールとブートストラップ
// src/app.module.ts — TypeORM 設定を持つルートモジュール
import { Module, ValidationPipe } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ArticlesModule } from './articles/articles.module';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.DB_HOST ?? 'localhost',
port: 5432,
database: process.env.DB_NAME ?? 'mydb',
username: process.env.DB_USER ?? 'postgres',
password: process.env.DB_PASSWORD ?? '',
autoLoadEntities: true,
synchronize: process.env.NODE_ENV !== 'production',
}),
ArticlesModule,
],
})
export class AppMo 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
NestJS
NestJS provides a modular architecture with dependency injection, decorators for routing and validation, guards for auth, and interceptors for cross-cutting concerns.
Installation
# Create new NestJS project
npm i -g @nestjs/cli
nest new my-api
cd my-api
npm i @nestjs/typeorm typeorm pg class-validator class-transformer
Project Structure
# Standard NestJS project layout
src/
├── main.ts # Bootstrap
├── app.module.ts # Root module
├── articles/
│ ├── articles.module.ts # Feature module
│ ├── articles.controller.ts
│ ├── articles.service.ts
│ ├── entities/article.entity.ts
│ └── dto/
│ ├── create-article.dto.ts
│ └── update-article.dto.ts
├── auth/
│ ├── auth.module.ts
│ ├── auth.guard.ts
│ └── auth.service.ts
└── common/
├── filters/
└── interceptors/
Module
// src/articles/articles.module.ts — feature module
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ArticlesController } from './articles.controller';
import { ArticlesService } from './articles.service';
import { Article } from './entities/article.entity';
@Module({
imports: [TypeOrmModule.forFeature([Article])],
controllers: [ArticlesController],
providers: [ArticlesService],
exports: [ArticlesService],
})
export class ArticlesModule {}
Entity
// src/articles/entities/article.entity.ts — TypeORM entity
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne } from 'typeorm';
import { User } from '../../users/entities/user.entity';
@Entity()
export class Article {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 200 })
title: string;
@Column('text')
body: string;
@ManyToOne(() => User, (user) => user.articles)
author: User;
@CreateDateColumn()
createdAt: Date;
}
DTOs with Validation
// src/articles/dto/create-article.dto.ts — validated DTO
import { IsString, IsNotEmpty, MaxLength } from 'class-validator';
export class CreateArticleDto {
@IsString()
@IsNotEmpty()
@MaxLength(200)
title: string;
@IsString()
@IsNotEmpty()
body: string;
}
Controller
// src/articles/articles.controller.ts — REST controller
import {
Controller, Get, Post, Body, Param, Delete,
ParseIntPipe, UseGuards, Query, HttpCode, HttpStatus,
} from '@nestjs/common';
import { ArticlesService } from './articles.service';
import { CreateArticleDto } from './dto/create-article.dto';
import { AuthGuard } from '../auth/auth.guard';
@Controller('articles')
export class ArticlesController {
constructor(private readonly articlesService: ArticlesService) {}
@Get()
findAll(@Query('page') page = 1, @Query('limit') limit = 20) {
return this.articlesService.findAll(+page, +limit);
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.articlesService.findOne(id);
}
@Post()
@UseGuards(AuthGuard)
@HttpCode(HttpStatus.CREATED)
create(@Body() dto: CreateArticleDto) {
return this.articlesService.create(dto);
}
@Delete(':id')
@UseGuards(AuthGuard)
@HttpCode(HttpStatus.NO_CONTENT)
remove(@Param('id', ParseIntPipe) id: number) {
return this.articlesService.remove(id);
}
}
Service
// src/articles/articles.service.ts — business logic with DI
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Article } from './entities/article.entity';
import { CreateArticleDto } from './dto/create-article.dto';
@Injectable()
export class ArticlesService {
constructor(
@InjectRepository(Article)
private readonly repo: Repository<Article>,
) {}
async findAll(page: number, limit: number) {
return this.repo.find({
skip: (page - 1) * limit,
take: limit,
order: { createdAt: 'DESC' },
relations: ['author'],
});
}
async findOne(id: number) {
const article = await this.repo.findOne({ where: { id }, relations: ['author'] });
if (!article) throw new NotFoundException(`Article #${id} not found`);
return article;
}
async create(dto: CreateArticleDto) {
const article = this.repo.create(dto);
return this.repo.save(article);
}
async remove(id: number) {
const result = await this.repo.delete(id);
if (result.affected === 0) throw new NotFoundException();
}
}
Guards
// src/auth/auth.guard.ts — JWT auth guard
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Request } from 'express';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest<Request>();
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) throw new UnauthorizedException();
try {
request['user'] = await this.jwtService.verifyAsync(token);
return true;
} catch {
throw new UnauthorizedException();
}
}
}
App Module and Bootstrap
// src/app.module.ts — root module with TypeORM config
import { Module, ValidationPipe } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ArticlesModule } from './articles/articles.module';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.DB_HOST ?? 'localhost',
port: 5432,
database: process.env.DB_NAME ?? 'mydb',
username: process.env.DB_USER ?? 'postgres',
password: process.env.DB_PASSWORD ?? '',
autoLoadEntities: true,
synchronize: process.env.NODE_ENV !== 'production',
}),
ArticlesModule,
],
})
export class AppModule {}
// src/main.ts — bootstrap with global pipes
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
app.enableCors();
await app.listen(3000);
}
bootstrap();
Testing
// src/articles/articles.service.spec.ts — unit test
import { Test } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { ArticlesService } from './articles.service';
import { Article } from './entities/article.entity';
describe('ArticlesService', () => {
let service: ArticlesService;
const mockRepo = { find: jest.fn().mockResolvedValue([]), create: jest.fn(), save: jest.fn() };
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
ArticlesService,
{ provide: getRepositoryToken(Article), useValue: mockRepo },
],
}).compile();
service = module.get(ArticlesService);
});
it('returns articles', async () => {
expect(await service.findAll(1, 20)).toEqual([]);
});
});
Key Patterns
- One module per feature; import only what you need
- Use
ValidationPipewithwhitelist: trueto strip unknown properties - Use guards for auth, interceptors for response mapping, filters for exceptions
- Set
synchronize: falsein production — use TypeORM migrations instead - Use
@nestjs/configwithConfigModule.forRoot()for environment variables