--- title: Автогенерация из OpenAPI description: Генерация REST-клиента из OpenAPI-спецификации через @gromlab/api-codegen. keywords: [rest, openapi, api-codegen, автогенерация, generated, npx] --- # Автогенерация из OpenAPI Автогенерация используется, когда у API есть актуальная OpenAPI-спецификация. Генератор создаёт TypeScript-клиент, типы и методы API, а разработчик вручную добавляет настройку клиента и GET-хуки. ## Пример API В примерах используется Swagger Petstore: ```text https://petstore3.swagger.io/api/v3/openapi.json ``` Имена модуля: ```text src/infrastructure/pet-store-api/ petStoreApi pet-store-api.generated.ts ``` ## Скрипт генерации `@gromlab/api-codegen` не устанавливается в `devDependencies`. Используем `npx @gromlab/api-codegen@latest`, чтобы запускать свежую версию. ```json { "scripts": { "codegen:pet-store-api": "npx @gromlab/api-codegen@latest -i https://petstore3.swagger.io/api/v3/openapi.json -o src/infrastructure/pet-store-api/generated -n pet-store-api.generated" } } ``` Параметры: - `-i` — путь к OpenAPI-спецификации: URL или локальный файл. - `-o` — директория для сгенерированного файла. - `-n` — имя сгенерированного файла без `.ts`. Ключ `--swr` не используется. GET-хуки REST-клиента пишутся вручную, чтобы сохранить проектный контракт: один GET-хук = один GET-метод, без бизнес-логики и композиции. ## Генерация ```bash npm run codegen:pet-store-api ``` Ожидаемый результат: ```text src/infrastructure/pet-store-api/generated/ └── pet-store-api.generated.ts ``` Сгенерированный файл не правится руками и коммитится в репозиторий. ## Проверка методов После генерации откройте `generated/pet-store-api.generated.ts` и проверьте фактические имена методов. Для Petstore нужны GET-операции вида: ```ts petStoreApi.pet.findPetsByStatus(...) petStoreApi.pet.getPetById(...) ``` Точные сигнатуры зависят от OpenAPI-схемы и версии генератора. В рабочих задачах всегда сверяйтесь с generated-файлом. ## `client.ts` Сгенерированный код не должен напрямую использоваться из приложения. Сначала создаётся настроенный инстанс клиента. ```ts // src/infrastructure/pet-store-api/client.ts import { Api, HttpClient } from './generated/pet-store-api.generated' const httpClient = new HttpClient({ baseUrl: 'https://petstore3.swagger.io/api/v3', baseApiParams: { secure: false, headers: { 'Content-Type': 'application/json', }, }, }) export const petStoreApi = new Api(httpClient) ``` В реальном проекте вместо строки `baseUrl` обычно берётся из env-переменной, нормализуется в `client.ts` и передаётся в `HttpClient` через конфиг. `client.ts` не содержит расширения типов, `declare module` и `Extended`-типы. Он только настраивает транспорт и экспортирует инстанс клиента. ## Расширение сгенерированных типов Сгенерированный файл не правится руками. Если OpenAPI-спецификация неполная или генератор дал слишком общий тип (`object`, `unknown`, отсутствующее поле), расширения живут в `types/`. ```text src/infrastructure/biocad-less-api/ ├── generated/ │ └── biocad-less-api.generated.ts ├── types/ │ ├── term.ts │ └── index.ts ├── client.ts └── index.ts ``` Пример расширения generated-типа: ```ts // src/infrastructure/biocad-less-api/types/term.ts import type { TermRecordItem } from '../generated/biocad-less-api.generated' declare module '../generated/biocad-less-api.generated' { interface TermRecordItem { media?: { file?: string title?: string url?: string } } } export type TermRecordItemExtended = Omit< TermRecordItem, 'categories' | 'tags' | 'fields' > & { categories?: Array<{ _id?: string id?: string slug?: string name?: string }> tags?: Array<{ _id?: string id?: string slug?: string name?: string }> fields?: Record } ``` ```ts // src/infrastructure/biocad-less-api/types/index.ts export type { TermRecordItemExtended } from './term' ``` `declare module` используется для добавления отсутствующих полей в generated-интерфейс. `Extended`-тип используется, когда нужно переопределить неточные поля, не трогая generated-файл. ## Публичный API ```ts // src/infrastructure/pet-store-api/index.ts export { petStoreApi } from './client' export type { Pet } from './generated/pet-store-api.generated' export * from './hooks' ``` Наружу импортируют только из `infrastructure/pet-store-api`, не из `generated/`. Если у модуля есть расширенные типы, они тоже реэкспортируются через `index.ts`: ```ts // src/infrastructure/biocad-less-api/index.ts export type { TermRecordItemExtended } from './types' ``` ## Регенерация При изменении OpenAPI-схемы: ```bash npm run codegen:pet-store-api ``` Что меняется: - `generated/pet-store-api.generated.ts` — перезаписывается генератором. - `client.ts`, `hooks/`, `types/`, `index.ts` — не трогаются автоматически. Если после регенерации поменялись сигнатуры методов или типы, это исправляется в ручном коде модуля. ## Следующий шаг После генерации и настройки `client.ts` проверьте серверный вызов метода клиента или добавьте [GET-хук REST-клиента](./hooks.md) для Client Components.