項目地址:https://github.com/wz2cool/swagger-ts-doc
demo代碼地址:https://github.com/wz2cool/swagger-ts-doc-demo
動機
Swagger API 文檔框架相信大家都使用過,並且真的很方便,但是大家應該都是用框架生成的出來swagger 文檔,可能很少人會去寫 yml或者json文檔吧。
確實我在使用nodejs 發現寫接口還是很方便,但是唯獨在寫swagger文檔時候發現nodejs中的框架並不好用,曾經用過swagger-jsdoc,寫了一堆注釋,然后自己崩潰了。
好歹我自己也寫了快2年的java了,為什么不照着java的方式寫一套呢,於是寫了 swagger-ts-doc,自用下來還是挺方便的。
Swagger 簡介
大家可打開一下 http://editor.swagger.io/ 看一下官方寫的一個例子。
info
這個應該是一些對這個文檔的描述信息,這個在swagger-ts-doc 是可以配置的, 對應的配置為 SwaggerInfoProperty。
definitions
這個是一個重要的節點,這個節點其實是定義了我們所有的類,比如有個requestBody 其實是一個類,就可以通過 $ref: "#/definitions/User" 進行關聯。
在swagger-ts-doc 中,這里的是通過apiModelProperty進行描述的
paths
這個節點就是最重要的節點,它描述了我們所有路由post,get,put,delete.
在swagger-ts-doc 中,這里是通過registerRequestMapping 進行描述的。
swagger-ts-doc 中類和方法
apiModelProperty 裝飾器
這個裝飾器主要是為了生成 definitions 中的model,我們看代碼可看到如何描述一個typescript中的一個類。
import { apiModelProperty, DataType } from "swagger-ts-doc";
export class UpdateStudentDto {
@apiModelProperty(
DataType.STRING, // 類型
false, // 是否必填
"學生姓名" // 描述
)
public name: string;
@apiModelProperty(DataType.INTEGER, false, "學生年齡")
public age: number;
}
最后會生成與之對應的swagger json 描述(這里我們不使用yml語法,使用的json 語法)
"UpdateStudentDto": {
"type": "object",
"required": ["name", "age"],
"properties": {
"name": {
"type": "string",
"description": "學生姓名"
},
"age": {
"type": "integer",
"description": "學生年齡"
}
}
},
Request參數
參考swagger 文檔:
https://swagger.io/docs/specification/describing-parameters/
https://swagger.io/docs/specification/describing-request-body/
- RequestBody 類對應文檔 requestBody
- PathVariable 類對應文檔 path parameters (in: path)
- RequestParam 類對弈文檔 query parameters (in: query)
Response
參考swagger 文檔:
https://swagger.io/docs/specification/describing-responses/
我們看一下定義多個返回相應
[
new Response(HttpStatusCode.OK, DataType.STRING, "ok"),
new Response(HttpStatusCode.INTERNAL_SERVER_ERROR, DataType.STRING, "內部錯誤"),
new Response(HttpStatusCode.NOT_FOUND, DataType.STRING, "學生未找到"),
],
registerRequestMapping 方法
這里就是我們要去生成swagger中paths節點調用的方法,這里我們舉一個修改學生的一個例子。
registerRequestMapping(
StudentApi, // tags 類似於把一些路由放到一個組里面
"/students/{id}", // 路由
RequestMethod.PUT,
[
new PathVariable("id", DataType.STRING, "學生ID"),
new RequestBody("student", DataType.OBJECT, UpdateStudentDto, "學生"),
],
[
new Response(HttpStatusCode.OK, DataType.STRING, "ok"),
new Response(HttpStatusCode.INTERNAL_SERVER_ERROR, DataType.STRING, "內部錯誤"),
new Response(HttpStatusCode.NOT_FOUND, DataType.STRING, "學生未找到"),
],
"修改學生"); // 對這個路由的描述
route.put("/:id", (req, res, next) => {
const input = req.body;
const id = req.params.id;
if (!id) {
res.status(HttpStatusCode.INTERNAL_SERVER_ERROR);
res.json("學生ID不能為空");
return;
}
if (lodash.findIndex(this.students, (x) => x.uuid === id) < 0) {
res.status(HttpStatusCode.NOT_FOUND);
res.json(`未能找到學生`);
return;
}
const student = new Student();
student.uuid = id;
student.name = input.name;
student.age = input.age;
this.modifyStudent(student);
res.json("ok");
});
我們最后看一下效果
結束
利用typescript 現在我們可以輕松用強類型來寫swagger文檔了,swagger-jsdoc 雖然很好但是寫起來太痛苦了,希望大家可以關注swagger-ts-doc 並提出寶貴的意見。