feat: добавить split-режим генерации REST-клиента
- добавлен режим генерации single, split и both - добавлены отдельные operation-файлы и createApiClient - удалена генерация SWR-хуков и зависимости React/SWR - обновлены CLI, шаблоны, примеры, документация и тесты - версия пакета повышена до 3.0.0
This commit is contained in:
120
README.md
120
README.md
@@ -1,20 +1,21 @@
|
||||
# @gromlab/api-codegen
|
||||
|
||||
CLI утилита для генерации TypeScript API клиента из OpenAPI спецификации.
|
||||
CLI утилита для генерации TypeScript REST-клиента из OpenAPI спецификации.
|
||||
|
||||
## Использование
|
||||
|
||||
```bash
|
||||
npx @gromlab/api-codegen -i <INPUT> -o <OUTPUT> [-n <NAME>] [--swr]
|
||||
npx @gromlab/api-codegen -i <INPUT> -o <OUTPUT> [-n <NAME>] [--mode single|split|both]
|
||||
```
|
||||
|
||||
**Аргументы:**
|
||||
- `-i, --input <path>` - Путь к OpenAPI файлу (локальный файл или URL)
|
||||
- `-o, --output <path>` - Директория для сохранения файлов
|
||||
- `-n, --name <name>` - Имя сгенерированного файла (опционально, по умолчанию из `spec.info.title`)
|
||||
- `--swr` - Генерировать SWR хуки для React
|
||||
- `-i, --input <path>` - путь к OpenAPI файлу или URL
|
||||
- `-o, --output <path>` - директория для сохранения файлов
|
||||
- `-n, --name <name>` - имя монолитного файла без `.ts`
|
||||
- `--mode <mode>` - режим генерации: `single`, `split`, `both` (по умолчанию `single`)
|
||||
- `--single-file` - устаревший алиас для `--mode single`
|
||||
|
||||
**Примеры:**
|
||||
## Примеры
|
||||
|
||||
```bash
|
||||
# Локальный файл
|
||||
@@ -23,33 +24,103 @@ npx @gromlab/api-codegen -i ./openapi.json -o ./src/api
|
||||
# URL на спецификацию
|
||||
npx @gromlab/api-codegen -i https://httpbin.org/spec.json -o ./src/api
|
||||
|
||||
# С кастомным именем файла
|
||||
# Монолитный файл с кастомным именем
|
||||
npx @gromlab/api-codegen -i ./openapi.json -o ./src/api -n MyApi
|
||||
|
||||
# С генерацией SWR хуков
|
||||
npx @gromlab/api-codegen -i ./openapi.json -o ./src/api --swr
|
||||
# Разложенный tree-shaking friendly клиент
|
||||
npx @gromlab/api-codegen -i ./openapi.json -o ./src/api --mode split
|
||||
|
||||
# Монолит и разложенный клиент одновременно
|
||||
npx @gromlab/api-codegen -i ./openapi.json -o ./src/api -n MyApi --mode both
|
||||
```
|
||||
|
||||
## Пример использования сгенерированного кода
|
||||
## Структура вывода
|
||||
|
||||
По умолчанию генерируется legacy монолитный клиент для обратной совместимости:
|
||||
|
||||
```text
|
||||
generated/
|
||||
└── MyApi.ts
|
||||
```
|
||||
|
||||
В режиме `split` генерируется tree-shaking friendly структура:
|
||||
|
||||
```text
|
||||
generated/
|
||||
├── create-api-client.ts
|
||||
├── data-contracts.ts
|
||||
├── http-client.ts
|
||||
├── index.ts
|
||||
└── operations/
|
||||
├── index.ts
|
||||
├── get-users.ts
|
||||
└── create-user.ts
|
||||
```
|
||||
|
||||
Каждый endpoint лежит в отдельном файле внутри `operations/`.
|
||||
|
||||
В режиме `both` генерируются оба варианта рядом.
|
||||
|
||||
## Пример Использования
|
||||
|
||||
Для `single` режима:
|
||||
|
||||
```typescript
|
||||
import { Api, HttpClient } from './src/api/MyApi';
|
||||
import { Api, HttpClient } from './generated/MyApi';
|
||||
|
||||
const httpClient = new HttpClient();
|
||||
httpClient.setSecurityData({ token: 'jwt-token' });
|
||||
const http = new HttpClient({ baseUrl: 'https://api.example.com' });
|
||||
const api = new Api(http);
|
||||
|
||||
const api = new Api(httpClient);
|
||||
const users = await api.users.getAll({});
|
||||
```
|
||||
|
||||
// GET запрос
|
||||
const user = await api.auth.getProfile();
|
||||
Для `split` режима:
|
||||
|
||||
// POST запрос
|
||||
const result = await api.auth.login({ email, password });
|
||||
```typescript
|
||||
import { createApiClient, HttpClient } from './generated';
|
||||
import { getAll } from './generated/operations/get-all';
|
||||
import { create } from './generated/operations/create';
|
||||
|
||||
const http = new HttpClient({
|
||||
baseUrl: 'https://api.example.com',
|
||||
securityWorker: (securityData: { token: string } | null) => {
|
||||
if (!securityData?.token) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
headers: {
|
||||
Authorization: `Bearer ${securityData.token}`,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const api = createApiClient(http, {
|
||||
users: {
|
||||
getAll,
|
||||
create,
|
||||
},
|
||||
});
|
||||
|
||||
const users = await api.users.getAll({});
|
||||
const createdUser = await api.users.create({ email, password });
|
||||
```
|
||||
|
||||
Если нужен максимально точечный импорт, operation можно вызвать напрямую:
|
||||
|
||||
```typescript
|
||||
import { HttpClient } from './generated/http-client';
|
||||
import { getAll } from './generated/operations/get-all';
|
||||
|
||||
const http = new HttpClient();
|
||||
const users = await getAll(http, {});
|
||||
```
|
||||
|
||||
## Разработка
|
||||
|
||||
### Сборка
|
||||
|
||||
```bash
|
||||
bun run build
|
||||
```
|
||||
@@ -57,20 +128,9 @@ bun run build
|
||||
### Тестирование
|
||||
|
||||
```bash
|
||||
# Все тесты
|
||||
bun test
|
||||
|
||||
# Юнит тесты
|
||||
bun run test:unit
|
||||
|
||||
# Интеграционные тесты
|
||||
bun run test:integration
|
||||
|
||||
# Watch режим
|
||||
bun run test:watch
|
||||
|
||||
# С coverage
|
||||
bun run test:coverage
|
||||
```
|
||||
|
||||
Подробная документация по тестированию в [`tests/README.md`](tests/README.md).
|
||||
|
||||
Reference in New Issue
Block a user