用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill nestjs命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Unified design foundations — design system architecture, tokens, component specs, visual principles, creative vision, figma integration, plus brand design system loader (66 real brands via DESIGN.md). Absorbs design, design-system, design-systems, design-principles, design-router, creative-vision, figma, design-md.
Render, summarize, and present markdown documents and structured content in multiple output modes
Ultra UI skill - combines Google's DESIGN.md spec (machine-readable design tokens) with the ui-ux-pro-max knowledge base (91 styles, 161 palettes, 73 font pairings, 161 products, 104 UX guidelines, 25 chart types). Generates lint-clean DESIGN.md files, validates token references and WCAG contrast, exports Tailwind/DTCG tokens, and diffs design systems version-over-version.
基于 SOC 职业分类
正在显示 SKILL.md
| name | nestjs |
| description | NestJS framework patterns — modules, providers, guards, interceptors, pipes, and microservices. |
| layer | domain |
| category | backend |
| triggers | ["nestjs","nest module","nest guard","nest interceptor","nest pipe"] |
| inputs | ["NestJS application architecture decisions","Module and provider organization","Guard and interceptor implementation","Microservice communication patterns"] |
| outputs | ["NestJS modules with proper dependency injection","Guards, interceptors, and pipes","Controller and service implementations","Microservice transport configurations"] |
| linksTo | ["typescript-patterns","graphql","websockets","microservices"] |
| linkedFrom | ["dependency-injection"] |
| preferredNextSkills | ["typescript-patterns","graphql","microservices"] |
| fallbackSkills | ["fastapi","hono"] |
| riskLevel | low |
| memoryReadPolicy | selective |
| memoryWritePolicy | none |
| sideEffects | [] |
Provide expert guidance on NestJS application architecture including module organization, dependency injection, request lifecycle (guards, interceptors, pipes, filters), microservice patterns, and production deployment. Covers NestJS 10+ with modern decorators and TypeScript strict mode.
Organize by domain, not technical concern:
src/
app.module.ts
main.ts
common/
decorators/
filters/
guards/
interceptors/
pipes/
config/
config.module.ts
config.service.ts
users/
users.module.ts
users.controller.ts
users.service.ts
users.repository.ts
dto/
create-user.dto.ts
update-user.dto.ts
entities/
user.entity.ts
orders/
orders.module.ts
orders.controller.ts
orders.service.ts
...
Module definition with proper imports/exports:
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { User } from './entities/user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService], // only export what other modules need
})
{}
Controllers handle HTTP concerns only. Delegate all business logic to services:
// src/users/users.controller.ts
import {
Controller, Get, Post, Put, Delete,
Param, Body, Query, HttpCode, HttpStatus,
ParseIntPipe, UseGuards,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { JwtAuthGuard } from '../common/guards/jwt-auth.guard';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { PaginationDto } from '../common/dto/pagination.dto';
@ApiTags('users')
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
@HttpCode(HttpStatus.CREATED)
@ApiOperation({ summary: 'Create a new user' })
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
@Get()
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
findAll(@Query() pagination: PaginationDto) {
return this.usersService.findAll(pagination);
}
@Get(':id')
@UseGuards(JwtAuthGuard)
findOne(@Param('id', ParseIntPipe) id: number) {
return this.usersService.findOneOrFail(id);
}
@Put(':id')
@UseGuards(JwtAuthGuard)
update(
@Param('id', ParseIntPipe) id: number,
@Body() updateUserDto: UpdateUserDto,
) {
return this.usersService.update(id, updateUserDto);
}
@Delete(':id')
@UseGuards(JwtAuthGuard)
@HttpCode(HttpStatus.NO_CONTENT)
remove(@Param('id', ParseIntPipe) id: number) {
return this.usersService.remove(id);
}
}
// src/users/users.service.ts
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';
import { PaginationDto } from '../common/dto/pagination.dto';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly userRepo: Repository<User>,
) {}
async create(dto: CreateUserDto): Promise<User> {
const exists = await this.userRepo.findOneBy({ email: dto.email });
if (exists) {
throw new ConflictException('Email already registered');
}
const user = this.userRepo.create(dto);
return this.userRepo.save(user);
}
async findAll(pagination: PaginationDto) {
const [items, total] = await this.userRepo.findAndCount({
skip: (pagination.page - 1) * pagination.limit,
take: pagination.limit,
order: { createdAt: 'DESC' },
});
return { items, total, page: pagination.page, limit: pagination.limit };
}
async findOneOrFail(id: number): Promise<User> {
const user = await this.userRepo.findOneBy({ id });
if (!user) throw new NotFoundException(`User #${id} not found`);
return user;
}
async update(id: number, dto: Partial<CreateUserDto>): Promise<User> {
const user = await this.findOneOrFail(id);
Object.assign(user, dto);
return this.userRepo.save(user);
}
async remove(id: number): Promise<void> {
const result = await this.userRepo.delete(id);
if (result.affected === 0) {
throw new NotFoundException(`User #${id} not found`);
}
}
}
// src/users/dto/create-user.dto.ts
import { IsEmail, IsString, MinLength, MaxLength } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class CreateUserDto {
@ApiProperty({ example: 'user@example.com' })
@IsEmail()
email: string;
@ApiProperty({ example: 'Jane Doe' })
@IsString()
@MinLength(1)
@MaxLength(100)
name: string;
@ApiProperty({ minLength: 8 })
@IsString()
@MinLength(8)
password: string;
}
// src/users/dto/update-user.dto.ts
import { PartialType } from '@nestjs/swagger';
import { CreateUserDto } from './create-user.dto';
export class UpdateUserDto extends PartialType(CreateUserDto) {}
JWT authentication guard:
// src/common/guards/jwt-auth.guard.ts
import { Injectable, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Reflector } from '@nestjs/core';
import { IS_PUBLIC_KEY } from '../decorators/public.decorator';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
constructor(private reflector: Reflector) {
super();
}
canActivate(context: ExecutionContext) {
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isPublic) return true;
return super.canActivate(context);
}
handleRequest(err: any, user: any) {
if (err || !user) {
throw err || new UnauthorizedException();
}
return user;
}
}
Role-based guard:
// src/common/guards/roles.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ROLES_KEY } from '../decorators/roles.decorator';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<string[]>(ROLES_KEY, [
context.getHandler(),
context.getClass(),
]);
if (!requiredRoles) return true;
const { user } = context.switchToHttp().getRequest();
return requiredRoles.some((role) => user.roles?.includes(role));
}
}
Logging interceptor:
// src/common/interceptors/logging.interceptor.ts
import {
Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger,
} from '@nestjs/common';
import { Observable, tap } from 'rxjs';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
private readonly logger = new Logger(LoggingInterceptor.name);
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const req = context.switchToHttp().getRequest();
const { method, url } = req;
const start = Date.now();
return next.handle().pipe(
tap(() => {
const duration = Date.now() - start;
this.logger.log(`${method} ${url} — ${duration}ms`);
}),
);
}
}
Transform response interceptor:
// src/common/interceptors/transform.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable, map } from 'rxjs';
export interface ApiResponse<T> {
data: T;
meta?: Record<string, any>;
}
@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, ApiResponse<T>> {
intercept(context: ExecutionContext, next: CallHandler): Observable<ApiResponse<T>> {
return next.handle().pipe(map((data) => ({ data })));
}
}
Custom validation pipe with whitelist:
// src/main.ts
import { ValidationPipe } from '@nestjs/common';
app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // strip non-decorated properties
forbidNonWhitelisted: true, // throw on unknown properties
transform: true, // auto-transform query params to types
transformOptions: {
enableImplicitConversion: true,
},
}),
);
// src/common/filters/all-exceptions.filter.ts
import {
ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus, Logger,
} from '@nestjs/common';
import { Request, Response } from 'express';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
private readonly logger = new Logger(AllExceptionsFilter.name);
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const message =
exception instanceof HttpException
? exception.getResponse()
: 'Internal server error';
this.logger.error(`${request.method} ${request.url}`, exception);
response.status(status).json({
statusCode: status,
message: typeof message === 'string' ? message : (message as any).message,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
// src/common/decorators/public.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
// src/common/decorators/roles.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const ROLES_KEY = 'roles';
export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);
// src/common/decorators/current-user.decorator.ts
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const CurrentUser = createParamDecorator(
(data: string | undefined, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return data ? request.user?.[data] : request.user;
},
);
// src/config/config.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule as NestConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
@Module({
imports: [
NestConfigModule.forRoot({
isGlobal: true,
validationSchema: Joi.object({
NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'),
PORT: Joi.number().default(3000),
DATABASE_URL: Joi.string().required(),
JWT_SECRET: Joi.string().required(),
JWT_EXPIRATION: Joi.string().default('1h'),
}),
}),
],
})
export class AppConfigModule {}
app.module.ts providers.@Body() without validation.@nestjs/config for env vars — Validate at startup with Joi.@nestjs/swagger — Auto-generate API docs from DTOs and decorators.@nestjs/testing — Use Test.createTestingModule() for isolated unit tests.| Pitfall | Problem | Fix |
|---|---|---|
| Circular dependency | Two modules importing each other | Use forwardRef() or extract shared logic to a third module |
Missing @Injectable() | Provider not recognized by DI | Always decorate services with @Injectable() |
| REQUEST scope leak | Entire dependency chain becomes request-scoped | Minimize REQUEST-scoped providers; use @Inject(REQUEST) sparingly |
No whitelist: true | Extra properties pass validation | Set whitelist and forbidNonWhitelisted in global ValidationPipe |
| Heavy controllers | Controllers contain business logic | Move logic to services; controllers handle HTTP only |
Forgetting async | Promise returned but not awaited | All DB operations should be async/await |