Skip to content

Latest commit

 

History

History
61 lines (45 loc) · 4.12 KB

File metadata and controls

61 lines (45 loc) · 4.12 KB

Что здесь ждёт генератора

Контракт первичен: источник истины — main.tsp, из него компилируются документы OpenAPI в openapi/, из них @hey-api/openapi-python генерирует pydantic-модели в app/types/handlers/. Генератор молодой (0.0.x), и часть работы, которую в TypeScript-версии он делает сам, здесь пока сделана руками. Ниже — что именно и на что это заменится.

Регистрация маршрутов написана своя

У TypeScript-версии есть серверный плагин: он вешает маршруты по спеке и типизирует обработчики полным набором операций контракта. У python-генератора такого плагина пока нет, поэтому регистрация написана в app/glue.py: он читает контракт, связывает операции с обработчиками по идентификатору и берёт оттуда же код успеха, описание и авторизацию.

Свойства при этом те же, что дал бы плагин: забытая операция роняет приложение на старте, лишняя — тоже, а авторизацию негде забыть, потому что обработчик про неё не знает.

Чего этот регистратор не даёт: обработчики не типизированы набором операций, то есть неверная сигнатура ловится не проверкой типов, а прогоном.

Когда появится серверный плагин: app/glue.py удаляется целиком, а регистрация берётся из сгенерированного.

Тесты ходят напрямую, а не через сгенерированный клиент

TypeScript-версия шлёт корректные запросы сгенерированным клиентом: контракт, который клиент не даёт выразить, тест выразить и не может. Python-генератор SDK пока печатает заглушки: метод объявлен без параметров, а в путь не подставляется {user_id}. Поэтому тесты ходят через httpx.

Когда SDK доделают: корректные запросы переезжают на него, а через httpx остаются те, что контракт нарушают намеренно.

Необязательное поле и обнуляемое поле не различаются

Генератор печатает любое необязательное поле контракта как Optional[...], поэтому модель принимает null там, где контракт его не разрешает. Для колонок NOT NULL это 500 на запросе, который схема пропустила.

Разница берётся из самого контракта в app/lib/changes.py: список обнуляемых полей читается из документа, и null в остальных отбивается как ошибка запроса.

Когда генератор научится различать: changes() сводится к model_dump(exclude_unset=True).

Пароль приходит обычной строкой

@secret в контракте превращается в format: password и writeOnly, но в модели это str, а не SecretStr: значение попадает в повторение объекта при отладке.

Когда генератор начнёт печатать SecretStr: правка сведётся к перегенерации.