翻译:疯狂的技术宅
原文:https://jonathas.com/document…未经许可,禁止转载!
本文首发微信公众号:前端先锋
欢迎关注,每天都给你推送新鲜的前端技术文章
当你为其他开发人员(前端,桌面,移动等)开发 API 时,需要生成一份风格良好的文档,以便他们知道可以使用的内容和方式,这非常重要。
为此,在 Node.js 项目中,我一直在使用 apiDoc,因为它能够从源代码中的注释生成 HTML 文档。
对于本文,我将使用我开发的 TODO List API 作为示例。你可以从这里克隆或下载它。
路由和注释
在我关于使用 mocha 进行测试并使用 istanbul 进行代码覆盖测试的文章中,我在 TODO List API 中显示了 Task 端点的示例:
import Task from "../controllers/tasks";
export = (app) => {
const endpoint = process.env.API_BASE + "tasks";
app.post(endpoint, Task.create);
app.delete(endpoint + "/:id", Task.delete);
app.get(endpoint + "/:id", Task.getOne);
app.get(endpoint, Task.getAll);
app.put(endpoint + "/:id", Task.update);
};
这代表了与系统中任务相关的所有端点。我们怎样才能使用它们呢?使用 API 的开发人员应该向每个端点发送什么数据呢?
到现在为止,他们除了去查看代码之外没有其他方法可以搞清楚,但是这些代码不应该被用作这个目的。
有了 apiDoc,我们可以用注释来生成文档。我的方法是在 routes 目录下的文件中配置的每个端点的前面编写它们。当我提到如何配置和组织我的 Node.js 项目时,如果你不确定我在说什么请 点击这里。
使用注释,我们的任务端点(内部 routes/tasks.ts)将如下所示:
import Task from "../controllers/tasks";
export = (app) => {
const endpoint = process.env.API_BASE + "tasks";
/**
* @api {post} /api/v1/tasks Create a task
* @apiVersion 1.0.0
* @apiName Create
* @apiGroup Task
* @apiPermission authenticated user
*
* @apiParam (Request body) {String} name The task name
*
* @apiExample {js} Example usage:
* const data = {
* "name": "Do the dishes"
* }
*
* $http.defaults.headers.common["Authorization"] = token;
* $http.post(url, data)
* .success((res, status) => doSomethingHere())
* .error((err, status) => doSomethingHere());
*
* @apiSuccess (Success 201) {String} message Task saved successfully!
* @apiSuccess (Success 201) {String} id The campaign id
*
* @apiSuccessExample {json} Success response:
* HTTPS 201 OK
* {
* "message": "Task saved successfully!",
* "id": "57e903941ca43a5f0805ba5a"
* }
*
* @apiUse UnauthorizedError
*/
app.post(endpoint, Task.create);
/**
* @api {delete} /api/v1/tasks/:id Delete a task
* @apiVersion 1.0.0
* @apiName Delete
* @apiGroup Task
* @apiPermission authenticated user
*
* @apiParam {String} id The task id
*
* @apiExample {js} Example usage:
* $http.defaults.headers.common["Authorization"] = token;
* $http.delete(url)
* .success((res, status) => doSomethingHere())
* .error((err, status) => doSomethingHere());
*
* @apiSuccess {String} message Task deleted successfully!
*
* @apiSuccessExample {json} Success response:
* HTTPS 200 OK
* {
* "message": "Task deleted successfully!"
* }
*
* @apiUse UnauthorizedError
*/
app.delete(endpoint + "/:id", Task.delete);
/**
* @api {get} /api/v1/tasks/:id Retrieve a task
* @apiVersion 1.0.0
* @apiName GetOne
* @apiGroup Task
* @apiPermission authenticated user
*
* @apiParam {String} id The task id
*
* @apiExample {js} Example usage:
* $http.defaults.headers.common["Authorization"] = token;
* $http.get(url)
* .success((res, status) => doSomethingHere())
* .error((err, status) => doSomethingHere());
*
* @apiSuccess {String} _id The task id
* @apiSuccess {String} name The task name
*
* @apiSuccessExample {json} Success response:
* HTTPS 200 OK
* {
* "_id": "57e8e94ea06a0c473bac50cc",
* "name": "Do the disehs",
* "__v": 0
* }
*
* @apiUse UnauthorizedError
*/
app.get(endpoint + "/:id", Task.getOne);
/**
* @api {get} /api/v1/tasks Retrieve all tasks
* @apiVersion 1.0.0
* @apiName GetAll
* @apiGroup Task
* @apiPermission authenticated user
*
* @apiExample {js} Example usage:
* $http.defaults.headers.common["Authorization"] = token;
* $http.get(url)
* .success((res, status) => doSomethingHere())
* .error((err, status) => doSomethingHere());
*
* @apiSuccess {String} _id The task id
* @apiSuccess {String} name The task name
*
* @apiSuccessExample {json} Success response:
* HTTPS 200 OK
* [{
* "_id": "57e8e94ea06a0c473bac50cc",
* "name": "Do the disehs"
* },
* {
* "_id": "57e903941ca43a5f0805ba5a",
* "name": "Take out the trash"
* }]
*
* @apiUse UnauthorizedError
*/
app.get(endpoint, Task.getAll);
/**
* @api {put} /api/v1/tasks/:id Update a task
* @apiVersion 1.0.0
* @apiName Update
* @apiGroup Task
* @apiPermission authenticated user
*
* @apiParam {String} id The task id
*
* @apiParam (Request body) {String} name The task name
*
* @apiExample {js} Example usage:
* const data = {
* "name": "Run in the park"
* }
*
* $http.defaults.headers.common["Authorization"] = token;
* $http.put(url, data)
* .success((res, status) => doSomethingHere())
* .error((err, status) => doSomethingHere());
*
* @apiSuccess {String} message Task updated successfully!
*
* @apiSuccessExample {json} Success response:
* HTTPS 200 OK
* {
* "message": "Task updated successfully!"
* }
*
* @apiUse UnauthorizedError
*/
app.put(endpoint + "/:id", Task.update);
};
如你所见,我们有 HTTP 方法的类型(post,put,get,delete)、端点地址、api 版本、它需要的权限类型、它需要的参数,还有如果用户是未经授权的应该返回怎样的响应和错误。
在官方网站中,你可以查看注释文档和可用参数。
那么这个 UnauthorizedError 来自哪里呢?
apiDoc 设置
有一些设置可以用 apiDoc 完成,这个 UnauthorizedError 就是我经常要用到的。
在 routes 目录中创建一个名为 __apidoc.js
的文件,其中包含以下内容:
// -----------------------------------------------------------
// General apiDoc documentation blocks and old history blocks.
// -----------------------------------------------------------
// -----------------------------------------------------------
// Current Success.
// -----------------------------------------------------------
// -----------------------------------------------------------
// Current Errors.
// -----------------------------------------------------------
// -----------------------------------------------------------
// Current Permissions.
// -----------------------------------------------------------
/**
* @apiDefine UnauthorizedError
* @apiVersion 1.0.0
*
* @apiError Unauthorized Only authenticated users can access the endpoint.
*
* @apiErrorExample Unauthorized response:
* HTTP 401 Unauthorized
* {
* "message": "Invalid credentials"
* }
*/
// -----------------------------------------------------------
// History.
// -----------------------------------------------------------
我还创建了另一个文件,也在 routes 目录中,名为 apidoc.json
该文件包含以下内容(示例):
{
"name": "Test API - This is my API",
"version": "1.0.0",
"description": "This is my very powerful API",
"title": "Test API - This is my API",
"url": "https://testapi.com"
}
生成文档时,apiDoc 将会使用这两个文件。
生成文档
在为每个端点编写注释并配置好项目之后,我们需要配置一个任务来生成文档。
我用 gulp 来做到这一切。安装所需的依赖项:
npm i gulp gulp-apidoc --save-dev
然后在项目的根目录中创建一个名为 gulpfile.js
的文件。如果它已经存在,只需添加与 apiDoc 相关的部分:
const gulp = require("gulp");
const apidoc = require("gulp-apidoc");
gulp.task("apidoc", (done) => {
apidoc({
src: "./routes",
dest: "../docs/apidoc"
}, done);
});
gulp.task("watch", () => {gulp.watch(["./routes/**"], ["apidoc"]);
});
你可以将那里的“dest”目录更改为另一个更适合你的目录。这就是你希望生成输出的位置。
现在你需要做的就是运行:
gulp apidoc
之后,你只需要在上面“dest”中配置的目录中打开 index.html 文件,就会看到类似这样的内容):
其他开发人员也可以用 gulp 生成相同的内容,或者你甚至可以通过 Nginx 为生成的目录提供 Web 服务。
总结
在这本文中,我们了解了如何使用注释来记录 API,并使用 apiDoc 为它们生成 HTML 格式的文档。
你是否还用了其他软件来为你的 API 生成文档,或者你是否以其他方式使用 apiDoc?请在下面评论中留言讨论!
本文首发微信公众号:前端先锋
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章
欢迎继续阅读本专栏其它高赞文章:
- 深入理解 Shadow DOM v1
- 一步步教你用 WebVR 实现虚拟现实游戏
- 13 个帮你提高开发效率的现代 CSS 框架
- 快速上手 BootstrapVue
- JavaScript 引擎是如何工作的?从调用栈到 Promise 你需要知道的一切
- WebSocket 实战:在 Node 和 React 之间进行实时通信
- 关于 Git 的 20 个面试题
- 深入解析 Node.js 的 console.log
- Node.js 究竟是什么?
- 30 分钟用 Node.js 构建一个 API 服务器
- Javascript 的对象拷贝
- 程序员 30 岁前月薪达不到 30K,该何去何从
- 14 个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩展插件
- Node.js 多线程完全指南
- 把 HTML 转成 PDF 的 4 个方案及实现
- 更多文章 …