chore(wiki): concept openapi-generator 3.1 gotchas (F&F sched 2026-08-18)
This commit is contained in:
66
.wiki/concepts/openapi-generator-3-1-spec-gotchas.md
Normal file
66
.wiki/concepts/openapi-generator-3-1-spec-gotchas.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
title: openapi-generator + OpenAPI 3.1 — gotchas генерации клиентов
|
||||||
|
type: concept
|
||||||
|
tags: [openapi, openapi-generator, codegen, python, sched, ff, api-contract]
|
||||||
|
related: [[sched-fnf-r8-verification-stand]]
|
||||||
|
updated: 2026-08-18
|
||||||
|
---
|
||||||
|
|
||||||
|
# openapi-generator + OpenAPI 3.1 — gotchas
|
||||||
|
|
||||||
|
Проверено вживую на F&F-раунде sched «клиент на любом ЯП одной командой»
|
||||||
|
(2026-08-18): Python-клиент из `@sched/admin-api@0.1.2` спеки (3.1.0, 15 путей)
|
||||||
|
через `openapi-generator` **7.24.0** (`-g python`, pydantic v2). Спеку НЕ чинили
|
||||||
|
(их импл, TDD) — обходили. Находки F-1..F-5 полные — в
|
||||||
|
`sched/.agents/inbox/2026-08-18T19-15-43Z-admin-fnf-openapi-client-report.md`;
|
||||||
|
здесь — переиспользуемая суть.
|
||||||
|
|
||||||
|
## Гоча 1 — ответы `{}` в спеке ломают десериализацию (главная)
|
||||||
|
|
||||||
|
Если операция объявляет ответ `{}` (пустая схема), а сервер реально отдаёт
|
||||||
|
объект (`{task: …}`, `{run: …}`, `{schedule: …}`, `{logChunk, logTotalLength}`),
|
||||||
|
сгенерированный клиент валится на **pydantic ValidationError** — он пытается
|
||||||
|
десериализовать wrapped-тело в объявленную модель, а требуемых полей на верхнем
|
||||||
|
уровне нет (все None).
|
||||||
|
|
||||||
|
- Симптом: `ValidationError` на 2xx с полями `input_value=None`.
|
||||||
|
- Фикс (у имплементера спеки): объявлять реальные схемы ответов
|
||||||
|
(`{task: TaskRecord}` и т.п.). Без этого ни один генератор не даёт рабочий клиент.
|
||||||
|
- Обход (у потребителя): raw-транспорт + ручная валидация:
|
||||||
|
```python
|
||||||
|
resp = client.call_api("POST", client.configuration.host + "/tasks", body=body)
|
||||||
|
data = json.loads(resp.read()) # resp.data может быть None до read()
|
||||||
|
rec = TaskRecord.model_validate(data["task"])
|
||||||
|
```
|
||||||
|
Важно: в raw-вызове `call_api` **НЕ делает snake→camel конвертацию** запроса —
|
||||||
|
сериализуй через `model_dump(exclude_none=True, by_alias=True)`.
|
||||||
|
|
||||||
|
## Гоча 2 — `const: true` компилится в строковый enum
|
||||||
|
|
||||||
|
`"ok": { "type": "boolean", "const": true }` → openapi-generator генерит
|
||||||
|
`enum ('true')` со СТРОКОВЫМ значением → настоящий `true` (boolean) не проходит
|
||||||
|
валидацию. Убирать `const` из схемы или не использовать его на булевых полях.
|
||||||
|
|
||||||
|
## Гоча 3 — oneOf + discriminator не десериализуется
|
||||||
|
|
||||||
|
`Schedule` (kind: cron|interval|once, oneOf + discriminator) в сгенерированной
|
||||||
|
модели приходит с `actual_instance=None` — правило (`cron`) недостижимо через
|
||||||
|
модель, только через raw JSON: `raw["schedule"]["schedule"]["cron"]`.
|
||||||
|
Касается любого oneOf+discriminator на этой версии генератора (3.1-ветка).
|
||||||
|
|
||||||
|
## Окружение (Windows)
|
||||||
|
|
||||||
|
- `openapi-generator` 7.x требует **Java 11+**: системная Java 8 падает на
|
||||||
|
class-load; ставь `JAVA_HOME` на новый JDK (Temurin 25 работает).
|
||||||
|
Запуск: `npx --yes @openapitools/openapi-generator-cli generate -i spec.json -g python -o out --additional-properties=packageName=...`
|
||||||
|
- Windows excluded port ranges (Hyper-V/WinNAT) резервируют порты (напр. 8090/8091):
|
||||||
|
`EACCES` на listen. Проверка: `netsh interface ipv4 show excludedportrange protocol=tcp`.
|
||||||
|
- Консоль cp1251: не печатай `→`/`«»` в скриптах — `'charmap' codec can't encode`; ASCII-only.
|
||||||
|
|
||||||
|
## Паттерн обхода (потребитель, клиент не трогаем)
|
||||||
|
|
||||||
|
Тонкий raw-слой рядом с сгенерированным пакетом (в примере — `raw_ops.py`):
|
||||||
|
только операции, где спека `{}`, через `call_api`; остальное — через типизированный
|
||||||
|
клиент. Сгенерированный пакет остаётся перегенерируемым.
|
||||||
|
|
||||||
|
Пример целиком: `sched/examples/admin-client-python/` (24/24 сьют, 19/19 smoke).
|
||||||
@@ -21,6 +21,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
|
|||||||
- [windows-recovery-host](entities/windows-recovery-host.md) — Windows Recovery Host (рабочий PC пользователя)
|
- [windows-recovery-host](entities/windows-recovery-host.md) — Windows Recovery Host (рабочий PC пользователя)
|
||||||
|
|
||||||
## Concepts
|
## Concepts
|
||||||
|
- [openapi-generator-3-1-spec-gotchas](concepts/openapi-generator-3-1-spec-gotchas.md) — генерация клиентов из 3.1-спеки (openapi-generator 7.24.0, python): ответы `{}` + wrapped-тело → ValidationError (raw-обход + by_alias), `const:true` → строковый enum, oneOf+discriminator → actual_instance=None, Java 11+, Windows excluded-порты
|
||||||
- [nvm-junction-ismain-gate-gotcha](concepts/nvm-junction-ismain-gate-gotcha.md) — ESM isMain-гейт молча не выполняется под junction'нутым npm-рутом (nvm/mise/volta); realpath-фикс; диагностика за 30 сек
|
- [nvm-junction-ismain-gate-gotcha](concepts/nvm-junction-ismain-gate-gotcha.md) — ESM isMain-гейт молча не выполняется под junction'нутым npm-рутом (nvm/mise/volta); realpath-фикс; диагностика за 30 сек
|
||||||
- [nvm-windows-node-switch](concepts/nvm-windows-node-switch.md) — смена версии Node на nvm-windows: junction, per-version глобалы, PATH-кэш, npm 11 allow-scripts; Node 22→24 evidence
|
- [nvm-windows-node-switch](concepts/nvm-windows-node-switch.md) — смена версии Node на nvm-windows: junction, per-version глобалы, PATH-кэш, npm 11 allow-scripts; Node 22→24 evidence
|
||||||
- [sched-fnf-r8-verification-stand](concepts/sched-fnf-r8-verification-stand.md) — стенд верификации F&F r8 (schedule-as-entity): путь, версии core 0.40.2/ui 0.2.0, карта репро-скриптов (миграции/движок/политики/API 52/UI 13), подтверждённый контракт (ceiling, retryCount, snapshot, pause AND, tz-hoist, PATCH-merge), находки №5 (U1 форма-tz, U2 вёрстка), как закрыть раунд
|
- [sched-fnf-r8-verification-stand](concepts/sched-fnf-r8-verification-stand.md) — стенд верификации F&F r8 (schedule-as-entity): путь, версии core 0.40.2/ui 0.2.0, карта репро-скриптов (миграции/движок/политики/API 52/UI 13), подтверждённый контракт (ceiling, retryCount, snapshot, pause AND, tz-hoist, PATCH-merge), находки №5 (U1 форма-tz, U2 вёрстка), как закрыть раунд
|
||||||
|
|||||||
@@ -135,3 +135,4 @@ Append-only log of wiki operations (ingests, promotions, lints, migrations).
|
|||||||
|
|
||||||
## [2026-08-18] ingest | UPDATE concepts/sched-fnf-r8-verification-stand.md — сессия №4/№5: admin-api-test.mjs (52/52, F1 tz-hoist + F3 PATCH-merge подтверждены на core 0.40.2), UI-стенд ui-backend.mjs + sched-ui serve :8081 + браузерный CDP (13/13), находки U1 (форма-tz interval/once → 400) и U2 (таблица шире контейнера ~58px). index.md hook обновлён.
|
## [2026-08-18] ingest | UPDATE concepts/sched-fnf-r8-verification-stand.md — сессия №4/№5: admin-api-test.mjs (52/52, F1 tz-hoist + F3 PATCH-merge подтверждены на core 0.40.2), UI-стенд ui-backend.mjs + sched-ui serve :8081 + браузерный CDP (13/13), находки U1 (форма-tz interval/once → 400) и U2 (таблица шире контейнера ~58px). index.md hook обновлён.
|
||||||
## [2026-08-18] ingest | NEW concepts/nvm-junction-ismain-gate-gotcha.md — ESM isMain-гейт молча no-op под junction-префиксом npm-рута (C:\nvm4w\nodejs → realpath …\nvm\v22.22.0): import.meta.url резолвится в realpath, argv[1] держит литеральный → main() не выполняется, exit 0. Бьёт global-install под любым version-manager'ом (nvm/mise/volta). Фикс realpath-сравнения (sched bd38aab, daemon 0.3.2). NEW concepts/nvm-windows-node-switch.md — Node 22→24.19.0 рецепт: junction-свап, per-version глобалы, PATH-кэш shell'а, npm 11 allow-scripts. Оба из сессии CLI-F&F sched 2026-08-18. index.md updated (+2).
|
## [2026-08-18] ingest | NEW concepts/nvm-junction-ismain-gate-gotcha.md — ESM isMain-гейт молча no-op под junction-префиксом npm-рута (C:\nvm4w\nodejs → realpath …\nvm\v22.22.0): import.meta.url резолвится в realpath, argv[1] держит литеральный → main() не выполняется, exit 0. Бьёт global-install под любым version-manager'ом (nvm/mise/volta). Фикс realpath-сравнения (sched bd38aab, daemon 0.3.2). NEW concepts/nvm-windows-node-switch.md — Node 22→24.19.0 рецепт: junction-свап, per-version глобалы, PATH-кэш shell'а, npm 11 allow-scripts. Оба из сессии CLI-F&F sched 2026-08-18. index.md updated (+2).
|
||||||
|
## [2026-08-18] ingest | NEW concepts/openapi-generator-3-1-spec-gotchas.md — из F&F openapi-client sched (2026-08-18): генерация Python-клиента из 3.1-спеки openapi-generator 7.24.0. Гочи: (1) ответы `{}` в спеке + wrapped-тело ({task/run/schedule:…}) → pydantic ValidationError, фикс — реальные схемы ответов, обход raw-транспорт + by_alias=True; (2) `const:true` → строковый enum ('true') ломает boolean; (3) oneOf+discriminator → actual_instance=None, контент только через raw JSON; Java 11+ обязателен (системная 8 падает), Windows excluded-порты 8090/8091 (EACCES), консоль cp1251 без →/«». Полные находки F-1..F-5: sched/.agents/inbox репорт 19:15Z; пример sched/examples/admin-client-python (24/24). index.md updated.
|
||||||
|
|||||||
Reference in New Issue
Block a user