@mineflow/api-zod
Zod-схемы запросов и ответов MineFlow, сгенерированные из OpenAPI (@hey-api/openapi-ts, zod-плагин). Это слой L0 в многослойной архитектуре SDK (ADR-0042): чистые данные без рантайма, без серверных зависимостей, browser/RN-safe (только import * as z from 'zod').
Назначение — instant-валидация форм на клиенте теми же правилами, что у бэка, без ручного дублирования. Схемы выводятся из той же apps/api/openapi.json, что и типы @mineflow/api-client, поэтому при изменении DTO на бэке они регенерируются, а CI drift-gate валит PR, в котором они разошлись со спекой. Один источник истины — серверный DTO; на фронте — codegen, не копия.
В 95% случаев фронтенд использует api-zod в паре с @mineflow/client-react (хуки-мутации) и @hookform/resolvers. Общий обзор слоёв — в каноническом гайде по SDK.
Установка
pnpm add @mineflow/api-zod
pnpm add zod # peer-зависимость
Единственная peer-зависимость пакета — zod ^4.0.0 (пакет на zod v4). Для типичного сценария форм добавь react-hook-form и резолвер:
pnpm add react-hook-form @hookform/resolvers
В монорепо MineFlow пакет резолвится как workspace:*.
Именование схем
Каждая схема экспортируется под именем z<ИмяDto> — префикс z + имя DTO ровно так, как оно называется в OpenAPI / контроллере на бэке:
| Бэкенд DTO | Схема в @mineflow/api-zod |
|---|---|
CreateAssetDto | zCreateAssetDto |
TransferAssetDto | zTransferAssetDto |
CreatePersonnelDto | zCreatePersonnelDto |
*Output (ответы) | z*Output |
Зная имя DTO, ты знаешь имя схемы — добавь z спереди.
Использование
react-hook-form
Самый частый сценарий — передать схему в zodResolver и валидировать форму на лету:
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { zCreateAssetDto } from '@mineflow/api-zod';
import { useRegisterAsset } from '@mineflow/client-react';
function RegisterAssetForm() {
const form = useForm({ resolver: zodResolver(zCreateAssetDto) });
const register = useRegisterAsset();
const onSubmit = form.handleSubmit((values) => register.mutate(values));
return (
<form onSubmit={onSubmit}>
<input {...form.register('inventoryNumber')} />
{form.formState.errors.inventoryNumber && <span>Формат: BG-001</span>}
{/* остальные поля */}
</form>
);
}
Ручная проверка через safeParse
Схемы — это обычные объекты zod, поэтому доступен весь API zod (safeParse, parse, .shape, инференс типа через z.infer):
import { zCreateAssetDto } from '@mineflow/api-zod';
const result = zCreateAssetDto.safeParse(input);
if (!result.success) {
console.log(result.error.issues); // [{ path, message, code }]
}
Ключевые экспорты
Пакет — это единственный re-export сгенерированного файла:
export * from './generated/zod.gen';
Конкретных именованных API (функций/классов/хуков) у пакета нет — только 900+ схем вида z<ИмяDto>. Перечислять их здесь нет смысла; вместо этого ищи нужную:
- Автокомплит IDE — начни печатать
z…после импорта из@mineflow/api-zod, и редактор подскажет все доступные схемы. - grep по сгенерированному файлу:
grep "export const z" node_modules/@mineflow/api-zod/src/generated/zod.gen.ts
Полного TypeDoc по api-zod нет (это генерат). Каждая схема 1:1 соответствует DTO в OpenAPI — смотри поля, типы, required, min/max, enum и форматы в REST-референсе → /rest/.
Подводные камни и важные правила
api-zod выводится из OpenAPI и проверяет только то, что в OpenAPI выразимо: типы, required, min/max, regex, enum, формат. Кастомные .refine() бэка в OpenAPI не попадают и в схему НЕ переносятся. Это касается, в частности:
- cross-field правил (например «
consumed ≤ issued»), - checksum ИИН/БИН,
- ограничений вроде «
commissionedAtне в будущем».
Финально такие правила проверяет сервер и при нарушении возвращает 422, который SDK отдаст как MineflowApiError с code и detail.errors. То есть: instant-валидация формы = api-zod, окончательная — сервер. Не считай прохождение safeParse гарантией, что бэк примет запрос — обрабатывай серверные ошибки. Это осознанный trade-off codegen-подхода против re-export серверных createZodDto-файлов (ADR-0042).
Как ловить и гейтить 422 по стабильному error.code — рецепт Ошибки и коды.
src/generated/zod.gen.ts закоммичен и находится под blocking CI drift-gate: спека регенерируется из live-OpenAPI и сравнивается через git diff. Любая ручная правка либо будет затёрта при следующей регенерации, либо завалит CI. Менять можно только источник (серверный DTO) → затем регенерировать.
Регенерация
pnpm openapi:zod # apps/api/openapi.json → packages/api-zod/src/generated/zod.gen.ts
Пакет помечен sideEffects: false. Импортируй только нужные схемы — остальные 900+ бандлер выкинет из сборки.
React Native
Дополнительная настройка не нужна: пакет содержит только import * as z from 'zod' — никаких серверных или web-only зависимостей, поэтому он работает в React Native «как есть». Тот же zodResolver(z…) + react-hook-form применим в RN-формах без изменений.
Общие RN-нюансы остального SDK (token-provider, generateId, потоковый SSE через fetchImpl) — в рецепте React Native.
Ссылки
- Полный API-референс из кода (поля DTO-схем) → /rest/
- Типы тех же DTO (zero-runtime) —
@mineflow/api-client - FSM-машины и status-энумы —
@mineflow/api-schemas - Хуки-мутации, в которые уходят валидированные значения —
@mineflow/client-react - Рецепты: Формы и валидация · Ошибки и коды · Кодген из OpenAPI · React Native