{"id":"nestjs-expert","name":"nestjs-expert","summary":"エンタープライズグレードのTypeScriptバックエンドアプリケーション向けに、NestJSモジュール、コントローラ、サービス、DTO、ガード、インターセプターの作成・構成を行います。","body":"# NestJS Expert\n\nSenior NestJS specialist with deep expertise in enterprise-grade, scalable TypeScript backend applications.\n\n## Core Workflow\n\n1. **Analyze requirements** — Identify modules, endpoints, entities, and relationships\n2. **Design structure** — Plan module organization and inter-module dependencies\n3. **Implement** — Create modules, services, and controllers with proper DI wiring\n4. **Secure** — Add guards, validation pipes, and authentication\n5. **Verify** — Run `npm run lint`, `npm run test`, and confirm DI graph with `nest info`\n6. **Test** — Write unit tests for services and E2E tests for controllers\n\n## Reference Guide\n\nLoad detailed guidance based on context:\n\n| Topic | Reference | Load When |\n|-------|-----------|-----------|\n| Controllers | `references/controllers-routing.md` | Creating controllers, routing, Swagger docs |\n| Services | `references/services-di.md` | Services, dependency injection, providers |\n| DTOs | `references/dtos-validation.md` | Validation, class-validator, DTOs |\n| Authentication | `references/authentication.md` | JWT, Passport, guards, authorization |\n| Testing | `references/testing-patterns.md` | Unit tests, E2E tests, mocking |\n| Express Migration | `references/migration-from-express.md` | Migrating from Express.js to NestJS |\n\n## Code Examples\n\n### Controller with DTO Validation and Swagger\n\n```typescript\n// create-user.dto.ts\nimport { IsEmail, IsString, MinLength } from 'class-validator';\nimport { ApiProperty } from '@nestjs/swagger';\n\nexport class CreateUserDto {\n  @ApiProperty({ example: 'user@example.com' })\n  @IsEmail()\n  email: string;\n\n  @ApiProperty({ example: 'strongPassword123', minLength: 8 })\n  @IsString()\n  @MinLength(8)\n  password: string;\n}\n\n// users.controller.ts\nimport { Body, Controller, Post, HttpCode, HttpStatus } from '@nestjs/common';\nimport { ApiCreatedResponse, ApiTags } from '@nestjs/swagger';\nimport { UsersService } from './users.service';\nimport { CreateUserDto } from './dto/create-user.dto';\n\n@ApiTags('users')\n@Controller('users')\nexport class UsersController {\n  constructor(private readonly usersService: UsersService) {}\n\n  @Post()\n  @HttpCode(HttpStatus.CREATED)\n  @ApiCreatedResponse({ description: 'User created successfully.' })\n  create(@Body() createUserDto: CreateUserDto) {\n    return this.usersService.create(createUserDto);\n  }\n}\n```\n\n### Service with Dependency Injection and Error Handling\n\n```typescript\n// users.service.ts\nimport { Injectable, ConflictException, NotFoundException } from '@nestjs/common';\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { Repository } from 'typeorm';\nimport { User } from './entities/user.entity';\nimport { CreateUserDto } from './dto/create-user.dto';\n\n@Injectable()\nexport class UsersService {\n  constructor(\n    @InjectRepository(User)\n    private readonly usersRepository: Repository<User>,\n  ) {}\n\n  async create(createUserDto: CreateUserDto): Promise<User> {\n    const existing = await this.usersRepository.findOneBy({ email: createUserDto.email });\n    if (existing) {\n      throw new ConflictException('Email already registered');\n    }\n    const user = this.usersRepository.create(createUserDto);\n    return this.usersRepository.save(user);\n  }\n\n  async findOne(id: number): Promise<User> {\n    const user = await this.usersRepository.findOneBy({ id });\n    if (!user) {\n      throw new NotFoundException(`User #${id} not found`);\n    }\n    return user;\n  }\n}\n```\n\n### Module Definition\n\n```typescript\n// users.module.ts\nimport { Module } from '@nestjs/common';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { UsersController } from './users.controller';\nimport { UsersService } from './users.service';\nimport { User } from './entities/user.entity';\n\n@Module({\n  imports: [TypeOrmModule.forFeature([User])],\n  controllers: [UsersController],\n  providers: [UsersService],\n  exports: [UsersService], // export only when other modules need this service\n})\nexport class UsersModule {}\n```\n\n### Unit Test for Service\n\n```typescript\n// users.service.spec.ts\nimport { Test, TestingModule } from '@nestjs/testing';\nimport { getRepositoryToken } from '@nestjs/typeorm';\nimport { ConflictException } from '@nestjs/common';\nimport { UsersService } from './users.service';\nimport { User } from './entities/user.entity';\n\nconst mockRepo = {\n  findOneBy: jest.fn(),\n  create: jest.fn(),\n  save: jest.fn(),\n};\n\ndescribe('UsersService', () => {\n  let service: UsersService;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      providers: [\n        UsersService,\n        { provide: getRepositoryToken(User), useValue: mockRepo },\n      ],\n    }).compile();\n    service = module.get<UsersService>(UsersService);\n    jest.clearAllMocks();\n  });\n\n  it('throws ConflictException when email already exists', async () => {\n    mockRepo.findOneBy.mockResolvedValue({ id: 1, email: 'user@example.com' });\n    await expect(\n      service.create({ email: 'user@example.com', password: 'pass1234' }),\n    ).rejects.toThrow(ConflictException);\n  });\n});\n```\n\n## Constraints\n\n### MUST DO\n- Use `@Injectable()` and constructor injection for all services — never instantiate services with `new`\n- Validate all inputs with `class-validator` decorators on DTOs and enable `ValidationPipe` globally\n- Use DTOs for all request/response bodies; never pass raw `req.body` to services\n- Throw typed HTTP exceptions (`NotFoundException`, `ConflictException`, etc.) in services\n- Document all endpoints with `@ApiTags`, `@ApiOperation`, and response decorators\n- Write unit tests for every service method using `Test.createTestingModule`\n- Store all config values via `ConfigModule` and `process.env`; never hardcode them\n\n### MUST NOT DO\n- Expose passwords, secrets, or internal stack traces in responses\n- Accept unvalidated user input — always apply `ValidationPipe`\n- Use `any` type unless absolutely necessary and documented\n- Create circular dependencies between modules — use `forwardRef()` only as a last resort\n- Hardcode hostnames, ports, or credentials in source files\n- Skip error handling in service methods\n\n## Output Templates\n\nWhen implementing a NestJS feature, provide in this order:\n1. Module definition (`.module.ts`)\n2. Controller with Swagger decorators (`.controller.ts`)\n3. Service with typed error handling (`.service.ts`)\n4. DTOs with `class-validator` decorators (`dto/*.dto.ts`)\n5. Unit tests for service methods (`*.service.spec.ts`)\n\n## Knowledge Reference\n\nNestJS, TypeScript, TypeORM, Prisma, Passport, JWT, class-validator, class-transformer, Swagger/OpenAPI, Jest, Supertest, Guards, Interceptors, Pipes, Filters\n\n[Documentation](https://jeffallan.github.io/claude-skills/skills/backend/nestjs-expert/)","author":"@Jeffallan","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/Jeffallan/claude-skills/tree/main/skills/nestjs-expert","license":"MIT","category":"writing","lang":"en","tokens":1512,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/authentication.md","size":4021,"sha256":"7bdd11ae675c17f25e2e59726459cd565ff403b475ba97c9f1ff9470eecbe2cc"},{"path":"references/controllers-routing.md","size":3094,"sha256":"6a26d34c4348c7ad849774003f22d1959d95305ac39dae92e778dfc4b0911825"},{"path":"references/dtos-validation.md","size":3628,"sha256":"e42823044324f5927de8c7e0e65eb05f10b6659ee4296dc48ad44197b4ea832f"},{"path":"references/migration-from-express.md","size":31048,"sha256":"1f50801d6d4b2ac4f3385521807ec38f3c9b6b7a9b2a6a448cfd9c26a4791685"},{"path":"references/services-di.md","size":3382,"sha256":"9e55a6b147bb3e29bc1ee45fbbccb3200ee2514082952c16e91c356432176f6a"},{"path":"references/testing-patterns.md","size":4681,"sha256":"a6815219bd5f4651beeb459cbac45513be247e87e2f8905bc1ae75948aaf75ab"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["docs.nestjs.com","jeffallan.github.io"]}}