> 웹 프론트엔드 > JS 튜토리얼 > Node.js에서 Joi를 사용하여 Swagger 문서화 자동화: API 문서화 워크플로 단순화

Node.js에서 Joi를 사용하여 Swagger 문서화 자동화: API 문서화 워크플로 단순화

Patricia Arquette
풀어 주다: 2024-10-06 08:15:03
원래의
593명이 탐색했습니다.

Automating Swagger Documentation with Joi in Node.js: Simplify Your API Documentation Workflow

Maintaining accurate and up-to-date API documentation is a common challenge for developers, especially when working in teams. Manually updating Swagger files for each API route can lead to frequent merge conflicts and inconsistencies between the actual API behavior and the documentation. These issues not only slow down development but can also lead to confusion and errors when using the API.

The solution? Automate the generation of Swagger documentation using Joi validation schemas in Node.js with Express. By doing this, you ensure that your documentation stays in sync with your codebase, while eliminating the need for manual updates.

In this article, we will walk through:

  • Setting up Joi validation and Swagger documentation automation.
  • Solving the problem of manual Swagger updates and merge conflicts.
  • Ensuring robust API contract validation for all routes.

Let’s break it down step by step.


The Problem: Manual Swagger Maintenance

When developing an API, it's common to manually update Swagger documentation for each route. In large teams, this leads to conflicts when multiple developers edit the same file, often resulting in lost changes, inconsistent documentation, and wasted time resolving merge conflicts.

By automating Swagger documentation generation using Joi, we can solve this problem. Joi allows us to validate incoming requests to ensure they match our expectations, and at the same time, we can use those same Joi schemas to generate Swagger documentation automatically.

This approach ensures that documentation is always accurate, in sync with the codebase, and reflects the actual structure of the API.

Step 1: Setting Up Joi Validation Middleware

The first step is creating middleware that validates incoming requests using Joi. This middleware ensures that the request's parameters, headers, body, and query strings are valid according to the schema you define. Additionally, the same Joi schema will be used to automatically generate Swagger documentation.

Here’s the middleware:


const Joi = require("joi");

const schemasEnum = Object.freeze({
    BODY: 'body',
    PARAMS: 'params',
    QUERY: 'query',
    HEADERS: 'headers'
});

const validationMiddleware = (schema) => {
    return (request, response, nextFunction) => {
        const validationOptions = {
            abortEarly: false,
            allowUnknown: true,
            stripUnknown: true
        };

        const schemas = Object.values(schemasEnum);
        const validationResults = {};

        for (const key of schemas) {
            if (schema[key]) {
                const { error, value } = schema[key].validate(request[key], validationOptions);

                if (error) {
                    return response.status(400).json({
                        error: `Validation error in ${key}: ${error.details.map((x) => x.message).join(', ')}`
                    });
                } else {
                    validationResults[key] = value;
                }
            }
        }

        Object.assign(request, validationResults);
        nextFunction();
    };
};

module.exports = { validationMiddleware };


로그인 후 복사

This middleware validates incoming requests based on the schema defined for each route. If the validation fails, it returns an error; otherwise, it allows the request to proceed.

Step 2: Registering Routes with Joi and Automatically Generating Swagger

Next, we create a function that registers routes and automatically generates Swagger documentation using the joi-to-swagger library. This function applies the validation middleware and generates the Swagger documentation at the same time.

Here’s how the registerRoute function works:


const { validationMiddleware } = require("../middlewares/validationMiddelware");
const convert = require("joi-to-swagger");

const routes = [];

const registerRoute = (router, {
    method,
    path,
    schema = {},
    handler,
    middlewares = [],
    summary,
    description,
    tags = []
}) => {
    if (schema && Object.keys(schema).length > 0) {
        middlewares.unshift(validationMiddleware(schema));
    }

    router[method](path, ...middlewares, handler);

    const parameters = [];
    const requestBody = {};

    if (schema.params) {
        const { swagger: paramsSwagger } = convert(schema.params);
        parameters.push(...Object.keys(paramsSwagger.properties).map(key => ({
            name: key,
            in: 'path',
            required: schema.params._flags.presence === 'required',
            schema: paramsSwagger.properties[key],
            description: "paramsSwagger.properties[key].description"
        })));
    }

    if (schema.query) {
        const { swagger: querySwagger } = convert(schema.query);
        parameters.push(...Object.keys(querySwagger.properties).map(key => ({
            name: key,
            in: 'query',
            required: schema.query._flags.presence === 'required',
            schema: querySwagger.properties[key],
            description: "querySwagger.properties[key].description"
        })));
    }

    if (schema.body) {
        const { swagger: bodySwagger } = convert(schema.body);
        requestBody.content = {
            'application/json': {
                schema: bodySwagger
            }
        };
    }

    routes.push({
        path,
        method,
        summary,
        description,
        tags,
        parameters,
        requestBody
    });
};

module.exports = { registerRoute, routes };


로그인 후 복사

This function registers the route, applies the Joi validation middleware, and generates Swagger documentation for the route automatically. The joi-to-swagger library is responsible for converting the Joi schema into Swagger format.

Step 3: Defining Joi Schemas for Routes

Now, let’s define the Joi validation schema for a route. In this example, we define a schema for depositing a balance. It validates the userId parameter and the amount in the request body.

Here’s the Joi schema:


const Joi = require("joi");
const { appErrorSchema } = require("../../../shared/infra/http/schemas/AppErrorSchema");

const depositBalanceParamsSchema = Joi.object({
    userId: Joi.number().integer().required().description("User id"),
});

const depositBalanceBodySchema = Joi.object({
    amount: Joi.number().positive().greater(0).required().description("Amount to deposit"),
});

const depositBalanceResponsesSchema = {
    204: Joi.any().empty(),
    400: appErrorSchema,
    404: appErrorSchema,
};

module.exports = { depositBalanceParamsSchema, depositBalanceBodySchema, depositBalanceResponsesSchema };


로그인 후 복사

In this schema:

  • The userId must be a required integer.
  • The amount must be a positive number greater than 0.
  • The responses include validation for status codes 204, 400, and 404 using an error schema.

Step 4: Registering the Deposit Balance Route

Now that we have the schema, let’s create a route that validates the incoming request and automatically generates Swagger documentation:


const { Router } = require("express");
const { DepositBalanceController } = require("../../../useCases/depositBalance/DepositBalanceController");
const { registerRoute } = require("../../../../shared/infra/http/routes/registerRoute");
const { depositBalanceParamsSchema, depositBalanceBodySchema, depositBalanceResponsesSchema } = require("../../../useCases/depositBalance/DepositBalanceSchema");

const balancesRouter = Router();
const depositBalanceController = new DepositBalanceController();

registerRoute(balancesRouter, {
    description: "\"Deposit balance\","
    handler: depositBalanceController.handle,
    method: "post",
    path: "/balances/deposit/:userId",
    summary: "Deposit balance",
    schema: {
        params: depositBalanceParamsSchema,
        body: depositBalanceBodySchema,
        responses: depositBalanceResponsesSchema
    },
    tags: ["Balances"]
});

module.exports = { balancesRouter };


로그인 후 복사

This route handles deposit requests and validates them using the Joi schema defined earlier. The Swagger documentation is automatically generated based on the Joi schema.

Step 5: Generating the Swagger Document

To serve the Swagger documentation, we aggregate the registered routes and generate the Swagger document based on the route definitions.


const { routes } = require("../routes/registerRoute");

const swaggerDocument = {
    openapi: '3.0.0',
    info: {
        title: "'API Documentation',"
        version: '1.0.0'
    },
    paths: {}
};

routes.forEach(route => {
    const path = route.path.replace(/:([a-zA-Z0-9_]+)/g, '{$1}');
    if (!swaggerDocument.paths[path]) {
        swaggerDocument.paths[path] = {};
    }
    swaggerDocument.paths[path][route.method] = {
        summary: route.summary,
        description: "route.description,"
        tags: route.tags,
        parameters: route.parameters,
        requestBody: route.requestBody
    };
});

module.exports = { swaggerDocument };


로그인 후 복사

This code dynamically builds the Swagger document using the registered routes.

Step 6: Setting Up the Express Server

To complete the implementation, we set up the Express server and include the Swagger documentation endpoint.

Here’s the server.js file:


// server.js
const app = require('./app');

init();

async function init() {
  try {
    app.listen(3001, () => {
      console.log('Express App Listening on Port 3001');
    });
  } catch (error) {
    console.error(`An error occurred: ${JSON.stringify(error)}`);
    process.exit(1);
  }
}


로그인 후 복사

And the app.js file:


// app.js
require("express-async-errors");
const express = require('express');
const bodyParser = require('body-parser');
const { appRouter } =

 require("./modules/shared/infra/http/routes/app.routes");
const swaggerUi = require("swagger-ui-express");
const { swaggerDocument } = require("./swagger/swaggerConfig");
const app = express();

app.use(bodyParser.json());

// Use your app's routes
app.use(appRouter);

// Serve the Swagger documentation
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));

module.exports = app;


로그인 후 복사

Once the server is running, you can access the Swagger documentation at:


http://localhost:3001/api-docs


로그인 후 복사

How to Install and Run

To run the project and set up the automated Swagger documentation, follow these steps:

  1. Install Dependencies: Make sure you install all the required libraries, including express, joi, swagger-ui-express, and joi-to-swagger.

   npm install express joi joi-to-swagger swagger-ui-express body-parser express-async-errors


로그인 후 복사

These libraries are essential for setting up the Express server, validating incoming requests with Joi, and generating Swagger documentation automatically.

  1. Run the Server: Once the dependencies are installed, you can run the server using:

   node server.js


로그인 후 복사

This will start your Express server and listen on port 3001 (or any other port you specify).

  1. Access Swagger Documentation: Open your browser and navigate to the following URL to view the automatically generated Swagger documentation:

   http://localhost:3001/api-docs


로그인 후 복사

This endpoint serves the interactive Swagger UI, allowing you to test and explore your API routes directly in the browser.


Conclusion

Automating Swagger documentation with Joi streamlines the documentation process, eliminates merge conflicts, and ensures that your API documentation is always in sync with your actual code. By using Joi validation schemas to automatically generate Swagger documentation, you save time and improve the accuracy of your API contracts.

With the steps outlined in this article, you can easily integrate automatic Swagger generation into your Node.js projects, making your development workflow smoother and more efficient.

In summary:

  • Joi simplifies request validation and ensures that incoming data conforms to the expected format.
  • Swagger documentation is automatically generated from Joi schemas, eliminating manual updates.
  • Developers can focus on writing code without worrying about synchronizing documentation and API contracts.

This approach provides a robust solution for both API validation and documentation, allowing teams to work more efficiently and with fewer errors.

위 내용은 Node.js에서 Joi를 사용하여 Swagger 문서화 자동화: API 문서화 워크플로 단순화의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿