Derived Modular Arch
Инструменты

dma check

Жёсткая проверка графа зависимостей для CI — установка, запуск и разбор правил.

dma check — главная команда DMA. Она строит граф импортов по проекту и проверяет архитектурные правила. Если что-то нарушено — ненулевой код выхода, CI падает.

Линтеры в редакторе полезны, но не заменяют check: циклы, предикаты входящих рёбер и полный граф видит только CLI.

Установка

npm install -D @derived-modular/cli

Нужен Node.js 18+.

Запуск — только через имя пакета:

npx @derived-modular/cli check
npx @derived-modular/cli check .          # явный путь к корню проекта
npx @derived-modular/cli check --format json
npx @derived-modular/cli check --suggest  # план безопасных фиксов (без записи)
npx @derived-modular/cli check --fix     # применить фиксы, затем снова check

В package.json:

{
  "scripts": {
    "dma-check": "npx @derived-modular/cli check ."
  }
}

По умолчанию CLI ищет дерево src/{app|pages|routes, features, services?, shared} относительно переданного пути.

Коды выхода

КодЗначение
0Ошибок нет
1Найдены архитектурные нарушения
2Сбой окружения: нет src/, битый tsconfig, неверные аргументы

В CI обычно достаточно:

npx @derived-modular/cli check .

Для GitHub Actions и агентов — --format json (стабильный отчёт version: 1).

Цветной вывод отключается через NO_COLOR=1.

Безопасный autofix (--suggest / --fix)

Механические правки, которые не «придумывают» архитектуру:

ФлагПоведение
--suggestПечатает план; файлы не трогает
--fixПрименяет план, затем снова запускает check

Сейчас поддерживается:

  • no-barrel — переписать импорты в barrel с одним export … from на прямой public path (как ESLint autofix). Сам barrel-файл не удаляется.
  • public-api — переписать deep import на mirrored public/<тот-же-относительный-путь>, только если такой файл уже есть.

Нужен один project root (не multi-root discover). Флаги взаимоисключающие. Не создаёт public/ и не вызывает promote.

Что именно проверяется

ПравилоСмысл
layer-directionИмпорты только вниз: app/pages/routes → features → services → shared
feature-to-featureFeature не импортирует другой feature
public-apiМежмодульные импорты идут в */public/*
no-barrelНет barrel index с реэкспортами внутри модулей
no-cycleГраф модулей ацикличен
feature-has-inboundFeature с входящими рёбрами от модулей → должен быть в services/
service-no-inboundService без потребителей среди модулей → нарушение предиката

Входящие рёбра считаются только от модулей (features/*, services/*). Монтирование из app/, pages/, routes/ promotion не вызывает.

Контекст правил — в Четыре инварианта и Слои. Алгоритм «куда положить файл» — Куда положить файл.

Справочник нарушений

Типичные ruleId из отчёта check и что с ними делать.

ruleIdПричинаТипичный фиксПодробнее
feature-to-featureFeature импортирует другой featurePromotion в services/, перенос в shared/, или связка в корень композицииСклейка модулей, Куда положить файл
layer-directionИмпорт вверх по слою (например, feature → app/)Уберите импорт; передайте данные через props/events из корня композицииСлои
public-apiМежмодульный импорт мимо */public/*Импортируйте */public/<file> напрямую; internal — только relative внутри модуляМодули
no-barrelindex.ts с реэкспортами внутри модуляУдалите barrel; импортируйте конкретные файлыПочему нет barrel
no-cycleЦикл в графе модулейВынесите в shared/, promotion в services/, или порт + привязка в app/Склейка модулей
feature-has-inboundУ feature есть входящих рёбер от другого модуляdma promote <name> --apply, затем пересмотрите public/dma promote · Эволюция кода
service-no-inboundService без потребителей среди модулейВерните размещение рядом в feature или удалите пустой serviceСлои

Код выхода 2 (окружение)

СимптомЧто проверить
Нет src/ / нет DMA-корнейSingle-app: корень приложения. Корень монорепо: discovery должен найти apps, или --roots / --include-packages
Битый tsconfigpaths для @/ в tsconfig приложения
Неверные аргументыnpx @derived-modular/cli check --help

См. Монорепо для нескольких app roots.

Что CLI умеет анализировать

Сканируются статические импорты в:

  • .ts, .tsx, .js, .jsx, .mjs, .cjs
  • .vue, .svelte, .astro
  • .md, .mdx — импорты в контенте тоже попадают в граф (актуально для doc-apps и MDX-компонентов)

Учитываются import, export … from, import type, динамический import() и require() — в том числе цели next/dynamic и React.lazy.

Алиасы путей подхватываются из tsconfig.json.

Форматы вывода

ФорматКогда использовать
human (default)Локальная разработка
jsonCI, скрипты, AI-агенты
sarifGitHub Code Scanning
npx @derived-modular/cli check --format sarif > dma.sarif

check vs doctor

dma checkdma doctor
НазначениеЖёсткие правилаМягкие сигналы эволюции
Код выхода при находках10 (по умолчанию)
Где запускатьCI, pre-pushЛокально

doctor подсказывает shared-candidate, stage-growth, dense-services, orphan-public — но не дублирует ошибки check. Подробнее — на странице dma doctor.

Линтеры — дополнение, не замена

В редакторе можно подключить ESLint, Biome или Oxlint плагины DMA. Они ловят часть правил по одному файлу, но не видят циклы и предикаты входящих рёбер.

Всегда запускайте npx @derived-modular/cli check в CI. Линтеры — для быстрой обратной связи в IDE.

Обзор всех адаптеров — Инструменты: обзор.

Пример для монорепо DMA

Если вы в репозитории derived-modular-architecture:

npx @derived-modular/cli check .

Что дальше

On this page