Nx NestJs — Как автогенерировать спецификации OpenApi/Swagger

Привет всем, на этот раз короткая статья.
Когда я начал использовать NestJs с Nx, я заметил один непредвиденный момент, до сих пор идут споры о том, как активировать OpenApi/Swagger в NestJs с опцией автоматической документации.

Больше не бойтесь, в конце этого руководства эта проблема будет решена.

Используемые версии

Я использую последнюю версию Nx на момент написания статьи, а именно V14, с NestJs 8.0 и NestJs Swagger 5.2.

Пакеты

Сначала установите необходимый пакет, если вы используете express, установите npm install --save @nestjs/swagger swagger-ui-express в противном случае, для fastify используйте npm install --save @nestjs/swagger fastify-swagger.

Добавьте модуль Swagger

В main.ts из папки проекта NestJs добавьте следующее:

function setupOpenApi(app: INestApplication) {
  const config = new DocumentBuilder().setTitle('API Documentation').setVersion('1.0').addTag('api').build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);
}
Войти в полноэкранный режим Выйти из полноэкранного режима

затем в функции bootstrap просто вызовите функцию setupOpenApi.

Весь мой main.ts выглядит следующим образом, обратите внимание, что я предпочел следующие варианты:

  • Я использовал Fastify, потому что у меня нет жесткой зависимости от express middleware, и это улучшает производительность.
  • Я использовал глобальный префикс, поэтому мне пришлось установить useGlobalPrefix:true в функции выше.
  • Глобальный префикс, который я использовал, по умолчанию api, что конфликтует с маршрутом по умолчанию для OpenApi, который в документации совпадает с api. Если вы оставите их в таком виде без добавления флага useGlobalPrefix: true, то вы сможете получить доступ и к API, и к OpenAPI на http://localhost:3000/api, но вы заметите, что документация неверна, поскольку в ней не указан используемый globalPrefix. Чтобы исправить это, мы должны установить флаг useGlobalPrefix: true для OpenAPI и получить доступ к документации по адресу http://localhost:3000/api/api, что выглядит странно, поэтому я изменил его на http://localhost:3000/api/openApi Пример работы ниже:
/**
 * This is not a production server yet!
 * This is only a minimal backend to get started.
 */
import { INestApplication, Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

import { AppModule } from './app/app.module';

async function bootstrap() {
  const fastifyOptions: ConstructorParameters<typeof FastifyAdapter>[0] = {
    logger: true,
  };
  const fastifyAdapter = new FastifyAdapter(fastifyOptions);
  const app = await NestFactory.create<NestFastifyApplication>(AppModule, fastifyAdapter);

  const globalPrefix = 'api';
  app.setGlobalPrefix(globalPrefix);
  setupOpenApi(app);

  const port = process.env.PORT || 3333;
  await app.listen(port);
  Logger.log(`🚀 Application is running on: http://localhost:${port}/${globalPrefix}`);
}

bootstrap();

function setupOpenApi(app: INestApplication) {
  const config = new DocumentBuilder().setTitle('API Documentation').setVersion('1.0').addTag('api').build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('openApi', app, document, { useGlobalPrefix: true });
}

Вход в полноэкранный режим Выход из полноэкранного режима

Сейчас вы готовы использовать часть пакета с ручной документацией, но мы оба знаем, что вы здесь не для этого.

Автоматическая документация

Это будет довольно коротко, у нас есть 2 не хакерских способа сделать это.

Nest-Cli.json — Не предлагается

Просто создайте файл nest-cli.json в корне проекта, затем добавьте в него

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "apps",
  "compilerOptions": {
    "plugins": [
      {
        "name": "@nestjs/swagger/plugin",
        "options": {
          "dtoFileNameSuffix": [".entity.ts", ".dto.ts"],
          "controllerFileNameSuffix": [".controller.ts"],
          "classValidatorShim": true,
          "dtoKeyOfComment": "description",
          "controllerKeyOfComment": "description",
          "introspectComments": true
        }
      }
    ]
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Не пугайтесь приведенных выше настроек, это просто настройки по умолчанию, чтобы быть более явными. Что действительно изменяется, так это sourceRoot, который в случае с NX (по крайней мере, для пресетов с приложениями) является папкой apps.

Это должно определить ваши параметры и имена классов, но, скорее всего, не увидит, что находится внутри ваших классов, и они будут казаться пустыми.

TsPlugin — рекомендуется, более настраиваемый

Перейдите к вашему project.json в папке проекта NestJs или angular.json в корневой папке для более старой версии и найдите нужный вам проект. Нам потребуется изменить команду build.

Вся команда сборки показана ниже

 "build": {
      "executor": "@nrwl/node:webpack",
      "outputs": ["{options.outputPath}"],
      "options": {
        "outputPath": "dist/apps/api",
        "main": "apps/api/src/main.ts",
        "tsConfig": "apps/api/tsconfig.app.json",
        "tsPlugins": [
          {
            "name": "@nestjs/swagger/plugin",
            "options": {
              "dtoFileNameSuffix": [".entity.ts", ".dto.ts"],
              "controllerFileNameSuffix": [".controller.ts"],
              "classValidatorShim": true,
              "dtoKeyOfComment": "description",
              "controllerKeyOfComment": "description",
              "introspectComments": true
            }
          }
        ],
        "assets": ["apps/api/src/assets"]
      },
Вход в полноэкранный режим Выйти из полноэкранного режима

Как вы можете заметить, мы добавили пользовательский Webpack TsPlugin, как указано в документации над этим https://docs.nestjs.com/openapi/cli-plugin#integration-with-ts-jest-e2e-tests.

Как уже упоминалось, это рекомендуемый подход, он будет видеть все классы из любого места в монорепо, если они импортированы в проект.

Последние детали

Помните следующее:

  • Вы можете использовать только classes, а не interfacees.
  • Вам необходимо добавить .dto.ts или .entity.ts, если вы не измените это.

Спасибо за прочтение!

Оцените статью
Procodings.ru
Добавить комментарий