@rm-graph/core
v0.1.13
Published
RM-Graphs Core - Charting library built on SciChart
Downloads
91
Maintainers
Readme
@rm-graph/core
RM-Graphs Core - Framework-agnostic charting library built on SciChart.js. This package provides the core functionality for creating high-performance 2D and 3D charts, including license management with encrypted storage.
Installation
npm install @rm-graph/core
# or
pnpm add @rm-graph/core
# or
yarn add @rm-graph/core
scichartis automatically installed as a dependency!
Quick Start
import { createColumn3DChart, createPRPDChart, loadLicense } from '@rm-graph/core';
// Load license on app startup (optional - removes watermark)
await loadLicense();
// Create a 3D column chart
const chart = await createColumn3DChart('container-id', {
theme: 'dark',
data: [[45, 1500, 1], [90, 2200, 2], [180, 1800, 3]],
xAxisTitle: 'Phase Angle (°)',
yAxisTitle: 'Amplitude (mVp)',
zAxisTitle: 'Cycle',
});
// Update data dynamically
chart.setData([[50, 1600, 1], [95, 2300, 2]]);
// Change theme
chart.setOptions({ theme: 'light' });
// Cleanup when done
chart.destroy();Chart Types
Column3DChart
3D column/bar charts for phase-resolved data visualization.
import { createColumn3DChart, type Column3DDataPoint } from '@rm-graph/core';
// Data format: [phaseAngle, amplitude, cycle][]
const data: Column3DDataPoint[] = [
[45, 1500, 1], // 45° phase, 1500mV amplitude, cycle 1
[90, 2200, 2], // 90° phase, 2200mV amplitude, cycle 2
[180, 1800, 3], // 180° phase, 1800mV amplitude, cycle 3
];
const chart = await createColumn3DChart('container', {
data,
theme: 'dark',
xAxisTitle: 'Phase Angle (°)',
yAxisTitle: 'Amplitude (mVp)',
zAxisTitle: 'Cycle',
xRange: { min: 0, max: 360 },
yRange: { min: 0, max: 5000 },
zRange: { min: 0, max: 50 },
barFill: '#52aaf2',
barOpacity: 0.95,
showSineWave: true,
});PRPDChart
Phase Resolved Partial Discharge heatmap visualization.
import { createPRPDChart, type PRPDDataPoint } from '@rm-graph/core';
// Data format: [phaseAngle, amplitude, count][]
const data: PRPDDataPoint[] = [
[45, 1500, 10], // 45° phase, 1500mV amplitude, 10 pulses
[90, 2200, 25], // 90° phase, 2200mV amplitude, 25 pulses
[180, -1800, 15], // 180° phase, -1800mV amplitude, 15 pulses
];
const chart = await createPRPDChart('container', {
data,
maxPeak: 5000,
minPeak: -5000,
maxPhaseAngle: 360,
showSineWave: true,
showColorPalette: true,
});Surface3DChart
3D surface visualization for continuous data.
import { createSurface3DChart } from '@rm-graph/core';
const chart = await createSurface3DChart('container', {
yValues: surfaceData, // 2D array of height values
theme: 'dark',
colorMin: 0,
colorMax: 100,
});Theming
Built-in themes: light, dark, modern, midnight
import { getThemeManager, lightTheme, darkTheme } from '@rm-graph/core';
// Use built-in theme
const chart = await createColumn3DChart('container', {
theme: 'dark',
// ...
});
// Register custom theme
getThemeManager().registerTheme({
name: 'custom',
backgroundColor: '#1a1a2e',
textColor: '#ffffff',
gridLineColor: '#333366',
colorPalette: ['#ff6b6b', '#4ecdc4', '#45b7d1'],
});
// Use custom theme
chart.setOptions({ theme: 'custom' });Theme Configuration
interface ThemeConfig {
name: string;
backgroundColor: string;
textColor: string;
gridLineColor: string;
axisColor: string;
colorPalette: string[];
// ... more options
}🔑 License Management System
The core package includes a complete license management system for SciChart.js with encrypted storage support.
Overview
SciChart.js requires a valid license key to remove watermarks from charts. The @rm-graph/core package provides:
- Encrypted Storage: License keys are encrypted before storing in localStorage
- Multiple Configuration Methods: UI component, programmatic, or environment variables
- Automatic Loading: Load license on app startup
- Status Tracking: Check if license is stored and applied
How Licensing Works Internally
┌─────────────────────────────────────────────────────────────────┐
│ LICENSE FLOW DIAGRAM │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User enters license key │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ validateFormat()│ ──── Invalid ───► Show error message │
│ └────────┬────────┘ │
│ │ Valid │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ encryptLicense(key, passphrase) │ │
│ │ - Uses AES-256-GCM (Web Crypto API) │ │
│ │ - Falls back to Base64 if no HTTPS │ │
│ └────────┬────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ localStorage.setItem( │ │
│ │ 'RMGRAPH_LICENSE_DATA', │ │
│ │ encryptedData │ │
│ │ ) │ │
│ └────────┬────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ SciChartSurface.setRuntimeLicenseKey() │ │
│ │ - Applies license to SciChart │ │
│ │ - Removes watermark from charts │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘Encryption Details
The license system uses two-tier encryption:
Primary: AES-256-GCM (Secure Contexts)
When Web Crypto API is available (HTTPS or localhost):
// Encryption process:
1. Derive key from passphrase using PBKDF2 (100,000 iterations, SHA-256)
2. Generate random 12-byte IV (Initialization Vector)
3. Encrypt license key using AES-256-GCM
4. Combine IV + encrypted data
5. Encode as Base64 for storage
// Storage format in localStorage:
"RMGRAPH_LICENSE_DATA": "base64(IV + AES-GCM-encrypted-data)"Fallback: Base64 Obfuscation (Insecure Contexts)
When Web Crypto API is NOT available (HTTP over IP):
// Simple obfuscation:
1. Prepend "rmgraph:" prefix
2. Encode as Base64
// Storage format:
"RMGRAPH_LICENSE_DATA": "base64('rmgraph:' + licenseKey)"Security Note: Base64 is NOT encryption - it only provides basic obfuscation. For production, always use HTTPS and combine with SciChart's domain-locking.
License Management API
Core Functions
import {
// High-level operations
setLicense, // Encrypt, store, and apply license
loadLicense, // Load from storage and apply
removeLicense, // Remove stored license
applyLicenseKey, // Apply directly without storing
// Status checks
hasStoredLicense, // Check if license exists in storage
isLicenseApplied, // Check if license is active in session
getLicenseStatus, // Get full status object
validateLicenseFormat, // Validate key format (basic)
// Configuration
configureLicenseEncryption, // Set custom passphrase
// Low-level crypto (advanced)
encryptLicense,
decryptLicense,
saveEncryptedLicense,
loadEncryptedLicense,
clearStoredLicense,
getLicenseStorageKey,
// Types
type LicenseConfig,
type LicenseStatus,
} from '@rm-graph/core';Function Reference
setLicense(licenseKey: string): Promise<boolean>
Encrypts and stores a license key, then applies it to SciChart.
const success = await setLicense('your-scichart-license-key');
if (success) {
console.log('License saved and applied!');
} else {
console.log('Failed to save license');
}loadLicense(): Promise<boolean>
Loads license from encrypted storage and applies to SciChart.
// Call on app startup
const loaded = await loadLicense();
if (loaded) {
console.log('License loaded from storage');
} else {
console.log('No license found - charts will show watermark');
}removeLicense(): void
Removes the stored license from localStorage.
removeLicense();
// Note: Page reload required to remove license from SciCharthasStoredLicense(): boolean
Checks if a license exists in localStorage (without decrypting).
if (hasStoredLicense()) {
console.log('License found in storage');
}isLicenseApplied(): boolean
Checks if a license has been applied to SciChart in the current session.
if (isLicenseApplied()) {
console.log('License is active');
}getLicenseStatus(): LicenseStatus
Returns complete license status.
const status = getLicenseStatus();
// { hasLicense: true, isApplied: true }validateLicenseFormat(licenseKey: string): boolean
Basic format validation (length check only - doesn't verify with SciChart).
if (validateLicenseFormat(userInput)) {
await setLicense(userInput);
}configureLicenseEncryption(config: LicenseConfig): void
Configure custom passphrase for encryption (optional).
// Call before setLicense/loadLicense if using custom passphrase
configureLicenseEncryption({
passphrase: 'my-app-secret-key'
});Usage Examples
Example 1: Basic Setup
import { loadLicense, createColumn3DChart } from '@rm-graph/core';
async function initApp() {
// Load license on startup
await loadLicense();
// Create charts (will be watermark-free if license is valid)
const chart = await createColumn3DChart('container', {
data: myData,
});
}
initApp();Example 2: Programmatic License Configuration
import { setLicense, loadLicense, hasStoredLicense } from '@rm-graph/core';
async function configureLicense(licenseKey: string) {
// Check if already configured
if (hasStoredLicense()) {
console.log('License already stored');
await loadLicense();
return;
}
// Save new license
const success = await setLicense(licenseKey);
if (success) {
console.log('License configured successfully');
}
}Example 3: Environment Variable Setup
import { setupSciChartLicense } from '@rm-graph/core';
// .env file:
// VITE_SCICHART_LICENSE_KEY=your-license-key
// In main.ts:
await setupSciChartLicense({
fromEnv: true, // Check VITE_SCICHART_LICENSE_KEY
fromLocalStorage: true, // Also check encrypted storage
});Example 4: Custom Passphrase
import {
configureLicenseEncryption,
setLicense,
loadLicense
} from '@rm-graph/core';
// Use custom passphrase for extra security
configureLicenseEncryption({
passphrase: 'my-unique-app-identifier-2024'
});
// Now save/load will use this passphrase
await setLicense('your-license-key');
await loadLicense();Types
interface LicenseConfig {
/** Custom passphrase for encryption/decryption */
passphrase?: string;
}
interface LicenseStatus {
/** Whether a license is stored in localStorage */
hasLicense: boolean;
/** Whether the license was successfully applied to SciChart */
isApplied: boolean;
/** Error message if license operation failed */
error?: string;
}Storage Details
| Key | Value | Description |
|-----|-------|-------------|
| RMGRAPH_LICENSE_DATA | Base64 encoded encrypted data | Encrypted license key |
Security Considerations
Client-Side Encryption: The encryption happens in the browser. While AES-256-GCM is strong, the decryption key (passphrase) is in the client code.
Domain Locking: For production security, always use SciChart's domain-locking feature. Register your domains at SciChart License Portal.
HTTPS Required: Full AES encryption requires HTTPS or localhost. HTTP over IP will use Base64 fallback.
Don't Commit Keys: Never commit license keys to source control. Use environment variables.
Utilities
import {
generateId, // Generate unique IDs
parseSize, // Parse CSS size values
deepMerge, // Deep merge objects
debounce, // Debounce function calls
throttle, // Throttle function calls
hexToRgba, // Convert hex to RGBA
formatNumber, // Format numbers
clamp, // Clamp value to range
lerp, // Linear interpolation
} from '@rm-graph/core';WebAssembly Configuration
SciChart uses WebAssembly for high performance. The package auto-configures to use CDN:
import { configureSciChart } from '@rm-graph/core';
// Default: Uses CDN (auto-configured)
// Custom WASM location:
configureSciChart({
wasmUrl: '/path/to/scichart2d.wasm'
});Framework Integrations
This core package is framework-agnostic. For framework-specific components:
- React:
@rm-graph/react- React components and hooks - Angular:
@rm-graph/angular- Angular components
Both packages re-export all core functionality plus framework-specific UI components like LicenseManager.
API Reference
Chart Factory Functions
| Function | Description |
|----------|-------------|
| createColumn3DChart(container, config) | Create 3D column chart |
| createPRPDChart(container, config) | Create PRPD heatmap |
| createSurface3DChart(container, config) | Create 3D surface |
Chart Instance Methods
| Method | Description |
|--------|-------------|
| setData(data) | Update chart data |
| setOptions(options) | Update chart options |
| destroy() | Cleanup and remove chart |
Theme Functions
| Function | Description |
|----------|-------------|
| getThemeManager() | Get theme manager instance |
| lightTheme | Built-in light theme |
| darkTheme | Built-in dark theme |
| modernTheme | Built-in modern theme |
| midnightTheme | Built-in midnight theme |
License Functions
| Function | Description |
|----------|-------------|
| setLicense(key) | Save and apply license |
| loadLicense() | Load license from storage |
| removeLicense() | Remove stored license |
| hasStoredLicense() | Check if license exists |
| isLicenseApplied() | Check if license is active |
| getLicenseStatus() | Get full status |
Troubleshooting
Charts show watermark
- Verify license is loaded:
console.log(getLicenseStatus()) - Check browser console for license errors
- Ensure domain is registered in SciChart portal
- Try reloading page after setting license
Crypto errors on HTTP
Web Crypto API requires secure context (HTTPS or localhost). The system will fallback to Base64 encoding automatically.
License not persisting
Check if localStorage is available and not blocked by browser settings.
License
MIT
See framework-specific packages for UI components and additional documentation.
