mirror of
https://github.com/gromlab-ru/slm-design.git
synced 2026-08-22 07:30:16 +03:00
chore: Обновить ридми и CI скачивания скилла
This commit is contained in:
43
.github/workflows/docs.yml
vendored
43
.github/workflows/docs.yml
vendored
@@ -7,8 +7,13 @@ on:
|
||||
- '.github/workflows/docs.yml'
|
||||
- 'docs/**'
|
||||
- 'site/**'
|
||||
- 'src-skills/**'
|
||||
- 'skills/**'
|
||||
- 'scripts/build-skill.mjs'
|
||||
- 'scripts/check-skill.mjs'
|
||||
- 'scripts/check-docs.mjs'
|
||||
- 'scripts/check-site.mjs'
|
||||
- 'scripts/lib/skill-bundle.mjs'
|
||||
- 'scripts/lib/slugify-heading.mjs'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
@@ -17,8 +22,13 @@ on:
|
||||
- '.github/workflows/docs.yml'
|
||||
- 'docs/**'
|
||||
- 'site/**'
|
||||
- 'src-skills/**'
|
||||
- 'skills/**'
|
||||
- 'scripts/build-skill.mjs'
|
||||
- 'scripts/check-skill.mjs'
|
||||
- 'scripts/check-docs.mjs'
|
||||
- 'scripts/check-site.mjs'
|
||||
- 'scripts/lib/skill-bundle.mjs'
|
||||
- 'scripts/lib/slugify-heading.mjs'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
@@ -49,8 +59,37 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Check documentation
|
||||
run: npm run check:site
|
||||
- name: Check project
|
||||
run: npm run check
|
||||
|
||||
- name: Resolve skill tree hash
|
||||
id: skill
|
||||
run: echo "tree_hash=$(git rev-parse HEAD:skills/slm-design)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Restore skill archive
|
||||
id: skill-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/slm-design.zip
|
||||
key: slm-design-zip-v1-${{ steps.skill.outputs.tree_hash }}
|
||||
|
||||
- name: Pack skill
|
||||
if: steps.skill-cache.outputs.cache-hit != 'true'
|
||||
run: >-
|
||||
git archive
|
||||
--format=zip
|
||||
--prefix=slm-design/
|
||||
--mtime=2000-01-01T00:00:00Z
|
||||
--output="$RUNNER_TEMP/slm-design.zip"
|
||||
"${{ steps.skill.outputs.tree_hash }}"
|
||||
|
||||
- name: Verify skill archive
|
||||
run: unzip -t "$RUNNER_TEMP/slm-design.zip"
|
||||
|
||||
- name: Add skill archive to Pages
|
||||
run: |
|
||||
mkdir -p site/.vitepress/dist/downloads
|
||||
cp "$RUNNER_TEMP/slm-design.zip" site/.vitepress/dist/downloads/slm-design.zip
|
||||
|
||||
- name: Configure Pages
|
||||
uses: actions/configure-pages@v5
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
name: rest-client
|
||||
description: "Используй при создании, изменении или ревью REST API клиента и infra REST-модуля. Триггеры: REST API, REST client, API client, backend API, external API, OpenAPI, Swagger, ручной клиент без OpenAPI, @gromlab/api-codegen, @gromlab/api-codegen@5.1.0, src/infra/*-rest-api, *-rest-api-sdk, REST SDK, npm SDK, client.ts, rest-api.ts, operations-tree.ts, *HttpClient, *RestApi, generated/, operations/, operations/*, data-contracts, hooks/, types/, errors/, HttpClient, ApiRequestClient, RequestParams, ContentType, createApiClient, operationsTree, full client, minimal client, SDK exports, onRequest, onResponse, onError, JWT, refresh token, ApiError, useGet*, get*Key, useSWR, SWRConfiguration, DTO, API error, public API REST-модуля. НЕ используй для любого fetch вне REST-клиента проекта, route-level data fetching Next.js, SLM-архитектуры без REST-модуля, code style, SVG sprites или генерации шаблонов."
|
||||
metadata:
|
||||
internal: true
|
||||
---
|
||||
|
||||
<!-- Generated from src/SKILL.md. Do not edit manually. -->
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
name: slm-design
|
||||
description: "Экспертная работа с архитектурой SLM Design: проектирование, изменение, миграция и ревью слоёв app/compositions/domains/infra/ui/shared, модулей, доменов, публичных фасетов index/client/browser/server, групп, сегментов, вложенных модулей, зависимостей, состояния и lifecycle. Триггеры: SLM, Scoped Layered Module Design, SLM root, ответственность, владелец, модульная граница, domains vs compositions, доменный контракт, DTO, глубокий импорт, модульный цикл, архитектурное ревью. НЕ применять для обычного code style или локальной правки, не затрагивающей архитектурное решение."
|
||||
metadata:
|
||||
internal: true
|
||||
---
|
||||
|
||||
# SLM Design
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
name: style-guide
|
||||
description: "Используй при создании, изменении, форматировании или ревью frontend-кода для соблюдения code style и style guide. Триггеры: JS, TS, JSX, TSX, HTML, CSS, .js, .ts, .jsx, .tsx, .module.css, React-компонент, props, стили, CSS Modules, JSDoc, документация, именование, импорты/экспорты, типизация, отформатировать по гайду, поправить кодстайл. НЕ используй для архитектуры SLM, выбора слоя/модуля/public API, генерации .templates, Next.js routing/data fetching/rendering, настройки PostCSS/tooling, backend-кода и вопросов без правки frontend-кода."
|
||||
description: "Используй при создании, изменении, форматировании или ревью frontend-кода и физическом оформлении уже спроектированных SLM-модулей по code style и style guide. Триггеры: JS, TS, JSX, TSX, HTML, CSS, .js, .ts, .jsx, .tsx, .module.css, React-компонент, Provider, Guard, Error Boundary, props, components/, providers/, modules/, ErrorCode, код ошибки, SCREAMING_SNAKE_CASE, стили, CSS Modules, JSDoc, документация, именование, импорты/экспорты, типизация, отформатировать по гайду, поправить кодстайл. НЕ используй для выбора владельца, слоя, модульной границы или public API по SLM, генерации .templates, Next.js routing/data fetching/rendering, настройки PostCSS/tooling, backend-кода и вопросов без правки frontend-кода; в смешанной задаче сначала примени slm-design."
|
||||
metadata:
|
||||
internal: true
|
||||
---
|
||||
|
||||
<!-- Generated from src/SKILL.md. Do not edit manually. -->
|
||||
@@ -38,6 +40,7 @@ description: "Используй при создании, изменении, ф
|
||||
| Переменные и функции | `camelCase` |
|
||||
| Классы, типы, React-компоненты | `PascalCase` |
|
||||
| Константы верхнего уровня | `SCREAMING_SNAKE_CASE` |
|
||||
| Собственные коды ошибок | `SCREAMING_SNAKE_CASE` |
|
||||
| Хуки | `useSomething` |
|
||||
| CSS-классы в CSS Modules | `camelCase` |
|
||||
| Enum-ключи | `SCREAMING_SNAKE_CASE` |
|
||||
@@ -89,6 +92,57 @@ description: "Используй при создании, изменении, ф
|
||||
- Имена соответствуют типу сущности и локальному стандарту проекта.
|
||||
- Комментарии объясняют причину или назначение, а не пересказывают код.
|
||||
|
||||
## Физическая структура SLM
|
||||
|
||||
Сначала определи архитектурную роль единицы по правилам `slm-design`. Этот раздел не выбирает владельца и не решает, нужен компонент или вложенный модуль: он задаёт обязательный путь после принятого архитектурного решения.
|
||||
|
||||
### Сопоставление единиц с каталогами
|
||||
|
||||
- Вложенные framework-компоненты, кроме `Provider`, размещай в `components/`.
|
||||
- `Guard` и `Error Boundary` считай framework-компонентами и размещай в `components/`.
|
||||
- Вложенные `Provider` размещай в `providers/`, а не в `components/`.
|
||||
- Вложенные SLM-модули размещай в `modules/`.
|
||||
- Внутри модуля не используй `ui/`, `parts/` или другой каталог как альтернативное имя для `components/`, `providers/` или `modules/`.
|
||||
- Не создавай эти каталоги заранее: добавляй каталог, когда в модуле появляется соответствующая единица.
|
||||
|
||||
```text
|
||||
checkout/
|
||||
├── index.ts
|
||||
├── checkout.tsx
|
||||
├── styles/
|
||||
├── types/
|
||||
├── components/
|
||||
│ ├── order-summary/
|
||||
│ ├── checkout-guard/
|
||||
│ └── checkout-error-boundary/
|
||||
├── providers/
|
||||
│ └── checkout-events-provider/
|
||||
└── modules/
|
||||
└── form-session/
|
||||
```
|
||||
|
||||
### Корневой framework-файл
|
||||
|
||||
Один главный framework-файл модуля может находиться непосредственно в корне, если он реализует или собирает ответственность модуля. Исключение распространяется и на главный `Provider`.
|
||||
|
||||
Корневой файл не дублируй в `components/` или `providers/`. Остальные компоненты и providers этого модуля размещай в соответствующих каталогах.
|
||||
|
||||
### Ограничение вложенности
|
||||
|
||||
- Единицы внутри `components/` и `providers/` являются соседями относительно модуля.
|
||||
- Каталог компонента или Provider не содержит собственные `components/`, `providers/` или `modules/`.
|
||||
- Следующий структурный уровень создавай только через вложенный модуль в `modules/`.
|
||||
- Runtime-вложенность JSX не повторяй файловой вложенностью: компонент может рендерить другой компонент, оставаясь его файловым соседом.
|
||||
|
||||
### Чеклист структуры SLM
|
||||
|
||||
- Архитектурная роль определена до выбора каталога.
|
||||
- Компоненты, Guards и Error Boundaries находятся в `components/`.
|
||||
- Вложенные Providers находятся в `providers/`.
|
||||
- Вложенные модули находятся в `modules/`.
|
||||
- Главный framework-файл является единственной корневой implementation-единицей модуля.
|
||||
- Компонентные каталоги не создают рекурсивную файловую иерархию.
|
||||
|
||||
## JS/TS
|
||||
|
||||
Применяй этот раздел к `.js`, `.ts` и JS/TS-частям `.jsx` и `.tsx`. Для React-компонентов дополнительно применяй раздел `React и TSX`, для разметки - раздел `HTML, JSX и TSX`.
|
||||
@@ -466,6 +520,28 @@ export type OrderFilters = {
|
||||
}
|
||||
```
|
||||
|
||||
#### Коды ошибок
|
||||
|
||||
- Собственные коды ошибок проекта записывай в `SCREAMING_SNAKE_CASE` независимо от способа их представления.
|
||||
- Не переименовывай непрозрачный код внешнего источника: сначала интерпретируй его на границе владельца и сопоставь с собственным кодом проекта.
|
||||
- Каждый type, объявляющий набор кодов ошибок, документируй многострочным JSDoc.
|
||||
- Каждый литерал в union кодов ошибок снабжай отдельным JSDoc непосредственно перед литералом.
|
||||
- Комментарий литерала объясняет ожидаемый исход, условие его возникновения или решение, которое по нему принимает потребитель.
|
||||
- Не пересказывай в комментарии имя кода и не объединяй несколько кодов одним комментарием.
|
||||
|
||||
```ts
|
||||
/**
|
||||
* Ожидаемые неуспешные исходы сценариев заказа.
|
||||
*/
|
||||
export type OrderErrorCode =
|
||||
/** Товар изменился после добавления в черновик заказа. */
|
||||
| 'PRODUCT_CHANGED'
|
||||
/** Запрошенное количество товара отсутствует на складе. */
|
||||
| 'INSUFFICIENT_STOCK'
|
||||
/** Заказ нельзя отменить в его текущем состоянии. */
|
||||
| 'CANNOT_CANCEL'
|
||||
```
|
||||
|
||||
#### Константы
|
||||
|
||||
- Документируй константу только если она является публичным контрактом, доменным ограничением, magic value или переиспользуемой конфигурацией.
|
||||
@@ -534,29 +610,36 @@ export const formatPrice = (value: number): string => {
|
||||
- Доменные guards размещены рядом с владельцем данных, а не в `shared/lib/value-predicates`.
|
||||
- Импорты типов оформлены через `import type`, а экспорты типов через `export type`.
|
||||
- Public API не раскрывает implementation details.
|
||||
- Собственные error codes записаны в `SCREAMING_SNAKE_CASE`, а каждый код имеет отдельный содержательный JSDoc.
|
||||
- JS/TS-функции, классы, типы, интерфейсы, поля типов, enum, значения enum и константы-контракты документированы по правилам своего подраздела.
|
||||
|
||||
## React и TSX
|
||||
|
||||
Этот раздел описывает прикладную форму React UI-сущности после того, как архитектура уже определила её место: компонент внутри `ui/` или UI-модуль с корневым `.tsx`. Архитектурные границы компонентов, модулей, сегментов и public API определяет `slm-design`. Форму JSX-разметки дополнительно проверяй по разделу `HTML, JSX и TSX`.
|
||||
Этот раздел описывает прикладную форму React framework-компонента после того, как архитектура уже определила его владельца и место. Правила распространяются на визуальные компоненты, Providers, Guards и Error Boundaries. Архитектурные границы компонентов, модулей, сегментов и public API определяет `slm-design`. Форму JSX-разметки дополнительно проверяй по разделу `HTML, JSX и TSX`.
|
||||
|
||||
### Базовая React UI-сущность
|
||||
### Обязательный обвес framework-компонента
|
||||
|
||||
- Используй эту форму для базового React-компонента или UI-модуля с корневым компонентом.
|
||||
- Используй эту форму для каждого React framework-компонента, включая Provider, Guard и Error Boundary.
|
||||
- Каждый вложенный framework-компонент размещай в отдельной папке согласно разделу `Физическая структура SLM`.
|
||||
- Держи `.tsx`, props-типы, CSS Module и локальный `index.ts` в отдельных файлах.
|
||||
- Файлы структуры обязательны даже для невизуального компонента без собственного DOM: `.tsx`, `types/`, `styles/`, `index.ts`.
|
||||
- Не объявляй props-типы внутри `.tsx`.
|
||||
- Не размещай CSS рядом с TSX-кодом: стили живут в `styles/{name}.module.css`.
|
||||
- Корневой CSS-класс всегда называется `.root`.
|
||||
- Для компонента с собственным DOM корневой CSS-класс называется `.root`.
|
||||
- Для невизуального компонента создай пустой CSS Module, но не импортируй его до появления стилизуемого DOM.
|
||||
- Не добавляй Provider, Guard или другой невизуальный компонент DOM-wrapper только ради использования CSS Module.
|
||||
- Компонент обязан иметь JSDoc-комментарий по React-шаблону.
|
||||
- Всё, что не является React-компонентом, документируй по правилам `Документирование JS/TS`.
|
||||
|
||||
### Структура файлов
|
||||
|
||||
- Базовая React UI-сущность живёт в собственной папке.
|
||||
- Файлы структуры обязательны для новой сущности: `.tsx`, `types/`, `styles/`, `index.ts`.
|
||||
- Вложенный framework-компонент живёт в собственной папке.
|
||||
- Имя файла props-типа строится как `{name}-props.type.ts`.
|
||||
- CSS Module строится как `{name}.module.css`.
|
||||
- `index.ts` экспортирует компонент и public props-тип.
|
||||
- Локальный `index.ts` экспортирует компонент и props-тип для использования внутри модуля.
|
||||
- Единственное исключение из собственной папки — главный framework-файл модуля, включая главный Provider.
|
||||
- Для главного framework-файла папкой компонента является корень модуля: `styles/` и `types/` создаются непосредственно в нём.
|
||||
- Корневой `index.ts` остаётся публичным фасетом модуля и экспортирует компонент только через фасет, разрешённый архитектурой и средой выполнения.
|
||||
|
||||
```text
|
||||
user-status/
|
||||
@@ -568,16 +651,29 @@ user-status/
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
Корневой framework-файл использует тот же обвес без дополнительной папки:
|
||||
|
||||
```text
|
||||
module/
|
||||
├── index.ts
|
||||
├── <root-framework-file>.tsx
|
||||
├── styles/
|
||||
│ └── {name}.module.css
|
||||
└── types/
|
||||
└── {name}-props.type.ts
|
||||
```
|
||||
|
||||
### Типизация props
|
||||
|
||||
- Props-типы выноси в `types/{name}-props.type.ts`.
|
||||
- Собственные параметры компонента называй `{Name}Params`.
|
||||
- Атрибуты корневого HTML-элемента называй `RootAttrs`.
|
||||
- Атрибуты собственного корневого HTML-элемента называй `RootAttrs`.
|
||||
- Итоговый тип props называй `{Name}Props`.
|
||||
- `RootAttrs` типизируй через `ComponentPropsWithoutRef<'tag'>`.
|
||||
- Для компонента с собственным DOM типизируй `RootAttrs` через `ComponentPropsWithoutRef<'tag'>`.
|
||||
- Для Provider или другого компонента без собственного DOM не создавай фиктивный `RootAttrs`.
|
||||
- Исключай из `RootAttrs` атрибуты, которыми компонент управляет сам: например `children`, если компонент рендерит собственный контент.
|
||||
- Если собственный параметр конфликтует с HTML-атрибутом, исключай этот атрибут через `Omit`.
|
||||
- Документируй `Params`, `RootAttrs`, `Props` и каждое поле props по правилам `JS/TS`.
|
||||
- Документируй все объявленные `Params`, `RootAttrs`, `Props` и каждое поле props по правилам `JS/TS`.
|
||||
|
||||
```ts
|
||||
import type { ComponentPropsWithoutRef } from 'react'
|
||||
@@ -605,17 +701,20 @@ export type UserStatusProps = RootAttrs & UserStatusParams
|
||||
|
||||
### Реализация TSX
|
||||
|
||||
- В `.tsx` держи сам компонент, импорт props-типа, импорт CSS Module и импорт функции склейки классов.
|
||||
- В `.tsx` держи сам компонент и импорт props-типа.
|
||||
- CSS Module и функцию склейки классов импортируй только для компонента с собственным стилизуемым DOM.
|
||||
- Функцию склейки классов импортируй как `cl`: `import cl from 'clsx'`.
|
||||
- Компонент объявляй через `const` и именованный экспорт, если framework или локальный стандарт не требует другой формы.
|
||||
- Функциональный компонент объявляй через `const` и именованный экспорт, если framework или локальный стандарт не требует другой формы.
|
||||
- Нативный React Error Boundary разрешено объявлять классом, потому что React не предоставляет функциональный lifecycle для перехвата ошибок дочернего дерева.
|
||||
- Не используй `React.FC` по умолчанию.
|
||||
- Параметр компонента называй `props` и типизируй через `{Name}Props`.
|
||||
- Параметр функционального компонента называй `props` и типизируй через `{Name}Props`.
|
||||
- Возвращаемый тип компонента не указывай: TypeScript корректно выводит JSX-результат, а явный `ReactElement` сужает допустимые варианты возврата.
|
||||
- Деструктурируй props внутри тела компонента, а не в сигнатуре.
|
||||
- Из props обязательно выделяй `className` и `...rootAttrs`, если корневой элемент принимает HTML-атрибуты.
|
||||
- Прокидывай `rootAttrs` на корневой DOM-элемент.
|
||||
- Корневой элемент обязан получить `styles.root` первым CSS-классом.
|
||||
- Деструктурируй props функционального компонента внутри тела, а не в сигнатуре.
|
||||
- Из props выделяй `className` и `...rootAttrs`, если компонент имеет собственный корневой DOM-элемент и принимает его HTML-атрибуты.
|
||||
- Прокидывай `rootAttrs` на собственный корневой DOM-элемент.
|
||||
- Собственный корневой DOM-элемент обязан получить `styles.root` первым CSS-классом.
|
||||
- Внешний `className` добавляй последним аргументом в `cl(...)`.
|
||||
- Не добавляй невизуальному компоненту DOM-элемент, `className` или `rootAttrs`, если они не нужны его контракту.
|
||||
- Не создавай вложенный компонент внутри render без причины.
|
||||
- Не дублируй условия в JSX, если их можно выразить через заранее подготовленную переменную с понятным именем.
|
||||
- Для сложной разметки сначала упрощай данные и условия, потом JSX.
|
||||
@@ -668,11 +767,13 @@ export const UserStatus = (props: UserStatusProps) => {
|
||||
|
||||
### Стили
|
||||
|
||||
- CSS Module размещай в `styles/{name}.module.css`.
|
||||
- Корневой CSS-класс всегда называй `.root`.
|
||||
- CSS Module всегда создавай в `styles/{name}.module.css`.
|
||||
- Если компонент имеет собственный DOM, корневой CSS-класс называй `.root`.
|
||||
- `.root` описывает реальный корневой DOM-элемент компонента.
|
||||
- Дополнительные классы описывай рядом с `.root` и подключай через `styles.*`.
|
||||
- Не подменяй `.root` внешним `className`: внешний класс только дополняет `styles.root`.
|
||||
- CSS Module невизуального компонента оставляй пустым и не импортируй, пока у компонента не появится собственный стилизуемый DOM.
|
||||
- Не создавай DOM-wrapper только для применения `.root`.
|
||||
|
||||
```css
|
||||
.root {
|
||||
@@ -685,10 +786,11 @@ export const UserStatus = (props: UserStatusProps) => {
|
||||
|
||||
### Локальный экспорт
|
||||
|
||||
- В `index.ts` экспортируй компонент и public props-тип.
|
||||
- В локальном `index.ts` экспортируй компонент и props-тип.
|
||||
- Компонент экспортируй обычным named export.
|
||||
- Props экспортируй через `export type`.
|
||||
- Не экспортируй `Params` и `RootAttrs` наружу без необходимости.
|
||||
- Для корневого framework-файла используй публичный фасет модуля и не обходи его требования к среде выполнения.
|
||||
|
||||
```ts
|
||||
export { UserStatus } from './user-status'
|
||||
@@ -697,9 +799,10 @@ export type { UserStatusProps } from './types/user-status-props.type'
|
||||
|
||||
### Документирование компонентов
|
||||
|
||||
- Каждый React-компонент должен иметь многострочный JSDoc-комментарий.
|
||||
- Каждый React framework-компонент, включая Provider, Guard и Error Boundary, должен иметь многострочный JSDoc-комментарий.
|
||||
- Комментарий ставь непосредственно перед объявлением компонента.
|
||||
- Компонент документируй по React-шаблону, а не по шаблону функции из `JS/TS`.
|
||||
- Нативный Error Boundary, объявленный классом, также документируй по React-шаблону как компонент.
|
||||
- Компонент описывает назначение и сценарии применения.
|
||||
- Комментарий должен помогать понять, когда использовать компонент, без чтения реализации.
|
||||
- В `Используется для` указывай только реальные сценарии применения.
|
||||
@@ -737,15 +840,16 @@ export const UserStatus = (props: UserStatusProps) => {
|
||||
|
||||
### Чеклист React/TSX
|
||||
|
||||
- Базовая React UI-сущность имеет `.tsx`, `types/`, `styles/` и `index.ts`.
|
||||
- Props вынесены в `types/{name}-props.type.ts` и собраны из `{Name}Params`, `RootAttrs`, `{Name}Props`.
|
||||
- Каждый framework-компонент имеет `.tsx`, `types/`, `styles/` и локальный `index.ts`; главный framework-файл использует корень и фасет модуля.
|
||||
- Props вынесены в `types/{name}-props.type.ts`; `RootAttrs` добавлен только компоненту с собственным DOM.
|
||||
- Props-типы и поля props документированы по правилам `JS/TS`.
|
||||
- Компонент объявлен через `const`, принимает `props` и деструктурирует их внутри тела.
|
||||
- Функциональный компонент объявлен через `const`, принимает `props` и деструктурирует их внутри тела; нативный Error Boundary может быть классом.
|
||||
- Компонент не использует `React.FC` по умолчанию и не указывает возвращаемый тип без необходимости.
|
||||
- Корневой DOM-элемент получает `{...rootAttrs}` и `className={cl(styles.root, ..., className)}`.
|
||||
- CSS Module лежит в `styles/{name}.module.css`, корневой класс называется `.root`.
|
||||
- `index.ts` экспортирует компонент и props-тип.
|
||||
- Каждый React-компонент имеет комментарий по React-шаблону с назначением и сценариями применения.
|
||||
- Собственный корневой DOM-элемент получает `{...rootAttrs}` и `className={cl(styles.root, ..., className)}`.
|
||||
- CSS Module лежит в `styles/{name}.module.css`; у компонента с DOM корневой класс называется `.root`.
|
||||
- Невизуальный компонент имеет пустой CSS Module без неиспользуемого импорта и искусственного DOM-wrapper.
|
||||
- Локальный `index.ts` экспортирует компонент и props-тип; корневой компонент экспортируется через подходящий фасет модуля.
|
||||
- Каждый framework-компонент имеет комментарий по React-шаблону с назначением и сценариями применения.
|
||||
- Callback props названы через `on*`, внутренние обработчики - через `handle*`.
|
||||
- Named handlers и custom hooks документированы по правилам `JS/TS`; вызовы hooks и inline callbacks не документируются.
|
||||
- Hooks вызваны только на верхнем уровне компонента или custom hook.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
interface:
|
||||
display_name: "Style Guide"
|
||||
short_description: "Frontend code style, naming and local consistency"
|
||||
default_prompt: "Use $style-guide to format or review frontend code according to the project style guide and local code conventions."
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
name: svg-sprites-ru
|
||||
description: "Используй только при настройке, изменении или диагностике @gromlab/svg-sprites. Триггеры: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes для standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit или Alpine.js, SpriteConfig.input, --input, SpriteViewer и --icon-color-N. НЕ используй для самописных SVG-спрайтов, inline SVG, favicon, растровых изображений, icon fonts или выбора библиотеки иконок."
|
||||
metadata:
|
||||
internal: true
|
||||
---
|
||||
|
||||
<!-- Generated from skills/svg-sprites/src/ru/SKILL.md. Do not edit manually. -->
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
name: template-generation
|
||||
description: "Используй при создании, изменении или проверке повторяемой файловой структуры и шаблонов генерации. Триггеры: .templates, @gromlab/create, Template File Generator, scaffold, шаблон, генератор, создать компонент, модуль, layout, screen, widget, business, store, hook, service, page-entry, boilerplate, index.ts, типы, стили, тесты, повторить структуру без copy-paste, настроить генерацию файлов. НЕ используй для одноразовой точечной правки, code style, SLM-архитектуры без генерации файлов, Next.js routing, REST-клиентов или SVG sprites."
|
||||
metadata:
|
||||
internal: true
|
||||
---
|
||||
|
||||
<!-- Generated from src/SKILL.md. Do not edit manually. -->
|
||||
|
||||
129
README.md
129
README.md
@@ -1,33 +1,128 @@
|
||||
# SLM Design
|
||||
|
||||
Документация и agent skill для архитектуры Scoped Layered Module Design.
|
||||
**Scoped Layered Module Design (SLM)** - архитектурная модель для организации кода внутри фронтенд-приложения. Она описывает владельцев поведения, роли слоёв, границы модулей, публичные API и допустимые зависимости.
|
||||
|
||||
## Структура
|
||||
Цель SLM - сделать архитектурные решения наблюдаемыми в структуре проекта: понимать, какой модуль отвечает за результат, что доступно его потребителям и как изменение повлияет на остальное приложение.
|
||||
|
||||
- `docs/` - документация SLM и единственный источник содержимого сайта и reference-материалов skill.
|
||||
- `site/` - VitePress-рендерер: конфигурация, тема и статические ресурсы без собственной копии документации.
|
||||
- `old-docs/` - архив legacy-документации, не используемый текущим skill.
|
||||
- `src-skills/` - исходники agent skills.
|
||||
- `skills/` - собранные skills для установки через `npx skills`.
|
||||
[Документация](https://gromlab-ru.github.io/slm-design/) | [Пример React-приложения](./examples/react-vite/)
|
||||
|
||||
## Сборка
|
||||
## AI skill
|
||||
|
||||
```bash
|
||||
npx skills add gromlab-ru/slm-design
|
||||
```
|
||||
|
||||
Или [скачать `slm-design.zip`](https://gromlab-ru.github.io/slm-design/downloads/slm-design.zip).
|
||||
|
||||
## О чём SLM
|
||||
|
||||
SLM отвечает на три основных вопроса:
|
||||
|
||||
1. Какой модуль владеет конкретным результатом или поведением?
|
||||
2. Какие возможности модуль открывает внешним потребителям?
|
||||
3. От каких других модулей он может зависеть?
|
||||
|
||||
Базовый принцип модели: **у каждой самостоятельной ответственности есть ровно один модуль-владелец**.
|
||||
|
||||
Модуль определяет публичный API ответственности, её зависимости, модели и правила, состояние, жизненный цикл и внутреннюю реализацию. Компонент, Provider, hook, store или service остаются механизмами реализации и не становятся отдельными архитектурными владельцами только из-за своей технической роли.
|
||||
|
||||
SLM применяется внутри `SLM root` - границы структурной архитектуры одного приложения. Конкретный проект сам сопоставляет свои пути с сущностями SLM.
|
||||
|
||||
## Структурная модель
|
||||
|
||||
```text
|
||||
SLM root
|
||||
└── слой
|
||||
├── модуль
|
||||
│ ├── публичные фасеты
|
||||
│ ├── сегменты
|
||||
│ └── вложенные модули
|
||||
└── группа
|
||||
└── модули
|
||||
```
|
||||
|
||||
| Сущность | Назначение |
|
||||
|---|---|
|
||||
| `SLM root` | Ограничивает область архитектуры одним приложением |
|
||||
| Слой | Классифицирует код по архитектурной роли и ограничивает направления зависимостей |
|
||||
| Модуль | Владеет одной самостоятельной ответственностью и её публичным API |
|
||||
| Домен | Специализирует модуль для предметной ответственности и доменных сценариев |
|
||||
| Группа | Навигационно классифицирует модули, но не владеет кодом или API |
|
||||
| Сегмент | Организует внутренний код одного модуля без собственной ответственности |
|
||||
| Вложенный модуль | Владеет отдельной подответственностью внутри родительского модуля |
|
||||
|
||||
Слой, группа и сегмент не являются владельцами. По умолчанию код внутри `SLM root` принадлежит ближайшему модулю; исключениями остаются точки входа `app` и небольшие детерминированные ресурсы `shared`.
|
||||
|
||||
## Слои
|
||||
|
||||
SLM определяет шесть архитектурных ролей:
|
||||
|
||||
| Слой | Роль |
|
||||
|---|---|
|
||||
| `app` | Запуск приложения, маршруты, преобразование внешних входов и подключение готовых публичных API |
|
||||
| `compositions` | Представление и связывание готовых возможностей в страницы, макеты, экраны и виджеты |
|
||||
| `domains` | Предметные ответственности и сценарии: модели, правила, состояние, операции с данными и доменный UI |
|
||||
| `infra` | Технические сервисы без собственной предметной модели |
|
||||
| `ui` | Универсальные интерфейсные модули без знания о конкретном продукте или странице |
|
||||
| `shared` | Детерминированный фундамент без продуктового знания, ввода-вывода и изменяемого состояния |
|
||||
|
||||
Проект создаёт только те слои, для которых появился соответствующий код. Пустые слои и обязательное прохождение через каждый промежуточный уровень не требуются.
|
||||
|
||||
## Ключевые свойства
|
||||
|
||||
- **Один владелец ответственности.** Контракт, состояние, зависимости и внутренняя реализация связного результата принадлежат одному модулю.
|
||||
- **Закрытая модульная граница.** Внешний код использует модуль только через его публичные фасеты. Глубокие импорты во внутренние файлы запрещены.
|
||||
- **Фасеты сред выполнения.** Обязательный `index` содержит универсальный API; `client`, `browser` и `server` добавляются только при необходимости.
|
||||
- **Вертикальные домены.** Домен владеет сценарием целиком: предметным контрактом, правилами, состоянием, ошибками, доменным UI и адаптацией источников данных.
|
||||
- **Независимость от DTO.** Внешние request, response и error types остаются внутри интеграционной границы и не становятся публичной моделью домена.
|
||||
- **Ацикличный модульный граф.** Межмодульные импорты проходят через публичный API, учитывают направление слоёв и не образуют циклов.
|
||||
- **Рост по ответственности.** Сегменты организуют внутренний код, а новый или вложенный модуль появляется только для самостоятельной ответственности.
|
||||
- **Владение состоянием и ресурсами.** Модуль определяет источник истины, область жизни, число экземпляров и очистку долгоживущих ресурсов.
|
||||
|
||||
## Проверка архитектуры
|
||||
|
||||
SLM разделяет смысловые и структурные решения.
|
||||
|
||||
- На архитектурном ревью проверяются ответственность, единственный владелец, роль слоя, состав публичного API, доменный контракт, состояние и жизненный цикл.
|
||||
- Автоматически можно проверять направления между слоями, доступ через публичные фасеты, отсутствие глубоких импортов и циклов в модульном графе.
|
||||
|
||||
Блокирующие правила собраны в едином реестре и имеют стабильные коды. Рекомендации и примеры объясняют модель, но не подменяют нормативные требования.
|
||||
|
||||
## Что SLM не определяет
|
||||
|
||||
SLM не требует конкретного фреймворка, state manager, способа получения данных или потока управления. Модель не задаёт фиксированные имена сегментов, полный файловый стайлгайд и правила организации монорепозитория.
|
||||
|
||||
Эти решения остаются за проектом. SLM определяет только архитектурный смысл владельцев, границ и зависимостей внутри одного приложения.
|
||||
|
||||
## Документация и пример
|
||||
|
||||
- [Обзор архитектурной модели](https://gromlab-ru.github.io/slm-design/architecture/)
|
||||
- [Слои](https://gromlab-ru.github.io/slm-design/architecture/layers)
|
||||
- [Модули и публичный API](https://gromlab-ru.github.io/slm-design/architecture/modules)
|
||||
- [Домены и граница внешних данных](https://gromlab-ru.github.io/slm-design/architecture/domains)
|
||||
- [Зависимости и модульный граф](https://gromlab-ru.github.io/slm-design/architecture/dependencies)
|
||||
- [Терминология](https://gromlab-ru.github.io/slm-design/reference/terminology)
|
||||
- [Реестр правил](https://gromlab-ru.github.io/slm-design/rules/registry)
|
||||
- [Проверка архитектуры](https://gromlab-ru.github.io/slm-design/reference/validation)
|
||||
- [Пример React + Vite приложения](./examples/react-vite/)
|
||||
|
||||
<details>
|
||||
<summary>Разработка репозитория</summary>
|
||||
|
||||
Требуется Node.js 20 или новее.
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
npm run build:skill
|
||||
npm run check:skill
|
||||
npm run check:docs
|
||||
npm run check:site
|
||||
npm run check
|
||||
```
|
||||
|
||||
`npm run check:docs` проверяет правила и ссылки документации. `npm run check:site` собирает VitePress из `docs/` и проверяет опубликованные страницы. Skill собирается из `src-skills/slm-design/`, а всё дерево `docs/` рекурсивно включается в `skills/slm-design/reference/docs/`. Собранные файлы не редактируются вручную.
|
||||
|
||||
## Установка
|
||||
|
||||
После публикации репозитория:
|
||||
Локальный запуск документации:
|
||||
|
||||
```bash
|
||||
npx skills add gromlab-ru/slm-design --skill slm-design
|
||||
npm run docs:dev
|
||||
```
|
||||
|
||||
Документация находится в `docs/`, исходник skill - в `src-skills/slm-design/`. Собранный каталог `skills/slm-design/` не редактируется вручную.
|
||||
|
||||
</details>
|
||||
|
||||
Reference in New Issue
Block a user