Koa+koa-swagger-decorator实战篇:打造高效优雅的API文档
前言
好记性不如烂笔头,记录一下koa
接入swagger
踩得坑
So here's the question
(那么问题来了),我们为什么要写接口文档呢?
为什么要写接口文档?
- 提供清晰的接口定义:接口文档可以详细描述接口的功能、参数、返回值等,使开发人员清楚了解如何正确调用接口。
- 促进团队合作:接口文档可以作为开发人员、产品经理、测试人员等不同角色之间的沟通工具,确保大家对接口的理解一致,减少沟通成本。
- 确保开发质量:接口文档可以作为开发人员编写单元测试、集成测试和验收测试的依据,确保开发过程中的质量控制。
- 方便接口调试和问题排查:接口文档可以帮助前后端开发人员在调试接口时快速定位问题,加快问题排查和解决的速度。
- 支持接口升级和扩展:接口文档可以指导开发人员进行接口的升级和扩展,同时也可以帮助其他开发人员快速了解新接口的使用方式。
所以写好接口文档是一个成熟的程序员必备的技能
安装
pnpm i koa-swagger-decorator@next //notice: 一定要加next,我们要使用最新的版本,2版本,如果不加的话,那么可能就会使用1版本了
有人这里可能要问了,为什么不用koa2-swagger-ui
swagger-jsdoc
呢,用过的小伙伴应该都知道,那文档真是越写越多,啥都要写,本来我使用swagger来减轻工作量的,结果工作量越来越大,这不和我们的初衷相反么。而有的小伙伴说koa-swagger-decorator
的入侵性很强,不适合二次开发?我对此表示疑问。我觉得koa-swagger-decorator
写起来方便,也方便修改。我觉得还好呀。
大家如果有什么使用问题,也可以提issue
,writer也会很快回答的right now
一个完整的配置过程
支持装饰器模式
因为要支持装饰器模式,所以要安装
pnpm install babel-plugin-transform-decorators-legacy
然后配置babelrc
{
"presets": [["env", { "targets": { "node": "current" } }]],
"plugins": ["transform-decorators-legacy"]
}
typescript配置
这是必须配置的
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
}
}
新建src/routes/index.ts文件
因为koa-swagger-decorator
包括routes
了,所以所有routes
啥的都可以在这里配置,并且不需要引入
koa-router
import { SwaggerRouter } from 'koa-swagger-decorator';
import UserController from '../controller/user';
import { registerExtraComponents } from '../common/swagger-extra';
const router = new SwaggerRouter({
spec: {
info: {
title: 'koa模版',
version: 'v1.0',
},
},
swaggerHtmlEndpoint: '/swagger-html',
swaggerJsonEndpoint: '/swagger-json',
});
router.prefix('/api');
registerExtraComponents(router.registry);
// apply swagger docs routes
// 只开发环境运行
if (process.env.NODE_ENV === 'development') {
router.swagger();
}
// register user defined routes implementation
router.applyRoute(UserController);
// .applyRoute(DemoController); // chained for more then one controller imports
export default router;
notice: 所有的Controller都要applyRoute,否则会不起作用
配置授权
这样我们就可以配合jwt
使用了
export const AUTH_KEY = 'authorization';
export function registerExtraComponents(registry: any) {
registry.registerComponent('securitySchemes', 'authorization', {
type: 'apiKey',
name: 'authorization',
in: 'header',
});
registry.registerComponent('schemas', 'ExtraSchemasA', {
type: 'object',
properties: {
id: {
type: 'string',
},
},
});
}
notice: input内容的时候一定要加Bearer
,不加的话不会生效,谨记
使用
import { routeConfig, z, body, ParsedArgs } from 'koa-swagger-decorator';
// 需要授权的接口要使用
import { AUTH_KEY } from '../../common/swagger-extra';
class UserController {
@routeConfig({
path: '/login',
method: 'post',
summary: 'user login',
tags: ['USER'],
})
@body(CreateUserReq)
async login(ctx: Models.Ctx, args: ParsedArgs<LoginType>) {
const { username, password } = args.body as LoginType;
const user = await ctx.model.User.findOne({
where: { user_name: username },
});
if (!user) {
ctx.fail('该用户不存在');
return;
}
if (password !== user.password) {
ctx.fail('密码错误');
return;
}
const token = jwt.sign(
{
username,
},
Config.JWT.secret,
{ expiresIn: 60 * 60 }
);
ctx.success({ token }, '登录成功');
}
@routeConfig({
// define your API route info using @routeConfig decorator
method: 'get',
path: '/users',
summary: 'get users',
tags: ['USER'],
security: [{ [AUTH_KEY]: [] }], // notice: 需要授权的接口要加上security,不需要授权的就不需要写了
})
async getUsers(ctx: Models.Ctx) {
const users = await ctx.model.User.findAll({
attributes: {
exclude: ['password'],
},
});
ctx.success(users);
}
@routeConfig({
method: 'post',
path: '/register',
summary: 'create user',
tags: ['USER'],
})
@body(CreateUserReq)
async register(ctx: Models.Ctx, args: ParsedArgs<RegisterType>) {
const { password, username } = args.body as RegisterType;
// TODO:增加判断是否有重复用户
const user = await ctx.model.User.findOne({
where: { user_name: username },
});
if (user) {
ctx.fail('用户重复');
return;
}
// TODO:密码检测
// 注册
await ctx.model.User.create({ password, user_name: username });
ctx.success('', '注册成功');
}
}
此时访问/api/swagger-html
就可以了
配置了security的接口会有一把锁子的标志,需要设置Authorization
才行
总结
大家知道写一个接口文档很麻烦的,是一个重复的工作,有人说,大家接到需求的时候就要写呀,要不怎么前后端分离开发,可是随着接口体系的越来越庞大,所有的接口就需要一个总的文档,并且后续如果需要改接口的话,前端也可以很快进行修改,方便维护。
希望大家能从文章中学到东西,有什么使用问题都可以随时在评论区留言
参考
转载自:https://juejin.cn/post/7302344199445381158