원클릭으로
graph-dev
// Development workflow for @gravity-ui/graph. Use when implementing features, fixing bugs, or designing APIs in this library.
// Development workflow for @gravity-ui/graph. Use when implementing features, fixing bugs, or designing APIs in this library.
| name | graph-dev |
| description | Development workflow for @gravity-ui/graph. Use when implementing features, fixing bugs, or designing APIs in this library. |
| disable-model-invocation | true |
Follow these phases in order. Skip to Phase 3 only for trivial one-line fixes.
Before writing any code, understand what you are touching. Read the relevant source files. Use EnterPlanMode for non-trivial features.
Architecture questions to answer:
Which layers are affected?
Before deciding where to add or change something, discover all existing layers in the codebase:
src/ for classes that extend Layer to get the current full listIdentify the right layer:
GraphLayer or a new Canvas-only layerhtml property in Layer constructor with transformByCameraPosition: trueIf the task specifies which layer to use: read that layer's source, understand what it currently does, and verify the fit. If the specified layer seems wrong (wrong zIndex, wrong responsibility, event conflicts with existing handlers), raise the concern and clarify with the user before starting.
How do events propagate?
executеDefaultEventAction?What are the data boundaries?
RootStore, signals) — single source of truth$viewComponent signal bridgeDoes it touch the scheduler?
render() directly — always performRender()Are there circular dependency risks?
affectsUsableRect: false on HitBox to break cycles with boundary elementsOutput of this phase: A written plan with affected files, implementation approach, and potential risks.
After planning, forecast how the feature will be used — before writing a single line.
graph.addLayer(MyLayer, props), graph.setEntities(...), useGraphEvent)?super.afterInit(), wrong coordinate space)If a clean DX or UX requires compromises from the library — complexity, performance regressions, or incorrect behavior — eliminate the compromises, even at the cost of DX/UX.
The library is correct and performant first. API ergonomics are secondary. A footgun that the consumer can avoid with documentation beats a footgun baked into the library internals.
Output of this phase: A brief written DX/UX assessment. If you identified a tradeoff, explicitly state which side you chose and why.
Follow the conventions from CLAUDE.md. Key rules:
any type — use concrete types, void, or unknownsetState()/setProps() not direct assignment; performRender() not render()afterInit(), never in constructor or init()onGraphEvent, onCanvasEvent, etc.)Component.create(props) not new Component(props); return from updateChildren()batch(() => { ... })Choose the right test type for each concern.
Write a Jest unit test when the code under test:
src/utils/)Graph objectExamples: HitTest, IncrementalBoundingBoxTracker, coordinate math, store selectors, BatchPath2DRenderer.
npm run test
npm run test -- <pattern> # run specific test file
Add an e2e test to the test suite when the fix or feature requires:
setEntities lifecycle with real block components rendered in the browserE2e tests live in e2e/tests/. Use GraphPageObject and its Component Object Models.
npm run e2e:bundle # REQUIRED after any source change
npm run e2e # run all e2e tests
npx playwright test <pattern> # run specific test
Always run
npm run e2e:bundlebeforenpm run e2eif you changed TypeScript source. The e2e server must be on port 6006. Kill Storybook first if it's running there.
While implementing, write a temporary e2e test for yourself to verify that the code behaves as you expect before considering the task done. This is your development feedback loop, not a final test.
Rules for self-check tests:
e2e/tests/ alongside other tests — run them, iterate, confirm behaviorconsole.log calls, or debugging helpers in GraphPageObject, GraphBlockComponentObject, GraphConnectionComponentObject, or other shared POM/COM files. These files are the stable API for all tests — keep them clean. Add methods to them only if they are genuinely reusable.Don't write a unit test if the assertion would require:
CanvasRenderingContext2D in a non-trivial wayUse e2e for those cases instead.