Core Architecture
Purpose and Scope
This document explains the fundamental architecture of the relation-graph system, including its class structure, core design patterns, and component organization. It provides an overview of how the system achieves framework independence while maintaining a unified core logic.
For detailed information about specific aspects:
- Class inheritance details: see Class Inheritance Hierarchy
- Data structures and types: see Data Model & Types
- Node analysis utilities: see Node Analysis Utilities
- Instance lifecycle: see Core Instance & Lifecycle
- Data management: see Data Management System
- Platform integration: see Platform Integration
Architectural Overview
The relation-graph system employs a core-adapter architecture that separates framework-agnostic graph logic from platform-specific UI implementations. This design enables a single codebase to support Vue 2, Vue 3, React, Svelte, and Web Components.
graph TB
subgraph "Core Layer (Framework Agnostic)"
CORE["RelationGraphCore
packages/relation-graph-models/models/RelationGraphCore.ts"]
DATA_PROV["RGDataProvider
packages/relation-graph-models/data/RGDataProvider.ts"]
TYPES["Type System
packages/relation-graph-models/types.ts"]
LAYOUTS["Layout Engines
packages/relation-graph-models/layouts/*"]
UTILS["Utilities
packages/relation-graph-models/utils/*"]
end
subgraph "Adapter Layer (Platform Specific)"
DP_VUE2["RGDataProvider4Vue2"]
DP_VUE3["RGDataProvider4Vue3"]
DP_REACT["RGDataProvider4React"]
DP_SVELTE["RGDataProvider4Svelte"]
end
subgraph "UI Layer (Framework Components)"
VUE2_UI["Vue 2 Components
packages/platforms/vue2/"]
VUE3_UI["Vue 3 Components
packages/platforms/vue3/"]
REACT_UI["React Components
packages/platforms/react/"]
SVELTE_UI["Svelte Components
packages/platforms/svelte/"]
end
CORE --> DATA_PROV
CORE --> LAYOUTS
CORE --> UTILS
CORE --> TYPES
DATA_PROV -.extends.-> DP_VUE2
DATA_PROV -.extends.-> DP_VUE3
DATA_PROV -.extends.-> DP_REACT
DATA_PROV -.extends.-> DP_SVELTE
DP_VUE2 --> VUE2_UI
DP_VUE3 --> VUE3_UI
DP_REACT --> REACT_UI
DP_SVELTE --> SVELTE_UI
VUE2_UI -.uses.-> CORE
VUE3_UI -.uses.-> CORE
REACT_UI -.uses.-> CORE
SVELTE_UI -.uses.-> CORESources: packages/relation-graph-models/models/RelationGraphCore.ts:1-70, packages/relation-graph-models/models/RelationGraphWith2Data.ts:1-120
Progressive Enhancement Inheritance Pattern
The core system uses a progressive enhancement pattern where RelationGraphCore inherits capabilities through a chain of specialized classes. Each RelationGraphWithX class adds one focused set of capabilities.
graph TB
RGB["RelationGraphBase
Core utilities, events, UUID generation
packages/.../RelationGraphBase.ts"]
RGB --> RGW1["RelationGraphWith1View
DOM coordination, coordinate conversion
packages/.../RelationGraphWith1View.ts"]
RGW1 --> RGW2["RelationGraphWith2Data
Reactive data integration
setReactiveData4Vue2/Vue3/React/Svelte
packages/.../RelationGraphWith2Data.ts"]
RGW2 --> RGW3O1["RelationGraphWith3Options1Update
Options management, loading states
_updateOptions, setCanvasOffset
packages/.../RelationGraphWith3Options1Update.ts"]
RGW3O1 --> RGW3O2["RelationGraphWith3Options2API
Options API, creating line/node state
getCreatingLine, getCreatingNode
packages/.../RelationGraphWith3Options2API.ts"]
RGW3O2 --> RGW4["RelationGraphWith4Line
Line path generation
createLineDrawInfo, generateLinePath
packages/.../RelationGraphWith4Line.ts"]
RGW4 --> RGW5["RelationGraphWith5Zoom
Zoom operations
zoom, setZoom
packages/.../RelationGraphWith5Zoom.ts"]
RGW5 --> RGW6E["RelationGraphWith6Effect
Visual effects, centering
zoomToFit, moveToCenter
packages/.../RelationGraphWith6Effect.ts"]
RGW6E --> RGW6L["RelationGraphWith6Layout
Layout algorithms
doLayout, createLayout
packages/.../RelationGraphWith6Layout.ts"]
RGW6L --> RGW7["RelationGraphWith7Event
User interactions
onNodeClick, onNodeDragStart
packages/.../RelationGraphWith7Event.ts"]
RGW7 --> RGW9["RelationGraphWith9EasyView
Performance mode rendering
updateEasyView, evDrawNode
packages/.../RelationGraphWith9EasyView.ts"]
RGW9 --> RGW91["RelationGraphWith91Editing
Node/line editing
setEditingNodes, onResizeStart
packages/.../RelationGraphWith91Editing.ts"]
RGW91 --> RGW92["RelationGraphWith92MiniView
Minimap overview
updateMiniView, mvDrawNode
packages/.../RelationGraphWith92MiniView.ts"]
RGW92 --> RGW93["RelationGraphWith93Image
Image generation preparation
prepareForImageGeneration
packages/.../RelationGraphWith93Image.ts"]
RGW93 --> RGW95["RelationGraphWith95Dom
DOM observers
setDom, initDom
packages/.../RelationGraphWith95Dom.ts"]
RGW95 --> RGW99["RelationGraphWith99API
Public API surface
setJsonData, updateNode, getNodes
packages/.../RelationGraphWith99API.ts"]
RGW99 --> CORE["RelationGraphCore
Final instance
ready, beforeUnmount
packages/.../RelationGraphCore.ts"]
style RGB fill:#f9f9f9
style RGW2 fill:#f9f9f9
style RGW7 fill:#f9f9f9
style CORE fill:#e0e0e0Capability Layers
| Layer | Class | Primary Responsibility | Key Methods |
|---|---|---|---|
| Base | RelationGraphBase |
Event system, UUID generation | emitEvent(), generateNewUUID() |
| View | RelationGraphWith1View |
Coordinate transformations | getCanvasXyByViewXy(), getViewXyByCanvasXy() |
| Data | RelationGraphWith2Data |
Framework reactivity integration | setReactiveData4Vue2(), setReactiveData4React() |
| Options | RelationGraphWith3Options1Update |
Configuration management | _updateOptions(), setCheckedNode() |
| Line Drawing | RelationGraphWith4Line |
Line path computation | createLineDrawInfo(), generateLinePath() |
| Zoom | RelationGraphWith5Zoom |
Zoom operations | zoom(), setZoom() |
| Effects | RelationGraphWith6Effect |
Visual effects | zoomToFit(), moveToCenter() |
| Layout | RelationGraphWith6Layout |
Layout algorithms | doLayout(), createLayout() |
| Events | RelationGraphWith7Event |
User interaction handling | onNodeClick(), onNodeDragStart() |
| Performance | RelationGraphWith9EasyView |
Canvas rendering | updateEasyView(), evDrawNode() |
| Editing | RelationGraphWith91Editing |
Interactive editing | setEditingNodes(), onResizeStart() |
| MiniView | RelationGraphWith92MiniView |
Minimap rendering | updateMiniView(), mvDrawNode() |
| Image | RelationGraphWith93Image |
Image export preparation | prepareForImageGeneration() |
| DOM | RelationGraphWith95Dom |
DOM observation | setDom(), initDom() |
| API | RelationGraphWith99API |
Public API | setJsonData(), getGraphJsonData() |
| Core | RelationGraphCore |
Instance lifecycle | ready(), beforeUnmount() |
Sources: packages/relation-graph-models/models/RelationGraphBase.ts:1-345, packages/relation-graph-models/models/RelationGraphCore.ts:1-70
Core Components
RelationGraphCore Instance
RelationGraphCore is the central instance that aggregates all capabilities. Each <RelationGraph /> component creates and binds one instance.
graph LR
subgraph "RelationGraphCore Instance"
CORE_INST["graphInstance
RelationGraphCore"]
subgraph "Internal Components"
DP["dataProvider
RGDataProvider"]
OPTIONS["options
RGOptionsFull"]
LISTENERS["listeners
RGListeners"]
EVENT_HANDLERS["eventHandlers
RGEventHandler[]"]
end
subgraph "DOM References"
DOM["$dom
HTMLDivElement"]
CANVAS_DOM["$canvasDom
HTMLDivElement"]
end
end
CORE_INST --> DP
CORE_INST --> OPTIONS
CORE_INST --> LISTENERS
CORE_INST --> EVENT_HANDLERS
CORE_INST --> DOM
CORE_INST --> CANVAS_DOM
DP -.references.-> OPTIONSKey Instance Properties:
| Property | Type | Purpose |
|---|---|---|
dataProvider |
RGDataProvider |
Manages graph data, nodes, lines |
options |
RGOptionsFull |
Configuration state |
listeners |
RGListeners |
Event handler callbacks |
eventHandlers |
RGEventHandler[] |
Custom event handlers |
$dom |
HTMLDivElement |
Root container element |
$canvasDom |
HTMLDivElement |
Canvas container element |
instanceId |
string |
Unique instance identifier |
Sources: packages/relation-graph-models/models/RelationGraphCore.ts:1-70, packages/relation-graph-models/models/RelationGraphBase.ts:19-31
RGDataProvider System
The RGDataProvider acts as the single source of truth for graph data. Platform-specific data providers extend it to integrate with framework reactivity systems.
graph TB
subgraph "Base Data Provider"
BASE["RGDataProvider
Base data management
packages/.../data/RGDataProvider.ts"]
BASE_PROPS["Properties:
- graphData: RGGraphData
- options: RGOptionsFull
- commits: DataCommits
- nodeMap: Map
- linkMap: Map"]
BASE --> BASE_PROPS
end
subgraph "Platform Adapters"
VUE2_DP["RGDataProvider4Vue2
Vue.set() integration
packages/.../data/RGDataProvider4Vue2.ts"]
VUE3_DP["RGDataProvider4Vue3
ref() stores
packages/.../data/RGDataProvider4Vue3.ts"]
REACT_DP["RGDataProvider4React
setState() hook
packages/.../data/RGDataProvider4React.ts"]
SVELTE_DP["RGDataProvider4Svelte
Svelte stores
packages/.../data/RGDataProvider4Svelte.ts"]
end
BASE -.extends.-> VUE2_DP
BASE -.extends.-> VUE3_DP
BASE -.extends.-> REACT_DP
BASE -.extends.-> SVELTE_DP
VUE2_DP --> VUE2_UPDATE["updateViewHook()
triggers Vue 2 reactivity"]
VUE3_DP --> VUE3_UPDATE["updateViewHook()
updates ref() stores"]
REACT_DP --> REACT_UPDATE["updateViewHook()
calls setState()"]
SVELTE_DP --> SVELTE_UPDATE["updateViewHook()
updates Svelte stores"]Data Provider Methods:
// Core data access
getNodes(): RGNode[]
getLines(): RGLine[]
getLinks(): RGLink[]
getNodeById(id: string): RGNode | undefined
// Data manipulation
updateNode(nodeId: string, props: Partial<RGNode>): void
updateLine(lineId: string, props: Partial<RGLine>): void
addNodes(nodes: JsonNode[]): void
addLines(lines: JsonLine[]): void
removeNode(nodeId: string): void
// State management
updateOptions(options: Partial<RGOptionsFull>): void
getOptions(): RGOptionsFull
dataUpdated(): void // Triggers view update
Sources: packages/relation-graph-models/models/RelationGraphWith2Data.ts:1-120, packages/relation-graph-models/data/RGDataProvider.ts
Data Flow Architecture
The system implements unidirectional data flow with reactive updates.
graph TB
subgraph "User Actions"
USER["User Interactions
Click, Drag, Zoom"]
end
subgraph "Event Layer"
EVENTS["RelationGraphWith7Event
onNodeClick()
onNodeDragStart()
onLineClick()"]
end
subgraph "Core Instance"
CORE["RelationGraphCore
Business Logic"]
UPDATE_OPS["Update Operations
updateNode()
updateLine()
updateOptions()"]
end
subgraph "Data Provider"
DP["RGDataProvider
Data Storage"]
COMMITS["DataCommits
Change Tracking
- nodesListChanged
- linesListChanged
- changedNodes[]"]
end
subgraph "Platform Layer"
FW_DP["Platform DataProvider
Vue2/Vue3/React/Svelte"]
STORES["Reactive Stores
- optionsStore
- nodesStore
- linesStore"]
end
subgraph "View Layer"
COMPONENTS["UI Components
RGCanvas
RGNodePeel
RGLinePath"]
DOM["Rendered DOM"]
end
USER -->|triggers| EVENTS
EVENTS -->|calls methods| CORE
CORE -->|delegates| UPDATE_OPS
UPDATE_OPS -->|modifies| DP
DP -->|tracks| COMMITS
DP -->|calls updateViewHook| FW_DP
FW_DP -->|updates| STORES
STORES -.reactive binding.-> COMPONENTS
COMPONENTS -->|renders| DOM
DOM -.user interaction.-> USERCommit System
The data provider tracks changes using a commit system to optimize updates:
interface DataCommits {
nodesListChanged: boolean; // Full node list changed
linesListChanged: boolean; // Full line list changed
changedNodes: RGNode[]; // Specific modified nodes
changedLines: RGLine[]; // Specific modified lines
}
Only changed data triggers reactive updates, preventing unnecessary re-renders.
Sources: packages/relation-graph-models/models/RelationGraphWith7Event.ts:1-50, packages/relation-graph-models/data/RGDataProvider.ts
Platform Abstraction Layer
The architecture achieves framework independence through the updateViewHook pattern.
graph LR
subgraph "Core Logic (Framework Agnostic)"
CORE_METHOD["Core Method
updateNode()"]
DP_UPDATE["RGDataProvider
updateNode()"]
end
subgraph "Abstraction Point"
HOOK["updateViewHook()
Platform-specific implementation"]
end
subgraph "Vue 2 Implementation"
VUE2_IMPL["RGDataProvider4Vue2
Vue.set(node, prop, value)"]
end
subgraph "Vue 3 Implementation"
VUE3_IMPL["RGDataProvider4Vue3
ref.value = newValue"]
end
subgraph "React Implementation"
REACT_IMPL["RGDataProvider4React
setState(newState)"]
end
subgraph "Svelte Implementation"
SVELTE_IMPL["RGDataProvider4Svelte
store.set(newValue)"]
end
CORE_METHOD --> DP_UPDATE
DP_UPDATE --> HOOK
HOOK -.implements.-> VUE2_IMPL
HOOK -.implements.-> VUE3_IMPL
HOOK -.implements.-> REACT_IMPL
HOOK -.implements.-> SVELTE_IMPLPlatform-Specific Initialization
Each platform initializes reactivity differently:
Vue 2:
// packages/relation-graph-models/models/RelationGraphWith2Data.ts:31-36
setReactiveData4Vue2(graphData, reactiveOptions, runtimeData, initRawPropertyFn)
Vue 3:
// packages/relation-graph-models/models/RelationGraphWith2Data.ts:44-60
setReactiveData4Vue3(dataStores, graphData, reactiveOptions, runtimeData, initRawPropertyFn)
React:
// packages/relation-graph-models/models/RelationGraphWith2Data.ts:68-78
setReactiveData4React(dataStores, updateViewHook)
Svelte:
// packages/relation-graph-models/models/RelationGraphWith2Data.ts:95-105
setReactiveData4Svelte(dataStores, updaters)
Sources: packages/relation-graph-models/models/RelationGraphWith2Data.ts:1-120
Type System
The type system provides strong contracts across the architecture.
Core Data Types
| Type | Purpose | Location |
|---|---|---|
RGNode |
Runtime node with layout data | packages/relation-graph-models/types.ts:245-275 |
JsonNode |
Serializable node | packages/relation-graph-models/types.ts:206-241 |
RGLine |
Runtime line | packages/relation-graph-models/types.ts:355-358 |
JsonLine |
Serializable line | packages/relation-graph-models/types.ts:295-339 |
RGLink |
Line with node references | packages/relation-graph-models/types.ts:371-380 |
RGOptions |
User configuration | packages/relation-graph-models/types.ts:688 |
RGOptionsFull |
Complete configuration | packages/relation-graph-models/types.ts:641-684 |
RelationGraphInstance |
Core instance type | packages/relation-graph-models/types.ts:30 |
Type Relationships
graph TB
JSON_NODE["JsonNode
User input format
Serializable"]
RG_NODE["RGNode
Runtime format
+ lot (layout)
+ rgShouldRender
+ rgCalcedVisibility"]
JSON_LINE["JsonLine
User input format
from: string
to: string"]
RG_LINE["RGLine
Runtime format
+ id
+ isReverse"]
RG_LINK["RGLink
Link object
+ fromNode: RGNode
+ toNode: RGNode
+ line: RGLine"]
JSON_NODE -->|json2Node| RG_NODE
RG_NODE -->|transNodeToJson| JSON_NODE
JSON_LINE -->|json2Line| RG_LINE
RG_LINE --> RG_LINK
RG_NODE --> RG_LINKSources: packages/relation-graph-models/types.ts:1-100
Event System
The event system provides extensibility through a hierarchical event emission model.
graph TB
subgraph "Event Source"
USER_ACTION["User Action
e.g., node click"]
INTERNAL["Internal Event
e.g., layout finish"]
end
subgraph "Event Emission (RelationGraphBase)"
EMIT["emitEvent(eventName, ...args)"]
DEFAULT["defaultEventHandler()
Check listeners property"]
CUSTOM["Custom Event Handlers
eventHandlers: RGEventHandler[]"]
HOOK["_emitHook
Vue emit integration"]
end
subgraph "Event Handlers"
LISTENER["RGListeners
onNodeClick
onNodeDragStart
onLineClick
etc."]
HANDLER["Custom Handlers
addEventHandler(handler)"]
end
USER_ACTION --> EMIT
INTERNAL --> EMIT
EMIT --> DEFAULT
EMIT --> CUSTOM
EMIT --> HOOK
DEFAULT --> LISTENER
CUSTOM --> HANDLEREvent Types
// packages/relation-graph-models/types.ts
enum RGEventNames {
onReady = "onReady",
onNodeClick = "onNodeClick",
onNodeDragStart = "onNodeDragStart",
onNodeDragging = "onNodeDragging",
onNodeDragEnd = "onNodeDragEnd",
onLineClick = "onLineClick",
onCanvasClick = "onCanvasClick",
onNodeExpand = "onNodeExpand",
onNodeCollapse = "onNodeCollapse",
onZoomEnd = "onZoomEnd",
// ... many more
}
Event Emission Flow:
- User action triggers event handler method (e.g.,
onNodeClick()) - Method calls
emitEvent(RGEventNames.onNodeClick, node, e) - System checks
defaultEventHandler()for registered listeners - Calls custom event handlers from
eventHandlersarray - Invokes
_emitHookfor framework integration (Vue emit) - Returns custom result if provided, allowing event cancellation
Sources: packages/relation-graph-models/models/RelationGraphBase.ts:110-334, packages/relation-graph-models/types.ts:1000-1100
Key Design Patterns
1. Progressive Enhancement via Inheritance
Each WithX class adds one concern, creating a clear separation of responsibilities. This pattern:
- Makes the codebase testable (test each layer independently)
- Enables partial feature adoption
- Clarifies the dependency chain
2. Core-Adapter Pattern
Framework-agnostic core + platform-specific adapters:
RelationGraphCorecontains no framework code- Platform adapters (
RGDataProvider4Vue2, etc.) handle reactivity - UI components consume the core instance
3. Data Provider as Single Source of Truth
All data modifications go through RGDataProvider:
- Centralized state management
- Change tracking via commits
- Consistent API across platforms
4. Observer Pattern for DOM Integration
RelationGraphWith95Dom uses browser observers:
ResizeObserverfor element size changesMutationObserverfor DOM mutations- Decouples DOM monitoring from business logic
5. Factory Pattern for Layouts
createLayout() instantiates layout algorithms:
RGTreeLayout,RGForceLayout,RGCircleLayout, etc.- Pluggable layout system
- Configuration-driven selection
Sources: packages/relation-graph-models/models/RelationGraphWith6Layout.ts:1-50, packages/relation-graph-models/models/RelationGraphWith95Dom.ts:1-100
This architecture enables relation-graph to maintain a single codebase while supporting multiple frameworks, achieving both code reuse and platform-native reactivity patterns. The progressive enhancement pattern keeps complexity manageable as features scale, while the core-adapter pattern ensures clean separation between graph logic and UI integration.