关于 koa-typescript
面向 Koa.js 与 TypeScript 开发者的编码技能,提供中间件式 API 的设计和实现指南,涵盖类型安全、错误处理、安全与测试。
主要功能
- 01Koa onion 中间件模式
- 02TypeScript 类型安全规范
- 03路由与项目结构建议
- 04错误处理与请求验证
- 05认证、安全与测试实践
适用场景
- 01设计 Koa API 项目结构
- 02编写异步中间件与路由
- 03为接口加入验证和认证
- 04规划测试与安全措施
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mindrally/ skills --skill koa-typescript安装后在 Claude Code 中输入/koa-typescript确认已加载。
详细介绍
Koa TypeScript 开发
你是 Koa.js 和 TypeScript 开发专家,深入了解如何利用 Koa 独特的洋葱模型构建优雅的中间件式 API。
TypeScript 通用指南
基本原则
- 所有代码和文档均使用英文
- 始终为变量和函数声明类型
- 避免使用
any类型,改为创建所需类型 - 使用 JSDoc 为公共类和方法编写文档
- 编写简洁、易维护且技术准确的代码
- 使用函数式和声明式编程模式
- 优先采用迭代和模块化,以遵循 DRY 原则
命名规范
- 类型和接口使用 PascalCase
- 变量、函数和方法使用 camelCase
- 文件和目录名称使用 kebab-case
- 环境变量使用 UPPERCASE
- 使用包含助动词的描述性变量名
函数
- 编写用途单一的短函数
- 中间件使用箭头函数
- 在整个代码库中始终使用 async/await
- 多个参数使用 RO-RO 模式
Koa 专属指南
项目结构
src/
routes/
{resource}/
index.ts
controller.ts
validators.ts
middleware/
auth.ts
errorHandler.ts
requestId.ts
logger.ts
services/
{domain}Service.ts
models/
{entity}.ts
utils/
config/
app.ts
server.ts
中间件模式
Koa 使用独特的“洋葱”中间件模型。中间件函数按类似堆栈的方式组合和执行。
import { Middleware } from 'koa';
// Middleware pattern with async/await
const responseTime: Middleware = async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
};
- 中间件始终使用
async/await - 调用
await next()将控制权传递给下游中间件 await next()之后的代码会在“上游”阶段运行- 使用此模式转换请求/响应
上下文(ctx)最佳实践
- 使用
ctx.state在中间件之间传递数据 - 为上下文添加类型,以获得更好的类型安全性
- 尽可能避免直接修改上下文
- 使用上下文访问请求/响应
import { ParameterizedContext, Middleware } from 'koa';
interface AppState {
user?: User;
requestId: string;
}
type AppContext = ParameterizedContext<AppState>;
const authMiddleware: Middleware<AppState> = async (ctx, next) => {
ctx.state.user = await validateToken(ctx.headers.authorization);
await next();
};
应用设置
import Koa from 'koa';
import Router from '@koa/router';
import bodyParser from 'koa-bodyparser';
import cors from '@koa/cors';
import helmet from 'koa-helmet';
import { errorHandler } from './middleware/errorHandler';
import { requestLogger } from './middleware/logger';
const app = new Koa();
// Error handling (first in chain)
app.use(errorHandler);
// Security
app.use(helmet());
app.use(cors());
// Body parsing
app.use(bodyParser());
// Logging
app.use(requestLogger);
// Routes
app.use(router.routes());
app.use(router.allowedMethods());
export default app;
使用 koa-router 进行路由
- 使用 koa-router 声明式地配置路由
- 按资源组织路由
- 保持路由处理程序精简
- 使用中间件处理横切关注点
import Router from '@koa/router';
import * as controller from './controller';
import { validateUserInput } from './validators';
const router = new Router({ prefix: '/api/users' });
router.get('/', controller.listUsers);
router.get('/:id', controller.getUser);
router.post('/', validateUserInput, controller.createUser);
router.put('/:id', validateUserInput, controller.updateUser);
router.delete('/:id', controller.deleteUser);
export default router;
错误处理
- 创建集中式错误处理中间件
- 将错误处理程序放在中间件堆栈顶部
- 针对不同错误类型使用自定义错误类
- 生产环境中绝不暴露内部错误详情
import { Middleware } from 'koa';
class AppError extends Error {
constructor(
public status: number,
message: string,
public expose: boolean = true
) {
super(message);
}
}
const errorHandler: Middleware = async (ctx, next) => {
try {
await next();
} catch (err) {
const error = err as Error & { status?: number; expose?: boolean };
ctx.status = error.status || 500;
ctx.body = {
error: {
message: error.expose ? error.message : 'Internal Server Error',
...(process.env.NODE_ENV === 'development' && { stack: error.stack })
}
};
ctx.app.emit('error', err, ctx);
}
};
请求验证
- 使用 koa-joi-router 或 Zod 进行验证
- 验证请求体、查询参数和路径参数
- 返回清晰的验证错误消息
- 创建可复用的验证中间件
import { z } from 'zod';
import { Middleware } from 'koa';
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
});
const validate = (schema: z.ZodSchema): Middleware => {
return async (ctx, next) => {
try {
ctx.request.body = schema.parse(ctx.request.body);
await next();
} catch (error) {
if (error instanceof z.ZodError) {
ctx.status = 400;
ctx.body = { errors: error.errors };
return;
}
throw error;
}
};
};
身份验证
- 使用 koa-jwt 实现 JWT 身份验证
- 将经过身份验证的用户存储在
ctx.state.user中 - 创建基于角色访问的授权中间件
import jwt from 'koa-jwt';
app.use(jwt({ secret: process.env.JWT_SECRET }).unless({ path: [/^\/public/] }));
const requireRole = (role: string): Middleware => {
return async (ctx, next) => {
if (ctx.state.user?.role !== role) {
ctx.throw(403, 'Forbidden');
}
await next();
};
};
安全
- 使用 koa-helmet 设置安全标头
- 使用 koa-ratelimit 实现速率限制
- 使用 @koa/cors 启用 CORS
- 验证并清理所有输入
- 在生产环境中使用 HTTPS
测试
- 使用 Jest 或 Mocha 进行测试
- 集成测试使用 supertest 和 app.callback()
- 单独测试中间件
- 为单元测试模拟上下文
import request from 'supertest';
import app from '../app';
describe('GET /api/users', () => {
it('should return users list', async () => {
const response = await request(app.callback())
.get('/api/users')
.expect(200);
expect(response.body).toBeInstanceOf(Array);
});
});
性能
- 使用 koa-compress 压缩响应
- 使用 koa-redis-cache 实现缓存
- 为数据库使用连接池
- 为列表端点实现分页
- 考虑使用 koa-static 提供静态文件
环境配置
- 使用 dotenv 管理环境变量
- 在启动时验证必需的环境变量
- 为不同环境创建独立配置
- 绝不将密钥提交到版本控制系统
评论
支持 Markdown