As usual, this article isn’t meant as an in-depth guide, as much as a documentation of the what, why, and how of certain architectural choices. If you’re trying to achieve the same thing and need help, leave a comment!
Goals & Constraints
- To document BobaBoard‘s REST API.
- Standardize (and document) both the parameters and the return values of various endpoints.
- The documentation should be as close as possible to the source code it describes.
- The documentation should be served through a docusaurus instance hosted on a different server.
Final Result
Architecture
Documentation
How To
Packages used
-
SwaggerJSDoc: to turn JSDocs into the final OpenAPI spec (served at
/open-api.json
). - Redocusaurus: to embed Redoc into Docusaurus. There are other options for documentation, like any OpenAPI/Swagger compatible tool (e.g. SwaggerUI), but Redoc is the nicest feeling one.
Configuration (Express)
OpenAPI Options
const options = {
definition: {
openapi: "3.1.0",
info: {
title: "BobaBoard's API documentation.",
version: "0.0.1",
// Note: indenting the description will cause the markdown not to format correctly.
description: `
# Intro
Welcome to the BobaBoard's backend API. This is still a WIP.
# Example Section
This is just to test that sections work. It will be written better later.
`,
contact: {
name: "Ms. Boba",
url: "https://www.bobaboard.com",
email: "ms.boba@bobaboard.com",
},
},
servers: [
{
url: "http://localhost:4200/",
description: "Development server",
},
],
// These are used to group endpoints in the sidebar
tags: [
{
name: "/posts/",
description: "All APIs related to the /posts/ endpoints.",
},
{
name: "/boards/",
description: "All APIs related to the /boards/ endpoints.",
},
{
name: "todo",
description: "APIs whose documentation still needs work.",
},
],
// Special Redoc section to control how tags display in the sidebar.
"x-tagGroups": [
{
name: "general",
tags: ["/posts/", "/boards/"],
},
],
},
// Which paths to parse the API specs from.
apis: ["./types/open-api/*.yaml", "./server/*/routes.ts"],
};
Open API endpoint
import swaggerJsdoc from "swagger-jsdoc";
const specs = swaggerJsdoc(options);
app.get("/open-api.json", (req, res) => {
res.setHeader("Content-Type", "application/json");
res.send(specs);
});
Type Spec
/types/open-api/contribution.yaml
# Note the /components/schemas/[component name] hierarchy.
# This is used to refer to these types in the endpoint
# documentation.
components:
schemas:
Contribution:
type: object
properties:
post_id:
type: string
format: uuid
parent_thread_id:
type: string
format: uuid
parent_post_id:
type: string
format: uuid
secret_identity:
$ref: "#/components/schemas/Identity"
required:
- post_id
- parent_thread_id
- secret_identity
Endpoint Documentation
This should be repeated for every API endpoint you wish to document.
/**
* @openapi
* posts/{postId}/contribute:
* post:
* summary: Replies to a contribution
* description: Posts a contribution replying to the one with id {postId}.
* tags:
* - /posts/
* - todo
* parameters:
* - name: postId
* in: path
* description: The uuid of the contribution to reply to.
* required: true
* schema:
* type: string
* format: uuid
* responses:
* 403:
* description: User is not authorized to perform the action.
* 200:
* description: The contribution was successfully created.
* content:
* application/json:
* schema:
* type: object
* properties:
* contribution:
* $ref: "#/components/schemas/Contribution"
* description: Finalized details of the contributions just posted.
*/
router.post("/:postId/contribute", isLoggedIn, async (req, res) => {
// The endpoint code
}
Configuration (Docusaurus)
docusaurus.config.js
:
module.exports = {
// other config stuff
// ...
presets: [
// other presets,
[
"redocusaurus",
{
specs: [
{
routePath: "docs/engineering/rest-api/",
// process.env.API_SPEC is used to serve from localhost during development
specUrl:
process.env.API_SPEC ||
"[prod_server_url]/open-api.json",
},
],
theme: {
// See options at https://github.com/Redocly/redoc#redoc-options-object
redocOptions: {
expandSingleSchemaField: true,
expandResponses: "200",
pathInMiddlePanel: true,
requiredPropsFirst: true,
hideHostname: true,
},
},
},
],
],
}
Print
Share
Comment
Cite
Upload
Translate
APA
Essential Randomness | Sciencx (2024-03-29T04:45:55+00:00) » Documenting Express REST APIs with OpenAPI and JSDoc. Retrieved from https://www.scien.cx/2021/07/18/documenting-express-rest-apis-with-openapi-and-jsdoc/.
MLA" » Documenting Express REST APIs with OpenAPI and JSDoc." Essential Randomness | Sciencx - Sunday July 18, 2021, https://www.scien.cx/2021/07/18/documenting-express-rest-apis-with-openapi-and-jsdoc/
HARVARDEssential Randomness | Sciencx Sunday July 18, 2021 » Documenting Express REST APIs with OpenAPI and JSDoc., viewed 2024-03-29T04:45:55+00:00,<https://www.scien.cx/2021/07/18/documenting-express-rest-apis-with-openapi-and-jsdoc/>
VANCOUVEREssential Randomness | Sciencx - » Documenting Express REST APIs with OpenAPI and JSDoc. [Internet]. [Accessed 2024-03-29T04:45:55+00:00]. Available from: https://www.scien.cx/2021/07/18/documenting-express-rest-apis-with-openapi-and-jsdoc/
CHICAGO" » Documenting Express REST APIs with OpenAPI and JSDoc." Essential Randomness | Sciencx - Accessed 2024-03-29T04:45:55+00:00. https://www.scien.cx/2021/07/18/documenting-express-rest-apis-with-openapi-and-jsdoc/
IEEE" » Documenting Express REST APIs with OpenAPI and JSDoc." Essential Randomness | Sciencx [Online]. Available: https://www.scien.cx/2021/07/18/documenting-express-rest-apis-with-openapi-and-jsdoc/. [Accessed: 2024-03-29T04:45:55+00:00]
rf:citation » Documenting Express REST APIs with OpenAPI and JSDoc | Essential Randomness | Sciencx | https://www.scien.cx/2021/07/18/documenting-express-rest-apis-with-openapi-and-jsdoc/ | 2024-03-29T04:45:55+00:00
https://github.com/addpipe/simple-recorderjs-demo