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

Оскільки **FastAPI** базується на специфікації **OpenAPI**, його API можна описати у стандартному форматі, який розуміють багато інструментів.

Це спрощує створення актуальної **документації**, клієнтських бібліотек (<abbr title="Software Development Kits - Набори для розробки програмного забезпечення">**SDKs**</abbr>) багатьма мовами, а також **тестування** чи **автоматизованих робочих процесів**, що залишаються синхронізованими з вашим кодом.

У цьому посібнику ви дізнаєтеся, як згенерувати **TypeScript SDK** для вашого бекенда на FastAPI.

## Генератори SDK з відкритим кодом { #open-source-sdk-generators }

Універсальним варіантом є [OpenAPI Generator](https://openapi-generator.tech/), який підтримує **багато мов програмування** та може генерувати SDK з вашої специфікації OpenAPI.

Для **клієнтів TypeScript** [Hey API](https://heyapi.dev/) — спеціалізоване рішення, що надає оптимізований досвід для екосистеми TypeScript.

Більше генераторів SDK ви можете знайти на [OpenAPI.Tools](https://openapi.tools/#sdk).

/// tip | Порада

FastAPI автоматично генерує специфікації **OpenAPI 3.1**, тож будь-який інструмент, який ви використовуєте, має підтримувати цю версію.

///

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

У цьому розділі представлено рішення від компаній, що спонсорують FastAPI: вони мають **венчурну підтримку** та **корпоративну підтримку**. Ці продукти надають **додаткові можливості** та **інтеграції** поверх високоякісно згенерованих SDK.

Завдяки ✨ [**спонсорству FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ ці компанії допомагають підтримувати фреймворк та його **екосистему** здоровими та **сталими**.

Їхня підтримка також демонструє сильну відданість **спільноті** FastAPI (вам), показуючи, що їм важливо не лише надавати **відмінний сервіс**, а й підтримувати **міцний і процвітаючий фреймворк**, FastAPI. 🙇

Наприклад, ви можете спробувати:

* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship)
* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral)
* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi)

Деякі з цих рішень також можуть бути з відкритим кодом або мати безкоштовні тарифи, тож ви можете спробувати їх без фінансових зобов'язань. Інші комерційні генератори SDK також доступні й їх можна знайти онлайн. 🤓

## Створити TypeScript SDK { #create-a-typescript-sdk }

Почнімо з простого застосунку FastAPI:

{* ../../docs_src/generate_clients/tutorial001_py310.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`.

Ви можете дізнатися, як [встановити `@hey-api/openapi-ts`](https://heyapi.dev/openapi-ts/get-started), і почитати про [згенерований результат](https://heyapi.dev/openapi-ts/output) на їхньому сайті.

### Використання SDK { #using-the-sdk }

Тепер ви можете імпортувати та використовувати клієнтський код. Це може виглядати так; зверніть увагу, що ви отримуєте «автодоповнення» для методів:

<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_py310.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})
```

...це тому, що генератор клієнта використовує внутрішній OpenAPI **operation ID** для кожної *операції шляху*.

OpenAPI вимагає, щоб кожен operation ID був унікальним для всіх *операцій шляху*, тому FastAPI використовує **назву функції**, **шлях** і **HTTP-метод/операцію** для генерації цього operation ID, адже так воно може гарантувати унікальність operation ID.

Але далі я покажу, як це покращити. 🤓

## Користувацькі operation ID та кращі назви методів { #custom-operation-ids-and-better-method-names }

Ви можете **змінити** спосіб **генерації** цих operation ID, щоб зробити їх простішими та мати **простіші назви методів** у клієнтах.

У цьому випадку вам потрібно буде іншим способом гарантувати, що кожен operation ID є **унікальним**.

Наприклад, ви можете переконатися, що кожна *операція шляху* має мітку, а потім генерувати operation ID на основі **мітки** та **назви** *операції шляху* (назви функції).

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

FastAPI використовує **унікальний ID** для кожної *операції шляху*, який застосовується для **operation ID**, а також для назв будь-яких потрібних користувацьких моделей для запитів чи відповідей.

Ви можете налаштувати цю функцію. Вона приймає `APIRoute` і повертає строку.

Наприклад, тут використовується перша мітка (у вас, ймовірно, буде лише одна мітка) і назва *операції шляху* (назва функції).

Потім ви можете передати цю користувацьку функцію до **FastAPI** як параметр `generate_unique_id_function`:

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

### Згенерувати TypeScript-клієнт з користувацькими operation 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, адже так гарантується унікальність operation ID.

Але для згенерованого клієнта ми можемо **змінити** operation ID в OpenAPI безпосередньо перед генерацією клієнтів, просто щоб зробити назви методів приємнішими та **чистішими**.

Ми можемо завантажити JSON OpenAPI у файл `openapi.json`, а потім **прибрати цей префікс із міткою** за допомогою такого скрипту:

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

//// tab | Node.js

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

////

Після цього operation 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 }

Використовуючи автоматично згенеровані клієнти, ви отримаєте **автодоповнення** для:

* Методів.
* Корисного навантаження запиту в тілі, параметрах запиту тощо.
* Корисного навантаження відповіді.

Також ви матимете **вбудовані помилки** для всього.

І щоразу, коли ви оновлюєте код бекенда та **перегенеровуєте** фронтенд, у ньому з'являтимуться нові *операції шляху* як методи, старі буде видалено, а будь-які інші зміни відобразяться у згенерованому коді. 🤓

Це також означає, що якщо щось змінилося, це буде **відображено** в клієнтському коді автоматично. А якщо ви **зіберете** клієнт, буде повідомлено про помилку, якщо є будь-яка **невідповідність** у використаних даних.

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