# Генерация SDK { #generating-sdks }

Поскольку **FastAPI** основан на спецификации **OpenAPI**, его API можно описать в стандартном формате, понятном множеству инструментов.

Это упрощает генерацию актуальной **документации**, клиентских библиотек (<abbr title="Software Development Kits – Наборы средств разработки">**SDKs**</abbr>) на разных языках, а также **тестирования** или **воркфлоу автоматизации**, которые остаются синхронизированными с вашим кодом.

В этом руководстве вы узнаете, как сгенерировать **TypeScript SDK** для вашего бэкенда на FastAPI.

## Генераторы SDK с открытым исходным кодом { #open-source-sdk-generators }

Гибкий вариант — <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>, который поддерживает **многие языки программирования** и умеет генерировать SDK из вашей спецификации OpenAPI.

Для **TypeScript‑клиентов** <a href="https://heyapi.dev/" class="external-link" target="_blank">Hey API</a> — специализированное решение, обеспечивающее оптимальный опыт для экосистемы TypeScript.

Больше генераторов SDK можно найти на <a href="https://openapi.tools/#sdk" class="external-link" target="_blank">OpenAPI.Tools</a>.

/// tip | Совет

FastAPI автоматически генерирует спецификации **OpenAPI 3.1**, поэтому любой используемый инструмент должен поддерживать эту версию.

///

## Генераторы SDK от спонсоров FastAPI { #sdk-generators-from-fastapi-sponsors }

В этом разделе представлены решения с **венчурной поддержкой** и **поддержкой компаний** от компаний, которые спонсируют FastAPI. Эти продукты предоставляют **дополнительные возможности** и **интеграции** сверх высококачественно генерируемых SDK.

Благодаря ✨ [**спонсорству FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ эти компании помогают обеспечивать, чтобы фреймворк и его **экосистема** оставались здоровыми и **устойчивыми**.

Их спонсорство также демонстрирует серьёзную приверженность **сообществу** FastAPI (вам), показывая, что им важно не только предоставлять **отличный сервис**, но и поддерживать **надёжный и процветающий фреймворк** FastAPI. 🙇

Например, вы можете попробовать:

* <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a>
* <a href="https://www.stainless.com/?utm_source=fastapi&utm_medium=referral" class="external-link" target="_blank">Stainless</a>
* <a href="https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi" class="external-link" target="_blank">liblab</a>

Некоторые из этих решений также могут быть open source или иметь бесплатные тарифы, так что вы сможете попробовать их без финансовых затрат. Другие коммерческие генераторы SDK доступны и их можно найти онлайн. 🤓

## Создать TypeScript SDK { #create-a-typescript-sdk }

Начнём с простого приложения FastAPI:

{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}

Обратите внимание, что *операции пути (обработчики пути)* определяют модели, которые они используют для полезной нагрузки запроса и полезной нагрузки ответа, с помощью моделей `Item` и `ResponseMessage`.

### Документация API { #api-docs }

Если перейти на `/docs`, вы увидите **схемы** данных, отправляемых в запросах и принимаемых в ответах:

<img src="/img/tutorial/generate-clients/image01.png">

Вы видите эти схемы, потому что они были объявлены с моделями в приложении.

Эта информация доступна в **схеме OpenAPI** приложения и затем отображается в документации API.

Та же информация из моделей, включённая в OpenAPI, может использоваться для **генерации клиентского кода**.

### Hey API { #hey-api }

Как только у нас есть приложение FastAPI с моделями, мы можем использовать Hey API для генерации TypeScript‑клиента. Самый быстрый способ сделать это — через npx.

```sh
npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
```

Это сгенерирует TypeScript SDK в `./src/client`.

Вы можете узнать, как <a href="https://heyapi.dev/openapi-ts/get-started" class="external-link" target="_blank">установить `@hey-api/openapi-ts`</a> и почитать о <a href="https://heyapi.dev/openapi-ts/output" class="external-link" target="_blank">сгенерированном результате</a> на их сайте.

### Использование SDK { #using-the-sdk }

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

<img src="/img/tutorial/generate-clients/image02.png">

Вы также получите автозавершение для отправляемой полезной нагрузки:

<img src="/img/tutorial/generate-clients/image03.png">

/// tip | Совет

Обратите внимание на автозавершение для `name` и `price`, это было определено в приложении FastAPI, в модели `Item`.

///

Вы получите ошибки прямо в редакторе для отправляемых данных:

<img src="/img/tutorial/generate-clients/image04.png">

Объект ответа также будет иметь автозавершение:

<img src="/img/tutorial/generate-clients/image05.png">

## Приложение FastAPI с тегами { #fastapi-app-with-tags }

Во многих случаях ваше приложение FastAPI будет больше, и вы, вероятно, будете использовать теги, чтобы разделять разные группы *операций пути*.

Например, у вас может быть раздел для **items** и другой раздел для **users**, и они могут быть разделены тегами:

{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}

### Генерация TypeScript‑клиента с тегами { #generate-a-typescript-client-with-tags }

Если вы генерируете клиент для приложения FastAPI с использованием тегов, обычно клиентский код также будет разделён по тегам.

Таким образом вы сможете иметь всё правильно упорядоченным и сгруппированным в клиентском коде:

<img src="/img/tutorial/generate-clients/image06.png">

В этом случае у вас есть:

* `ItemsService`
* `UsersService`

### Имена методов клиента { #client-method-names }

Сейчас сгенерированные имена методов вроде `createItemItemsPost` выглядят не очень аккуратно:

```TypeScript
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
```

...это потому, что генератор клиента использует внутренний **ID операции** OpenAPI для каждой *операции пути*.

OpenAPI требует, чтобы каждый ID операции был уникален среди всех *операций пути*, поэтому FastAPI использует **имя функции**, **путь** и **HTTP‑метод/операцию** для генерации этого ID операции, так как таким образом можно гарантировать уникальность ID операций.

Но далее я покажу, как это улучшить. 🤓

## Пользовательские ID операций и лучшие имена методов { #custom-operation-ids-and-better-method-names }

Вы можете **изменить** способ **генерации** этих ID операций, чтобы сделать их проще, а имена методов в клиентах — **более простыми**.

В этом случае вам нужно будет обеспечить, чтобы каждый ID операции был **уникальным** другим способом.

Например, вы можете гарантировать, что у каждой *операции пути* есть тег, и затем генерировать ID операции на основе **тега** и **имени** *операции пути* (имени функции).

### Пользовательская функция генерации уникального ID { #custom-generate-unique-id-function }

FastAPI использует **уникальный ID** для каждой *операции пути*, который применяется для **ID операции**, а также для имён любых необходимых пользовательских моделей запросов или ответов.

Вы можете кастомизировать эту функцию. Она принимает `APIRoute` и возвращает строку.

Например, здесь берётся первый тег (скорее всего у вас один тег) и имя *операции пути* (имя функции).

Затем вы можете передать эту пользовательскую функцию в **FastAPI** через параметр `generate_unique_id_function`:

{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}

### Генерация TypeScript‑клиента с пользовательскими ID операций { #generate-a-typescript-client-with-custom-operation-ids }

Теперь, если снова сгенерировать клиент, вы увидите, что имена методов улучшились:

<img src="/img/tutorial/generate-clients/image07.png">

Как видите, теперь имена методов содержат тег, а затем имя функции; больше они не включают информацию из URL‑пути и HTTP‑операции.

### Предобработка спецификации OpenAPI для генератора клиента { #preprocess-the-openapi-specification-for-the-client-generator }

Сгенерированном коде всё ещё есть **дублирующаяся информация**.

Мы уже знаем, что этот метод относится к **items**, потому что это слово есть в `ItemsService` (взято из тега), но при этом имя тега всё ещё добавлено префиксом к имени метода. 😕

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

Но для сгенерированного клиента мы можем **модифицировать** ID операций OpenAPI непосредственно перед генерацией клиентов, чтобы сделать имена методов более приятными и **чистыми**.

Мы можем скачать OpenAPI JSON в файл `openapi.json`, а затем **убрать этот префикс‑тег** таким скриптом:

{* ../../docs_src/generate_clients/tutorial004_py39.py *}

//// tab | Node.js

```Javascript
{!> ../../docs_src/generate_clients/tutorial004.js!}
```

////

После этого ID операций будут переименованы с чего‑то вроде `items-get_items` просто в `get_items`, и генератор клиента сможет создавать более простые имена методов.

### Генерация TypeScript‑клиента с предобработанным OpenAPI { #generate-a-typescript-client-with-the-preprocessed-openapi }

Так как конечный результат теперь в файле `openapi.json`, нужно обновить входное расположение:

```sh
npx @hey-api/openapi-ts -i ./openapi.json -o src/client
```

После генерации нового клиента у вас будут **чистые имена методов**, со всем **автозавершением**, **ошибками прямо в редакторе** и т.д.:

<img src="/img/tutorial/generate-clients/image08.png">

## Преимущества { #benefits }

При использовании автоматически сгенерированных клиентов вы получите **автозавершение** для:

* Методов.
* Данных запроса — в теле запроса, query‑параметрах и т.д.
* Данных ответа.

У вас также будут **ошибки прямо в редакторе** для всего.

И каждый раз, когда вы обновляете код бэкенда и **перегенерируете** фронтенд, в нём появятся новые *операции пути* как методы, старые будут удалены, а любые другие изменения отразятся в сгенерированном коде. 🤓

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

Таким образом, вы **обнаружите многие ошибки** очень рано в цикле разработки, вместо того чтобы ждать, когда ошибки проявятся у конечных пользователей в продакшн, и затем пытаться отладить, в чём проблема. ✨
