Data Management System
Purpose and Scope
The Data Management System is responsible for storing, updating, and synchronizing all graph data (nodes, lines, links) with the UI layer across multiple JavaScript frameworks. It provides a framework-agnostic core with reactive adapters for Vue 2, Vue 3, React, and Svelte, enabling bidirectional data flow between user interactions and visual rendering.
For information about specific CRUD operations, see CRUD Operations & State Updates. For details on framework-specific reactive integration, see Reactive Data Integration. For querying and analysis capabilities, see Graph Analysis & Queries.
Architecture Overview
The data management system follows a layered architecture with a framework-agnostic core (RGDataProvider) and framework-specific adapters that handle reactive updates.
graph TB
subgraph "Framework Layer"
Vue2["RelationGraphWith2Data
setReactiveData4Vue2()"]
Vue3["RelationGraphWith2Data
setReactiveData4Vue3()"]
React["RelationGraphWith2Data
setReactiveData4React()"]
Svelte["RelationGraphWith2Data
setReactiveData4Svelte()"]
end
subgraph "Core Data Management"
DP["RGDataProvider
(extends RGDataGetter)"]
DPVue2["RGDataProvider4Vue2"]
DPVue3["RGDataProvider4Vue3"]
DPReact["RGDataProvider4React"]
DPSvelte["RGDataProvider4Svelte"]
end
subgraph "Data Structures"
GraphData["RGGraphData
{nodes, normalLines, fakeLines, rootNode}"]
Options["RGOptionsFull
{layout, zoom, offset, editing...}"]
Runtime["Runtime Maps
runtimeDATA4NodeMap
runtimeDATA4LinkMap
runtimeDATA4Links"]
ShouldRender["Render Lists
shouldRenderNodes
shouldRenderLines
shouldRenderFakeLines"]
end
subgraph "Update Mechanism"
Commits["DataCommits
{changedNodes, changedLines,
nodesListChanged...}"]
UpdateHook["updateViewHook()
Triggers framework re-render"]
end
Vue2 --> DPVue2
Vue3 --> DPVue3
React --> DPReact
Svelte --> DPSvelte
DPVue2 --> DP
DPVue3 --> DP
DPReact --> DP
DPSvelte --> DP
DP --> GraphData
DP --> Options
DP --> Runtime
DP --> ShouldRender
DP --> Commits
Commits --> UpdateHook
UpdateHook --> Vue2
UpdateHook --> Vue3
UpdateHook --> React
UpdateHook --> SvelteSources:
- packages/relation-graph-models/models/RelationGraphWith2Data.ts:1-125
- packages/relation-graph-models/data/RGDataProvider.ts:1-60
Core Data Structures
RGGraphData
The primary container for all graph elements, maintained by RGDataProvider:
| Property | Type | Description |
|---|---|---|
nodes |
RGNode[] |
All nodes in the graph |
normalLines |
RGLine[] |
Standard lines connecting nodes |
fakeLines |
RGFakeLine[] |
Virtual lines for element connections |
rootNode |
RGNode | undefined |
The designated root node for layouts |
Sources:
Runtime Data Maps
For fast lookups and relationship tracking:
graph LR
subgraph "RGDataProvider Internal Storage"
NodeMap["runtimeDATA4NodeMap
Map<nodeId, RGNode>"]
LinkMap["runtimeDATA4LinkMap
Map<lineId, RGLink>"]
Links["runtimeDATA4Links
RGLink[]"]
ElTargets["runtimeDATA4ElLineTargets
RGLineTarget[]"]
ConnectTargets["runtimeDATA4ConnectTargets
RGConnectTargetData[]"]
end
NodeMap -.->|"O(1) lookup"| Node["RGNode"]
LinkMap -.->|"O(1) lookup"| Link["RGLink"]
Links --> FromNode["fromNode: RGNode"]
Links --> ToNode["toNode: RGNode"]
ElTargets -.->|"HTML element"| HTMLEl["DOM Element"]
ConnectTargets -.->|"connection points"| NodeOrCanvas["Node or Canvas"]Sources:
- packages/relation-graph-models/data/RGDataGetter.ts (base class)
- packages/relation-graph-models/data/RGDataProvider.ts:45-55
Data Provider System
RGDataProvider Class Hierarchy
graph TB
RDG["RGDataGetter
Read-only query methods"]
RDP["RGDataProvider
CRUD + commit tracking"]
RDG --> RDP
RDP4V2["RGDataProvider4Vue2
Vue.set() reactivity"]
RDP4V3["RGDataProvider4Vue3
ref/reactive API"]
RDP4R["RGDataProvider4React
setState hook"]
RDP4S["RGDataProvider4Svelte
writable stores"]
RDP --> RDP4V2
RDP --> RDP4V3
RDP --> RDP4R
RDP --> RDP4SFramework Adapter Initialization
Each framework has a dedicated setup method in RelationGraphWith2Data:
| Framework | Method | Data Provider Class | Key Features |
|---|---|---|---|
| Vue 2 | setReactiveData4Vue2() |
RGDataProvider4Vue2 |
Uses Vue.set() for reactivity |
| Vue 3 | setReactiveData4Vue3() |
RGDataProvider4Vue3 |
Uses ref() and reactive() |
| React | setReactiveData4React() |
RGDataProvider4React |
Calls updateViewHook() to trigger setState |
| Svelte | setReactiveData4Svelte() |
RGDataProvider4Svelte |
Uses writable stores with updaters |
Sources:
- packages/relation-graph-models/models/RelationGraphWith2Data.ts:31-110
- packages/relation-graph-models/data/RGDataProvider4Vue2.ts
- packages/relation-graph-models/data/RGDataProvider4Vue3.ts
- packages/relation-graph-models/data/RGDataProvider4React.ts
- packages/relation-graph-models/data/RGDataProvider4Svelte.ts
Commit-Based Update Mechanism
DataCommits Structure
The system tracks changes through a commit object that records what data has been modified:
type DataCommits = {
optionsChanged: boolean,
changedNodes: string[], // Node IDs that changed
nodesListChanged: boolean, // Structural change (add/remove)
changedLines: string[],
linesListChanged: boolean,
changedFakeLines: string[],
fakeLinesListChanged: boolean,
changedConnectTargets: string[],
connectTargetsListChanged: boolean
}
Sources:
Update Flow Diagram
sequenceDiagram
participant User
participant API as "Public API
(addNode, updateNode...)"
participant DP as "RGDataProvider"
participant Commits as "DataCommits"
participant Hook as "updateViewHook()"
participant Framework as "Framework
(Vue/React/Svelte)"
User->>API: addNode(nodeJson)
API->>DP: addNodes([rgNode])
DP->>DP: graphData.nodes.push(rgNode)
DP->>DP: runtimeDATA4NodeMap.set(id, node)
DP->>Commits: commits.nodesListChanged = true
API->>DP: dataUpdated()
DP->>DP: const commits = this.commits
DP->>DP: this.commits = resetCommits()
DP->>Hook: updateViewHook(commits)
Hook->>Framework: Trigger re-render
Framework-->>User: UI updatesSources:
- packages/relation-graph-models/data/RGDataProvider.ts:109-122
- packages/relation-graph-models/models/RelationGraphWith2Data3Update.ts:385-416
Commit Tracking Methods
Key methods in RGDataProvider for tracking changes:
| Method | Purpose | Lines Changed |
|---|---|---|
commitNode(nodeId) |
Mark a node as changed | packages/relation-graph-models/data/RGDataProvider.ts:85-96 |
commitLine(lineId) |
Mark a line as changed | packages/relation-graph-models/data/RGDataProvider.ts:79-84 |
commitFakeLine(lineId) |
Mark a fake line as changed | packages/relation-graph-models/data/RGDataProvider.ts:97-102 |
dataUpdated() |
Execute all commits and trigger view update | packages/relation-graph-models/data/RGDataProvider.ts:109-122 |
Data Synchronization Flow
CRUD Operation Pipeline
graph LR
subgraph "Input Layer"
JsonNode["JsonNode
{id, text, x, y...}"]
JsonLine["JsonLine
{from, to, text...}"]
end
subgraph "Transformation"
J2N["json2Node()
Convert & validate"]
J2L["json2Line()
Convert & validate"]
end
subgraph "Data Provider Operations"
AddNode["addNodes(RGNode[])"]
AddLine["addLines(RGLine[])"]
UpdateNode["updateNode(id, updates)"]
RemoveNode["removeNodeById(ids)"]
end
subgraph "Storage Updates"
NodeArr["graphData.nodes[]"]
LineArr["graphData.normalLines[]"]
NodeMap["runtimeDATA4NodeMap"]
LinkUpdate["updateLinks()
Rebuild RGLink[]"]
end
subgraph "Rendering Pipeline"
Commits["Commit tracking"]
ViewUpdate["updateViewHook()"]
ShouldRender["updateShouldRenderGraphData()
(Performance mode)"]
end
JsonNode --> J2N
JsonLine --> J2L
J2N --> AddNode
J2L --> AddLine
AddNode --> NodeArr
AddNode --> NodeMap
AddLine --> LineArr
AddLine --> LinkUpdate
UpdateNode --> NodeMap
RemoveNode --> NodeArr
RemoveNode --> NodeMap
NodeArr --> Commits
LineArr --> Commits
LinkUpdate --> Commits
Commits --> ViewUpdate
Commits --> ShouldRenderSources:
- packages/relation-graph-models/models/RelationGraphWith2Data3Update.ts:385-456
- packages/relation-graph-models/data/RGNodeDataUtils.ts:10-96
- packages/relation-graph-models/data/RGLineDataUtils.ts
Key Transformation Functions
json2Node() - Node Creation
Converts user-provided JSON to internal RGNode format with defaults:
json2Node(originData: JsonNode, graphOptions?: RGOptions): RGNode
Key transformations:
- Validates required
idfield - Applies default node shape, width, height from
graphOptions - Initializes
lot(layout tracking object) with empty children array - Sets
el_Wandel_H(element width/height) for rendering - Defaults
expanded: true,rgCalcedVisibility: true,rgShouldRender: true
Sources:
json2Line() - Line Creation
Converts user-provided line JSON to internal RGLine format:
Key transformations:
- Generates unique
idif not provided - Applies default line shape, color, width from
graphOptions - Normalizes
from/to(also acceptssource/targetaliases) - Sets junction points, line shape, arrow visibility
- Initializes
isReverseflag for bidirectional rendering
Sources:
Performance Optimizations
Viewport Culling with shouldRender Lists
For large graphs (>1000 nodes), the system maintains filtered lists of visible elements:
graph TB
subgraph "Full Data"
AllNodes["graphData.nodes
(All nodes)"]
AllLines["graphData.normalLines
(All lines)"]
AllFake["graphData.fakeLines
(All fake lines)"]
end
subgraph "Update Trigger"
Trigger["Canvas offset/zoom changes
or node position updates"]
end
subgraph "Culling Algorithm"
UpdateMethod["updateShouldRenderGraphData()"]
ViewBox["Calculate viewport bounds
considering zoom & offset"]
Filter["Filter nodes/lines
within viewport"]
end
subgraph "Optimized Render Lists"
RenderNodes["shouldRenderNodes[]
(Visible nodes only)"]
RenderLines["shouldRenderLines[]
(Visible lines only)"]
RenderFake["shouldRenderFakeLines[]
(Visible fake lines)"]
end
subgraph "UI Components"
Canvas["RGCanvas components
iterate shouldRender* lists"]
end
AllNodes --> UpdateMethod
AllLines --> UpdateMethod
AllFake --> UpdateMethod
Trigger --> UpdateMethod
UpdateMethod --> ViewBox
ViewBox --> Filter
Filter --> RenderNodes
Filter --> RenderLines
Filter --> RenderFake
RenderNodes --> Canvas
RenderLines --> Canvas
RenderFake --> CanvasKey Method: updateShouldRenderGraphData()
This method is called when:
- Canvas offset changes (pan)
- Canvas zoom changes
- Node positions update (drag, layout)
- Performance mode is enabled (
options.performanceMode)
Sources:
- packages/relation-graph-models/data/RGDataProvider.ts:129-145
- packages/relation-graph-models/models/RelationGraphWith2Data.ts:36-63
Data Stores Structure
The dataStores object provides direct references to reactive containers for each framework:
dataStores: {
optionsStore: any, // Main options object
shouldRenderNodesStore: any, // Culled node list
shouldRenderLinesStore: any, // Culled line list
shouldRenderFakeLinesStore: any, // Culled fake line list
optionsRef?: any, // Vue 3 ref wrapper
shouldRenderNodesRef?: any, // Vue 3 ref wrapper
shouldRenderLinesRef?: any, // Vue 3 ref wrapper
shouldRenderFakeLinesRef?: any // Vue 3 ref wrapper
}
Sources:
Node and Line Management
Node CRUD Operations
| Operation | Method | Description |
|---|---|---|
| Create | addNode(JsonNode) |
Converts JSON to RGNode and adds to graph |
| Create Batch | addNodes(JsonNode[]) |
Batch add multiple nodes |
| Read | getNodeById(id) |
O(1) lookup via runtimeDATA4NodeMap |
| Update | updateNode(id, Partial<RGNode>) |
Merge updates into existing node |
| Delete | removeNodeById(id) |
Removes node and associated lines |
Important: Node removal automatically triggers beforeNodeBeRemove() which deletes:
- All lines connected to the node (
from === nodeId || to === nodeId) - All fake lines connected to the node
- Connect targets associated with the node
Sources:
- packages/relation-graph-models/models/RelationGraphWith2Data3Update.ts:144-168
- packages/relation-graph-models/data/RGDataProvider.ts:220-236
Line CRUD Operations
| Operation | Method | Description |
|---|---|---|
| Create | addLine(JsonLine) |
Converts JSON to RGLine and adds to graph |
| Create Batch | addLines(JsonLine[]) |
Batch add; auto-separates normal/fake lines |
| Read | getLineById(id) |
Searches normalLines array |
| Update | updateLine(id, Partial<RGLine>) |
Updates line properties |
| Delete | removeLineById(id) |
Removes line and associated RGLink |
Link Generation: When lines are added, updateLinks() creates RGLink objects that store references to actual RGNode objects for fast rendering:
type RGLink = {
fromNode: RGNode,
toNode: RGNode,
lineId: string,
currentLineIndex: number, // For multi-line spacing
totalLinesBetweenNodes: number // Total lines between same nodes
}
Sources:
- packages/relation-graph-models/models/RelationGraphWith2Data3Update.ts:174-205
- packages/relation-graph-models/data/RGDataProvider.ts:237-253
Options Management
RGOptionsFull Structure
The options object controls all graph behavior and visual state:
graph TB
subgraph "Configuration"
Layout["layout: RGLayoutOptions
{layoutName, direction, gaps...}"]
Visual["Visual Settings
defaultNodeColor, defaultLineShape..."]
Interaction["Interaction
disableDragNode, canvasMoveMode..."]
end
subgraph "Runtime State"
Canvas["Canvas State
canvasZoom, canvasOffset, viewSize"]
Checked["Selection State
checkedNodeId, checkedLineId"]
Editing["Editing State
editingController, editingLineController"]
end
subgraph "Feature Flags"
Performance["performanceMode, showEasyView"]
Animation["enableNodeXYAnimation, enableCanvasTransformAnimation"]
UI["showToolBar, showMiniView, showReferenceLine"]
end
Options["RGOptionsFull"] --> Layout
Options --> Visual
Options --> Interaction
Options --> Canvas
Options --> Checked
Options --> Editing
Options --> Performance
Options --> Animation
Options --> UIDefault Creation: createDefaultConfig() generates default options with sensible values:
Sources:
- packages/relation-graph-models/data/RGOptionsDataUtils.ts:15-242
- packages/relation-graph-models/models/RelationGraphWith3Options1Update.ts:21-58
Updating Options
Options updates go through RGDataProvider.updateOptions():
updateOptions(options: Partial<RGOptionsFull>): void
This method:
- Merges new values into
this.optionsviaObject.assign() - Handles special cases for performance mode viewport changes
- Sets
commits.optionsChanged = true - Does NOT call
dataUpdated()automatically (caller must invoke)
Sources:
Data Lifecycle Example
Complete flow of adding a node and line:
sequenceDiagram
participant User as "User Code"
participant API as "graphInstance"
participant With2Data3 as "RelationGraphWith2Data3Update"
participant DP as "RGDataProvider"
participant Maps as "Internal Maps"
participant View as "UI Components"
Note over User,View: 1. Add Node
User->>API: addNode({id:'A', text:'Node A'})
API->>With2Data3: _addNodes([jsonNode])
With2Data3->>With2Data3: json2Node(jsonNode, options)
With2Data3->>DP: addNodes([rgNode])
DP->>Maps: graphData.nodes.push(rgNode)
DP->>Maps: runtimeDATA4NodeMap.set('A', rgNode)
DP->>DP: commits.nodesListChanged=true
With2Data3->>DP: _dataUpdated()
DP->>DP: dataUpdated()
DP->>View: updateViewHook(commits)
View-->>User: Node renders
Note over User,View: 2. Add Line
User->>API: addLine({from:'A', to:'B'})
API->>With2Data3: _addLines([jsonLine])
With2Data3->>With2Data3: json2Line(jsonLine, options)
With2Data3->>DP: addLines([rgLine])
DP->>Maps: graphData.normalLines.push(rgLine)
DP->>DP: updateLinks()
DP->>Maps: Create RGLink{fromNode, toNode}
DP->>Maps: runtimeDATA4Links.push(link)
DP->>Maps: runtimeDATA4LinkMap.set(lineId, link)
DP->>DP: commits.linesListChanged=true
With2Data3->>DP: _dataUpdated()
DP->>DP: dataUpdated()
DP->>View: updateViewHook(commits)
View-->>User: Line rendersSources: