Platform
    • RTK Query
    • Mock Server (MSW)
    • Data Converters
    • OpenAPI Codegen
Projects
  • API Connections & Tools
  1. Documentation
  2. Documentation

OpenAPI → T*Backend

Строгий пайплайн: сырые типы остаются в generated/backend.types.ts; домен видит только T*Backend из entities/*/types.

Codegen и изоляция типов

Правило: Не импортируйте schema OpenAPI в converters или api. Один раз алиасьте в T*Backend, затем мапьте во frontend-модели.

011. Скрипты codegen

openapi.steps.scripts.description
package.json
1{ 2 "scripts": { 3 "codegen:types": "tsx --env-file=.env scripts/generate-api-types.ts", 4 "codegen:paths": "tsx --env-file=.env scripts/generate-api-paths.ts", 5 "codegen": "npm run codegen:types && npm run codegen:paths" 6 } 7}
scripts/generate-api-types.ts
1/** 2 * Генерация TypeScript-типов из OpenAPI-спецификации. 3 * npx tsx --env-file=.env scripts/generate-api-types.ts 4 */ 5import { dirname, join, resolve } from "path"; 6import { fileURLToPath } from "url"; 7import { generateApi } from "swagger-typescript-api"; 8 9const __dirname = dirname(fileURLToPath(import.meta.url)); 10const API_URL = process.env.VITE_BASE_URL; 11const OUTPUT_DIR = join(resolve(__dirname, ".."), "src/shared/api/generated"); 12 13const SPEC_URL = API_URL.endsWith("/openapi.json") 14 ? API_URL 15 : `${API_URL.replace(/\/$/, "")}/openapi.json`; 16 17await generateApi({ 18 fileName: "backend.types.ts", 19 output: OUTPUT_DIR, 20 url: SPEC_URL, 21 generateClient: false, 22 extractEnums: true, 23 extractRequestParams: true, 24 extractRequestBody: true 25}); 26
scripts/generate-api-paths.ts (excerpt)
1/** 2 * Группирует OpenAPI paths по tags → paths/<tag>.paths.ts 3 * Каждый entry: { url, method, _types: { body, query, response } } 4 * npx tsx --env-file=.env scripts/generate-api-paths.ts 5 */ 6// См. полный скрипт в blogix-admin / MCP openapi-pattern.md 7// Итог: 8export const ADMIN_PROMOCODE_PATHS = { 9 readPromocodes: { 10 url: "/adv-admin/promocode/list", 11 method: "POST", 12 _types: {} as { 13 body: ReadPromocodesRequest; 14 query: void; 15 response: ReadPromocodesResponse; 16 } 17 } as const 18} as const; 19

022. Адаптер T*Backend

Только entities/*/types/*-backend.interface.ts может импортировать generated/backend.types. Экспортируйте алиасы TFooBackend (и re-export enum).
entities/[entity]/types/[entity]-backend.interface.ts
1// entities/promocode/types/promocode-backend.interface.ts 2// ЕДИНСТВЕННОЕ место импорта schema из backend.types.ts 3import type { 4 CreatePromocodeRequest, 5 PromocodeDiscountType, 6 PromocodeResponse, 7 ReadPromocodesResponse 8} from "@/shared/api/generated/backend.types"; 9import { ADMIN_PROMOCODE_PATHS } from "@/shared/api/generated/paths/admin-promocode.paths"; 10 11export type TPromocodeBackend = PromocodeResponse; 12export type TPromocodesBackend = ReadPromocodesResponse; 13export type TCreatePromocodeRequestBackend = CreatePromocodeRequest; 14export type TSetPromocodeActiveQueryBackend = 15 typeof ADMIN_PROMOCODE_PATHS.setPromocodeActive._types.query; 16 17export { PromocodeDiscountType }; 18export type TPromocodeDiscountTypeBackend = PromocodeDiscountType; 19

033. converters / api

Берите T*Backend и enum из ../types. PATHS разрешены в api/handlers. Прямой backend.types.ts — запрещён.
converters — OK
1// entities/promocode/converters/promocode.converters.ts — OK 2import type { TPromocodeBackend } from "../types"; 3import { PromocodeDiscountType } from "../types"; 4 5export const mapPromocodeToFrontend = (data: TPromocodeBackend) => ({ 6 id: data.id, 7 code: data.code 8 // … 9}); 10
converters / api — FORBIDDEN
1// ❌ FORBIDDEN in converters / api / handlers / UI 2import type { PromocodeResponse } from "@/shared/api"; 3import { OrderStatus } from "@/shared/api/generated/backend.types"; 4

044. ESLint gate

Ограничьте generated/backend.types глобально; разрешите только в entities/**/types и shared/api/generated. Лучше не реэкспортировать backend.types из @/shared/api.
eslint.config.js
1// eslint.config.js — fragment 2{ 3 rules: { 4 "no-restricted-imports": [ 5 "error", 6 { 7 patterns: [ 8 { 9 group: [ 10 "**/shared/api/generated/backend.types", 11 "**/shared/api/generated/backend.types.ts", 12 "@/shared/api/generated/backend.types" 13 ], 14 message: 15 "Raw backend.types.ts types only in entities/*/types as T*Backend. Use ../types aliases elsewhere." 16 } 17 ] 18 } 19 ] 20 } 21}, 22{ 23 files: [ 24 "src/entities/**/types/**/*.{ts,tsx}", 25 "src/shared/api/generated/**/*.{ts,tsx}" 26 ], 27 rules: { "no-restricted-imports": "off" } 28} 29