ADR-UI-003. Структура проекта src-ui

ADR Версия: 1.0 accepted

Каркас src-ui, созданный ng new, минимален. По мере роста (страницы, сервисы, компоненты, модели, гарды) нужен предсказуемый физический layout: чтобы человек и ИИ одинаково находили место для нового кода, а генераторы опирались на стабильные пути. Учитываем переносимость набора ui/ и отсутствие внешнего UI-kit.

⟨/⟩ Исходник

1. Контекст и постановка задачи

Нужен предсказуемый физический layout src-ui, чтобы:

Две особенности ICD, отличающие раскладку от типовой: собственный переносимый набор компонентов ui/ (должен быть самодостаточным, включая дизайн-токены) и отсутствие внешнего UI-kit (нет antd-overrides и подобного).

2. Драйверы решения

  1. Единственная ответственность папок — каждая папка верхнего уровня имеет понятное назначение, новый код легко классифицировать.
  2. Плоские модули — никакой группировки modules/<group>/<feature>/; навигационная группировка живёт в меню, не в файловой системе.
  3. Lazy loading — каждая фича modules/<feature>/ подключается ленивыми маршрутами.
  4. Стабильные пути — для автоматизации и предсказуемого ревью.
  5. Самодостаточность ui/ — набор с токенами переносится в другой проект целиком, без внешних стилевых зависимостей.

3. Рассмотренные варианты

4. Решение

Выбран Вариант A. Папки создаются по мере надобности (не заводим пустые заранее); назначение каждой зафиксировано ниже. Именование файлов — по стилю Angular 22 без суффиксов (см. ADR-UI-002).

4.1. Дерево верхнего уровня (целевое)

src-ui/
└── src/
    ├── app/
    │   ├── consts/         # Глобальные константы
    │   ├── directives/     # Атрибутивные/структурные директивы
    │   ├── guards/         # CanActivate-гарды
    │   ├── models/         # Общие модели (Option, Pagination, Sorting, …)
    │   ├── modules/        # Фичи (плоско, см. ниже)
    │   ├── pipes/          # Глобальные pipe-ы
    │   ├── services/       # Singleton-сервисы (root)
    │   │   ├── api-clients/  # Клиенты к backend (генерируемые; см. ADR про API)
    │   │   └── router/       # Реестры маршрутов
    │   ├── ui/             # Собственный переносимый набор компонентов (см. ниже)
    │   ├── utils/          # Чистые функции
    │   ├── app.ts
    │   ├── app.config.ts
    │   ├── app.routes.ts
    │   └── app.const.ts
    ├── styles/
    │   └── theme/          # Переопределения токенов набора под проект (тема)
    ├── styles.scss         # Точка входа стилей (подключает токены ui/ и styles/theme/)
    ├── index.html
    └── main.ts

4.2. Набор ui/ — самодостаточный и переносимый

app/ui/
├── tokens/            # Дизайн-токены (CSS custom properties): палитра, отступы, типографика.
│                      #   Едут ВМЕСТЕ с набором — часть его контракта.
├── <component>/       # Папка на компонент (button/, table/, …): <name>.ts|html|scss + index.ts
└── index.ts           # Общий barrel набора

Набор зависит только «вниз» (Angular, @angular/cdk, свои токены) и не импортирует доменный код (см. ADR-UI-002, принципы переносимости).

4.3. Структура папки фичи (modules/<feature>/)

modules/<feature>/
├── components/         # Под-компоненты страниц
├── models/             # Доменные UI-модели фичи
├── pages/
│   └── <page>/
│       ├── <page>.ts
│       ├── <page>.html
│       └── <page>.scss
├── services/           # Per-page сервисы (регистрируются в providers страницы)
└── <feature>.routes.ts # Ленивые маршруты фичи

4.4. Принципы организации

  1. Модули — плоско. Никакого modules/<group>/<feature>/; группировка — только в меню.
  2. ui/ — переиспользуемые виджеты, не привязанные к фиче; самодостаточны (с токенами).
  3. services/ (app) — только глобальные singleton + api-clients/ и router/. Per-page сервисы — в modules/<feature>/services/.
  4. models/ (app) — только общие; доменные — в фиче.
  5. Без store/ — глобального store нет (ADR-UI-001).

4.5. Стили и кастомизация набора

4.6. TS-алиасы (tsconfig.json)

{
  "compilerOptions": {
    "paths": {
      "@app/*": ["src/app/*"],
      "@api/*": ["src/app/services/api-clients/*"],
      "@ui/*":  ["src/app/ui/*"]
    }
  }
}

Алиасы обязательны для всего, что вне текущей папки фичи — импорты устойчивы к рефакторингу путей. Для набора ui/ алиас @ui/* дополнительно облегчает будущий вынос в библиотеку.

4.7. API-клиенты

Место — app/services/api-clients/<context>/. Список контекстов и способ генерации клиента из backend-контракта уточняются отдельным ADR при появлении API; сейчас фиксируется только место.

5. Положительные следствия

6. Отрицательные следствия и компромиссы

7. Проверка

8. Открытые вопросы / отложено

Связанные артефакты

Документы