Перейти к основному содержимому

@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
CreateAssetDtozCreateAssetDto
TransferAssetDtozTransferAssetDto
CreatePersonnelDtozCreatePersonnelDto
*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
Code-референс схем

Полного 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
Tree-shaking

Пакет помечен 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.

Ссылки