Skip to content

Глава 8. Серверная часть

Создадим новое nodejs приложение и в визарде выберем фреймворк fastify.

shell
$ npx nx g @nx/node:application apps/api
NX  Generating @nx/node:application
 Which linter would you like to use? · eslint
 Which unit test runner would you like to use? · none
 Which end-to-end test runner would you like to use? · none
 Which framework do you want to use? · fastify

$ npx nx g vitest --project api

Fastify - отличный фреймворк для серверного приложения. Он современный, быстрый и расширяемый - так как использует модульную архитектуру.

Сразу из коробки устаналивается плагин fastify-sensible — он добавляет набор полезных утилит и стандартных обработчиков для удобства разработки API. Он включает часто используемые HTTP-ответы, хелперы для ошибок, редиректов, кеширования и другие "sensible" (разумные/практичные) решения.

Fastify-autoload

Fastify предоставляет возможность автозагрузки плагинов - нужно просто разместить код инициализации плагина в папке plugins.

На данный момент, vitest не дружит с fastify-autoload и для работы тестов нужно прописать в настройки vite.config.ts:

server: {
      deps: {
        inline: ["@fastify/autoload"],
      },
    },

Vitest использует Vite, который, по умолчанию, ориентирован на ESM, а server.deps.inline — это своего рода "костыль" для совместимости Vitest с CommonJS-зависимостями и динамическими импортами.

Также и Autoload для роутов тоже не будет работать в Vitest, нужно сделать явную загрузку роутов.

Swagger

Swagger это инструмент, который добавляет спецификацию OpenAPI, описывая наш API в стандартизированном формате.

Подключим плагины:

  • @fastify/swagger - для автоматической документации API, валидации и, в последующем, для проверки типов запроса клиентских вызовов.

  • @fastify/swagger-ui - для просмотра спецификации в браузере.

shell
npm i @fastify/swagger @fastify/swagger-ui

и добавим файл иницализации в папку plugins.

При запуске сервера в develop-моде будет запущен также swagger-ui http://localhost:3000/docs.

OpenAPI схемы

Теперь можно добавить схему в параметры роута:

typescript
  fastify.get<{
  // тут описываем дженерик-типы параметров
}>(
  path,
  {
    shema: {
      // тут описываем схему
    }
  },
  handler);

Fastify использует синтаксис OpenAPI, для описания схем эндпоинтов, а это означает, что нужно описать в терминах TypeBox все входные (path, querystring, body), и выходные параметры (response).

Генерация схем

При разработке API, обычно, сначала создают OpenAPI схемы и из них генерят DTO. Но мне кажется, что гораздо удобнее создавать сначала DTO, а уже из них создавать схемы. В экосистеме typebox есть библиотека ts2typebox. Она позволяет генерировать схемы на основе существующих TypeScript-типов.

bash
$ npm install -D ts2typebox

Осталось подключить генерацию схем в сборку. Можно добавить конфигурацию руками, а для тех, кому лень открывать документацию у Nx есть генератор команд:

bash
$ nx generate @nx/workspace:run-commands \
  --name generate-schemas \
  --command "npx ts2typebox -i apps/api/src/dto/types.ts -o apps/api/src/typebox/index.ts" \
  --cwd apps/api \
  --project api
Осталось добавить зависимость в конфигурацию билда
json5
{
  "targets": {
    "build": {
      // ...
      "dependsOn": [
        "generate-schemas"
      ]
    }
  }
}

Дженерики

Для роутов мы дублируем информацию в дженериках и в схеме. К счастью, в сообществе fastify есть плагин fastify-type-provider-typebox, который решает это проблему и типизирует параметры прямо из схемы.

bash
$ npm i @fastify/type-provider-typebox

Дженерики больше не нужны, если использовать в роутах тип FastifyTypeBox вместо FastifyInstance.

typescript
export type FastifyTypeBox = FastifyInstance<
  RawServerDefault,
  RawRequestDefaultExpression,
  RawReplyDefaultExpression,
  FastifyBaseLogger,
  TypeBoxTypeProvider
>;