- Добавлена документация SLM-архитектуры, базовых правил и прикладных разделов - Добавлены разделы: стили, SVG-спрайты, шаблоны генерации, PostCSS, REST, Realtime - Удалены устаревшие файлы (спрайты, скрипты, стили из app/)
122 lines
3.9 KiB
Markdown
122 lines
3.9 KiB
Markdown
---
|
|
title: Business-композиция
|
|
description: Когда REST-данные нужно объединить или интерпретировать в бизнес-модуле.
|
|
keywords: [rest, business, композиция, hooks, domain, isAuth]
|
|
---
|
|
|
|
# Business-композиция
|
|
|
|
Business-композиция используется, когда простого GET-метода или прозрачного GET-хука недостаточно: нужно объединить несколько источников, преобразовать DTO или вычислить доменное состояние.
|
|
|
|
## Когда использовать
|
|
|
|
- Нужно объединить несколько GET-запросов.
|
|
- Нужно вычислить `isAuth`, `canEdit`, `hasAccess`, `hasPets`.
|
|
- Нужно преобразовать DTO в доменную модель.
|
|
- Нужно спрятать бизнес-сценарий за доменным API.
|
|
|
|
Такая логика не пишется в `infrastructure/`. REST-клиент остаётся прозрачным адаптером к API.
|
|
|
|
## Пример поверх одного GET-хука
|
|
|
|
```ts
|
|
// src/business/pets/hooks/use-available-pets.hook.ts
|
|
import { useGetPetList } from 'infrastructure/pet-store-api'
|
|
|
|
/**
|
|
* Доменный список доступных питомцев.
|
|
*/
|
|
export const useAvailablePets = () => {
|
|
const query = useGetPetList('available')
|
|
|
|
return {
|
|
...query,
|
|
hasPets: Boolean(query.data?.length),
|
|
}
|
|
}
|
|
```
|
|
|
|
`useGetPetList` — infrastructure-хук. `hasPets` — бизнес-интерпретация, поэтому она появляется в `business/pets`.
|
|
|
|
## Пример композиции нескольких GET-хуков
|
|
|
|
```ts
|
|
// src/business/pets/hooks/use-pets-dashboard.hook.ts
|
|
import { useGetPetList } from 'infrastructure/pet-store-api'
|
|
|
|
/**
|
|
* Данные dashboard по питомцам.
|
|
*/
|
|
export const usePetsDashboard = () => {
|
|
const availablePets = useGetPetList('available')
|
|
const pendingPets = useGetPetList('pending')
|
|
const soldPets = useGetPetList('sold')
|
|
|
|
return {
|
|
availablePets,
|
|
pendingPets,
|
|
soldPets,
|
|
total:
|
|
(availablePets.data?.length ?? 0) +
|
|
(pendingPets.data?.length ?? 0) +
|
|
(soldPets.data?.length ?? 0),
|
|
}
|
|
}
|
|
```
|
|
|
|
Композиция нескольких запросов не добавляется в `infrastructure/pet-store-api/hooks/`, потому что это уже сценарий потребления данных.
|
|
|
|
## Пример auth-состояния
|
|
|
|
```ts
|
|
// src/business/auth/hooks/use-auth-state.hook.ts
|
|
import { useGetCurrentUser } from 'infrastructure/backend-api'
|
|
|
|
/**
|
|
* Состояние авторизации текущего пользователя.
|
|
*/
|
|
export const useAuthState = () => {
|
|
const currentUser = useGetCurrentUser()
|
|
const user = currentUser.data
|
|
|
|
return {
|
|
...currentUser,
|
|
user,
|
|
isAuth: Boolean(user),
|
|
}
|
|
}
|
|
```
|
|
|
|
`isAuth` не является частью REST-клиента. Это доменный смысл результата запроса.
|
|
|
|
## Где размещать
|
|
|
|
```text
|
|
src/business/
|
|
└── pets/
|
|
├── hooks/
|
|
│ └── use-available-pets.hook.ts
|
|
├── mappers/
|
|
│ └── map-pet-dto-to-pet.ts
|
|
├── types/
|
|
└── index.ts
|
|
```
|
|
|
|
Модуль `business/` экспортирует наружу готовый доменный API через `index.ts`.
|
|
|
|
## Что запрещено
|
|
|
|
```ts
|
|
// Плохо — business-смысл внутри infrastructure-хука
|
|
export const useGetPetList = (status: PetStatus) => {
|
|
const query = useSWR(...)
|
|
|
|
return {
|
|
...query,
|
|
hasPets: Boolean(query.data?.length),
|
|
}
|
|
}
|
|
```
|
|
|
|
REST-модуль отвечает за доступ к API. Business-модуль отвечает за смысл этих данных в продукте.
|