JavaScript is required

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 --> Svelte

Sources:


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:


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 --> RDP4S

Framework 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:


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 updates

Sources:

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 --> ShouldRender

Sources:

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 id field
  • Applies default node shape, width, height from graphOptions
  • Initializes lot (layout tracking object) with empty children array
  • Sets el_W and el_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 id if not provided
  • Applies default line shape, color, width from graphOptions
  • Normalizes from/to (also accepts source/target aliases)
  • Sets junction points, line shape, arrow visibility
  • Initializes isReverse flag 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 --> Canvas

Key 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:

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:

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:


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 --> UI

Default Creation: createDefaultConfig() generates default options with sensible values:

Sources:

Updating Options

Options updates go through RGDataProvider.updateOptions():

updateOptions(options: Partial<RGOptionsFull>): void

This method:

  1. Merges new values into this.options via Object.assign()
  2. Handles special cases for performance mode viewport changes
  3. Sets commits.optionsChanged = true
  4. 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 renders

Sources: