mirror of
https://github.com/gromlab-ru/slm-design.git
synced 2026-08-22 07:30:16 +03:00
sync
This commit is contained in:
@@ -10,21 +10,20 @@
|
||||
|
||||
Определения, рекомендации, разрешения, примеры и открытые вопросы не получают код правила.
|
||||
|
||||
Нормативные определения объявляются в терминологии соответствующего уровня. Они обязательны для толкования правил, но нормативность определения сама по себе не превращает его в правило.
|
||||
Нормативные определения объявляются в [терминологии SLM](../architecture/terminology.md). Они обязательны для толкования правил, но нормативность определения сама по себе не превращает его в правило.
|
||||
|
||||
## Код правила
|
||||
|
||||
```text
|
||||
SLM-L{level}-{group}-{class}{number}
|
||||
SLM-{group}-{class}{number}
|
||||
```
|
||||
|
||||
| Часть | Значение |
|
||||
|---|---|
|
||||
| `SLM` | Принадлежность архитектуре SLM |
|
||||
| `L{level}` | Уровень архитектуры |
|
||||
| `group` | Раздел правил |
|
||||
| `class` | Способ проверки: `A` или `R` |
|
||||
| `number` | Трёхзначный номер внутри уровня |
|
||||
| `number` | Глобально уникальный трёхзначный номер правила |
|
||||
|
||||
## Способы проверки
|
||||
|
||||
@@ -50,44 +49,33 @@ SLM-L{level}-{group}-{class}{number}
|
||||
| `COMPONENT` | Компоненты |
|
||||
| `NESTED_MODULE` | Вложенные модули |
|
||||
| `LIFECYCLE` | Жизненный цикл |
|
||||
| `DOMAIN` | Домены |
|
||||
| `API` | Доменный API |
|
||||
| `FACTORY` | Фабрики Domain API |
|
||||
| `ERROR` | Ошибки домена |
|
||||
| `PORT` | Dependency ports |
|
||||
| `ADAPTER` | Адаптеры |
|
||||
| `ASSEMBLY` | Сборка API и жизненный цикл |
|
||||
| `ENVIRONMENT` | Границы сред выполнения |
|
||||
| `FRAMEWORK` | Модули фреймворков |
|
||||
| `STATE` | Материализация состояния |
|
||||
| `REALTIME` | Realtime-взаимодействие |
|
||||
| `TEST` | Тестирование |
|
||||
|
||||
Код раздела записывается полным английским именем в `UPPER_SNAKE_CASE`. Новый код добавляется в таблицу до первого использования.
|
||||
|
||||
## Формат записи
|
||||
|
||||
```md
|
||||
### SLM-L1-MODULE-A004
|
||||
### SLM-MODULE-A004
|
||||
|
||||
> **Публичный API модуля**
|
||||
>
|
||||
> Каждый модуль предоставляет единый публичный API; код за пределами модуля импортирует его содержимое только через этот API.
|
||||
> Каждый модуль предоставляет единый логический публичный API через обязательный корневой фасет `index` и, при необходимости, фасеты `client`, `browser` и `server`; код за пределами модуля импортирует его содержимое только через эти фасеты.
|
||||
```
|
||||
|
||||
Код является заголовком третьего уровня и автоматически получает адрес для ссылки `#slm-l1-module-a004`.
|
||||
Код является заголовком третьего уровня и автоматически получает адрес для ссылки `#slm-module-a004`.
|
||||
|
||||
Название и описание входят в одну цитату. Название выделяется жирным и служит кратким именем правила. Описание полностью формулирует требование и занимает одну физическую строку.
|
||||
|
||||
Ссылка из тематического черновика:
|
||||
|
||||
```md
|
||||
[`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
|
||||
[`SLM-MODULE-A004`](./registry.md#slm-module-a004)
|
||||
```
|
||||
|
||||
## Как формулировать правила
|
||||
|
||||
1. Правило понятно без чтения тематической главы и опирается только на нормативные термины своего уровня.
|
||||
1. Правило понятно без чтения тематической главы и опирается только на нормативные термины SLM.
|
||||
2. Правило защищает один архитектурный инвариант.
|
||||
3. Один инвариант получает один код независимо от числа участников и способов проверки.
|
||||
4. Название является кратким и устойчивым именем правила.
|
||||
@@ -103,7 +91,7 @@ SLM-L{level}-{group}-{class}{number}
|
||||
|
||||
## Нумерация
|
||||
|
||||
1. Номер уникален внутри уровня независимо от раздела и способа проверки.
|
||||
1. Номер глобально уникален независимо от раздела и способа проверки.
|
||||
2. Номер не обозначает важность или порядок выполнения.
|
||||
3. Удалённый номер не переиспользуется для другого правила.
|
||||
4. При изменении способа проверки номер сохраняется, но меняется полный код.
|
||||
@@ -124,7 +112,6 @@ SLM-L{level}-{group}-{class}{number}
|
||||
|
||||
Корневой скрипт `draft-rules.js` читает объявления только из этой директории, проверяет формат и уникальность кодов, валидирует ссылки из остальных черновиков и выводит правила разделами «Автоматические» и «Для ревью». Скрипт проверяет документы, а не архитектуру приложения.
|
||||
|
||||
## Наборы правил
|
||||
## Реестр
|
||||
|
||||
- [Первый уровень](./level-1.md)
|
||||
- [Второй уровень](./level-2.md)
|
||||
- [Единый реестр правил SLM](./registry.md)
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
# Правила SLM второго уровня
|
||||
|
||||
Доменный пакет Level 2 соблюдает правила Level 1 и дополнительные правила этого реестра. Для предметной области в пакетной форме [`SLM-L1-DOMAIN-R015`](./level-1.md#slm-l1-domain-r015) заменяется правилами доменного пакета; остальные предметные области того же SLM root могут сохранять форму доменного модуля Level 1. [`SLM-L1-GROUP-R007`](./level-1.md#slm-l1-group-r007) сохраняется для Groups внутри пакета и вне слоя `domains`, а для навигационных Groups слоя `domains` заменяется `SLM-L2-GROUP-R004`. Для модуля `api` правило [`SLM-L1-MODULE-A004`](./level-1.md#slm-l1-module-a004) уточняется `SLM-L2-API-A019`: объявленные фасеты вместе образуют один логический публичный API и не считаются deep imports. Ранее использовавшиеся номера `SLM-L2-DOMAIN-R001` и `SLM-L2-MIGRATION-A017` не переиспользуются.
|
||||
|
||||
## Граница доменного пакета
|
||||
|
||||
### SLM-L2-DOMAIN-R002
|
||||
|
||||
> **Предметная граница пакета**
|
||||
>
|
||||
> Каждая предметная область, использующая пакетную форму Level 2, представлена ровно одним доменным пакетом; все его модули относятся только к этой предметной области.
|
||||
|
||||
### SLM-L2-DOMAIN-A003
|
||||
|
||||
> **Корень доменного пакета**
|
||||
>
|
||||
> Корень доменного пакета содержит только декларативную metadata, модуль `api` и допустимые Groups и не содержит других прямых модулей, исполняемых файлов, изменяемого состояния, ресурсов жизненного цикла, публичного API или реэкспортов.
|
||||
|
||||
### SLM-L2-GROUP-R004
|
||||
|
||||
> **Навигационная Group доменов**
|
||||
>
|
||||
> Group, расположенная непосредственно в слое `domains` или другой такой Group, содержит только доменные модули Level 1, доменные пакеты Level 2 и навигационные Groups и не владеет реализацией, состоянием, жизненным циклом или публичным API.
|
||||
|
||||
## Доменный API
|
||||
|
||||
### SLM-L2-API-R005
|
||||
|
||||
> **Модуль api**
|
||||
>
|
||||
> Каждый доменный пакет содержит ровно один модуль `api`, который объявляет один или несколько именованных Domain API, их публичные модели, результаты, ошибки, dependency ports и фабрики.
|
||||
|
||||
### SLM-L2-API-R006
|
||||
|
||||
> **Семантическая власть Domain API**
|
||||
>
|
||||
> Доступные приложению доменные данные, модели, validation, семантика команд и запросов, результаты и ожидаемые ошибки производятся или проверяются модулем `api`; adapters, assemblies и framework bindings не определяют параллельную предметную модель или переход.
|
||||
|
||||
### SLM-L2-API-A007
|
||||
|
||||
> **Импортная замкнутость api**
|
||||
>
|
||||
> Все runtime- и type-only импорты модуля `api`, кроме междоменных зависимостей по `SLM-L2-DEPENDENCY-A012`, ведут только к файлам этого модуля, объявленным environment-neutral ресурсам `shared` и внешним пакетам, объявленным как API-safe.
|
||||
|
||||
### SLM-L2-FACTORY-R008
|
||||
|
||||
> **Фабрики Domain API**
|
||||
>
|
||||
> Каждому публичному Domain API соответствует ровно одна именованная фабрика фасета `api/factory`; фабрика получает явные ports и cross-domain API, создаёт только этот Domain API, не выбирает adapter или assembly и не запускает скрытые ресурсы жизненного цикла.
|
||||
|
||||
## Ошибки домена
|
||||
|
||||
### SLM-L2-ERROR-R009
|
||||
|
||||
> **Публичный контракт ошибок**
|
||||
>
|
||||
> Каждый ожидаемый сбой публичной операции Domain API представлен именованным readonly сериализуемым типом собственной доменной ошибки с устойчивым кодом; тип экспортируется через `api`, а необходимые внешним потребителям runtime-коды и guards только через `api/runtime`.
|
||||
|
||||
### SLM-L2-ERROR-R010
|
||||
|
||||
> **Изоляция исходных ошибок**
|
||||
>
|
||||
> Сбой provider, adapter, SDK, транспорта, storage или другого домена, доступный приложению через Domain API, представлен только безопасной ошибкой собственного доменного контракта и не раскрывает исходный объект, тип, message, status, payload или cause.
|
||||
|
||||
## Assemblies и зависимости
|
||||
|
||||
### SLM-L2-ASSEMBLY-R011
|
||||
|
||||
> **Роль assembly**
|
||||
>
|
||||
> Каждая assembly является SLM-модулем одного объявленного production-контекста, выбирает adapter-модули, вызывает одну или несколько фабрик своего `api` и возвращает явный именованный граф готовых Domain API, не добавляя предметные операции, модели или ошибки.
|
||||
|
||||
### SLM-L2-DEPENDENCY-A012
|
||||
|
||||
> **Междоменные импорты Level 2**
|
||||
>
|
||||
> Статическая связь между разными доменными границами, хотя бы одна из которых является пакетом Level 2, допускает только type-only импорт публичного API доменного модуля Level 1 или фасета `api` пакета Level 2 либо runtime-импорт `api/runtime` пакета Level 2; остальные публичные и внутренние пути другого домена не импортируются.
|
||||
|
||||
### SLM-L2-ENVIRONMENT-A013
|
||||
|
||||
> **Совместимость среды выполнения**
|
||||
>
|
||||
> Для каждой объявленной точки входа, поддерживаемого набора resolver conditions и framework execution phase её достижимый executable import-граф не содержит несовместимых runtime capabilities; type-only связи, framework reference и deferred edges проверяются отдельно и не считаются обычным выполнением.
|
||||
|
||||
## Framework Groups и тестирование
|
||||
|
||||
### SLM-L2-FRAMEWORK-R014
|
||||
|
||||
> **Framework Group домена**
|
||||
>
|
||||
> Framework binding modules доменного пакета размещаются в Group, названной по фреймворку, и каждый прямой дочерний элемент этой Group является framework binding module.
|
||||
|
||||
### SLM-L2-FRAMEWORK-R015
|
||||
|
||||
> **Framework binding module**
|
||||
>
|
||||
> Модуль внутри Framework Group владеет одной domain-specific framework-ответственностью, получает готовые Domain API, материализует их значения средствами фреймворка и не вызывает фабрики, не выбирает adapters, не обращается к предметному внешнему источнику в обход Domain API и не владеет страницей, маршрутом или multi-domain композицией.
|
||||
|
||||
### SLM-L2-TEST-R016
|
||||
|
||||
> **Проверка владельцев Level 2**
|
||||
>
|
||||
> Каждый публичный сценарий проверяется через фабрику владеющего им Domain API, каждый adapter — по контракту реализуемого port, а основные тесты assembly и framework binding module проверяют только собственные публичные границы и не повторяют полный набор сценариев Domain API.
|
||||
|
||||
## Совместное применение форм
|
||||
|
||||
### SLM-L2-DOMAIN-A026
|
||||
|
||||
> **Однозначная форма домена**
|
||||
>
|
||||
> Каждая предметная область объявлена ровно в одной форме: как доменный модуль Level 1 либо как доменный пакет Level 2; один SLM root может одновременно содержать разные предметные области обеих форм.
|
||||
|
||||
## Внешние библиотеки api
|
||||
|
||||
### SLM-L2-API-R018
|
||||
|
||||
> **API-safe внешний пакет**
|
||||
>
|
||||
> Внешний пакет объявляется API-safe только если он детерминирован, не выполняет ввод-вывод, не владеет изменяемым состоянием или runtime capability и не является SDK, generated client, storage, state/query manager, framework или другой технической интеграцией.
|
||||
|
||||
## Публичные фасеты api
|
||||
|
||||
### SLM-L2-API-A019
|
||||
|
||||
> **Публичные фасеты api**
|
||||
>
|
||||
> Публичный API модуля `api` имеет обязательные entry points `api` только с type exports и `api/factory` только с runtime exports, может иметь `api/ports` только при наличии объявленного dependency port и только с type exports и `api/runtime` только с runtime exports и не имеет других публичных путей или deep imports.
|
||||
|
||||
## Обязательная штатная сборка
|
||||
|
||||
### SLM-L2-ASSEMBLY-A020
|
||||
|
||||
> **Обязательная assembly default**
|
||||
>
|
||||
> Корень каждого доменного пакета содержит ровно одну непустую Group `assemblies` с ровно одним прямым модулем `default`; каждый другой прямой дочерний элемент Group также является объявленной границей assembly-модуля.
|
||||
|
||||
### SLM-L2-ADAPTER-R021
|
||||
|
||||
> **Модули production adapters**
|
||||
>
|
||||
> Если хотя бы одна фабрика имеет dependency port, корень доменного пакета содержит непустую Group `adapters`, а каждая связная production-реализация одного или нескольких ports принадлежит ровно одному adapter-модулю этой Group и не определяется в другом месте production-графа.
|
||||
|
||||
### SLM-L2-API-A022
|
||||
|
||||
> **Потребители фасетов и сборочных модулей**
|
||||
>
|
||||
> Фасет `api` импортируется извне только через `import type`, `api/ports` импортируют только adapters своего домена, assemblies и тесты, `api/factory` и concrete adapters в production импортируют только assemblies своего домена, а `api/runtime` не импортируют adapters и используют только через объявленный публичный путь с соблюдением правил слоёв и междоменных зависимостей.
|
||||
|
||||
## Жизненный цикл assembly
|
||||
|
||||
### SLM-L2-ASSEMBLY-R023
|
||||
|
||||
> **Транзакционный lifecycle assembly**
|
||||
>
|
||||
> Assembly не запускает скрытую долгоживущую работу; cleanup каждого созданного ею ресурса и каждого полученного adapter lifecycle handle немедленно регистрируется, при частичной ошибке выполняется в обратном порядке, а успешный результат с cleanup obligations предоставляет идемпотентный aggregate cleanup, после завершения которого resources не вызывают callbacks.
|
||||
|
||||
## Недетерминизм api
|
||||
|
||||
### SLM-L2-API-R024
|
||||
|
||||
> **Явные источники недетерминизма**
|
||||
>
|
||||
> Операция Domain API получает текущее время, timer, random, ID generator, environment и другие источники недетерминизма только через явные ports фабрики и не читает их из скрытого runtime-окружения.
|
||||
|
||||
## Публичный runtime api
|
||||
|
||||
### SLM-L2-API-R025
|
||||
|
||||
> **Детерминированный runtime api**
|
||||
>
|
||||
> Фасет `api/runtime` экспортирует только необходимые реальным внешним потребителям детерминированные значения и функции без ввода-вывода, изменяемого состояния, runtime capability или environment-specific поведения.
|
||||
|
||||
## Dependency ports
|
||||
|
||||
### SLM-L2-PORT-R027
|
||||
|
||||
> **Consumer-owned port**
|
||||
>
|
||||
> Каждый dependency port принадлежит модулю `api`, описывает минимальную необходимую ему capability и закрытый набор ожидаемых port failures без concrete provider, SDK, framework или transport types; adapter реализует этот контракт, но не определяет его семантику.
|
||||
|
||||
## Материализация состояния
|
||||
|
||||
### SLM-L2-STATE-R028
|
||||
|
||||
> **Framework-owned materialization**
|
||||
>
|
||||
> Framework binding или composition может владеть framework metadata и собственным UI-state, но материализует доменный payload только из values, outcomes и events, произведённых или проверенных Domain API, и применяет предметный optimistic merge, reconciliation или transition только через операцию либо детерминированный runtime модуля `api`.
|
||||
|
||||
## Realtime
|
||||
|
||||
### SLM-L2-REALTIME-R029
|
||||
|
||||
> **Проверяемый realtime-контракт**
|
||||
>
|
||||
> Каждый realtime port явно определяет correlation, момент подтверждения команды, ordering, duplicate, reconnect, resync, cancellation и cleanup semantics; adapter скрывает transport protocol, а Domain API публикует только проверенные события, outcomes и собственные стабильные ошибки.
|
||||
|
||||
## Runtime-граф assemblies
|
||||
|
||||
### SLM-L2-ASSEMBLY-R030
|
||||
|
||||
> **Ацикличная runtime-сборка**
|
||||
>
|
||||
> Runtime-граф публичных API доменных модулей Level 1 и Domain API пакетов Level 2, включая assembly inputs, factory dependencies и передаваемые callbacks, не содержит циклов, а graph owner создаёт независимые API раньше зависимых и очищает их в обратном порядке.
|
||||
|
||||
### SLM-L2-ASSEMBLY-R031
|
||||
|
||||
> **Контекст default assembly**
|
||||
>
|
||||
> `assemblies/default` представляет один объявленный штатный production-набор API, dependencies, runtime capabilities и lifecycle; имя `default` само по себе не означает browser-, server- или isomorphic-совместимость, а отличающийся контекст получает отдельную именованную assembly.
|
||||
@@ -1,21 +1,22 @@
|
||||
# Правила SLM первого уровня
|
||||
Здесь собраны правила первого уровня. Это единственное место, где они формулируются; тематические черновики объясняют их и ссылаются на коды.
|
||||
# Реестр правил SLM
|
||||
|
||||
Здесь собраны правила SLM. Это единственное место, где они формулируются; тематические черновики объясняют их и ссылаются на коды.
|
||||
|
||||
## Размещение кода по слоям
|
||||
|
||||
### SLM-L1-LAYER-R001
|
||||
### SLM-LAYER-R001
|
||||
|
||||
> **Назначение слоёв**
|
||||
>
|
||||
> Код внутри SLM root размещается в слое, нормативная роль которого соответствует ответственности этого кода.
|
||||
|
||||
### SLM-L1-LAYER-A002
|
||||
### SLM-LAYER-A002
|
||||
|
||||
> **Направление зависимостей**
|
||||
>
|
||||
> Внутри одного SLM root код каждого слоя может зависеть только от кода целевых слоёв, разрешённых для него нормативной матрицей слоёв.
|
||||
|
||||
### SLM-L1-LAYER-R003
|
||||
### SLM-LAYER-R003
|
||||
|
||||
> **Граница слоя `app`**
|
||||
>
|
||||
@@ -23,31 +24,31 @@
|
||||
|
||||
## Границы модулей
|
||||
|
||||
### SLM-L1-MODULE-A004
|
||||
### SLM-MODULE-A004
|
||||
|
||||
> **Публичный API модуля**
|
||||
>
|
||||
> Каждый модуль предоставляет единый публичный API; код за пределами модуля импортирует его содержимое только через этот API.
|
||||
> Каждый модуль предоставляет единый логический публичный API через обязательный корневой фасет `index` и, при необходимости, фасеты `client`, `browser` и `server`; код за пределами модуля импортирует его содержимое только через эти фасеты.
|
||||
|
||||
### SLM-L1-MODULE-A014
|
||||
### SLM-MODULE-A014
|
||||
|
||||
> **Папка модуля**
|
||||
>
|
||||
> Каждый модуль размещается в отдельной папке; его публичный API и внутренняя реализация находятся внутри этой границы, а вложенные модули образуют собственные папки.
|
||||
|
||||
### SLM-L1-MODULE-R006
|
||||
### SLM-MODULE-R006
|
||||
|
||||
> **Ответственность модуля**
|
||||
>
|
||||
> Одна модульная граница содержит код одной связной ответственности; части, которые изменяются по несвязанным причинам, размещаются в разных модулях.
|
||||
|
||||
### SLM-L1-MODULE-R011
|
||||
### SLM-MODULE-R011
|
||||
|
||||
> **Владелец ответственности**
|
||||
>
|
||||
> Каждая самостоятельная ответственность и относящийся к ней код принадлежат ровно одному модулю; вне модульной границы допускаются только точки входа `app` и нормативные ресурсы `shared`.
|
||||
|
||||
### SLM-L1-MODULE-R012
|
||||
### SLM-MODULE-R012
|
||||
|
||||
> **Состав публичного API**
|
||||
>
|
||||
@@ -55,15 +56,15 @@
|
||||
|
||||
## Зависимости между модулями
|
||||
|
||||
### SLM-L1-DEPENDENCY-A005
|
||||
### SLM-DEPENDENCY-A005
|
||||
|
||||
> **Циклические зависимости**
|
||||
>
|
||||
> Граф зависимостей модулей внутри одного SLM root, включая вложенные модули, не содержит циклов.
|
||||
> Зависимости между модулями внутри одного SLM root, включая вложенные модули, не образуют циклов.
|
||||
|
||||
## Назначение групп
|
||||
|
||||
### SLM-L1-GROUP-R007
|
||||
### SLM-GROUP-R007
|
||||
|
||||
> **Назначение группы**
|
||||
>
|
||||
@@ -71,15 +72,15 @@
|
||||
|
||||
## Назначение сегментов
|
||||
|
||||
### SLM-L1-SEGMENT-R008
|
||||
### SLM-SEGMENT-R008
|
||||
|
||||
> **Граница сегмента**
|
||||
>
|
||||
> Сегмент организует код только внутри одного модуля и не имеет собственной ответственности, публичного API или узла графа зависимостей.
|
||||
> Сегмент организует код только внутри одного модуля и не имеет собственной ответственности, публичного API или границы зависимостей.
|
||||
|
||||
## Ответственность компонентов
|
||||
|
||||
### SLM-L1-COMPONENT-R009
|
||||
### SLM-COMPONENT-R009
|
||||
|
||||
> **Ответственность компонента**
|
||||
>
|
||||
@@ -87,7 +88,7 @@
|
||||
|
||||
## Границы вложенных модулей
|
||||
|
||||
### SLM-L1-NESTED_MODULE-A010
|
||||
### SLM-NESTED_MODULE-A010
|
||||
|
||||
> **Доступ к вложенному модулю**
|
||||
>
|
||||
@@ -95,16 +96,34 @@
|
||||
|
||||
## Жизненный цикл
|
||||
|
||||
### SLM-L1-LIFECYCLE-R013
|
||||
### SLM-LIFECYCLE-R013
|
||||
|
||||
> **Жизненный цикл ресурсов**
|
||||
>
|
||||
> Для каждого ресурса жизненного цикла модуль-владелец определяет создание, область жизни, число экземпляров и очистку; ресурс активен только внутри своей области жизни.
|
||||
|
||||
## Граница доменных модулей
|
||||
## Границы сред выполнения
|
||||
|
||||
### SLM-L1-DOMAIN-R015
|
||||
### SLM-ENVIRONMENT-R016
|
||||
|
||||
> **Доменный модуль**
|
||||
> **Универсальный фасет**
|
||||
>
|
||||
> Каждая самостоятельная предметная область слоя `domains` представлена ровно одним доменным модулем; принадлежащие ей модели, правила, сценарии и продуктовое состояние размещаются внутри его границы, включая границы вложенных модулей.
|
||||
> Корневой фасет `index` экспортирует только публичный код, совместимый как с серверным рендерингом, включая RSC, так и с клиентским выполнением, и не импортирует или реэкспортирует код фасетов `client`, `browser` или `server` прямо либо транзитивно.
|
||||
|
||||
### SLM-ENVIRONMENT-R017
|
||||
|
||||
> **Клиентский фасет**
|
||||
>
|
||||
> Фасет `client` экспортирует только клиентский код, который не может выполняться как RSC, и не импортирует или реэкспортирует код фасетов `browser` или `server` прямо либо транзитивно.
|
||||
|
||||
### SLM-ENVIRONMENT-R018
|
||||
|
||||
> **Браузерный фасет**
|
||||
>
|
||||
> Фасет `browser` экспортирует только browser-only код, а потребители импортируют его только динамически с отключённым SSR.
|
||||
|
||||
### SLM-ENVIRONMENT-R019
|
||||
|
||||
> **Серверный фасет**
|
||||
>
|
||||
> Фасет `server` экспортирует только server-only код и не импортируется или реэкспортируется фасетами `index`, `client` или `browser` прямо либо транзитивно.
|
||||
Reference in New Issue
Block a user