- Удалён shiki (9.5→0 МБ), создан regex-токенизатор для html/css/xml - CLI переведён с аргументов на конфиг-файл svg-sprites.config.ts - Превью переработано: React-приложение вместо инлайн HTML - Добавлен футер с названием пакета и ссылкой на репозиторий - Исправлена загрузка dev-data.js для Vite 8 - Футер прижат к низу, содержимое центрировано
666 lines
28 KiB
Markdown
666 lines
28 KiB
Markdown
---
|
||
title: Архитектура
|
||
scope: basics
|
||
keywords: [SLM Design, слой, модуль, сегмент, архитектура, FSD, scoped layered module]
|
||
when: "Организация кода: слои, модули, зависимости между модулями"
|
||
---
|
||
|
||
<!-- /index -->
|
||
# SLM Design
|
||
Scoped Layered Module Design — модульная архитектура фронтенд-приложений. Код организован по слоям ответственности, а модуль содержит всё, что ему нужно: компоненты, хуки, сторы, типы, стили.
|
||
|
||
## Преимущества
|
||
|
||
### Вертикальная организация домена
|
||
|
||
Бизнес-домен не разбивается по техническим слоям — сценарии, сущности, типы и UI живут в одном модуле. Это сокращает время навигации и упрощает сопровождение: все изменения домена локализованы.
|
||
|
||
### Dependency Injection без фреймворков
|
||
|
||
Cross-domain зависимости в бизнес-слое реализуются через фабрики — модуль декларирует что ему нужно, а точка использования предоставляет зависимости. Домены изолированы без DI-контейнеров, провайдеров и шин событий.
|
||
|
||
### Разделение ответственности без перегрузки слоёв
|
||
|
||
Сервисы приложения (`infrastructure/`), UI-кит (`ui/`) и общие ресурсы (`shared/`) — три разных слоя с разной природой. Ни один слой не превращается в свалку разнородного кода.
|
||
|
||
### Горизонтальная инкапсуляция
|
||
|
||
Вложенные модули (`parts/`) и направление зависимостей позволяют нескольким разработчикам работать над одной областью приложения параллельно, не затрагивая код друг друга.
|
||
|
||
### Колокация по умолчанию
|
||
|
||
Код начинает жизнь рядом с местом использования и поднимается в общие слои только при реальной потребности. Глобальные слои не засоряются преждевременными абстракциями.
|
||
|
||
### Явное разделение каркаса и контента
|
||
|
||
Каркас группы маршрутов (`layouts/`) и контент конкретной страницы (`screens/`) — независимые слои с собственной ответственностью.
|
||
|
||
### Масштабирование через группировку
|
||
|
||
При росте проекта слои не теряют структуру — модули группируются по естественным признакам: бизнес-домены по субдоменам, страницы по разделам, UI-компоненты по уровню абстракции (примитивы и композиции).
|
||
|
||
## Происхождение
|
||
|
||
SLM Design вырос на основе:
|
||
|
||
- **Feature-Sliced Design** — слоистая структура, публичный API модуля, направление зависимостей
|
||
- **Vertical Slice Architecture** — модуль как вертикальный срез, содержащий всё необходимое
|
||
- **Screaming Architecture** — структура проекта «кричит» о назначении: открыл `business/auth` — видишь авторизацию
|
||
- **Colocation Principle** — код живёт рядом с местом использования
|
||
|
||
## Пример структуры проекта
|
||
|
||
```text
|
||
src/
|
||
├── app/
|
||
│
|
||
├── layouts/
|
||
│ ├── main/
|
||
│ └── dashboard/
|
||
│
|
||
├── screens/
|
||
│ ├── home/
|
||
│ ├── products/
|
||
│ ├── product-detail/
|
||
│ └── about/
|
||
│
|
||
├── widgets/
|
||
│ ├── page-heading/
|
||
│ ├── hero-section/
|
||
│ └── promo-banner/
|
||
│
|
||
├── business/
|
||
│ ├── auth/
|
||
│ ├── catalog/
|
||
│ ├── orders/
|
||
│ └── chat/
|
||
│
|
||
├── infrastructure/
|
||
│ ├── theme/
|
||
│ ├── i18n/
|
||
│ ├── backend-api/
|
||
│ └── logger/
|
||
│
|
||
├── ui/
|
||
│ ├── button/
|
||
│ ├── input/
|
||
│ ├── modal/
|
||
│ ├── toast/
|
||
│ └── dropdown/
|
||
│
|
||
└── shared/
|
||
├── lib/
|
||
├── types/
|
||
└── styles/
|
||
```
|
||
|
||
## Принципы
|
||
|
||
- **Домен — единое целое.** Всё, что относится к домену, живёт в одном модуле.
|
||
- **Колокация.** Код рождается рядом с местом использования и поднимается только при необходимости.
|
||
- **Зависимости однонаправлены.** Импорты только сверху вниз, только через публичный API.
|
||
- **Архитектура — каркас, не клетка.** Правила фиксируют направление зависимостей и структуру модуля, остальное определяет команда.
|
||
|
||
<!-- /reference/layers -->
|
||
## Слои
|
||
|
||
Раздел описывает слои SLM: что такое слой, какие бывают, как между ними направлены зависимости и какие правила действуют на каждом.
|
||
|
||
### Определение
|
||
|
||
**Слой — уровень организации кода внутри `src/`. Каждый слой отвечает за свою область (каркас страницы, бизнес-логика, UI-кит) и задаёт правила для кода внутри: направление импортов, именование, допустимые связи между модулями.**
|
||
|
||
### Группы слоёв
|
||
|
||
Слои делятся на три группы:
|
||
|
||
| Группа | Слои | Описание |
|
||
|--------|------|----------|
|
||
| Композиция | `app`, `layouts`, `screens`, `widgets` | Собирают интерфейс из готовых блоков: маршруты, каркасы, страницы |
|
||
| Ядро | `business`, `infrastructure`, `ui` | Реализация продукта: бизнес-домены, техсервисы, UI-кит |
|
||
| Фундамент | `shared` | Общие ресурсы: утилиты, хелперы, стили, конфиги |
|
||
|
||
### Направление зависимостей
|
||
|
||
Любой импорт между модулями — только через публичный API.
|
||
|
||
```
|
||
app → [ layouts | screens ] → widgets → business → infrastructure → ui → shared
|
||
```
|
||
|
||
- `layouts` и `screens` — параллельные слои, не импортируют друг друга
|
||
- Модули одного слоя в группе «Композиция» изолированы друг от друга
|
||
- Модули одного слоя `infrastructure` и `ui` могут импортировать друг друга через публичный API
|
||
- Модули `business` — cross-domain зависимости по коду через фабрику, `import type` напрямую
|
||
- Импорт типов (`import type`) в «Ядре» разрешён в обоих направлениях
|
||
|
||
|
||
### Слой App
|
||
|
||
Точка входа приложения. Отвечает за запуск, роутинг и композицию маршрутов из layout и screen.
|
||
|
||
В отличие от остальных слоёв, `app/` не содержит модулей SLM. Здесь живут только инфраструктурные файлы, которые не могут быть никаким другим слоем: файлы фреймворка роутинга, точка запуска и код инициализации.
|
||
|
||
#### Требования
|
||
|
||
- Не содержит модулей SLM — только файлы фреймворка, роутинг, инициализация
|
||
- Содержит: файлы маршрутов, bootstrap, обработку ошибок верхнего уровня (404, error boundary), подключение глобальных стилей и ассетов
|
||
- Провайдеры и гарды — только подключает готовые из нижних слоёв, не реализует
|
||
- Не содержит бизнес-логику, UI-компоненты, хуки, сторы, сервисы
|
||
- Никем не импортируется
|
||
|
||
### Слой Layouts
|
||
|
||
Каркас страницы: общие элементы, одинаковые для группы маршрутов (header, footer, sidebar).
|
||
|
||
```text
|
||
src/layouts/
|
||
├── main/
|
||
├── dashboard/
|
||
└── auth/
|
||
```
|
||
|
||
#### Требования
|
||
|
||
- Содержит только модули
|
||
- Не содержит бизнес-логику
|
||
- Контекстно-зависимые блоки принимает через пропсы от `app`, не импортирует напрямую
|
||
|
||
### Слой Screens
|
||
|
||
Контент конкретной страницы: собирает её из модулей нижних слоёв.
|
||
|
||
```text
|
||
src/screens/
|
||
├── home/
|
||
├── products/
|
||
├── product-detail/
|
||
├── about/
|
||
└── contacts/
|
||
```
|
||
|
||
Когда количество страниц затрудняет навигацию — вводится группировка по разделам. Группа — папка для организации, не модуль (без `index.ts`).
|
||
|
||
```text
|
||
src/screens/
|
||
├── shop/
|
||
│ ├── home/
|
||
│ ├── products/
|
||
│ ├── product-detail/
|
||
│ └── cart/
|
||
├── account/
|
||
│ ├── profile/
|
||
│ ├── settings/
|
||
│ └── order-history/
|
||
└── info/
|
||
├── about/
|
||
├── contacts/
|
||
└── faq/
|
||
```
|
||
|
||
#### Требования
|
||
|
||
- Содержит только модули
|
||
- Не содержит бизнес-логику
|
||
- Локальные одноразовые секции живут внутри screen-модуля, не выносятся в `widgets`/`business`
|
||
|
||
### Слой Widgets
|
||
|
||
Составной блок интерфейса, который компонует модули ядра, но не принадлежит конкретному бизнес-домену. Widget появляется когда блок используется в нескольких screens или layouts.
|
||
|
||
Если блок принадлежит домену — он живёт в `business/{area}/`, даже если переиспользуется. Если блок нужен только в одном месте — это `screens/{name}/parts/` или `layouts/{name}/parts/`, а не widget.
|
||
|
||
```text
|
||
src/widgets/
|
||
├── page-heading/
|
||
├── hero-section/
|
||
├── onboarding-checklist/
|
||
├── promo-banner/
|
||
└── error-boundary/
|
||
```
|
||
|
||
#### Требования
|
||
|
||
- Не принадлежит конкретному бизнес-домену. Если блок доменный — он живёт в `business/`
|
||
- Используется в нескольких screens или layouts
|
||
|
||
### Слой Business
|
||
|
||
Бизнес-домены приложения: auth, catalog, orders, checkout, chat. Каждый домен — отдельный модуль со своими типами, логикой, UI и сервисами.
|
||
|
||
Слой входит в группу «Ядро». Импортирует `infrastructure/`, `ui/`, `shared/`. Cross-domain зависимости по коду реализуются через фабрику. `import type` между доменами разрешён напрямую.
|
||
|
||
Business объединяет то, что в FSD разделено на `features` и `entities`: пользовательские сценарии и бизнес-сущности живут вместе, внутри одного домена. Внутри домена сегменты разделяют ответственность: `types/` — доменная модель, `hooks/` и `services/` — сценарии и логика, `mappers/` — трансформация данных, `parts/` — составные блоки.
|
||
|
||
```text
|
||
src/business/
|
||
├── auth/
|
||
├── catalog/
|
||
├── orders/
|
||
├── checkout/
|
||
└── chat/
|
||
```
|
||
|
||
Когда количество доменов затрудняет навигацию — вводится группировка по субдоменам. Группа — папка для организации, не модуль (без `index.ts`).
|
||
|
||
```text
|
||
src/business/
|
||
├── commerce/
|
||
│ ├── catalog/
|
||
│ ├── cart/
|
||
│ ├── orders/
|
||
│ └── checkout/
|
||
└── communication/
|
||
├── chat/
|
||
└── notifications/
|
||
```
|
||
|
||
#### Требования
|
||
|
||
- Один модуль = один бизнес-домен
|
||
- Циклические зависимости между доменами запрещены
|
||
- Импорт кода между доменами — через фабрику. `import type` — напрямую
|
||
- Доменные типы (`User`, `Product`) живут здесь, не в `shared/`
|
||
|
||
### Слой Infrastructure
|
||
|
||
Техсервисы приложения: theme, i18n, API-адаптеры, logger, realtime. Каждый сервис — отдельный модуль.
|
||
|
||
Слой входит в группу «Ядро». Импортирует `infrastructure/`, `ui/`, `shared/`.
|
||
|
||
Отличие от `shared/`: infrastructure — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги).
|
||
|
||
```text
|
||
src/infrastructure/
|
||
├── theme/
|
||
├── i18n/
|
||
├── backend-api/
|
||
├── maps-api/
|
||
├── logger/
|
||
├── feature-flags/
|
||
└── realtime/
|
||
```
|
||
|
||
#### Требования
|
||
|
||
- Один модуль = один техсервис
|
||
- Импортирует `infrastructure/`, `ui/`, `shared/`
|
||
|
||
### Слой UI
|
||
|
||
UI-кит без бизнес-логики: button, carousel, toast, modal.
|
||
|
||
Слой входит в группу «Ядро». Импортирует `ui/` и `shared/`.
|
||
|
||
Компоненты строятся друг на друге: `button` использует `icon`, `carousel` использует `button`.
|
||
|
||
```text
|
||
src/ui/
|
||
├── button/
|
||
├── input/
|
||
├── icon/
|
||
├── carousel/
|
||
├── modal/
|
||
├── toast/
|
||
├── dropdown/
|
||
├── tabs/
|
||
└── tooltip/
|
||
```
|
||
|
||
Когда количество компонентов затрудняет навигацию — вводится группировка на примитивы и композиции. Примитивы (`button`, `icon`, `input`) не импортируют композиции. Композиции (`carousel`, `modal`, `dropdown`) строятся на примитивах.
|
||
|
||
```text
|
||
src/ui/
|
||
├── primitives/
|
||
│ ├── button/
|
||
│ ├── input/
|
||
│ ├── icon/
|
||
│ └── badge/
|
||
└── composites/
|
||
├── carousel/
|
||
├── modal/
|
||
├── dropdown/
|
||
├── tabs/
|
||
└── tooltip/
|
||
```
|
||
|
||
#### Требования
|
||
|
||
- Не содержит бизнес-логику
|
||
- Импортирует только `ui/` и `shared/`
|
||
|
||
### Слой Shared
|
||
|
||
Общие ресурсы: утилиты, хелперы, стили, конфиги. Не знает о бизнес-домене.
|
||
|
||
Слой входит в группу «Фундамент» — ни о ком не знает, никого не импортирует.
|
||
|
||
Отличие от `infrastructure/`: infrastructure — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги).
|
||
|
||
Отличие от `ui/`: UI-компоненты (button, carousel, modal) живут в слое `ui/`, а не здесь.
|
||
|
||
```text
|
||
src/shared/
|
||
├── lib/
|
||
├── types/
|
||
├── styles/
|
||
└── sprites/
|
||
```
|
||
|
||
#### Требования
|
||
|
||
- Не имеет runtime-состояния
|
||
|
||
<!-- /reference/modules -->
|
||
## Модули
|
||
|
||
Раздел описывает модули SLM: что такое модуль, из чего он состоит и как взаимодействует с остальным кодом.
|
||
|
||
### Определение
|
||
|
||
**Модуль — универсальный строительный блок архитектуры. Живёт на слое и содержит всё необходимое для своей работы: компоненты, хуки, сторы, сервисы, типы, стили. Набор содержимого не фиксирован — включаются только нужные части.**
|
||
|
||
### Модуль vs компонент
|
||
|
||
**Компонент** — один `.tsx` файл. Не имеет своих сегментов, использует сегменты родительского модуля. Живёт в корне или `ui/` сегменте модуля.
|
||
|
||
**Модуль** — папка, которая может содержать корневой компонент, сегменты (`hooks/`, `types/`, `styles/`, `ui/`, `parts/` и т.д.) и публичный API (`index.ts`).
|
||
|
||
```text
|
||
auth/
|
||
├── ui/
|
||
│ ├── auth-guard.tsx
|
||
│ └── logout-button.tsx
|
||
├── parts/
|
||
│ ├── login-form/
|
||
│ ├── registration-form/
|
||
│ └── restore-form/
|
||
├── hooks/
|
||
├── stores/
|
||
├── types/
|
||
├── auth.tsx # корневой компонент (опционален)
|
||
└── index.ts
|
||
```
|
||
|
||
### Структура
|
||
|
||
Модуль состоит из сегментов. Ни один сегмент не обязателен — модуль может состоять даже из одного `index.ts` с реэкспортом типов.
|
||
|
||
```text
|
||
{module-name}/
|
||
├── {module-name}.tsx # корневой компонент (опционален)
|
||
├── ui/ # компоненты модуля (только .tsx)
|
||
├── parts/ # вложенные модули (со своими сегментами)
|
||
├── hooks/ # хуки
|
||
├── stores/ # сторы состояния
|
||
├── services/ # внешние источники данных
|
||
├── mappers/ # трансформация данных между форматами
|
||
├── types/ # типы
|
||
├── styles/ # стили
|
||
├── lib/ # утилиты модуля
|
||
├── config/ # константы
|
||
└── index.ts # публичный API
|
||
```
|
||
|
||
Подробное описание каждого сегмента — в разделе [Сегменты](/reference/segments).
|
||
|
||
### Публичный API
|
||
|
||
Модуль экспортирует наружу только то, что нужно другим. Всё остальное — внутреннее.
|
||
|
||
```ts
|
||
// business/auth/index.ts
|
||
export type { User, Session } from './types/user.types'
|
||
export { useAuth } from './hooks/use-auth.hook'
|
||
export { AuthGuard } from './ui/auth-guard'
|
||
```
|
||
|
||
Импорт в обход `index.ts` запрещён:
|
||
|
||
```ts
|
||
// Плохо
|
||
import { validateToken } from '@/business/auth/lib/tokens'
|
||
|
||
// Хорошо
|
||
import { useAuth } from '@/business/auth'
|
||
```
|
||
|
||
### Фабрика
|
||
|
||
Если модуль зависит от кода другого бизнес-домена — он экспортирует фабрику. Фабрика декларирует необходимые зависимости и возвращает API модуля. Точка использования (screen, widget, layout) предоставляет зависимости при вызове.
|
||
|
||
Модуль без cross-domain зависимостей экспортирует API напрямую. Типы всегда экспортируются напрямую — `import type` не является runtime-зависимостью.
|
||
|
||
#### Модуль без зависимостей — прямой экспорт:
|
||
|
||
```ts
|
||
// business/auth/index.ts
|
||
export { useAuth } from './hooks/use-auth'
|
||
export { useCurrentUser } from './hooks/use-current-user'
|
||
export type { User, Session } from './types'
|
||
```
|
||
|
||
#### Модуль с зависимостями — фабрика:
|
||
|
||
```ts
|
||
// business/chat/types/deps.ts
|
||
import type { User } from '@/business/auth'
|
||
|
||
export interface ChatDeps {
|
||
useCurrentUser: () => User | null
|
||
}
|
||
```
|
||
|
||
```ts
|
||
// business/chat/index.ts
|
||
import type { ChatDeps } from './types/deps'
|
||
|
||
export function chatFactory(deps: ChatDeps) {
|
||
return {
|
||
useMessages: (roomId: string) => {
|
||
const user = deps.useCurrentUser()
|
||
// ...
|
||
},
|
||
useSendMessage: (roomId: string) => {
|
||
const user = deps.useCurrentUser()
|
||
return (text: string) => { /* ... */ }
|
||
},
|
||
useChatRooms: () => {
|
||
const user = deps.useCurrentUser()
|
||
// ...
|
||
},
|
||
ChatBadge: ({ count }: { count: number }) => { /* ... */ },
|
||
}
|
||
}
|
||
|
||
export type { Message, ChatRoom } from './types'
|
||
export type { ChatDeps } from './types/deps'
|
||
```
|
||
|
||
#### Использование на странице:
|
||
|
||
```tsx
|
||
// screens/support/support.tsx
|
||
import { useCurrentUser } from '@/business/auth'
|
||
import { chatFactory } from '@/business/chat'
|
||
|
||
const chat = chatFactory({ useCurrentUser })
|
||
|
||
export function SupportScreen() {
|
||
const { useMessages, useSendMessage, ChatBadge } = chat
|
||
const messages = useMessages('support')
|
||
const sendMessage = useSendMessage('support')
|
||
|
||
return (
|
||
<div>
|
||
<ChatBadge count={messages.length} />
|
||
{messages.map(m => <MessageBubble key={m.id} {...m} />)}
|
||
<MessageInput onSend={sendMessage} />
|
||
</div>
|
||
)
|
||
}
|
||
```
|
||
|
||
### Жизненный цикл
|
||
|
||
Модуль рождается на самом низком уровне использования и поднимается выше только при реальной потребности.
|
||
|
||
- Нужен на одной странице → `screens/{name}/parts/`
|
||
- Появился в 2+ местах → поднимается по природе:
|
||
- абстрактный UI → `ui/`
|
||
- блок с данными/логикой → `widgets/`
|
||
- представление бизнес-домена → `business/{area}/parts/`
|
||
|
||
Подъём — обычный рефакторинг в рамках задачи, а не отдельная активность.
|
||
|
||
<!-- /reference/segments -->
|
||
## Сегменты
|
||
|
||
Раздел описывает сегменты SLM: что такое сегмент, какие бывают и что в каждом из них лежит.
|
||
|
||
### Определение
|
||
|
||
**Сегмент — папка внутри модуля, которая группирует файлы по назначению. Набор сегментов не фиксирован — модуль включает только те, которые ему нужны. Команда сама определяет какие сегменты используются в проекте — архитектура даёт рекомендацию.**
|
||
|
||
### Обзор
|
||
|
||
| Сегмент | Содержимое |
|
||
|---------|------------|
|
||
| `ui/` | Компоненты модуля — только `.tsx` файлы |
|
||
| `parts/` | Вложенные модули со своими сегментами |
|
||
| `hooks/` | React-хуки |
|
||
| `stores/` | Сторы состояния |
|
||
| `services/` | Работа с внешними источниками данных |
|
||
| `mappers/` | Трансформация данных между форматами |
|
||
| `types/` | TypeScript-типы и интерфейсы |
|
||
| `styles/` | Стили |
|
||
| `lib/` | Утилиты и хелперы модуля |
|
||
| `config/` | Константы и конфигурация |
|
||
|
||
### Сегмент ui/
|
||
|
||
Компоненты, принадлежащие модулю. Содержит только `.tsx` файлы — без своих сегментов, стилей, типов, хуков. Использует сегменты родительского модуля.
|
||
|
||
```text
|
||
auth/
|
||
├── ui/
|
||
│ ├── auth-provider.tsx
|
||
│ ├── auth-guard.tsx
|
||
│ └── logout-button.tsx
|
||
├── types/
|
||
├── hooks/
|
||
└── index.ts
|
||
```
|
||
|
||
Если компоненту нужны собственные сегменты — это уже не `ui/`, а `parts/`.
|
||
|
||
### Сегмент parts/
|
||
|
||
Вложенные модули со своими сегментами. Каждый элемент `parts/` — полноценный модуль: папка с компонентом, хуками, стилями, типами и т.д.
|
||
|
||
```text
|
||
home/
|
||
├── parts/
|
||
│ ├── hero-section/
|
||
│ │ ├── hero-section.tsx
|
||
│ │ ├── styles/
|
||
│ │ └── parts/
|
||
│ │ └── top-banner/
|
||
│ │ └── top-banner.tsx
|
||
│ └── features-section/
|
||
│ ├── features-section.tsx
|
||
│ └── hooks/
|
||
├── home.screen.tsx
|
||
└── index.ts
|
||
```
|
||
|
||
Отличие от `ui/`: элемент `parts/` — модуль со своими сегментами. Элемент `ui/` — компонент, один `.tsx` файл.
|
||
|
||
Вложенность `parts/` инкапсулирует область разработки горизонтально: каждый разработчик работает в своём `parts/`-модуле, не затрагивая чужие. Это снижает конфликты при параллельной разработке.
|
||
|
||
Если вложенный модуль обрастает своими `parts/` — это сигнал, что он достаточно самостоятельный для подъёма на уровень выше.
|
||
|
||
### Сегмент hooks/
|
||
|
||
React-хуки модуля. Инкапсулируют логику, состояние, подписки, побочные эффекты.
|
||
|
||
```text
|
||
hooks/
|
||
├── use-auth.hook.ts
|
||
├── use-session.hook.ts
|
||
└── use-permissions.hook.ts
|
||
```
|
||
|
||
### Сегмент stores/
|
||
|
||
Сторы состояния модуля. Конкретная реализация зависит от выбранного стейт-менеджера (Zustand, MobX, Redux и т.д.).
|
||
|
||
```text
|
||
stores/
|
||
├── auth.store.ts
|
||
└── session.store.ts
|
||
```
|
||
|
||
### Сегмент services/
|
||
|
||
Работа с внешними источниками данных: API-вызовы, запросы, подписки.
|
||
|
||
```text
|
||
services/
|
||
├── auth.service.ts
|
||
└── token.service.ts
|
||
```
|
||
|
||
### Сегмент mappers/
|
||
|
||
Функции трансформации данных из одного формата в другой: DTO в доменный тип, доменный тип в DTO, доменный тип в ViewModel.
|
||
|
||
```text
|
||
mappers/
|
||
├── map-user.ts
|
||
├── map-product.ts
|
||
└── map-order-to-dto.ts
|
||
```
|
||
|
||
### Сегмент types/
|
||
|
||
TypeScript-типы и интерфейсы модуля. Доменные типы, DTO, пропсы компонентов.
|
||
|
||
```text
|
||
types/
|
||
├── user.type.ts
|
||
└── session.type.ts
|
||
```
|
||
|
||
### Сегмент styles/
|
||
|
||
Стили модуля. Формат зависит от выбранного подхода (CSS Modules, SCSS, CSS-in-JS и т.д.).
|
||
|
||
```text
|
||
styles/
|
||
├── auth.module.css
|
||
└── login-form.module.css
|
||
```
|
||
|
||
### Сегмент lib/
|
||
|
||
Утилиты и хелперы, специфичные для модуля. Чистые функции без побочных эффектов.
|
||
|
||
```text
|
||
lib/
|
||
├── validate-email.ts
|
||
└── format-phone.ts
|
||
```
|
||
|
||
Отличие от `shared/lib/`: здесь лежат утилиты, нужные только этому модулю. Общие утилиты — в `shared/lib/`.
|
||
|
||
### Сегмент config/
|
||
|
||
Константы и конфигурация модуля: маршруты, лимиты, дефолтные значения.
|
||
|
||
```text
|
||
config/
|
||
├── routes.ts
|
||
└── constants.ts
|
||
```
|