# Архитектурные правила ## Изоляция modes Каждый полный mode key является независимым adapter со своим generated-контрактом: - `react@vite`; - `react@webpack`; - `next@app/turbopack`; - `next@app/webpack`; - `next@pages/turbopack`; - `next@pages/webpack`; - `standalone`; - `standalone@vite`; - `standalone@webpack`; - будущие `vue@*` и другие modes. Для каждого exact mode используется отдельный каталог `src/modes//`. Adapter самостоятельно определяет: - compile options; - список и имена generated-файлов; - runtime JavaScript; - TypeScript declarations; - manifest source; - CSS; - способ получения asset URL; - mode-specific result metadata. Изменение output одного mode не должно менять output другого mode. Дублирование component, manifest, declaration и CSS codegen между adapters является сознательной ценой изоляции. Запрещено: - импортировать один `src/modes//` из другого mode; - создавать общий framework/component/manifest/CSS codegen для нескольких modes; - создавать общий runtime asset URL generator для нескольких modes; - ветвиться по generic target внутри adapter; - писать generated-файлы непосредственно из adapter через `fs`; - импортировать exact-mode adapters из core. Единственное место, которое импортирует все adapters, — `src/mode-registry.ts`. ## Общий core Общими могут быть только mode-neutral данные и инфраструктура: - загрузка, merge и валидация config; - scanner исходных SVG; - shape IDs и проверка конфликтов; - низкоуровневый SVG compiler и transformations; - подготовка нейтрального compiled artifact; - protocol `ModeAdapter`/`OutputPlan`; - проверка output paths; - staged directory writer и symlink protection; - logger и базовые result types. Core не генерирует JavaScript, declarations, manifest source, CSS или framework-specific exports. Изменение общего compiler может ожидаемо изменить SVG всех modes; изменение generated source должно быть локально одному adapter. ## Generated-контракт Один config разрешается ровно в один mode и один output. Множественные modes не генерируются в один root; orchestration выполняется независимыми config/API/CLI вызовами. Runtime генерируется как ESM JavaScript. Типизация добавляется отдельными `.d.ts`; TypeScript/TSX не используется как runtime output. Core writer полностью владеет каталогом `.svg-sprite` и при каждой генерации заменяет его через временный каталог с rollback при ошибке. Корневым `.gitignore` writer владеет, когда exact-mode adapter запрашивает его через `OutputPlan`. Bare `standalone` не создаёт `.gitignore`; остальные modes создают. Sprite-level asset, icon data, manifest и facade лежат непосредственно в `.svg-sprite/`. `standalone@vite` и `standalone@webpack` генерируют нативный icon Web Component внутри своего facade; bare `standalone` остаётся без JavaScript runtime. Framework runtime группируется отдельно: React adapters используют `.svg-sprite/react/`, будущие framework adapters получают собственный framework-каталог. Adapter возвращает файлы в памяти. Только core writer проверяет paths, полностью заменяет `.svg-sprite` и обновляет управляемый `.gitignore`. ## Зависимости Допустимое направление импортов: ```text public API / CLI -> generate -> mode-registry -> один exact-mode adapter -> core protocols and services ``` Обратные и горизонтальные зависимости запрещены: ```text core -X-> modes mode A -X-> mode B mode A -X-> shared output codegen ``` `src/viewer/` с Web Component является framework-neutral browser runtime пакета, а не mode adapter. `src/react/` содержит только React bridge к этому runtime. ## Изменение mode При работе с adapter: 1. Изменяйте только его каталог и mode-neutral protocol, если это действительно необходимо. 2. Не переносите output-логику в core ради устранения дублирования. 3. Не меняйте generated-контракты других adapters автоматически. 4. Проверяйте отсутствие cross-mode imports.