Platform
    • FSD Layers
    • Import Boundaries
    • Entity Structure
    • Widget Structure
    • Project Structure
    • Shared Patterns
Projects
  • API Connections & Tools
  1. Documentation
  2. Documentation

Предметная область (Entities)

Сущности — это базовые бизнес-единицы проекта. Данный раздел описывает унифицированную структуру любой сущности, основанную на строгих архитектурных правилах.

01Файловая структура

Структура слоя Entities

Каждая бизнес-сущность внутри src/entities/* обязана следовать жестко-заданной директориальной структуре для изоляции логики и UI.

03Детальное описание модулей

/api

Отвечает исключительно за сетевое взаимодействие с backend-приложением в рамках одной сущности. Принимает аргументы для запроса и возвращает сырые DTO, которые затем обязательно передаются в конвертеры.

Изучить архитектуру RTK Query
api/booking-order.service.ts
1import { authApi } from "@/entities/auth/api/auth.api"; 2 3export const bookingOrderApi = authApi.injectEndpoints({ 4 endpoints: (builder) => ({ 5 getBookingOrders: builder.query<TResponse, TFilters>({ 6 query: (filters) => ({ url: "/booking/orders" }), 7 providesTags: [ENUM_API_TAGS.BOOKING_ORDERS] 8 }) 9 }) 10});

/converters

Мапперы данных. Превращают сырой DTO от сервера в удобную Domain Model. Это изолирует UI-компоненты от внезапных изменений контрактов бекенда.

converters/booking-order.converters.ts
1export const mapBookingOrderToFrontend = (data: IBookingOrderBackend): IOrder => ({ 2 orderId: data.order_id, 3 orderType: data.order_type as ENUM_ORDER_TYPE_OPTIONS_TYPE, 4 dateCreated: formatDate(data.date_created), 5 client: data.client, 6 status: data.status as ENUM_ORDER_STATUS_TYPE 7}); 8 9export const mapBookingOrderToBackend = (data: Partial<IOrderDetail>): Partial<IBookingOrderDetailBackend> => ({ 10 order_id: data.orderId, 11 order_type: data.orderType, 12 date_created: data.dateCreated, 13 client: data.client, 14 status: data.status 15});

/handlers

Обработчики MSW (Mock Service Worker). Используются для перехвата сетевых вызовов во время разработки и в интеграционных тестах (Vitest / RTL).

handlers/booking-order.handlers.ts
1import { HttpResponse, http } from "msw"; 2import { ENV } from "@/shared/config"; 3import { BOOKING_ORDERS_MOCK } from "../mock"; 4 5export const bookingOrderHandlers = [ 6 http.get(`${ENV.VITE_API_URL}/booking/orders`, ({ request }) => { 7 const url = new URL(request.url); 8 return HttpResponse.json({ 9 data: [...BOOKING_ORDERS_MOCK], 10 total: BOOKING_ORDERS_MOCK.length 11 }); 12 }), 13 http.get(`${ENV.VITE_API_URL}/booking/orders/:id`, ({ params }) => { 14 const order = BOOKING_ORDERS_MOCK.find((o) => o.orderId === params.id); 15 if (!order) return new HttpResponse(null, { status: 404 }); 16 return HttpResponse.json(order); 17 }) 18];

/mock

Статические фикстуры и фейковые данные (mock data), используемые для эмуляции ответа сервера в связке с MSW handlers или для Storybook.

mock/booking-order.mock.ts
1import type { IOrderDetail } from "../types"; 2 3export const BOOKING_ORDERS_MOCK: IOrderDetail[] = [ 4 { 5 orderId: "ORD-001", 6 orderType: "individual", 7 dateCreated: "2024-03-15T12:00:00Z", 8 client: "John Doe", 9 pax: 2, 10 dates: { from: "2024-04-01", to: "2024-04-10" }, 11 status: "CONFIRMED", 12 // ... full fields 13 } 14];

/schema

Single Source of Truth для типов данных сущности. Содержит Zod-объекты со встроенной интернационализацией (i18n) ошибок.

schema/order.schema.ts
1import { z } from "zod"; 2import { i18nKey } from "@/shared/config"; 3 4const msg = i18nKey<TBookingOrderKeys>(); 5 6export const BOOKING_ORDER_SCHEMA = z.object({ 7 client: z.string().min(1, { message: msg("errors.client.required") }), 8 status: z.enum(["PENDING", "CONFIRMED"]), 9 pax: z.number().min(1) 10}); 11 12export type TBookingOrderSchema = z.infer<typeof BOOKING_ORDER_SCHEMA>;

/slice

Хранит локальное состояние сущности (UI-слой), не связанное с кэшом сервера. Например: текущий выбранный элемент.

slice/order.slice.ts
1import { createSlice, PayloadAction } from "@reduxjs/toolkit"; 2 3interface IOrderSliceState { 4 selectedOrderId: string | null; 5} 6 7const initialState: IOrderSliceState = { 8 selectedOrderId: null 9}; 10 11export const orderSlice = createSlice({ 12 name: "bookingOrder", 13 initialState, 14 reducers: { 15 setSelectedOrder: (state, action: PayloadAction<string>) => { 16 state.selectedOrderId = action.payload; 17 } 18 } 19});

/ui

Набор "глупых" (dumb) компонентов отображения, привязанных к данной сущности. Не содержат логики запросов.

ui/order-card.tsx
1interface IOrderCardProps { 2 order: IOrder; 3 onSelect: (id: string) => void; 4} 5 6export const OrderCard = ({ order, onSelect }: IOrderCardProps) => ( 7 <Card onClick={() => onSelect(order.orderId)}> 8 <CardHeader>{order.client}</CardHeader> 9 <CardContent>Pax: {order.pax}</CardContent> 10 </Card> 11);

/types

Каталог TypeScript интерфейсов, описывающих сущность. Подразделяется на *.interface.ts и *.types.ts.

types/order.interface.ts
1export interface IOrderDates { 2 from: string; 3 to: string; 4} 5 6export interface IOrder { 7 orderId: string; 8 orderType: ENUM_ORDER_TYPE_OPTIONS_TYPE; 9 dateCreated: string; 10 client: string; 11 pax: number; 12 dates: IOrderDates; 13 status: ENUM_ORDER_STATUS_TYPE; 14}