Skip to content

Repository files navigation

mf-mono-project-graph / react-graph

npm license node

CLI и программная библиотека для построения графа зависимостей React/TypeScript‑монорепо с FSD-архитектурой и tsconfig aliases. Строит единый граф по репозиторию, сохраняет его в .graph/project-graph.json и даёт быстрые структурные ответы через CLI без повторного чтения кода.


Кратко: чем полезен граф

Граф выступает картой фронтенд‑монорепо: помогает сузить десятки файлов «наугад» до нескольких релевантных и экономит токены/время агента.

Оценки пользы из реального опыта работы агента с фронтенд‑монорепо:

Задача Оценка
Impact-анализ: что затронет изменение X 9/10
Состав страницы/виджета: из каких файлов состоит экран 9/10
Навигация по роутингу: какие страницы есть, какие entry-файлы 8/10
Зависимости фичи от entities/widgets 8/10
Изменение API модуля: кто импортирует и кому обновить контракт 8/10
FSD-рефакторинг: перенос слоя, проверка cross-слайс границ 8/10
Оценка объёма правок перед задачей 7/10
Поиск мёртвого кода и неиспользуемых модулей 7/10
Онбординг: как устроен сервис X 7/10
Связи компонент–хук на symbol-уровне 6/10

Общая полезность для агента в фронтенд-монорепо: 8/10.

Граф сильнее всего помогает в структурных задачах (зависимости, impact, границы приложений, рефакторинг, оценка объёма). Для тонкостей логики и дебага по‑прежнему нужно читать код, но граф существенно сужает область поиска.


Установка

npm install mf-mono-project-graph

TypeScript >=5.0.0 — optional peer dependency.
Пакет объявляет

"peerDependencies": {
  "typescript": ">=5.0.0"
},
"peerDependenciesMeta": {
  "typescript": {
    "optional": true
  }
}

и использует TS Compiler API из зависимостей проекта. npm не тянет свою копию TypeScript и не требует его наличия принудительно, но без TypeScript >=5.0.0 в проекте сборка графа работать не будет.
Конфигурация peerDependencies + peerDependenciesMeta.optional помогает мягче интегрировать пакет в существующее дерево зависимостей монорепо, но не гарантирует отсутствие предупреждений npm warn ERESOLVE overriding peer dependency.

Монорепо (npm workspaces)

В монорепо с несколькими воркспейсами рекомендуется устанавливать пакет в корне:

npm install mf-mono-project-graph --save-dev

При установке в реальном монорепо предупреждения ERESOLVE overriding peer dependency могут появляться и зависят от конфигурации всего проекта (версий TypeScript и других пакетов с peerDependencies).
Если при установке ты видишь такие предупреждения, имеет смысл проверить через npm ls typescript и npm ls --all пакеты с конфликтующими peerDependencies по TypeScript и связанным библиотекам — источник конфликта может быть как в mf-mono-project-graph, так и в других зависимостях.


Быстрый старт

1. Инициализировать Cursor-файлы

npx react-graph init-cursor --root .

Копирует три шаблона в .cursor/rules/, .cursor/skills/ и .cursor/agents/ — настраивает главного агента Cursor на работу с графом в двух режимах: через субагента graph-agent или напрямую через skill.

2. Собрать граф

npx react-graph build --root . --json

Граф сохраняется в одном местекорень/.graph/project-graph.json. Для монорепо всегда указывай --root на корень репозитория (не на каталог приложения/микрофронта). Пересобирай после изменений в services/** или package.json.

3. Задать вопрос к графу

Например, посмотреть, кто зависит от файла/символа:

npx react-graph who-uses "<nodeId>" --root . --json

CLI

Общие флаги

Флаг Алиас Команды Описание
--root <path> -r все Корень проекта (по умолчанию: cwd). В монорепо — только корень репо: граф один (.graph/ в корне), без дублей в микрофронтах.
--json все JSON-вывод вместо текстового
--resolve-packages -R deps, node-info Развернуть внутренние package:* в конкретные файлы
--files-only -f deps, node-info Вернуть только файловые узлы, без package:*
--partial -p find Поиск по подстроке вместо точного совпадения имени символа
--slice <slice> find Фильтр по FSD-слайсу (например, entityDrawer, projectData)

build

npx react-graph build --root <path> [--json]

Строит/обновляет граф. JSON-вывод: { rootDir, nodes, edges, durationMs, graphSizeBytes }.

deps

npx react-graph deps "<nodeId>" --root <path> [--json] [-R] [-f]

Прямые и транзитивные зависимости узла.

{
  "node": "<nodeId>",
  "directDependencies": ["..."],
  "transitiveDependencies": ["..."]
}

who-uses

npx react-graph who-uses "<nodeId>" --root <path> [--json]

Обратные зависимости — кто зависит от указанного узла. Используется для impact-анализа.

{ "node": "<nodeId>", "users": ["..."] }

node-info

npx react-graph node-info "<nodeId>" --root <path> [--json] [-R] [-f]

Всё в одном: тип узла, прямые/транзитивные зависимости, пользователи, пакеты.

find

npx react-graph find "<name>" --root <path> [--json] [--layer <fsd-layer>] [--mf <mf-name>] [--kind <component|hook|function>] [--partial|-p] [--slice <slice-name>]

Ищет symbol-узлы в графе по имени символа (компонент/хук/функция) без знания пути к файлу. Возвращает nodeId, который можно передавать в deps, who-uses, node-info.

Флаг Описание
--layer <layer> Фильтр по FSD-слою: pages, widgets, features, entities, shared, app
--mf <name> Фильтр по имени микрофронта (подстрока): gantt-v2-app, host-app
--kind <kind> Фильтр по типу символа: component, hook, function
--partial, -p Поиск по подстроке вместо точного совпадения: find "Gantt" --partial найдёт GanttComponent, GanttHeader и т.п.
--slice <slice> Фильтр по FSD-слайсу: entityDrawer, projectData — для сужения внутри слоя

JSON-вывод (точный поиск):

{
  "query": "ProjectData",
  "filters": { "layer": "pages", "mf": "gantt-v2-app" },
  "count": 1,
  "matches": [
    {
      "nodeId": "symbol:/abs/.../ProgectData/index.tsx#ProjectData",
      "type": "symbol",
      "symbolKind": "component",
      "layer": "pages",
      "slice": "projectData",
      "mf": "gantt-v2-app",
      "filePath": "/abs/.../ProgectData/index.tsx"
    }
  ]
}

При count: 0 в ответе только query, filters, count, matches (пустой массив). Используй --partial для поиска по подстроке или уточни фильтры.

Примеры использования:

# Точный поиск (по умолчанию) — MainLayout есть во всех МФ, уточняем через --mf
npx react-graph find "MainLayout" --root . --json --mf reports-app

# Частичный поиск — найти всё связанное с "Gantt"
npx react-graph find "Gantt" --root . --json --partial --mf gantt-v2-app

# Поиск хуков в конкретном слайсе
npx react-graph find "use" --root . --json --partial --layer entities --slice entityDrawer

# Получаем nodeId и дальше работаем через deps/who-uses
npx react-graph deps "symbol:/abs/.../MainLayout.tsx#MainLayout" --root . --json --files-only

init-cursor

npx react-graph init-cursor [--root <path>]

Копирует три шаблона в целевой проект (создаёт каталоги при необходимости):

Файл Назначение
.cursor/rules/react-graph.mdc Правило для главного агента: когда и как использовать граф, два режима работы, CLI API
.cursor/skills/react-graph.mdc Skill для прямой работы агента с графом (по явному запросу пользователя)
.cursor/agents/graph-agent.md Суб-агент graph-agent: flow из шагов, правило «только CLI», прозрачный summary ответа

Модель графа

Простая ASCII-схема для интуиции:

        project
           |
       package:app/*
        /       \
   file (page)  file (widget)
        \       /
      symbol (component)

Типы узлов

Тип ID Ключевые meta-поля
project project:<absPathToRoot> rootDir
file <absPath/to/file.tsx> filePath, layer, slice
package package:<name>
symbol symbol:<absPath>#<ExportName> symbolName, symbolKind, exportKind, loc, layer, slice

FSD-слои (meta.layer): app / pages / widgets / features / entities / shared / unknown.

package:* бывают:

  • Внешние npm: package:react, package:@reduxjs/toolkit
  • Внутренние alias-пакеты (FSD-слои): package:widgets/*, package:entities/*, package:features/*, package:pages/*, package:app/*, package:shared/*
  • Приложения (из router config): package:app/<appName> с meta.kind: "app"
  • Страницы (из router config): package:pages/<slice> с meta.kind: "page", routeId, routePath

Типы рёбер

Тип Направление Смысл
imports file → file/package Файл импортирует другой файл или пакет
depends_on project → package, package:* → file Зависимость из package.json; резолв alias-пакета в файлы
belongs_to_pkg package:* → file Файл входит в состав alias-пакета
contains file → symbol Файл содержит символ
exports_symbol file → symbol Файл экспортирует символ
calls symbol → symbol Символ вызывает другой символ
uses_jsx symbol → symbol Символ использует другой символ как JSX-компонент

Форматы nodeId

# Файл
/abs/path/src/features/auth/ui/LoginForm.tsx

# npm-пакет
package:react
package:@reduxjs/toolkit

# Внутренний alias-пакет (FSD)
package:widgets/digest
package:entities/user
package:app/host-app

# Символ
symbol:/abs/path/src/widgets/Header/ui/Header.tsx#Header
symbol:/abs/path/src/app/router/AppRouter.tsx#default

Паттерн работы с агентом

Правило: сначала граф, потом точечное чтение кода.

# 1. Пересобрать граф (если менялись файлы)
npx react-graph build --root . --json

# 2. Получить структуру
npx react-graph node-info "<nodeId>" --root . --json --resolve-packages --files-only

# 3. Прямые зависимости (для понимания скоупа правок)
npx react-graph deps "<nodeId>" --root . --json --resolve-packages --files-only

# 4. Обратные зависимости (impact-анализ)
npx react-graph who-uses "<nodeId>" --root . --json

По JSON-ответу агент выбирает минимальный набор файлов и читает только их.


Cursor-интеграция

После npx react-graph init-cursor --root . в проекте появляются три файла:

Файл Назначение
.cursor/rules/react-graph.mdc Правило для главного агента (alwaysApply): когда граф обязателен, два режима работы, CLI API с контрактами
.cursor/skills/react-graph.mdc Skill: прямая работа агента с графом по явному запросу пользователя
.cursor/agents/graph-agent.md Суб-агент graph-agent: flow, правило «только CLI», прозрачный summary CLI-вывода

Поддерживаются два режима: субагент (главный агент спрашивает разрешение пользователя, делегирует graph-agent) и skill (агент работает с графом напрямую по явной просьбе). Граф пересобирается каждый раз перед началом работы.


Интеграция через npm-скрипты

Добавь в package.json проекта для удобного вызова из корня:

"scripts": {
  "graph:build":     "react-graph build --root . --json",
  "graph:deps":      "react-graph deps --root .",
  "graph:who-uses":  "react-graph who-uses --root .",
  "graph:node-info": "react-graph node-info --root .",
  "graph:find":      "react-graph find --root ."
}

Примеры:

npm run graph:node-info -- "/abs/path/DigestPage.tsx" --json --resolve-packages --files-only
npm run graph:find -- "MainLayout" --json --mf reports-app

Программный API

import { buildGraph, loadGraph, QueryEngine, type ProjectGraph } from "mf-mono-project-graph";

const graph = buildGraph({ rootDir: "/abs/path/to/frontend" });
const engine = new QueryEngine(graph);
engine.deps(nodeId, { transitive: true, resolvePackages: true });
engine.whoUses(nodeId);

Ограничения

  • Barrel-файлы и entry-точки (entities/*/index.ts, pages/*/index.tsx) могут иметь мало входящих imports-рёбер, потому что на них ссылаются через alias-пакеты, а не напрямую. Для поиска мёртвого кода дополнительно смотри belongs_to_pkg.
  • Symbol-уровень неполный: рёбра calls/uses_jsx строятся только для верхнеуровневых функций/хуков/компонентов; namespace-импорты, динамические вызовы и обращения к методам объектов могут не давать рёбер.
  • Module Federation remotes (import("digest/DigestApp")) отражаются как package:digest/DigestApp — внутренняя структура remote-модулей не сканируется.
  • Конфиги и декларации (webpack.config.js, *.d.ts) почти не имеют входящих рёбер: пустой who-uses не означает мёртвый код.
  • Router config детектируется только по паттерну **/app/router/config.*; нестандартные пути не покрываются.
  • Установка и peer-зависимости TypeScript — пакет использует peerDependencies + peerDependenciesMeta.optional для typescript >=5.0.0, чтобы не тянуть свою копию TS и лучше вписываться в монорепо. Тем не менее, при установке в проектах с конфликтующими peerDependencies по TypeScript и другим библиотекам возможны предупреждения npm warn ERESOLVE overriding peer dependency; это известное ограничение, а не гарантированно устранённая проблема.
  • Сам граф весит ~10 MB JSON — целиком в контекст агента не тянется; работа идёт через CLI и уже отфильтрованный вывод.

Troubleshooting

  • Permission denied при запуске CLI (npx react-graph)

    • В версиях <1.0.1 бинарь dist/bin/cli.js мог публиковаться без права на выполнение, из-за чего запуск react-graph заканчивался ошибкой Permission denied.
    • Начиная с >=1.0.1 проблема исправлена: скрипт сборки scripts/copy-bin.js выставляет chmod 755 для dist/bin/cli.js, а в >=1.0.2 добавлен хук prepack, который гарантирует запуск сборки перед публикацией.
    • Если видишь Permission denied в реальном проекте, достаточно обновить пакет до актуальной версии mf-mono-project-graph; ручной chmod в node_modules не требуется.

Links

  • Repository: https://github.com/AlekseyGogolev/graph_agent
  • npm: https://www.npmjs.com/package/mf-mono-project-graph

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages