fastify-typescript
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFastify TypeScript Development
Fastify TypeScript 开发
You are an expert in Fastify and TypeScript development with deep knowledge of building high-performance, type-safe APIs.
您是Fastify和TypeScript开发专家,精通构建高性能、类型安全的API。
TypeScript General Guidelines
TypeScript 通用规范
Basic Principles
基本原则
- Use English for all code and documentation
- Always declare types for variables and functions (parameters and return values)
- Avoid using type - create necessary types instead
any - Use JSDoc to document public classes and methods
- Write concise, maintainable, and technically accurate code
- Use functional and declarative programming patterns; avoid classes
- Prefer iteration and modularization to adhere to DRY principles
- 所有代码和文档使用英文
- 始终为变量和函数(参数及返回值)声明类型
- 避免使用类型——必要时创建自定义类型
any - 使用JSDoc记录公共类和方法
- 编写简洁、可维护且技术准确的代码
- 使用函数式和声明式编程模式;避免使用类
- 优先使用迭代和模块化,遵循DRY原则
Nomenclature
命名规范
- Use PascalCase for types and interfaces
- Use camelCase for variables, functions, and methods
- Use kebab-case for file and directory names
- Use UPPERCASE for environment variables
- Use descriptive variable names with auxiliary verbs: ,
isLoading,hasErrorcanDelete - Start each function with a verb
- 类型和接口使用PascalCase命名
- 变量、函数和方法使用camelCase命名
- 文件和目录使用kebab-case命名
- 环境变量使用大写命名
- 使用带有辅助动词的描述性变量名:、
isLoading、hasErrorcanDelete - 每个函数以动词开头
Functions
函数
- Write short functions with a single purpose
- Use arrow functions for simple operations
- Use async/await consistently throughout the codebase
- Use the RO-RO pattern (Receive an Object, Return an Object) for multiple parameters
- 编写单一职责的短函数
- 简单操作使用箭头函数
- 代码库中统一使用async/await
- 多参数场景使用RO-RO模式(接收一个对象,返回一个对象)
Types and Interfaces
类型与接口
- Prefer interfaces over types for object shapes
- Avoid enums; use maps or const objects instead
- Use Zod for runtime validation with inferred types
- Use for immutable properties
readonly - Use for type-only imports
import type
- 对象结构优先使用接口而非类型别名
- 避免使用枚举;改用映射或常量对象
- 使用Zod进行运行时验证并推导类型
- 不可变属性使用
readonly - 仅类型导入使用
import type
Fastify-Specific Guidelines
Fastify 专属规范
Project Structure
项目结构
src/
routes/
{resource}/
index.ts
handlers.ts
schemas.ts
plugins/
auth.ts
database.ts
cors.ts
services/
{domain}Service.ts
repositories/
{entity}Repository.ts
types/
index.ts
utils/
config/
app.ts
server.tssrc/
routes/
{resource}/
index.ts
handlers.ts
schemas.ts
plugins/
auth.ts
database.ts
cors.ts
services/
{domain}Service.ts
repositories/
{entity}Repository.ts
types/
index.ts
utils/
config/
app.ts
server.tsRoute Organization
路由组织
- Organize routes by resource/domain
- Use route plugins for modular registration
- Define schemas alongside route handlers
- Use route prefixes for API versioning
typescript
import { FastifyPluginAsync } from 'fastify';
const usersRoutes: FastifyPluginAsync = async (fastify) => {
fastify.get('/', { schema: listUsersSchema }, listUsersHandler);
fastify.get('/:id', { schema: getUserSchema }, getUserHandler);
fastify.post('/', { schema: createUserSchema }, createUserHandler);
fastify.put('/:id', { schema: updateUserSchema }, updateUserHandler);
fastify.delete('/:id', { schema: deleteUserSchema }, deleteUserHandler);
};
export default usersRoutes;- 按资源/领域组织路由
- 使用路由插件进行模块化注册
- 路由处理程序旁定义Schema
- 使用路由前缀实现API版本控制
typescript
import { FastifyPluginAsync } from 'fastify';
const usersRoutes: FastifyPluginAsync = async (fastify) => {
fastify.get('/', { schema: listUsersSchema }, listUsersHandler);
fastify.get('/:id', { schema: getUserSchema }, getUserHandler);
fastify.post('/', { schema: createUserSchema }, createUserHandler);
fastify.put('/:id', { schema: updateUserSchema }, updateUserHandler);
fastify.delete('/:id', { schema: deleteUserSchema }, deleteUserHandler);
};
export default usersRoutes;Schema Validation with JSON Schema / Ajv
基于JSON Schema / Ajv的Schema验证
- Define JSON schemas for all request/response validation
- Use @sinclair/typebox for type-safe schema definitions
- Leverage Fastify's built-in Ajv integration
typescript
import { Type, Static } from '@sinclair/typebox';
const UserSchema = Type.Object({
id: Type.String({ format: 'uuid' }),
name: Type.String({ minLength: 1 }),
email: Type.String({ format: 'email' }),
createdAt: Type.String({ format: 'date-time' }),
});
type User = Static<typeof UserSchema>;
const createUserSchema = {
body: Type.Object({
name: Type.String({ minLength: 1 }),
email: Type.String({ format: 'email' }),
}),
response: {
201: UserSchema,
400: ErrorSchema,
},
};- 为所有请求/响应定义JSON Schema
- 使用@sinclair/typebox进行类型安全的Schema定义
- 利用Fastify内置的Ajv集成
typescript
import { Type, Static } from '@sinclair/typebox';
const UserSchema = Type.Object({
id: Type.String({ format: 'uuid' }),
name: Type.String({ minLength: 1 }),
email: Type.String({ format: 'email' }),
createdAt: Type.String({ format: 'date-time' }),
});
type User = Static<typeof UserSchema>;
const createUserSchema = {
body: Type.Object({
name: Type.String({ minLength: 1 }),
email: Type.String({ format: 'email' }),
}),
response: {
201: UserSchema,
400: ErrorSchema,
},
};Plugins and Decorators
插件与装饰器
- Use plugins for shared functionality
- Decorate Fastify instance with services and utilities
- Register plugins with proper encapsulation
typescript
import fp from 'fastify-plugin';
const databasePlugin = fp(async (fastify) => {
const prisma = new PrismaClient();
await prisma.$connect();
fastify.decorate('prisma', prisma);
fastify.addHook('onClose', async () => {
await prisma.$disconnect();
});
});
export default databasePlugin;- 使用插件实现共享功能
- 为Fastify实例装饰服务和工具
- 以正确的封装方式注册插件
typescript
import fp from 'fastify-plugin';
const databasePlugin = fp(async (fastify) => {
const prisma = new PrismaClient();
await prisma.$connect();
fastify.decorate('prisma', prisma);
fastify.addHook('onClose', async () => {
await prisma.$disconnect();
});
});
export default databasePlugin;Prisma Integration
Prisma 集成
- Use Prisma as the ORM for database operations
- Create repository classes for data access
- Use transactions for complex operations
typescript
class UserRepository {
constructor(private prisma: PrismaClient) {}
async findById(id: string): Promise<User | null> {
return this.prisma.user.findUnique({ where: { id } });
}
async create(data: CreateUserInput): Promise<User> {
return this.prisma.user.create({ data });
}
}- 使用Prisma作为数据库操作的ORM
- 创建仓储类处理数据访问
- 复杂操作使用事务
typescript
class UserRepository {
constructor(private prisma: PrismaClient) {}
async findById(id: string): Promise<User | null> {
return this.prisma.user.findUnique({ where: { id } });
}
async create(data: CreateUserInput): Promise<User> {
return this.prisma.user.create({ data });
}
}Error Handling
错误处理
- Use Fastify's built-in error handling
- Create custom error classes for domain errors
- Return consistent error responses
typescript
import { FastifyError } from 'fastify';
class NotFoundError extends Error implements FastifyError {
code = 'NOT_FOUND';
statusCode = 404;
constructor(resource: string, id: string) {
super(`${resource} with id ${id} not found`);
this.name = 'NotFoundError';
}
}
// Global error handler
fastify.setErrorHandler((error, request, reply) => {
const statusCode = error.statusCode || 500;
reply.status(statusCode).send({
error: error.name,
message: error.message,
statusCode,
});
});- 使用Fastify内置的错误处理机制
- 为领域错误创建自定义错误类
- 返回一致的错误响应
typescript
import { FastifyError } from 'fastify';
class NotFoundError extends Error implements FastifyError {
code = 'NOT_FOUND';
statusCode = 404;
constructor(resource: string, id: string) {
super(`${resource} with id ${id} not found`);
this.name = 'NotFoundError';
}
}
// 全局错误处理程序
fastify.setErrorHandler((error, request, reply) => {
const statusCode = error.statusCode || 500;
reply.status(statusCode).send({
error: error.name,
message: error.message,
statusCode,
});
});Testing with Jest
Jest 测试
- Write unit tests for services and handlers
- Use integration tests for routes
- Mock external dependencies
typescript
import { build } from '../app';
describe('Users API', () => {
let app: FastifyInstance;
beforeAll(async () => {
app = await build();
});
afterAll(async () => {
await app.close();
});
it('should list users', async () => {
const response = await app.inject({
method: 'GET',
url: '/api/users',
});
expect(response.statusCode).toBe(200);
expect(JSON.parse(response.payload)).toBeInstanceOf(Array);
});
});- 为服务和处理程序编写单元测试
- 为路由编写集成测试
- 模拟外部依赖
typescript
import { build } from '../app';
describe('Users API', () => {
let app: FastifyInstance;
beforeAll(async () => {
app = await build();
});
afterAll(async () => {
await app.close();
});
it('should list users', async () => {
const response = await app.inject({
method: 'GET',
url: '/api/users',
});
expect(response.statusCode).toBe(200);
expect(JSON.parse(response.payload)).toBeInstanceOf(Array);
});
});Performance
性能优化
- Fastify is one of the fastest Node.js frameworks
- Use schema validation for automatic serialization optimization
- Enable logging only when needed in production
- Use connection pooling for database connections
- Fastify是速度最快的Node.js框架之一
- 使用Schema验证实现自动序列化优化
- 生产环境仅在必要时启用日志
- 为数据库连接使用连接池
Security
安全防护
- Use @fastify/helmet for security headers
- Implement rate limiting with @fastify/rate-limit
- Use @fastify/cors for CORS configuration
- Validate all inputs with JSON Schema
- Use JWT for authentication with @fastify/jwt
- 使用@fastify/helmet设置安全头
- 使用@fastify/rate-limit实现速率限制
- 使用@fastify/cors配置跨域资源共享
- 使用JSON Schema验证所有输入
- 使用@fastify/jwt实现JWT认证