@rm-graph/core 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +545 -11
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,19 +1,26 @@
1
1
  # @rm-graph/core
2
2
 
3
- RM-Graphs Core - Framework-agnostic charting library built on SciChart.
3
+ 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.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install @rm-graph/core
9
+ # or
10
+ pnpm add @rm-graph/core
11
+ # or
12
+ yarn add @rm-graph/core
9
13
  ```
10
14
 
11
15
  > `scichart` is automatically installed as a dependency!
12
16
 
13
- ## Usage
17
+ ## Quick Start
14
18
 
15
19
  ```typescript
16
- import { createColumn3DChart, createPRPDChart } from '@rm-graph/core';
20
+ import { createColumn3DChart, createPRPDChart, loadLicense } from '@rm-graph/core';
21
+
22
+ // Load license on app startup (optional - removes watermark)
23
+ await loadLicense();
17
24
 
18
25
  // Create a 3D column chart
19
26
  const chart = await createColumn3DChart('container-id', {
@@ -24,7 +31,7 @@ const chart = await createColumn3DChart('container-id', {
24
31
  zAxisTitle: 'Cycle',
25
32
  });
26
33
 
27
- // Update data
34
+ // Update data dynamically
28
35
  chart.setData([[50, 1600, 1], [95, 2300, 2]]);
29
36
 
30
37
  // Change theme
@@ -34,26 +41,553 @@ chart.setOptions({ theme: 'light' });
34
41
  chart.destroy();
35
42
  ```
36
43
 
44
+ ---
45
+
37
46
  ## Chart Types
38
47
 
39
- - `createColumn3DChart` - 3D column charts for phase-resolved data
40
- - `createPRPDChart` - Phase Resolved Partial Discharge heatmaps
41
- - `createSurface3DChart` - 3D surface visualization
48
+ ### Column3DChart
49
+
50
+ 3D column/bar charts for phase-resolved data visualization.
51
+
52
+ ```typescript
53
+ import { createColumn3DChart, type Column3DDataPoint } from '@rm-graph/core';
54
+
55
+ // Data format: [phaseAngle, amplitude, cycle][]
56
+ const data: Column3DDataPoint[] = [
57
+ [45, 1500, 1], // 45° phase, 1500mV amplitude, cycle 1
58
+ [90, 2200, 2], // 90° phase, 2200mV amplitude, cycle 2
59
+ [180, 1800, 3], // 180° phase, 1800mV amplitude, cycle 3
60
+ ];
61
+
62
+ const chart = await createColumn3DChart('container', {
63
+ data,
64
+ theme: 'dark',
65
+ xAxisTitle: 'Phase Angle (°)',
66
+ yAxisTitle: 'Amplitude (mVp)',
67
+ zAxisTitle: 'Cycle',
68
+ xRange: { min: 0, max: 360 },
69
+ yRange: { min: 0, max: 5000 },
70
+ zRange: { min: 0, max: 50 },
71
+ barFill: '#52aaf2',
72
+ barOpacity: 0.95,
73
+ showSineWave: true,
74
+ });
75
+ ```
76
+
77
+ ### PRPDChart
78
+
79
+ Phase Resolved Partial Discharge heatmap visualization.
80
+
81
+ ```typescript
82
+ import { createPRPDChart, type PRPDDataPoint } from '@rm-graph/core';
83
+
84
+ // Data format: [phaseAngle, amplitude, count][]
85
+ const data: PRPDDataPoint[] = [
86
+ [45, 1500, 10], // 45° phase, 1500mV amplitude, 10 pulses
87
+ [90, 2200, 25], // 90° phase, 2200mV amplitude, 25 pulses
88
+ [180, -1800, 15], // 180° phase, -1800mV amplitude, 15 pulses
89
+ ];
90
+
91
+ const chart = await createPRPDChart('container', {
92
+ data,
93
+ maxPeak: 5000,
94
+ minPeak: -5000,
95
+ maxPhaseAngle: 360,
96
+ showSineWave: true,
97
+ showColorPalette: true,
98
+ });
99
+ ```
100
+
101
+ ### Surface3DChart
102
+
103
+ 3D surface visualization for continuous data.
104
+
105
+ ```typescript
106
+ import { createSurface3DChart } from '@rm-graph/core';
107
+
108
+ const chart = await createSurface3DChart('container', {
109
+ yValues: surfaceData, // 2D array of height values
110
+ theme: 'dark',
111
+ colorMin: 0,
112
+ colorMax: 100,
113
+ });
114
+ ```
115
+
116
+ ---
42
117
 
43
118
  ## Theming
44
119
 
45
120
  Built-in themes: `light`, `dark`, `modern`, `midnight`
46
121
 
47
122
  ```typescript
48
- import { getThemeManager } from '@rm-graph/core';
123
+ import { getThemeManager, lightTheme, darkTheme } from '@rm-graph/core';
124
+
125
+ // Use built-in theme
126
+ const chart = await createColumn3DChart('container', {
127
+ theme: 'dark',
128
+ // ...
129
+ });
49
130
 
50
131
  // Register custom theme
51
132
  getThemeManager().registerTheme({
52
133
  name: 'custom',
53
134
  backgroundColor: '#1a1a2e',
54
- colorPalette: ['#ff6b6b', '#4ecdc4'],
55
- // ...
135
+ textColor: '#ffffff',
136
+ gridLineColor: '#333366',
137
+ colorPalette: ['#ff6b6b', '#4ecdc4', '#45b7d1'],
56
138
  });
139
+
140
+ // Use custom theme
141
+ chart.setOptions({ theme: 'custom' });
142
+ ```
143
+
144
+ ### Theme Configuration
145
+
146
+ ```typescript
147
+ interface ThemeConfig {
148
+ name: string;
149
+ backgroundColor: string;
150
+ textColor: string;
151
+ gridLineColor: string;
152
+ axisColor: string;
153
+ colorPalette: string[];
154
+ // ... more options
155
+ }
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 🔑 License Management System
161
+
162
+ The core package includes a complete license management system for SciChart.js with **encrypted storage** support.
163
+
164
+ ### Overview
165
+
166
+ SciChart.js requires a valid license key to remove watermarks from charts. The `@rm-graph/core` package provides:
167
+
168
+ - **Encrypted Storage**: License keys are encrypted before storing in localStorage
169
+ - **Multiple Configuration Methods**: UI component, programmatic, or environment variables
170
+ - **Automatic Loading**: Load license on app startup
171
+ - **Status Tracking**: Check if license is stored and applied
172
+
173
+ ### How Licensing Works Internally
174
+
175
+ ```
176
+ ┌─────────────────────────────────────────────────────────────────┐
177
+ │ LICENSE FLOW DIAGRAM │
178
+ ├─────────────────────────────────────────────────────────────────┤
179
+ │ │
180
+ │ User enters license key │
181
+ │ │ │
182
+ │ ▼ │
183
+ │ ┌─────────────────┐ │
184
+ │ │ validateFormat()│ ──── Invalid ───► Show error message │
185
+ │ └────────┬────────┘ │
186
+ │ │ Valid │
187
+ │ ▼ │
188
+ │ ┌─────────────────────────────────────────┐ │
189
+ │ │ encryptLicense(key, passphrase) │ │
190
+ │ │ - Uses AES-256-GCM (Web Crypto API) │ │
191
+ │ │ - Falls back to Base64 if no HTTPS │ │
192
+ │ └────────┬────────────────────────────────┘ │
193
+ │ │ │
194
+ │ ▼ │
195
+ │ ┌─────────────────────────────────────────┐ │
196
+ │ │ localStorage.setItem( │ │
197
+ │ │ 'RMGRAPH_LICENSE_DATA', │ │
198
+ │ │ encryptedData │ │
199
+ │ │ ) │ │
200
+ │ └────────┬────────────────────────────────┘ │
201
+ │ │ │
202
+ │ ▼ │
203
+ │ ┌─────────────────────────────────────────┐ │
204
+ │ │ SciChartSurface.setRuntimeLicenseKey() │ │
205
+ │ │ - Applies license to SciChart │ │
206
+ │ │ - Removes watermark from charts │ │
207
+ │ └─────────────────────────────────────────┘ │
208
+ │ │
209
+ └─────────────────────────────────────────────────────────────────┘
210
+ ```
211
+
212
+ ### Encryption Details
213
+
214
+ The license system uses **two-tier encryption**:
215
+
216
+ #### Primary: AES-256-GCM (Secure Contexts)
217
+
218
+ When Web Crypto API is available (HTTPS or localhost):
219
+
220
+ ```typescript
221
+ // Encryption process:
222
+ 1. Derive key from passphrase using PBKDF2 (100,000 iterations, SHA-256)
223
+ 2. Generate random 12-byte IV (Initialization Vector)
224
+ 3. Encrypt license key using AES-256-GCM
225
+ 4. Combine IV + encrypted data
226
+ 5. Encode as Base64 for storage
227
+
228
+ // Storage format in localStorage:
229
+ "RMGRAPH_LICENSE_DATA": "base64(IV + AES-GCM-encrypted-data)"
230
+ ```
231
+
232
+ #### Fallback: Base64 Obfuscation (Insecure Contexts)
233
+
234
+ When Web Crypto API is NOT available (HTTP over IP):
235
+
236
+ ```typescript
237
+ // Simple obfuscation:
238
+ 1. Prepend "rmgraph:" prefix
239
+ 2. Encode as Base64
240
+
241
+ // Storage format:
242
+ "RMGRAPH_LICENSE_DATA": "base64('rmgraph:' + licenseKey)"
243
+ ```
244
+
245
+ > **Security Note**: Base64 is NOT encryption - it only provides basic obfuscation. For production, always use HTTPS and combine with SciChart's domain-locking.
246
+
247
+ ### License Management API
248
+
249
+ #### Core Functions
250
+
251
+ ```typescript
252
+ import {
253
+ // High-level operations
254
+ setLicense, // Encrypt, store, and apply license
255
+ loadLicense, // Load from storage and apply
256
+ removeLicense, // Remove stored license
257
+ applyLicenseKey, // Apply directly without storing
258
+
259
+ // Status checks
260
+ hasStoredLicense, // Check if license exists in storage
261
+ isLicenseApplied, // Check if license is active in session
262
+ getLicenseStatus, // Get full status object
263
+ validateLicenseFormat, // Validate key format (basic)
264
+
265
+ // Configuration
266
+ configureLicenseEncryption, // Set custom passphrase
267
+
268
+ // Low-level crypto (advanced)
269
+ encryptLicense,
270
+ decryptLicense,
271
+ saveEncryptedLicense,
272
+ loadEncryptedLicense,
273
+ clearStoredLicense,
274
+ getLicenseStorageKey,
275
+
276
+ // Types
277
+ type LicenseConfig,
278
+ type LicenseStatus,
279
+ } from '@rm-graph/core';
280
+ ```
281
+
282
+ #### Function Reference
283
+
284
+ ##### `setLicense(licenseKey: string): Promise<boolean>`
285
+
286
+ Encrypts and stores a license key, then applies it to SciChart.
287
+
288
+ ```typescript
289
+ const success = await setLicense('your-scichart-license-key');
290
+ if (success) {
291
+ console.log('License saved and applied!');
292
+ } else {
293
+ console.log('Failed to save license');
294
+ }
295
+ ```
296
+
297
+ ##### `loadLicense(): Promise<boolean>`
298
+
299
+ Loads license from encrypted storage and applies to SciChart.
300
+
301
+ ```typescript
302
+ // Call on app startup
303
+ const loaded = await loadLicense();
304
+ if (loaded) {
305
+ console.log('License loaded from storage');
306
+ } else {
307
+ console.log('No license found - charts will show watermark');
308
+ }
309
+ ```
310
+
311
+ ##### `removeLicense(): void`
312
+
313
+ Removes the stored license from localStorage.
314
+
315
+ ```typescript
316
+ removeLicense();
317
+ // Note: Page reload required to remove license from SciChart
318
+ ```
319
+
320
+ ##### `hasStoredLicense(): boolean`
321
+
322
+ Checks if a license exists in localStorage (without decrypting).
323
+
324
+ ```typescript
325
+ if (hasStoredLicense()) {
326
+ console.log('License found in storage');
327
+ }
328
+ ```
329
+
330
+ ##### `isLicenseApplied(): boolean`
331
+
332
+ Checks if a license has been applied to SciChart in the current session.
333
+
334
+ ```typescript
335
+ if (isLicenseApplied()) {
336
+ console.log('License is active');
337
+ }
57
338
  ```
58
339
 
59
- See main README for full documentation.
340
+ ##### `getLicenseStatus(): LicenseStatus`
341
+
342
+ Returns complete license status.
343
+
344
+ ```typescript
345
+ const status = getLicenseStatus();
346
+ // { hasLicense: true, isApplied: true }
347
+ ```
348
+
349
+ ##### `validateLicenseFormat(licenseKey: string): boolean`
350
+
351
+ Basic format validation (length check only - doesn't verify with SciChart).
352
+
353
+ ```typescript
354
+ if (validateLicenseFormat(userInput)) {
355
+ await setLicense(userInput);
356
+ }
357
+ ```
358
+
359
+ ##### `configureLicenseEncryption(config: LicenseConfig): void`
360
+
361
+ Configure custom passphrase for encryption (optional).
362
+
363
+ ```typescript
364
+ // Call before setLicense/loadLicense if using custom passphrase
365
+ configureLicenseEncryption({
366
+ passphrase: 'my-app-secret-key'
367
+ });
368
+ ```
369
+
370
+ ### Usage Examples
371
+
372
+ #### Example 1: Basic Setup
373
+
374
+ ```typescript
375
+ import { loadLicense, createColumn3DChart } from '@rm-graph/core';
376
+
377
+ async function initApp() {
378
+ // Load license on startup
379
+ await loadLicense();
380
+
381
+ // Create charts (will be watermark-free if license is valid)
382
+ const chart = await createColumn3DChart('container', {
383
+ data: myData,
384
+ });
385
+ }
386
+
387
+ initApp();
388
+ ```
389
+
390
+ #### Example 2: Programmatic License Configuration
391
+
392
+ ```typescript
393
+ import { setLicense, loadLicense, hasStoredLicense } from '@rm-graph/core';
394
+
395
+ async function configureLicense(licenseKey: string) {
396
+ // Check if already configured
397
+ if (hasStoredLicense()) {
398
+ console.log('License already stored');
399
+ await loadLicense();
400
+ return;
401
+ }
402
+
403
+ // Save new license
404
+ const success = await setLicense(licenseKey);
405
+ if (success) {
406
+ console.log('License configured successfully');
407
+ }
408
+ }
409
+ ```
410
+
411
+ #### Example 3: Environment Variable Setup
412
+
413
+ ```typescript
414
+ import { setupSciChartLicense } from '@rm-graph/core';
415
+
416
+ // .env file:
417
+ // VITE_SCICHART_LICENSE_KEY=your-license-key
418
+
419
+ // In main.ts:
420
+ await setupSciChartLicense({
421
+ fromEnv: true, // Check VITE_SCICHART_LICENSE_KEY
422
+ fromLocalStorage: true, // Also check encrypted storage
423
+ });
424
+ ```
425
+
426
+ #### Example 4: Custom Passphrase
427
+
428
+ ```typescript
429
+ import {
430
+ configureLicenseEncryption,
431
+ setLicense,
432
+ loadLicense
433
+ } from '@rm-graph/core';
434
+
435
+ // Use custom passphrase for extra security
436
+ configureLicenseEncryption({
437
+ passphrase: 'my-unique-app-identifier-2024'
438
+ });
439
+
440
+ // Now save/load will use this passphrase
441
+ await setLicense('your-license-key');
442
+ await loadLicense();
443
+ ```
444
+
445
+ ### Types
446
+
447
+ ```typescript
448
+ interface LicenseConfig {
449
+ /** Custom passphrase for encryption/decryption */
450
+ passphrase?: string;
451
+ }
452
+
453
+ interface LicenseStatus {
454
+ /** Whether a license is stored in localStorage */
455
+ hasLicense: boolean;
456
+ /** Whether the license was successfully applied to SciChart */
457
+ isApplied: boolean;
458
+ /** Error message if license operation failed */
459
+ error?: string;
460
+ }
461
+ ```
462
+
463
+ ### Storage Details
464
+
465
+ | Key | Value | Description |
466
+ |-----|-------|-------------|
467
+ | `RMGRAPH_LICENSE_DATA` | Base64 encoded encrypted data | Encrypted license key |
468
+
469
+ ### Security Considerations
470
+
471
+ 1. **Client-Side Encryption**: The encryption happens in the browser. While AES-256-GCM is strong, the decryption key (passphrase) is in the client code.
472
+
473
+ 2. **Domain Locking**: For production security, always use SciChart's domain-locking feature. Register your domains at [SciChart License Portal](https://www.scichart.com/licensing-scichart-js/).
474
+
475
+ 3. **HTTPS Required**: Full AES encryption requires HTTPS or localhost. HTTP over IP will use Base64 fallback.
476
+
477
+ 4. **Don't Commit Keys**: Never commit license keys to source control. Use environment variables.
478
+
479
+ ---
480
+
481
+ ## Utilities
482
+
483
+ ```typescript
484
+ import {
485
+ generateId, // Generate unique IDs
486
+ parseSize, // Parse CSS size values
487
+ deepMerge, // Deep merge objects
488
+ debounce, // Debounce function calls
489
+ throttle, // Throttle function calls
490
+ hexToRgba, // Convert hex to RGBA
491
+ formatNumber, // Format numbers
492
+ clamp, // Clamp value to range
493
+ lerp, // Linear interpolation
494
+ } from '@rm-graph/core';
495
+ ```
496
+
497
+ ---
498
+
499
+ ## WebAssembly Configuration
500
+
501
+ SciChart uses WebAssembly for high performance. The package auto-configures to use CDN:
502
+
503
+ ```typescript
504
+ import { configureSciChart } from '@rm-graph/core';
505
+
506
+ // Default: Uses CDN (auto-configured)
507
+
508
+ // Custom WASM location:
509
+ configureSciChart({
510
+ wasmUrl: '/path/to/scichart2d.wasm'
511
+ });
512
+ ```
513
+
514
+ ---
515
+
516
+ ## Framework Integrations
517
+
518
+ This core package is framework-agnostic. For framework-specific components:
519
+
520
+ - **React**: `@rm-graph/react` - React components and hooks
521
+ - **Angular**: `@rm-graph/angular` - Angular components
522
+
523
+ Both packages re-export all core functionality plus framework-specific UI components like `LicenseManager`.
524
+
525
+ ---
526
+
527
+ ## API Reference
528
+
529
+ ### Chart Factory Functions
530
+
531
+ | Function | Description |
532
+ |----------|-------------|
533
+ | `createColumn3DChart(container, config)` | Create 3D column chart |
534
+ | `createPRPDChart(container, config)` | Create PRPD heatmap |
535
+ | `createSurface3DChart(container, config)` | Create 3D surface |
536
+
537
+ ### Chart Instance Methods
538
+
539
+ | Method | Description |
540
+ |--------|-------------|
541
+ | `setData(data)` | Update chart data |
542
+ | `setOptions(options)` | Update chart options |
543
+ | `destroy()` | Cleanup and remove chart |
544
+
545
+ ### Theme Functions
546
+
547
+ | Function | Description |
548
+ |----------|-------------|
549
+ | `getThemeManager()` | Get theme manager instance |
550
+ | `lightTheme` | Built-in light theme |
551
+ | `darkTheme` | Built-in dark theme |
552
+ | `modernTheme` | Built-in modern theme |
553
+ | `midnightTheme` | Built-in midnight theme |
554
+
555
+ ### License Functions
556
+
557
+ | Function | Description |
558
+ |----------|-------------|
559
+ | `setLicense(key)` | Save and apply license |
560
+ | `loadLicense()` | Load license from storage |
561
+ | `removeLicense()` | Remove stored license |
562
+ | `hasStoredLicense()` | Check if license exists |
563
+ | `isLicenseApplied()` | Check if license is active |
564
+ | `getLicenseStatus()` | Get full status |
565
+
566
+ ---
567
+
568
+ ## Troubleshooting
569
+
570
+ ### Charts show watermark
571
+
572
+ 1. Verify license is loaded: `console.log(getLicenseStatus())`
573
+ 2. Check browser console for license errors
574
+ 3. Ensure domain is registered in SciChart portal
575
+ 4. Try reloading page after setting license
576
+
577
+ ### Crypto errors on HTTP
578
+
579
+ Web Crypto API requires secure context (HTTPS or localhost). The system will fallback to Base64 encoding automatically.
580
+
581
+ ### License not persisting
582
+
583
+ Check if localStorage is available and not blocked by browser settings.
584
+
585
+ ---
586
+
587
+ ## License
588
+
589
+ MIT
590
+
591
+ ---
592
+
593
+ See framework-specific packages for UI components and additional documentation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rm-graph/core",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "RM-Graphs Core - Charting library built on SciChart",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",