fix: ослаблена валидация content-type при загрузке спецификации по URL

- убрана строгая проверка content-type (ломала GitHub raw и другие серверы)
- вместо неё парсинг JSON с понятной ошибкой при невалидном ответе
- обновлён README: только npx, добавлен флаг --swr
- версия 1.0.7
This commit is contained in:
2026-04-01 19:21:34 +03:00
parent 2557568b5e
commit 961c7f0ec1
3 changed files with 42 additions and 63 deletions

View File

@@ -1,42 +1,39 @@
# API CodeGen
# @gromlab/api-codegen
CLI утилита для генерации TypeScript API клиента из OpenAPI спецификации.
## Установка
```bash
bun install
```
## Использование
```bash
api-codegen -u <URL> -i <INPUT> -o <OUTPUT> [-n <NAME>]
npx @gromlab/api-codegen -i <INPUT> -o <OUTPUT> [-n <NAME>] [--swr]
```
**Аргументы:**
- `-u, --url <url>` - Базовый URL API
- `-i, --input <path>` - Путь к OpenAPI файлу (локальный или URL)
- `-i, --input <path>` - Путь к OpenAPI файлу (локальный файл или URL)
- `-o, --output <path>` - Директория для сохранения файлов
- `-n, --name <name>` - Имя сгенерированного файла (опционально)
- `-n, --name <name>` - Имя сгенерированного файла (опционально, по умолчанию из `spec.info.title`)
- `--swr` - Генерировать SWR хуки для React
**Примеры:**
```bash
# Локальный файл
api-codegen -u https://api.example.com -i ./openapi.json -o ./src/api
npx @gromlab/api-codegen -i ./openapi.json -o ./src/api
# URL на спецификацию
api-codegen -u https://api.example.com -i https://petstore.swagger.io/v2/swagger.json -o ./src/api
npx @gromlab/api-codegen -i https://httpbin.org/spec.json -o ./src/api
# С кастомным именем файла
api-codegen -u https://api.example.com -i ./openapi.json -o ./src/api -n MyApiClient
npx @gromlab/api-codegen -i ./openapi.json -o ./src/api -n MyApi
# С генерацией SWR хуков
npx @gromlab/api-codegen -i ./openapi.json -o ./src/api --swr
```
## Пример использования
## Пример использования сгенерированного кода
```typescript
import { Api, HttpClient } from './src/api/Api';
import { Api, HttpClient } from './src/api/MyApi';
const httpClient = new HttpClient();
httpClient.setSecurityData({ token: 'jwt-token' });
@@ -48,12 +45,6 @@ const user = await api.auth.getProfile();
// POST запрос
const result = await api.auth.login({ email, password });
// React + SWR
function Profile() {
const { data } = useSWR('/auth/me', () => api.auth.getProfile());
return <div>{data?.email}</div>;
}
```
## Разработка
@@ -65,49 +56,24 @@ bun run build
### Тестирование
Проект использует комплексную систему тестирования с максимальным покрытием (~72 тестовых кейса).
**Запуск всех тестов:**
```bash
# Все тесты
bun test
# Юнит тесты
bun run test:unit
# Интеграционные тесты
bun run test:integration
# Watch режим
bun run test:watch
# С coverage
bun run test:coverage
```
**Только юнит тесты:**
```bash
bun test:unit
```
**Только интеграционные тесты:**
```bash
bun test:integration
```
**Watch режим:**
```bash
bun test:watch
```
**С coverage:**
```bash
bun test:coverage
```
Подробная документация по тестированию доступна в [`tests/README.md`](tests/README.md).
### Структура тестов
- **Юнит тесты** - CLI, генератор, утилиты, валидация
- **Интеграционные тесты** - E2E генерация, сгенерированный клиент
- **Тестовые фикстуры** - 7 OpenAPI спецификаций для различных сценариев
- **Mock сервер** - для тестирования HTTP запросов
**Покрываемые сценарии:**
- ✅ CLI команды и обработка ошибок
- ✅ Генерация TypeScript кода
- ✅ Компиляция сгенерированного кода
- ✅ HTTP запросы с mock сервером
- ✅ Аутентификация (Bearer tokens)
- ✅ Edge cases (Unicode, большие спецификации)
Подробная документация по тестированию в [`tests/README.md`](tests/README.md).
## Лицензия

View File

@@ -1,6 +1,6 @@
{
"name": "@gromlab/api-codegen",
"version": "1.0.5",
"version": "1.0.7",
"description": "CLI tool to generate TypeScript API client from OpenAPI specification",
"type": "module",
"bin": {

View File

@@ -33,7 +33,20 @@ export async function generate(config: GeneratorConfig): Promise<void> {
url = config.inputPath;
// Загружаем спецификацию для получения info.title
const response = await fetch(url);
spec = await response.json();
if (!response.ok) {
throw new Error(
`Failed to fetch OpenAPI spec from ${url}: ${response.status} ${response.statusText}`
);
}
const text = await response.text();
try {
spec = JSON.parse(text);
} catch {
throw new Error(
`Failed to parse OpenAPI spec from ${url} as JSON. ` +
`Response starts with: "${text.slice(0, 50)}..."`
);
}
} else {
inputPath = resolve(config.inputPath);
spec = await readJsonFile<any>(inputPath);