mcpField
K
koa-typescript

koa-typescript

github.com/mindrally开发287708 次安装3 周前更新
代码仓库

关于 koa-typescript

面向 Koa.js 与 TypeScript 开发者的编码技能,提供中间件式 API 的设计和实现指南,涵盖类型安全、错误处理、安全与测试。

主要功能

  1. 01Koa onion 中间件模式
  2. 02TypeScript 类型安全规范
  3. 03路由与项目结构建议
  4. 04错误处理与请求验证
  5. 05认证、安全与测试实践

适用场景

  1. 01设计 Koa API 项目结构
  2. 02编写异步中间件与路由
  3. 03为接口加入验证和认证
  4. 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