Files
twitch-panels/plans/TECHNICAL_ROADMAP.md
T
2026-02-09 11:46:18 +05:00

45 KiB
Raw Blame History

Технический план (Engineering & Architecture Roadmap)

Twitch Panels Creator

Анализ версии: 0.0.1
Дата анализа: 2025-02-09
Технологии: Svelte 5, TypeScript, Konva.js, Vitest


1. Аудит текущей архитектуры

1.1 State Management - КРИТИЧЕСКИЕ ПРОБЛЕМЫ

Проблема: Несогласованные паттерны управления состоянием.

Паттерн A: Фабрика функций ( Хорошо)

Файлы: src/states/texts.svelte.ts, src/states/textConfig.svelte.ts, src/states/theme.svelte.ts, src/states/konvaStage.svelte.ts

// Пример: texts.svelte.ts
function createState() {
  let texts = $state(defaultTexts);
  let nextId = $state(defaultTexts.length);

  return {
    get texts() { return texts; },
    addText(text: string) { ... },
    removeText(id: number) { ... },
  };
}
export const textsState = createState();

Преимущества:

  • Инкапсуляция приватных переменных
  • Геттеры/сеттеры для валидации
  • Легко тестировать (можно создавать инстансы)

Недостатки:

  • Избыточный код геттеров/сеттеров (см. textConfig.svelte.ts:24-61)

Паттерн B: Прямой $state ( ПЛОХО)

Файлы: src/states/konvaAllStages.svelte.ts, src/states/imageConfig.svelte.ts

// ПЛОХО - глобальный массив без инкапсуляции
export const konvaAllStagesState: Array<Stage> = $state([]);

// ПЛОХО - класс с $state полями, но без фабрики
export class ImageConfigState {
  image = $state<HTMLImageElement | undefined>(undefined);
  imageLink = $state("");
  // ...
}
export const imageConfigState = new ImageConfigState();

Проблемы:

  • konvaAllStagesState - глобальный изменяемый массив, нет контроля над операциями
  • ImageConfigState - класс с $state, но не фабрика, сложно тестировать
  • Нет единого подхода

Паттерн C: Смешанный (⚠️ НЕПРАВИЛЬНО)

Файлы: src/states/imageConfig.svelte.ts - класс с $state, но с приватными полями и методами

Рекомендация: Привести все состояния к Фабрике функций (Pattern A).


1.2 Сервисный слой - ОТСУТСТВУЕТ

Текущее состояние:

  • src/services/downloadService.ts - хороший пример
  • imageService.ts - отсутствует (логика загрузки размазана)
  • storageService.ts - отсутствует (localStorage в +layout.svelte:15)

Проблема: Бизнес-логика смешана с UI-компонентами.

Пример: src/components/image/ImageManager.svelte - UI без логики, кнопки не работают.

Рекомендация: Создать сервисы для всех доменных областей.


1.3 Компонентная архитектура - ОЦЕНКА ВСЕХ ГРУПП

Группа 1: layout/ (Базовые layout-компоненты)

Файлы: Card.svelte, AppHeader.svelte, PanelBar.svelte, TextBar.svelte, SettingsGrid.svelte, SettingsRow.svelte, InputGroup.svelte

Оценка: Хорошо

  • Четкое разделение: Card — контейнер, SettingsGrid/Row — формы, PanelBar/TextBar — компоновка секций
  • InputGroup.svelte простой flex wrapper, выполняет свою функцию
  • AppHeader.svelte содержит логику переключения темы, но это уместно (header — привязка к UI)
  • Нет дублирования, каждый компонент имеет уникальную ответственность
  • Рекомендаций: Нет

Группа 2: panel/ (Превью панелей)

Файлы: Preview.svelte, PreviewAll.svelte, PreviewControls.svelte, PreviewManager.svelte

Оценка: Хорошо

  • Preview — чистый компонент, принимает text и stage как props, рендерит Konva Stage + Layer + Image + Text
  • PreviewAll — off-screen рендеринг всех stages (необходимость для экспорта)
  • PreviewControls — навигация (prev/next), чистая логика
  • PreviewManager — оркестратор: управляет current index, direction, вызывает downloadService
  • Вывод: Хорошее разделение, каждая панель имеет свою зону ответственности

Потенциальная проблема:

  • PreviewManager.svelte:22-30 содержит $effect для синхронизации current с textsState.texts.length — это бизнес-логика, но в данном контексте допустимо
  • Рекомендация: Если логика усложнится, вынести в отдельный хук/сервис

Группа 3: text/ (Управление текстами)

Файлы: TextManager.svelte, TextConfig.svelte, TextInput.svelte, TextInlineEdit.svelte

Оценка: Хорошо

  • TextManager — управление списком текстов (add/delete), вызывает textsState
  • TextConfig — UI для глобальных настроек текста, bind:value к textConfigState
  • TextInput — простой input с обработкой Enter
  • TextInlineEdit — inline-редактирование с кнопкой удаления
  • Вывод: Чистые, сфокусированные компоненты, нет дублирования

Замечание:

  • TextInlineEdit.svelte:17 — <input type="text" bind:value={text} /> без валидации maxLength (есть в constants.ts:32)
  • Рекомендация: Добавить maxlength={TYPOGRAPHY.MAX_TEXT_LENGTH} и визуальный счетчик

Группа 4: image/ (Работа с изображениями)

Файлы: ImageManager.svelte, CropInline.svelte

Оценка: ⚠️ Частично реализовано (нефункционально)

  • ImageManager.svelte — UI есть, но кнопки не работают (Upload, Edit, Reset)
  • CropInline.svelte — визуальный crop box с handles, но нет интеграции с cropperjs и imageConfigState
  • Настройки яркости/контраста — только UI, нет логики применения
  • Вывод: Компоненты выглядят готовыми, но функциональность отсутствует

Рекомендации (High Priority):

  • Реализовать imageService.ts и интегрировать в ImageManager
  • Добавить логику crop в CropInline (drag, resize, update imageConfigState)
  • Применить фильтры яркости/контраста к Konva Image в Preview.svelte

Группа 5: ui/ (Переиспользуемые UI-компоненты)

Файлы: Button.svelte, RangeSlider.svelte, ColorPicker.svelte, SelectFont.svelte, Alignment.svelte, Badge.svelte

Оценка: Хорошо

  • Button — 5 типов (primary, secondary, outline, danger, mini), хороший API
  • RangeSlider — простой wrapper с отображением значения
  • ColorPicker — input type="color" + отображение hex
  • SelectFont — hardcoded список шрифтов (можно улучшить, вынести в constants)
  • Alignment — 3 кнопки выравнивания, bind:align
  • Badge — простой компонент для счетчиков
  • Вывод: Все компоненты маленькие, сфокусированные, легко переиспользовать

Рекомендации (Low Priority):

  • SelectFont.svelte:9-18 — шрифты hardcoded, лучше взять из TYPOGRAPHY.FONT_FAMILIES (constants.ts:15-24)
  • Button.svelte — добавить sizes (sm, md, lg) для гибкости
  • RangeSlider.svelte — добавить label и unit props для лучшего UX

Общий вывод по компонентной архитектуре:

Группа Оценка Приоритет исправления
layout Хорошо Нет
panel Хорошо Нет
text Хорошо Low (валидация)
image ⚠️ Частично High (доделать функционал)
ui Хорошо Low (улучшения)

Критическая проблема: Только группа image/ требует срочной доработки. Остальные группы следуют best practices и не нуждаются в рефакторинге.


1.4 Типизация - УДОВЛЕТВОРИТЕЛЬНО

Хорошее:

  • TypeScript везде
  • Интерфейсы для Props компонентов
  • Типы для сервисов (DownloadItem, DownloadResult)

Проблемы:

Рекомендация:

  • Создать src/lib/types/index.ts с экспортом всех доменных типов
  • Убрать any из тестов, создать моки с правильными типами

1.5 Обработка ошибок - ХОРОШО

Файлы: src/lib/error.types.ts, src/lib/utils/errorUtils.ts

Преимущества:

  • Иерархия ошибок (AppError → ImageError, TextError, CanvasError, StorageError)
  • Утилиты для форматирования и логирования
  • Используется в downloadService

Недостатки:

  • Нет обработки ошибок в UI (нет toast/notification системы)
  • Ошибки только в консоль, пользователь не видит

Рекомендация: Добавить notification system (например, src/components/ui/Notification.svelte).


1.6 Производительность - РИСКИ

Критические точки:

  1. Konva stages:

  2. Нет ленивой загрузки:

    • Все компоненты загружаются сразу
    • Изображения загружаются без lazy loading
  3. Нет debouncing:

    • src/states/textConfig.svelte.ts - каждый drag слайдера вызывает перерисовку Konva
    • Нет оптимизации частых обновлений

Рекомендация:

  • Виртуализация списка панелей (virtual scrolling)
  • Debounce для слайдеров (100-150ms)
  • Ленивая загрузка изображений

2. Укрепление базы (Рефакторинг)

2.1 Привести все состояния к фабричному паттерну (High Priority)

Цель: Единообразная структура для всех stores.

Текущие состояния:

Файл Текущий паттерн Целевой паттерн
texts.svelte.ts Фабрика Оставить
textConfig.svelte.ts Фабрика Упростить геттеры/сеттеры
theme.svelte.ts Фабрика Оставить
konvaStage.svelte.ts Фабрика Оставить
konvaAllStages.svelte.ts Глобальный $state Переделать в фабрику с методами
imageConfig.svelte.ts Класс с $state Переделать в фабрику

Пример рефакторинга konvaAllStages:

// BEFORE (src/states/konvaAllStages.svelte.ts)
export const konvaAllStagesState: Array<Stage> = $state([]);

// AFTER
function createState() {
  let stages: Array<Stage> = $state([]);

  return {
    get stages() {
      return stages;
    },
    addStage(stage: Stage) {
      stages.push(stage);
    },
    removeStage(stage: Stage) {
      stages = stages.filter((s) => s !== stage);
    },
    clear() {
      stages = [];
    },
  };
}
export const konvaAllStagesState = createState();

Задача: Рефакторинг всех состояний к единому паттерну.


2.2 Создать сервисный слой (High Priority)

Требуемые сервисы:

2.2.1 imageService.ts

Ответственность: Загрузка, обработка, валидация изображений.

API:

interface ImageService {
  // Загрузка
  uploadFromFile(file: File): Promise<ImageData>;
  uploadFromURL(url: string): Promise<ImageData>;
  uploadFromPaste(clipboardData: DataTransfer): Promise<ImageData>;

  // Обработка
  crop(image: ImageData, crop: CropRect): ImageData;
  applyFilters(image: ImageData, filters: ImageFilters): ImageData;

  // Валидация
  validateFormat(file: File): boolean;
  validateSize(file: File): boolean;

  // Кэш
  clearCache(): void;
}

Реализация:

  • Использовать Canvas API для обрезки и фильтров
  • Кэшировать загруженные изображения (Map<url, ImageData>)
  • Обработка ошибок через ImageError

2.2.2 Упрощенный подход: textsState как основной store

Решение: Вместо panelService оставить textsState как основной store для панелей.

Архитектура:

textsState (массив текстов) + textConfigState (глобальные настройки) + imageConfigState (глобальное изображение)
         ↓
PreviewManager (навигация по textsState)
         ↓
Preview (рендерит панель на основе text + textConfig + imageConfig)
         ↓
downloadService (экспорт)

Преимущества:

  • Нет лишних абстракций
  • Прямая реактивность через Svelte 5 runes
  • Простая debugging
  • Минимальный порог входа

Когда добавить panelService: Только если появятся персональные настройки на панель (не глобальные), или сложная бизнес-логика (валидация, bulk-операции, undo/redo).

Текущая логика в компонентах:

  • TextManagertextsState.addText() / removeText()
  • PreviewManager → читает textsState.texts для навигации
  • Preview → читает textsState.texts[current] + textConfigState + imageConfigState

Это достаточно для MVP.

2.2.3 storageService.ts

Ответственность: Сохранение/загрузка проектов.

API:

interface Project {
  id: string;
  name: string;
  createdAt: Date;
  updatedAt: Date;
  panels: Panel[];
  globalConfig: {
    textConfig: TextConfig;
    imageConfig: ImageConfig | null;
  };
}

interface StorageService {
  saveProject(project: Project): Promise<void>;
  loadProject(id: string): Project | null;
  listProjects(): ProjectInfo[];
  deleteProject(id: string): void;
  autoSave(project: Project): void; // debounced
}

Реализация:

  • localStorage с ключом twitch-panels-projects
  • JSON сериализация
  • Обработка квот localStorage (5-10MB)
  • Восстановление при старте

2.2.4 exportService.ts (расширить downloadService)

Ответственность: Экспорт в разные форматы.

API:

interface ExportService {
  exportPanel(panel: Panel, format: "png" | "jpeg" | "webp", quality?: number): Promise<Blob>;
  exportAll(panels: Panel[], format: "png" | "jpeg" | "webp", quality?: number): Promise<Blob>;
  exportPDF(panels: Panel[]): Promise<Blob>;
}

Реализация:

  • Использовать canvas.toBlob с качеством
  • PDF через библиотеку (pdf-lib или jsPDF)

2.3 Вынести общие UI-компоненты в библиотеку (Medium Priority)

Проблема: Компоненты в src/components/ui/ и src/components/layout/ используются везде, но:

  • Нет единого стиля (разные отступы, размеры)
  • Нет документации
  • Сложно переиспользовать в других проектах

Решение:

  1. Создать src/lib/components/ (или отдельный пакет)
  2. Документировать API каждого компонента
  3. Стандартизировать пропсы (size, variant, color scheme)
  4. Добавить темы (dark/light уже есть, но нужно формализовать)

Компоненты для выноса:

  • Button (уже хорош, но добавить sizes: sm, md, lg)
  • RangeSlider (добавить label, unit)
  • ColorPicker (добавить preset colors)
  • Card (упростить API, убрать snippets)

2.4 Оптимизировать работу с Konva (High Priority)

Проблемы:

  1. Утечка памяти:

    • src/states/imageConfig.svelte.ts:28-33 есть cleanup, но вызывается только при новой загрузке
    • Stages не уничтожаются при удалении панелей
    • konvaAllStages растет бесконечно
  2. Нет управления жизненным циклом:

    • Stages создаются в Preview.svelte, но не уничтожаются
    • Нет вызова stage.destroy() при unmount

Решение:

  1. Добавить destroy в Preview.svelte:
import { onDestroy } from "svelte";
onDestroy(() => {
  if (stage?.node) {
    stage.node.destroy();
  }
});
  1. Очищать konvaAllStages при удалении панелей:

    • В textsState.removeText() → удалять соответствующий stage из konvaAllStagesState
    • Вызывать stage.destroy()
  2. Лимитировать количество stages:

    • Виртуализация: рендерить только видимые панели
    • Или: рендерить все, но в hidden container (уже есть PreviewAll), но stages все равно в памяти

Рекомендация: Реализовать virtual scrolling для PreviewAll.


3. Стратегия тестирования

3.1 Текущее покрытие

Анализ тестов:

  • Unit тесты для states (texts, imageConfig, konvaStage, konvaAllStages, textConfig, theme)
  • Unit тесты для компонентов (Preview, PreviewAll, PreviewControls, PreviewManager, TextConfig, TextInlineEdit, TextInput, TextManager, CropInline, ImageManager, Card, InputGroup, SettingsGrid, SettingsRow, TextBar, AppHeader, Alignment, Badge, Button, ColorPicker, RangeSlider, SelectFont)
  • Unit тесты для сервисов (downloadService)
  • Unit тесты для утилит (errorUtils)
  • Unit тесты для констант и типов

Проблемы:

  • Нет интеграционных тестов (связь компонентов + состояния)
  • Нет E2E тестов (полные user flows)
  • Нет тестов для imageService (его нет)
  • Нет тестов для storageService (его нет)
  • Нет тестов для контрактов между компонентами

Оценка покрытия: ~40-50% (только unit, нет интеграций)


3.2 Оптимальный баланс тестов

Целевое распределение:

  • Unit: 40% - изолированные компоненты, утилиты, состояния
  • Integration: 40% - взаимодействие компонентов, сервисов, состояний
  • E2E: 20% - полные user flows (создание проекта → экспорт)

3.3 Критические сценарии для тестирования

HIGH PRIORITY (Интеграционные тесты)

1. Текстовый flow:

TextManager → textsState → PreviewManager → Preview → downloadService

Тест: tests/integration/text-flow.test.ts

it("should create panel with text and export it", async () => {
  // 1. Добавить текст через TextManager
  // 2. Проверить textsState.texts
  // 3. Проверить PreviewManager отображает текст
  // 4. Нажать "Скачать"
  // 5. Проверить downloadService.downloadPanel вызван с правильным именем
});

2. Изображение flow:

ImageManager → imageService → imageConfigState → Preview → export

Тест: tests/integration/image-flow.test.ts

it("should upload image, crop it, and apply to panel", async () => {
  // 1. Загрузить изображение (mock file)
  // 2. Проверить imageConfigState.image
  // 3. Установить crop values
  // 4. Проверить Preview отображает обрезанное изображение
});

3. Навигация flow:

textsState → PreviewControls → PreviewManager → Preview

Тест: tests/integration/navigation-flow.test.ts

it("should navigate between panels correctly", async () => {
  // 1. Добавить 3 текста
  // 2. Проверить PreviewControls показывает "1 / 3"
  // 3. Клик next → проверяем PreviewManager.current = 1
  // 4. Клик prev → проверяем PreviewManager.current = 0
  // 5. Проверить transition direction
});

4. Project persistence flow:

storageService ↔ localStorage ↔ app state

Тест: tests/integration/storage-flow.test.ts

it("should save and load project", async () => {
  // 1. Создать проект (несколько панелей)
  // 2. Вызвать storageService.saveProject()
  // 3. Проверить localStorage содержит данные
  // 4. Перезагрузить страницу (или создать новый инстанс)
  // 5. Вызвать storageService.loadProject()
  // 6. Проверить состояние восстановлено
});

MEDIUM PRIORITY (E2E тесты)

1. Полный user flow:

  • Открыть страницу
  • Добавить 3 текста
  • Загрузить изображение
  • Настроить текст (размер, цвет, выравнивание)
  • Настроить изображение (яркость, контраст, crop)
  • Экспортировать все панели в ZIP
  • Проверить ZIP содержит 3 файла

Тест: tests/e2e/create-panels.spec.ts (Playwright)

2. Project management flow:

  • Создать проект
  • Сохранить
  • Создать второй проект
  • Переключиться между проектами
  • Удалить проект

Тест: tests/e2e/projects.spec.ts


3.4 Тесты для новых сервисов

imageService.test.ts:

  • uploadFromFile (валидный/невалидный файл)
  • uploadFromURL (успех/ошибка)
  • crop (граничные случаи)
  • applyFilters (brightness, contrast)
  • validateFormat/validateSize

textsState.test.ts (уже есть, расширить):

  • Тесты на синхронизацию с konvaAllStages

  • Тесты на очистку stages при удалении текста

  • createPanel

  • updatePanel

  • deletePanel

  • validatePanel (текст слишком длинный, нет изображения и т.д.)

storageService.test.ts:

  • saveProject (квоты localStorage)
  • loadProject (несуществующий, поврежденный JSON)
  • listProjects
  • autoSave (debounce)

3.5 Улучшение существующих тестов

Проблемы в текущих тестах:

  1. tests/unit/states/texts.test.ts:70-100 - хорошие интеграционные тесты внутри state, но:

    • Нет тестов на edge cases (clear после удаления всех)
    • Нет тестов на валидацию (длина текста)
  2. tests/unit/services/downloadService.test.ts - хорошие моки, но:

    • Нет теста на downloadAll с пустым массивом
    • Нет теста на ошибку при создании ZIP
  3. Компонентные тесты:

    • Большинство - "should render without crashing"
    • Нет тестов на взаимодействие (клики, ввод)
    • Нет тестов на пропсы

Рекомендация:

  • Добавить тесты на взаимодействие для всех компонентов
  • Тесты на edge cases (empty state, error state, loading state)
  • Тесты на accessibility (aria-labels, keyboard navigation)

4. Приоритизация улучшений

Фаза 1: Стабилизация (2-3 недели) - HIGH PRIORITY

1.1 Рефакторинг состояний (High)

Задача: Привести все состояния к фабричному паттерну.

Файлы:

Тесты: Обновить существующие тесты под новые API.

Критерий успеха: Все состояния имеют одинаковую структуру.


1.2 Создание сервисного слоя (High)

Задача: Вынести всю бизнес-логику в сервисы.

Файлы:

Миграция:

  1. Создать imageService
  2. Переместить логику загрузки из ImageManager в imageService
  3. Интегрировать в ImageManager
  4. Аналогично для storageService

Тесты: Unit тесты для каждого сервиса (80%+ покрытия).

Критерий успеха: Компоненты только для UI, вся логика в сервисах.


1.3 Интеграционные тесты (High)

Задача: Покрыть критические user flows.

Файлы:

Технологии: Vitest + Testing Library (не Playwright, это не E2E).

Критерий успеха: 100% покрытия критических flows.


1.4 Управление памятью Konva (High)

Задача: Предотвратить утечки памяти.

Файлы:

Тесты: Тест на отсутствие утечек (Jest memory leak detection).

Критерий успеха: stages уничтожаются при удалении панелей.


Фаза 2: Улучшение качества (3-4 недели) - MEDIUM PRIORITY

2.1 Улучшение UI-компонентов (Medium)

Задача: Стандартизировать и вынести в библиотеку.

Файлы:

Документация: Storybook или doc comments.


2.2 Оптимизация производительности (Medium)

Задача: Ускорить рендеринг при большом количестве панелей.

Задачи:

  1. Debounce для слайдеров (в TextConfig и ImageManager)
  2. Virtual scrolling для PreviewAll (использовать svelte-virtual-list)
  3. Ленивая загрузка изображений (IntersectionObserver)

Файлы:

Тесты: Бенчмарки рендеринга (vitest-bench).


2.3 Улучшение доступности (Medium)

Задача: WCAG 2.1 AA compliance.

Файлы:

  • Все компоненты: добавить role, aria-*, tabindex
  • Клавиатурная навигация (Enter, Space, Arrow keys)
  • Фокусные состояния (визуальные)
  • Контрастность (проверить цвета)

Тесты: axe-core, Playwright accessibility audits.


2.4 Расширенные тесты (Medium)

Задача: Покрытие 80%+ кода.

Файлы:

  • Тесты для всех сервисов (imageService, storageService, exportService)
  • Тесты для всех компонентов (интеграционные)
  • E2E тесты (Playwright)

Критерий успеха: Coverage >80%.


Фаза 3: Продвинутые фичи (4+ недели) - LOW PRIORITY

3.1 Расширенные настройки текста (Low)

Задача: Тени, градиенты, прозрачность, несколько блоков.

Файлы:

Сложность: Высокая (Konva Text ограничен).


3.2 Расширенные настройки изображений (Low)

Задача: Фильтры, слои, blend modes.

Файлы:


3.3 Пресеты и шаблоны (Low)

Задача: Шаблоны для быстрого старта.

Файлы:


5. Безопасность

5.1 Валидация входных данных (High)

Текущее состояние: Почти отсутствует.

Требования:

  1. Тексты:

    • src/states/texts.svelte.ts:17 - есть trim().length === 0, но нет max length
    • Добавить: if (text.length > TYPOGRAPHY.MAX_TEXT_LENGTH) throw new TextError(...)
  2. Изображения:

    • src/services/imageService.ts - валидация:
      • Формат: file.type in IMAGE_SETTINGS.SUPPORTED_FORMATS
      • Размер: file.size <= IMAGE_SETTINGS.MAX_FILE_SIZE
      • URL: валидация схемы (http/https), нет XSS
  3. URL изображений:

    • Защита от XSS: не допускать javascript: URLs
    • Проверка CORS (crossOrigin="anonymous" уже есть)

5.2 Защита от XSS (High)

Риски:

  • Текст рендерится в Konva Text - безопасно (не innerHTML)
  • Но если добавить HTML в будущем - нужно санитизировать

Решение: Использовать DOMPurify для любого HTML.


5.3 Безопасная работа с localStorage (Medium)

Риски:

  • localStorage не изолирован (другие скрипты на домене)
  • Квоты (5-10MB)
  • Поврежденные данные

Решение:

  • Валидация при загрузке: JSON.parse в try-catch, проверка схемы
  • Ограничение размера: JSON.stringify(project).length < 5_000_000
  • Fallback: если localStorage полон/поврежден - предложить экспорт JSON

Файл: src/services/storageService.ts


6. Мониторинг и observability

6.1 Логирование ошибок (Medium)

Текущее состояние: src/lib/utils/errorUtils.ts:19-26 - console.error

Улучшение:

  • Отправлять ошибки в external service (Sentry, LogRocket)
  • Добавить контекст (user id, project id, action)
  • User-friendly сообщения (не показывать stack trace)

Файл: src/services/errorReportingService.ts


6.2 Метрики производительности (Low)

Что измерять:

  • Время загрузки страницы
  • Время рендеринга панелей (per panel)
  • Размер памяти (heap size)
  • Количество stages

Инструменты: Web Vitals, Chrome DevTools Performance.


7. CI/CD

7.1 Текущее состояние

package.json scripts:

  • test - vitest
  • test:unit - unit tests
  • test:integration - нет такой папки
  • test:e2e - playwright test (но playwright не в devDependencies? есть)

Проблемы:

  • Нет папки tests/integration/
  • Нет папки tests/e2e/
  • Нет GitHub Actions / CI pipeline

7.2 Настроить CI (Medium Priority)

Цель: Автоматические тесты на каждом PR.

GitHub Actions:

# .github/workflows/ci.yml
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm ci
      - run: npm run check
      - run: npm run test:unit
      - run: npm run test:integration
      - run: npm run test:e2e
      - run: npm run build

Критерий успеха: Все тесты проходят на CI.


8. Документация

8.1 Кодовая документация (Medium)

Текущее состояние: Нет JSDoc/TSDoc комментариев.

Рекомендация:

  • Добавить JSDoc для всех публичных API (сервисы, состояния, компоненты)
  • Использовать /** */ с @param, @returns, @throws
  • Генерация docs через TypeDoc

Пример:

/**
 * Uploads an image from a File object.
 * @param file - The File object to upload
 * @returns Promise<ImageData> - The processed image data
 * @throws {ImageError} If file format or size is invalid
 */
uploadFromFile(file: File): Promise<ImageData> { ... }

8.2 Architecture Decision Records (ADR) (Low)

Цель: Зафиксировать ключевые архитектурные решения.

Файлы: docs/adr/ (или plans/adr/)

Примеры:

  • ADR-001: Выбор Svelte 5 с runes
  • ADR-002: Паттерн фабрики для состояний
  • ADR-003: Сервисный слой для бизнес-логики
  • ADR-004: Konva.js для рендеринга

9. Приоритизация по фазам

Фаза 1: Стабилизация (2-3 недели) - КРИТИЧНО

Цель: Устранить архитектурные проблемы, создать сервисный слой, добавить тесты.

Задачи:

  1. Рефакторинг состояний (1.1) - 2 дня
  2. Создание imageService (2.2.1) - 3 дня
  3. Создание storageService (2.2.2) - 2 дня
  4. Интеграционные тесты (3.3) - 3 дня
  5. Управление памятью Konva (2.4) - 2 дня

Итого: ~15 рабочих дней

Критерий успеха:

  • Все состояния используют фабричный паттерн
  • Сервисы покрыты unit тестами (>80%)
  • Интеграционные тесты покрывают критические flows
  • Нет утечек памяти при создании/удалении панелей

Фаза 2: Улучшение качества (3-4 недели) - ВАЖНО

Цель: Повысить поддерживаемость, производительность, доступность.

Задачи:

  1. Стандартизация UI-компонентов (2.3) - 3 дня
  2. Оптимизация производительности (2.2) - 4 дня
  3. Улучшение доступности (2.4) - 3 дня
  4. Расширенные тесты (3.4) - 5 дней
  5. CI/CD настройка (7.2) - 2 дня
  6. Документация (8.1) - 2 дня

Итого: ~19 рабочих дней

Критерий успеха:

  • Покрытие тестами >80%
  • Все компоненты доступны (WCAG AA)
  • Производительность: рендеринг 50 панелей < 1s
  • CI паsses на всех PR

Фаза 3: Продвинутые фичи (4+ недели) - НИЗКИЙ

Цель: Добавить удобные фичи для power users.

Задачи:

  1. Расширенные настройки текста (3.1) - 1 неделя
  2. Расширенные настройки изображений (3.2) - 1 неделя
  3. Пресеты и шаблоны (3.3) - 5 дней
  4. История изменений (4.4) - 3 дня
  5. Экспорт в PDF (4.3) - 4 дня

Итого: ~4 недели


10. Метрики технического успеха

  • Покрытие тестами: >80% (критические paths: 100%)
  • Производительность: FCP < 1s, LCP < 2.5s, рендеринг 50 панелей < 1s
  • Утечки памяти: 0 (проверка через Chrome DevTools)
  • Доступность: WCAG 2.1 AA compliance (axe-score > 90)
  • TypeScript ошибки: 0 (strict mode)
  • Lint: 0 ошибок (eslint + svelte-check)
  • CI: 100% pass rate

11. Риски и митигация

Риск Вероятность Влияние Митигация
Сложность Konva Medium High Документировать API, добавить абстракции
Утечки памяти High High Приоритет 1.4, тесты на память
Нет эксперта по Svelte 5 Medium Medium Изучить документацию, использовать best practices
Cropper.js интеграция Medium Medium Выделить отдельный сервис, тестировать изолированно
localStorage квоты Low Medium Валидация размера, fallback на JSON export
Производительность при 50+ панелях High Medium Виртуализация (Фаза 2)

12. Следующие шаги

  1. Утвердить технический план
  2. Начать с Фазы 1:
    • День 1-2: Рефакторинг konvaAllStages и imageConfig
    • День 3-5: Создание imageService
    • День 6-7: Создание storageService
    • День 11-13: Интеграционные тесты
    • День 14-15: Управление памятью Konva
  3. Запустить CI после Фазы 1
  4. Продолжить Фазу 2

Примечание: Этот план должен обновляться по мере реализации. Каждая фаза заканчивается review и корректировкой последующих фаз.