翻译: 疯狂的技术宅
原文:jonathas.com/documenting…
未经许可,禁止转载!
当你为其他开发人员(前端,桌面,移动等)开发 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?请在下面评论中留言讨论!