@rm-graph/core 0.1.11 → 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.
- package/README.md +545 -11
- package/dist/{chunk-BNXHM7UU.mjs → chunk-PKJHVSFI.mjs} +33 -2
- package/dist/chunk-PKJHVSFI.mjs.map +1 -0
- package/dist/{chunk-QFDC4NU3.js → chunk-RLQMHQEV.js} +33 -2
- package/dist/chunk-RLQMHQEV.js.map +1 -0
- package/dist/index.js +20 -20
- package/dist/index.mjs +2 -2
- package/dist/{license-NCCUYGQL.mjs → license-MTK7WNNA.mjs} +3 -3
- package/dist/{license-NCCUYGQL.mjs.map → license-MTK7WNNA.mjs.map} +1 -1
- package/dist/{license-VBO3ZTOJ.js → license-U7ZNTU6D.js} +21 -21
- package/dist/{license-VBO3ZTOJ.js.map → license-U7ZNTU6D.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-BNXHM7UU.mjs.map +0 -1
- package/dist/chunk-QFDC4NU3.js.map +0 -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
|
-
##
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
@@ -6,7 +6,28 @@ import { SciChartSurface } from 'scichart';
|
|
|
6
6
|
var ALGORITHM = "AES-GCM";
|
|
7
7
|
var KEY_LENGTH = 256;
|
|
8
8
|
var STORAGE_KEY = "RMGRAPH_LICENSE_DATA";
|
|
9
|
+
function isCryptoAvailable() {
|
|
10
|
+
return typeof window !== "undefined" && typeof crypto !== "undefined" && crypto.subtle !== void 0;
|
|
11
|
+
}
|
|
12
|
+
function simpleEncode(data) {
|
|
13
|
+
const obfuscated = `rmgraph:${data}`;
|
|
14
|
+
return btoa(obfuscated);
|
|
15
|
+
}
|
|
16
|
+
function simpleDecode(encoded) {
|
|
17
|
+
try {
|
|
18
|
+
const decoded = atob(encoded);
|
|
19
|
+
if (decoded.startsWith("rmgraph:")) {
|
|
20
|
+
return decoded.substring(8);
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
9
27
|
async function deriveKey(passphrase) {
|
|
28
|
+
if (!isCryptoAvailable()) {
|
|
29
|
+
throw new Error("Web Crypto API is not available. Requires HTTPS or localhost.");
|
|
30
|
+
}
|
|
10
31
|
const encoder = new TextEncoder();
|
|
11
32
|
const keyMaterial = await crypto.subtle.importKey(
|
|
12
33
|
"raw",
|
|
@@ -30,6 +51,9 @@ async function deriveKey(passphrase) {
|
|
|
30
51
|
);
|
|
31
52
|
}
|
|
32
53
|
async function encryptLicense(licenseKey, passphrase) {
|
|
54
|
+
if (!isCryptoAvailable()) {
|
|
55
|
+
return simpleEncode(licenseKey);
|
|
56
|
+
}
|
|
33
57
|
const key = await deriveKey(passphrase);
|
|
34
58
|
const encoder = new TextEncoder();
|
|
35
59
|
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
@@ -45,6 +69,13 @@ async function encryptLicense(licenseKey, passphrase) {
|
|
|
45
69
|
}
|
|
46
70
|
async function decryptLicense(encryptedData, passphrase) {
|
|
47
71
|
try {
|
|
72
|
+
const simpleDecoded = simpleDecode(encryptedData);
|
|
73
|
+
if (simpleDecoded !== null) {
|
|
74
|
+
return simpleDecoded;
|
|
75
|
+
}
|
|
76
|
+
if (!isCryptoAvailable()) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
48
79
|
const key = await deriveKey(passphrase);
|
|
49
80
|
const combined = Uint8Array.from(atob(encryptedData), (c) => c.charCodeAt(0));
|
|
50
81
|
const iv = combined.slice(0, 12);
|
|
@@ -164,5 +195,5 @@ function validateLicenseFormat(licenseKey) {
|
|
|
164
195
|
}
|
|
165
196
|
|
|
166
197
|
export { applyLicenseKey, clearStoredLicense, configureLicenseEncryption, decryptLicense, encryptLicense, getCurrentPassphrase, getLicenseStatus, getLicenseStorageKey, hasEncryptedLicense, hasStoredLicense, isLicenseApplied, loadEncryptedLicense, loadLicense, removeLicense, resetPassphrase, saveEncryptedLicense, setLicense, validateLicenseFormat };
|
|
167
|
-
//# sourceMappingURL=chunk-
|
|
168
|
-
//# sourceMappingURL=chunk-
|
|
198
|
+
//# sourceMappingURL=chunk-PKJHVSFI.mjs.map
|
|
199
|
+
//# sourceMappingURL=chunk-PKJHVSFI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/license/crypto.ts","../src/license/index.ts"],"names":[],"mappings":";;;;;AASA,IAAM,SAAA,GAAY,SAAA;AAClB,IAAM,UAAA,GAAa,GAAA;AACnB,IAAM,WAAA,GAAc,sBAAA;AAMpB,SAAS,iBAAA,GAA6B;AACpC,EAAA,OACE,OAAO,MAAA,KAAW,WAAA,IAClB,OAAO,MAAA,KAAW,WAAA,IAClB,OAAO,MAAA,KAAW,MAAA;AAEtB;AAMA,SAAS,aAAa,IAAA,EAAsB;AAE1C,EAAA,MAAM,UAAA,GAAa,WAAW,IAAI,CAAA,CAAA;AAClC,EAAA,OAAO,KAAK,UAAU,CAAA;AACxB;AAKA,SAAS,aAAa,OAAA,EAAgC;AACpD,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,KAAK,OAAO,CAAA;AAC5B,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,UAAU,CAAA,EAAG;AAClC,MAAA,OAAO,OAAA,CAAQ,UAAU,CAAC,CAAA;AAAA,IAC5B;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKA,eAAe,UAAU,UAAA,EAAwC;AAC/D,EAAA,IAAI,CAAC,mBAAkB,EAAG;AACxB,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AAEA,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,WAAA,GAAc,MAAM,MAAA,CAAO,MAAA,CAAQ,SAAA;AAAA,IACvC,KAAA;AAAA,IACA,OAAA,CAAQ,OAAO,UAAU,CAAA;AAAA,IACzB,QAAA;AAAA,IACA,KAAA;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAGA,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,yBAAyB,CAAA;AAErD,EAAA,OAAO,OAAO,MAAA,CAAQ,SAAA;AAAA,IACpB;AAAA,MACE,IAAA,EAAM,QAAA;AAAA,MACN,IAAA;AAAA,MACA,UAAA,EAAY,GAAA;AAAA,MACZ,IAAA,EAAM;AAAA,KACR;AAAA,IACA,WAAA;AAAA,IACA,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,UAAA,EAAW;AAAA,IACtC,KAAA;AAAA,IACA,CAAC,WAAW,SAAS;AAAA,GACvB;AACF;AAQA,eAAsB,cAAA,CACpB,YACA,UAAA,EACiB;AAEjB,EAAA,IAAI,CAAC,mBAAkB,EAAG;AACxB,IAAA,OAAO,aAAa,UAAU,CAAA;AAAA,EAChC;AAEA,EAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,UAAU,CAAA;AACtC,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,KAAK,MAAA,CAAO,eAAA,CAAgB,IAAI,UAAA,CAAW,EAAE,CAAC,CAAA;AAEpD,EAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,CAAQ,OAAA;AAAA,IACrC,EAAE,IAAA,EAAM,SAAA,EAAW,EAAA,EAAG;AAAA,IACtB,GAAA;AAAA,IACA,OAAA,CAAQ,OAAO,UAAU;AAAA,GAC3B;AAGA,EAAA,MAAM,WAAW,IAAI,UAAA,CAAW,EAAA,CAAG,MAAA,GAAS,UAAU,UAAU,CAAA;AAChE,EAAA,QAAA,CAAS,IAAI,EAAE,CAAA;AACf,EAAA,QAAA,CAAS,IAAI,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG,GAAG,MAAM,CAAA;AAEjD,EAAA,OAAO,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,GAAG,QAAQ,CAAC,CAAA;AAC9C;AAQA,eAAsB,cAAA,CACpB,eACA,UAAA,EACwB;AACxB,EAAA,IAAI;AAEF,IAAA,MAAM,aAAA,GAAgB,aAAa,aAAa,CAAA;AAChD,IAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,MAAA,OAAO,aAAA;AAAA,IACT;AAGA,IAAA,IAAI,CAAC,mBAAkB,EAAG;AACxB,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,UAAU,CAAA;AACtC,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,aAAa,CAAA,EAAG,CAAC,CAAA,KAAM,CAAA,CAAE,UAAA,CAAW,CAAC,CAAC,CAAA;AAE5E,IAAA,MAAM,EAAA,GAAK,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC/B,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,CAAM,EAAE,CAAA;AAE9B,IAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,CAAQ,OAAA;AAAA,MACrC,EAAE,IAAA,EAAM,SAAA,EAAW,EAAA,EAAG;AAAA,MACtB,GAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,SAAS,CAAA;AAAA,EAC3C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAOA,eAAsB,oBAAA,CACpB,YACA,UAAA,EACe;AACf,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,IAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,EACjD;AACA,EAAA,MAAM,SAAA,GAAY,MAAM,cAAA,CAAe,UAAA,EAAY,UAAU,CAAA;AAC7D,EAAA,YAAA,CAAa,OAAA,CAAQ,aAAa,SAAS,CAAA;AAC7C;AAOA,eAAsB,qBACpB,UAAA,EACwB;AACxB,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,OAAA,CAAQ,WAAW,CAAA;AAClD,EAAA,IAAI,CAAC,WAAW,OAAO,IAAA;AACvB,EAAA,OAAO,cAAA,CAAe,WAAW,UAAU,CAAA;AAC7C;AAKO,SAAS,mBAAA,GAA+B;AAC7C,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,YAAA,CAAa,OAAA,CAAQ,WAAW,CAAA,KAAM,IAAA;AAC/C;AAKO,SAAS,kBAAA,GAA2B;AACzC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,IAAA;AAAA,EACF;AACA,EAAA,YAAA,CAAa,WAAW,WAAW,CAAA;AACrC;AAKO,SAAS,oBAAA,GAA+B;AAC7C,EAAA,OAAO,WAAA;AACT;;;ACvJA,IAAM,kBAAA,GAAqB,0BAAA;AAG3B,IAAI,iBAAA,GAAoB,kBAAA;AAGxB,IAAI,cAAA,GAAiB,KAAA;AAad,SAAS,2BAA2B,MAAA,EAA6B;AACtE,EAAA,IAAI,OAAO,UAAA,EAAY;AACrB,IAAA,iBAAA,GAAoB,MAAA,CAAO,UAAA;AAAA,EAC7B;AACF;AAKO,SAAS,oBAAA,GAA+B;AAC7C,EAAA,OAAO,iBAAA;AACT;AAKO,SAAS,eAAA,GAAwB;AACtC,EAAA,iBAAA,GAAoB,kBAAA;AACtB;AAiBA,eAAsB,WAAW,UAAA,EAAsC;AACrE,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,UAAA,IAAc,OAAO,UAAA,KAAe,QAAA,EAAU;AACjD,MAAA,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAAA,IACvC;AAGA,IAAA,MAAM,oBAAA,CAAqB,UAAA,CAAW,IAAA,EAAK,EAAG,iBAAiB,CAAA;AAG/D,IAAA,eAAA,CAAgB,oBAAA,CAAqB,UAAA,CAAW,IAAA,EAAM,CAAA;AACtD,IAAA,cAAA,GAAiB,IAAA;AAEjB,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,0BAA0B,KAAK,CAAA;AAC7C,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAkBA,eAAsB,WAAA,GAAgC;AACpD,EAAA,IAAI;AACF,IAAA,MAAM,UAAA,GAAa,MAAM,oBAAA,CAAqB,iBAAiB,CAAA;AAE/D,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,eAAA,CAAgB,qBAAqB,UAAU,CAAA;AAC/C,MAAA,cAAA,GAAiB,IAAA;AACjB,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,KAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,KAAK,CAAA;AAC9C,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAOO,SAAS,gBAAA,GAA4B;AAC1C,EAAA,OAAO,mBAAA,EAAoB;AAC7B;AAOO,SAAS,gBAAA,GAA4B;AAC1C,EAAA,OAAO,cAAA;AACT;AAMO,SAAS,aAAA,GAAsB;AACpC,EAAA,kBAAA,EAAmB;AACnB,EAAA,cAAA,GAAiB,KAAA;AACnB;AAQO,SAAS,gBAAgB,UAAA,EAA0B;AACxD,EAAA,IAAI,UAAA,IAAc,OAAO,UAAA,KAAe,QAAA,EAAU;AAChD,IAAA,eAAA,CAAgB,oBAAA,CAAqB,UAAA,CAAW,IAAA,EAAM,CAAA;AACtD,IAAA,cAAA,GAAiB,IAAA;AAAA,EACnB;AACF;AAOO,SAAS,gBAAA,GAAkC;AAChD,EAAA,OAAO;AAAA,IACL,YAAY,gBAAA,EAAiB;AAAA,IAC7B,SAAA,EAAW;AAAA,GACb;AACF;AASO,SAAS,sBAAsB,UAAA,EAA6B;AACjE,EAAA,IAAI,CAAC,UAAA,IAAc,OAAO,UAAA,KAAe,QAAA,EAAU;AACjD,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,WAAW,IAAA,EAAK;AAGhC,EAAA,OAAO,OAAA,CAAQ,MAAA,IAAU,EAAA,IAAM,OAAA,CAAQ,MAAA,IAAU,GAAA;AACnD","file":"chunk-PKJHVSFI.mjs","sourcesContent":["/**\r\n * Generic encryption/decryption utilities using Web Crypto API\r\n * Provides obfuscation for license keys stored in localStorage\r\n * \r\n * Note: This provides obfuscation, not true security.\r\n * The decryption key is in client code, so determined attackers can still decrypt.\r\n * For production, combine with SciChart's domain-locking for real protection.\r\n */\r\n\r\nconst ALGORITHM = 'AES-GCM';\r\nconst KEY_LENGTH = 256;\r\nconst STORAGE_KEY = 'RMGRAPH_LICENSE_DATA';\r\n\r\n/**\r\n * Check if Web Crypto API is available\r\n * Web Crypto API requires HTTPS or localhost (secure context)\r\n */\r\nfunction isCryptoAvailable(): boolean {\r\n return (\r\n typeof window !== 'undefined' &&\r\n typeof crypto !== 'undefined' &&\r\n crypto.subtle !== undefined\r\n );\r\n}\r\n\r\n/**\r\n * Simple base64 encoding fallback when Web Crypto is not available\r\n * This provides basic obfuscation (not encryption)\r\n */\r\nfunction simpleEncode(data: string): string {\r\n // Add a simple obfuscation prefix to distinguish from plain text\r\n const obfuscated = `rmgraph:${data}`;\r\n return btoa(obfuscated);\r\n}\r\n\r\n/**\r\n * Simple base64 decoding fallback\r\n */\r\nfunction simpleDecode(encoded: string): string | null {\r\n try {\r\n const decoded = atob(encoded);\r\n if (decoded.startsWith('rmgraph:')) {\r\n return decoded.substring(8); // Remove prefix\r\n }\r\n return null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Derive a consistent cryptographic key from a passphrase\r\n */\r\nasync function deriveKey(passphrase: string): Promise<CryptoKey> {\r\n if (!isCryptoAvailable()) {\r\n throw new Error('Web Crypto API is not available. Requires HTTPS or localhost.');\r\n }\r\n\r\n const encoder = new TextEncoder();\r\n const keyMaterial = await crypto.subtle!.importKey(\r\n 'raw',\r\n encoder.encode(passphrase),\r\n 'PBKDF2',\r\n false,\r\n ['deriveKey']\r\n );\r\n\r\n // Use a fixed salt for consistency across encrypt/decrypt\r\n const salt = encoder.encode('rmgraph-license-salt-v1');\r\n\r\n return crypto.subtle!.deriveKey(\r\n {\r\n name: 'PBKDF2',\r\n salt,\r\n iterations: 100000,\r\n hash: 'SHA-256',\r\n },\r\n keyMaterial,\r\n { name: ALGORITHM, length: KEY_LENGTH },\r\n false,\r\n ['encrypt', 'decrypt']\r\n );\r\n}\r\n\r\n/**\r\n * Encrypt a license key string\r\n * @param licenseKey - The plain text license key\r\n * @param passphrase - The passphrase to derive encryption key from\r\n * @returns Base64 encoded encrypted data\r\n */\r\nexport async function encryptLicense(\r\n licenseKey: string,\r\n passphrase: string\r\n): Promise<string> {\r\n // Fallback to simple encoding if Web Crypto is not available\r\n if (!isCryptoAvailable()) {\r\n return simpleEncode(licenseKey);\r\n }\r\n\r\n const key = await deriveKey(passphrase);\r\n const encoder = new TextEncoder();\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n\r\n const encrypted = await crypto.subtle!.encrypt(\r\n { name: ALGORITHM, iv },\r\n key,\r\n encoder.encode(licenseKey)\r\n );\r\n\r\n // Combine IV + encrypted data and encode as base64\r\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\r\n combined.set(iv);\r\n combined.set(new Uint8Array(encrypted), iv.length);\r\n\r\n return btoa(String.fromCharCode(...combined));\r\n}\r\n\r\n/**\r\n * Decrypt an encrypted license key\r\n * @param encryptedData - Base64 encoded encrypted data\r\n * @param passphrase - The passphrase to derive decryption key from\r\n * @returns The decrypted license key or null if decryption fails\r\n */\r\nexport async function decryptLicense(\r\n encryptedData: string,\r\n passphrase: string\r\n): Promise<string | null> {\r\n try {\r\n // Try simple decode first (for fallback encoding)\r\n const simpleDecoded = simpleDecode(encryptedData);\r\n if (simpleDecoded !== null) {\r\n return simpleDecoded;\r\n }\r\n\r\n // If Web Crypto is not available, we can't decrypt AES-encrypted data\r\n if (!isCryptoAvailable()) {\r\n return null;\r\n }\r\n\r\n // Try AES decryption\r\n const key = await deriveKey(passphrase);\r\n const combined = Uint8Array.from(atob(encryptedData), (c) => c.charCodeAt(0));\r\n\r\n const iv = combined.slice(0, 12);\r\n const data = combined.slice(12);\r\n\r\n const decrypted = await crypto.subtle!.decrypt(\r\n { name: ALGORITHM, iv },\r\n key,\r\n data\r\n );\r\n\r\n return new TextDecoder().decode(decrypted);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Save encrypted license to localStorage\r\n * @param licenseKey - The plain text license key\r\n * @param passphrase - The passphrase for encryption\r\n */\r\nexport async function saveEncryptedLicense(\r\n licenseKey: string,\r\n passphrase: string\r\n): Promise<void> {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n throw new Error('localStorage is not available');\r\n }\r\n const encrypted = await encryptLicense(licenseKey, passphrase);\r\n localStorage.setItem(STORAGE_KEY, encrypted);\r\n}\r\n\r\n/**\r\n * Load and decrypt license from localStorage\r\n * @param passphrase - The passphrase for decryption\r\n * @returns The decrypted license key or null if not found/decryption fails\r\n */\r\nexport async function loadEncryptedLicense(\r\n passphrase: string\r\n): Promise<string | null> {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return null;\r\n }\r\n const encrypted = localStorage.getItem(STORAGE_KEY);\r\n if (!encrypted) return null;\r\n return decryptLicense(encrypted, passphrase);\r\n}\r\n\r\n/**\r\n * Check if an encrypted license exists in localStorage\r\n */\r\nexport function hasEncryptedLicense(): boolean {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return false;\r\n }\r\n return localStorage.getItem(STORAGE_KEY) !== null;\r\n}\r\n\r\n/**\r\n * Clear stored license from localStorage\r\n */\r\nexport function clearStoredLicense(): void {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return;\r\n }\r\n localStorage.removeItem(STORAGE_KEY);\r\n}\r\n\r\n/**\r\n * Get the storage key used for license data\r\n */\r\nexport function getLicenseStorageKey(): string {\r\n return STORAGE_KEY;\r\n}\r\n","/**\r\n * License management module for @rm-graph packages\r\n * \r\n * Provides encrypted storage and retrieval of SciChart license keys.\r\n * License keys are encrypted using AES-256-GCM before storing in localStorage.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { setLicense, loadLicense, configureLicenseEncryption } from '@rm-graph/core';\r\n * \r\n * // Optional: Configure custom passphrase\r\n * configureLicenseEncryption({ passphrase: 'your-app-secret' });\r\n * \r\n * // Save a license (encrypts and stores in localStorage)\r\n * await setLicense('your-scichart-license-key');\r\n * \r\n * // Load license on app startup\r\n * await loadLicense();\r\n * ```\r\n */\r\n\r\nimport { SciChartSurface } from 'scichart';\r\nimport {\r\n encryptLicense,\r\n decryptLicense,\r\n saveEncryptedLicense,\r\n loadEncryptedLicense,\r\n hasEncryptedLicense,\r\n clearStoredLicense,\r\n getLicenseStorageKey,\r\n} from './crypto';\r\n\r\n// Re-export crypto utilities for advanced usage\r\nexport {\r\n encryptLicense,\r\n decryptLicense,\r\n saveEncryptedLicense,\r\n loadEncryptedLicense,\r\n hasEncryptedLicense,\r\n clearStoredLicense,\r\n getLicenseStorageKey,\r\n};\r\n\r\n/**\r\n * Configuration options for license encryption\r\n */\r\nexport interface LicenseConfig {\r\n /** Custom passphrase for encryption/decryption (optional) */\r\n passphrase?: string;\r\n}\r\n\r\n/**\r\n * License status information\r\n */\r\nexport interface LicenseStatus {\r\n /** Whether a license is stored */\r\n hasLicense: boolean;\r\n /** Whether the license was successfully loaded and applied */\r\n isApplied: boolean;\r\n /** Error message if any */\r\n error?: string;\r\n}\r\n\r\n// Default passphrase (can be overridden by the application)\r\nconst DEFAULT_PASSPHRASE = 'rmgraph-default-key-2024';\r\n\r\n// Current passphrase (mutable)\r\nlet currentPassphrase = DEFAULT_PASSPHRASE;\r\n\r\n// Track if license has been applied\r\nlet licenseApplied = false;\r\n\r\n/**\r\n * Configure the license encryption passphrase\r\n * Call this before saving or loading licenses if you want to use a custom passphrase\r\n * \r\n * @param config - Configuration options\r\n * \r\n * @example\r\n * ```typescript\r\n * configureLicenseEncryption({ passphrase: 'my-app-secret-key' });\r\n * ```\r\n */\r\nexport function configureLicenseEncryption(config: LicenseConfig): void {\r\n if (config.passphrase) {\r\n currentPassphrase = config.passphrase;\r\n }\r\n}\r\n\r\n/**\r\n * Get the current passphrase (for internal use)\r\n */\r\nexport function getCurrentPassphrase(): string {\r\n return currentPassphrase;\r\n}\r\n\r\n/**\r\n * Reset passphrase to default\r\n */\r\nexport function resetPassphrase(): void {\r\n currentPassphrase = DEFAULT_PASSPHRASE;\r\n}\r\n\r\n/**\r\n * Save and apply a SciChart license key\r\n * Encrypts the key and stores it in localStorage, then applies it to SciChart\r\n * \r\n * @param licenseKey - The SciChart license key to save\r\n * @returns Promise resolving to true if successful, false otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * const success = await setLicense('your-scichart-license-key');\r\n * if (success) {\r\n * console.log('License saved and applied!');\r\n * }\r\n * ```\r\n */\r\nexport async function setLicense(licenseKey: string): Promise<boolean> {\r\n try {\r\n if (!licenseKey || typeof licenseKey !== 'string') {\r\n throw new Error('Invalid license key');\r\n }\r\n\r\n // Save encrypted to localStorage\r\n await saveEncryptedLicense(licenseKey.trim(), currentPassphrase);\r\n\r\n // Apply to SciChart\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey.trim());\r\n licenseApplied = true;\r\n\r\n return true;\r\n } catch (error) {\r\n console.error('Failed to set license:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Load license from localStorage and apply to SciChart\r\n * \r\n * @returns Promise resolving to true if license was found and applied, false otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * // Call on app startup\r\n * const loaded = await loadLicense();\r\n * if (loaded) {\r\n * console.log('License loaded from storage');\r\n * } else {\r\n * console.log('No license found - charts will show watermark');\r\n * }\r\n * ```\r\n */\r\nexport async function loadLicense(): Promise<boolean> {\r\n try {\r\n const licenseKey = await loadEncryptedLicense(currentPassphrase);\r\n\r\n if (licenseKey) {\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey);\r\n licenseApplied = true;\r\n return true;\r\n }\r\n\r\n return false;\r\n } catch (error) {\r\n console.error('Failed to load license:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Check if a license is stored in localStorage\r\n * \r\n * @returns true if a license exists in storage\r\n */\r\nexport function hasStoredLicense(): boolean {\r\n return hasEncryptedLicense();\r\n}\r\n\r\n/**\r\n * Check if a license has been applied to SciChart in this session\r\n * \r\n * @returns true if a license has been applied\r\n */\r\nexport function isLicenseApplied(): boolean {\r\n return licenseApplied;\r\n}\r\n\r\n/**\r\n * Remove stored license from localStorage\r\n * Note: This doesn't remove the license from SciChart (requires page reload)\r\n */\r\nexport function removeLicense(): void {\r\n clearStoredLicense();\r\n licenseApplied = false;\r\n}\r\n\r\n/**\r\n * Apply a license key directly without storing it\r\n * Useful for temporary/session-only license application\r\n * \r\n * @param licenseKey - The SciChart license key\r\n */\r\nexport function applyLicenseKey(licenseKey: string): void {\r\n if (licenseKey && typeof licenseKey === 'string') {\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey.trim());\r\n licenseApplied = true;\r\n }\r\n}\r\n\r\n/**\r\n * Get current license status\r\n * \r\n * @returns License status information\r\n */\r\nexport function getLicenseStatus(): LicenseStatus {\r\n return {\r\n hasLicense: hasStoredLicense(),\r\n isApplied: licenseApplied,\r\n };\r\n}\r\n\r\n/**\r\n * Validate a license key format (basic validation)\r\n * Note: This doesn't validate if the license is actually valid with SciChart\r\n * \r\n * @param licenseKey - The license key to validate\r\n * @returns true if the format appears valid\r\n */\r\nexport function validateLicenseFormat(licenseKey: string): boolean {\r\n if (!licenseKey || typeof licenseKey !== 'string') {\r\n return false;\r\n }\r\n \r\n const trimmed = licenseKey.trim();\r\n \r\n // Basic validation: must be non-empty and have reasonable length\r\n return trimmed.length >= 10 && trimmed.length <= 5000;\r\n}\r\n"]}
|
|
@@ -8,7 +8,28 @@ var scichart = require('scichart');
|
|
|
8
8
|
var ALGORITHM = "AES-GCM";
|
|
9
9
|
var KEY_LENGTH = 256;
|
|
10
10
|
var STORAGE_KEY = "RMGRAPH_LICENSE_DATA";
|
|
11
|
+
function isCryptoAvailable() {
|
|
12
|
+
return typeof window !== "undefined" && typeof crypto !== "undefined" && crypto.subtle !== void 0;
|
|
13
|
+
}
|
|
14
|
+
function simpleEncode(data) {
|
|
15
|
+
const obfuscated = `rmgraph:${data}`;
|
|
16
|
+
return btoa(obfuscated);
|
|
17
|
+
}
|
|
18
|
+
function simpleDecode(encoded) {
|
|
19
|
+
try {
|
|
20
|
+
const decoded = atob(encoded);
|
|
21
|
+
if (decoded.startsWith("rmgraph:")) {
|
|
22
|
+
return decoded.substring(8);
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
11
29
|
async function deriveKey(passphrase) {
|
|
30
|
+
if (!isCryptoAvailable()) {
|
|
31
|
+
throw new Error("Web Crypto API is not available. Requires HTTPS or localhost.");
|
|
32
|
+
}
|
|
12
33
|
const encoder = new TextEncoder();
|
|
13
34
|
const keyMaterial = await crypto.subtle.importKey(
|
|
14
35
|
"raw",
|
|
@@ -32,6 +53,9 @@ async function deriveKey(passphrase) {
|
|
|
32
53
|
);
|
|
33
54
|
}
|
|
34
55
|
async function encryptLicense(licenseKey, passphrase) {
|
|
56
|
+
if (!isCryptoAvailable()) {
|
|
57
|
+
return simpleEncode(licenseKey);
|
|
58
|
+
}
|
|
35
59
|
const key = await deriveKey(passphrase);
|
|
36
60
|
const encoder = new TextEncoder();
|
|
37
61
|
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
@@ -47,6 +71,13 @@ async function encryptLicense(licenseKey, passphrase) {
|
|
|
47
71
|
}
|
|
48
72
|
async function decryptLicense(encryptedData, passphrase) {
|
|
49
73
|
try {
|
|
74
|
+
const simpleDecoded = simpleDecode(encryptedData);
|
|
75
|
+
if (simpleDecoded !== null) {
|
|
76
|
+
return simpleDecoded;
|
|
77
|
+
}
|
|
78
|
+
if (!isCryptoAvailable()) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
50
81
|
const key = await deriveKey(passphrase);
|
|
51
82
|
const combined = Uint8Array.from(atob(encryptedData), (c) => c.charCodeAt(0));
|
|
52
83
|
const iv = combined.slice(0, 12);
|
|
@@ -183,5 +214,5 @@ exports.resetPassphrase = resetPassphrase;
|
|
|
183
214
|
exports.saveEncryptedLicense = saveEncryptedLicense;
|
|
184
215
|
exports.setLicense = setLicense;
|
|
185
216
|
exports.validateLicenseFormat = validateLicenseFormat;
|
|
186
|
-
//# sourceMappingURL=chunk-
|
|
187
|
-
//# sourceMappingURL=chunk-
|
|
217
|
+
//# sourceMappingURL=chunk-RLQMHQEV.js.map
|
|
218
|
+
//# sourceMappingURL=chunk-RLQMHQEV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/license/crypto.ts","../src/license/index.ts"],"names":["SciChartSurface"],"mappings":";;;;;;;AASA,IAAM,SAAA,GAAY,SAAA;AAClB,IAAM,UAAA,GAAa,GAAA;AACnB,IAAM,WAAA,GAAc,sBAAA;AAMpB,SAAS,iBAAA,GAA6B;AACpC,EAAA,OACE,OAAO,MAAA,KAAW,WAAA,IAClB,OAAO,MAAA,KAAW,WAAA,IAClB,OAAO,MAAA,KAAW,MAAA;AAEtB;AAMA,SAAS,aAAa,IAAA,EAAsB;AAE1C,EAAA,MAAM,UAAA,GAAa,WAAW,IAAI,CAAA,CAAA;AAClC,EAAA,OAAO,KAAK,UAAU,CAAA;AACxB;AAKA,SAAS,aAAa,OAAA,EAAgC;AACpD,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,KAAK,OAAO,CAAA;AAC5B,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,UAAU,CAAA,EAAG;AAClC,MAAA,OAAO,OAAA,CAAQ,UAAU,CAAC,CAAA;AAAA,IAC5B;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKA,eAAe,UAAU,UAAA,EAAwC;AAC/D,EAAA,IAAI,CAAC,mBAAkB,EAAG;AACxB,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AAEA,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,WAAA,GAAc,MAAM,MAAA,CAAO,MAAA,CAAQ,SAAA;AAAA,IACvC,KAAA;AAAA,IACA,OAAA,CAAQ,OAAO,UAAU,CAAA;AAAA,IACzB,QAAA;AAAA,IACA,KAAA;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAGA,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,yBAAyB,CAAA;AAErD,EAAA,OAAO,OAAO,MAAA,CAAQ,SAAA;AAAA,IACpB;AAAA,MACE,IAAA,EAAM,QAAA;AAAA,MACN,IAAA;AAAA,MACA,UAAA,EAAY,GAAA;AAAA,MACZ,IAAA,EAAM;AAAA,KACR;AAAA,IACA,WAAA;AAAA,IACA,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,UAAA,EAAW;AAAA,IACtC,KAAA;AAAA,IACA,CAAC,WAAW,SAAS;AAAA,GACvB;AACF;AAQA,eAAsB,cAAA,CACpB,YACA,UAAA,EACiB;AAEjB,EAAA,IAAI,CAAC,mBAAkB,EAAG;AACxB,IAAA,OAAO,aAAa,UAAU,CAAA;AAAA,EAChC;AAEA,EAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,UAAU,CAAA;AACtC,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,KAAK,MAAA,CAAO,eAAA,CAAgB,IAAI,UAAA,CAAW,EAAE,CAAC,CAAA;AAEpD,EAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,CAAQ,OAAA;AAAA,IACrC,EAAE,IAAA,EAAM,SAAA,EAAW,EAAA,EAAG;AAAA,IACtB,GAAA;AAAA,IACA,OAAA,CAAQ,OAAO,UAAU;AAAA,GAC3B;AAGA,EAAA,MAAM,WAAW,IAAI,UAAA,CAAW,EAAA,CAAG,MAAA,GAAS,UAAU,UAAU,CAAA;AAChE,EAAA,QAAA,CAAS,IAAI,EAAE,CAAA;AACf,EAAA,QAAA,CAAS,IAAI,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG,GAAG,MAAM,CAAA;AAEjD,EAAA,OAAO,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,GAAG,QAAQ,CAAC,CAAA;AAC9C;AAQA,eAAsB,cAAA,CACpB,eACA,UAAA,EACwB;AACxB,EAAA,IAAI;AAEF,IAAA,MAAM,aAAA,GAAgB,aAAa,aAAa,CAAA;AAChD,IAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,MAAA,OAAO,aAAA;AAAA,IACT;AAGA,IAAA,IAAI,CAAC,mBAAkB,EAAG;AACxB,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,UAAU,CAAA;AACtC,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,aAAa,CAAA,EAAG,CAAC,CAAA,KAAM,CAAA,CAAE,UAAA,CAAW,CAAC,CAAC,CAAA;AAE5E,IAAA,MAAM,EAAA,GAAK,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC/B,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,CAAM,EAAE,CAAA;AAE9B,IAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,CAAQ,OAAA;AAAA,MACrC,EAAE,IAAA,EAAM,SAAA,EAAW,EAAA,EAAG;AAAA,MACtB,GAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,SAAS,CAAA;AAAA,EAC3C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAOA,eAAsB,oBAAA,CACpB,YACA,UAAA,EACe;AACf,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,IAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,EACjD;AACA,EAAA,MAAM,SAAA,GAAY,MAAM,cAAA,CAAe,UAAA,EAAY,UAAU,CAAA;AAC7D,EAAA,YAAA,CAAa,OAAA,CAAQ,aAAa,SAAS,CAAA;AAC7C;AAOA,eAAsB,qBACpB,UAAA,EACwB;AACxB,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,OAAA,CAAQ,WAAW,CAAA;AAClD,EAAA,IAAI,CAAC,WAAW,OAAO,IAAA;AACvB,EAAA,OAAO,cAAA,CAAe,WAAW,UAAU,CAAA;AAC7C;AAKO,SAAS,mBAAA,GAA+B;AAC7C,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,YAAA,CAAa,OAAA,CAAQ,WAAW,CAAA,KAAM,IAAA;AAC/C;AAKO,SAAS,kBAAA,GAA2B;AACzC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,IAAA;AAAA,EACF;AACA,EAAA,YAAA,CAAa,WAAW,WAAW,CAAA;AACrC;AAKO,SAAS,oBAAA,GAA+B;AAC7C,EAAA,OAAO,WAAA;AACT;;;ACvJA,IAAM,kBAAA,GAAqB,0BAAA;AAG3B,IAAI,iBAAA,GAAoB,kBAAA;AAGxB,IAAI,cAAA,GAAiB,KAAA;AAad,SAAS,2BAA2B,MAAA,EAA6B;AACtE,EAAA,IAAI,OAAO,UAAA,EAAY;AACrB,IAAA,iBAAA,GAAoB,MAAA,CAAO,UAAA;AAAA,EAC7B;AACF;AAKO,SAAS,oBAAA,GAA+B;AAC7C,EAAA,OAAO,iBAAA;AACT;AAKO,SAAS,eAAA,GAAwB;AACtC,EAAA,iBAAA,GAAoB,kBAAA;AACtB;AAiBA,eAAsB,WAAW,UAAA,EAAsC;AACrE,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,UAAA,IAAc,OAAO,UAAA,KAAe,QAAA,EAAU;AACjD,MAAA,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAAA,IACvC;AAGA,IAAA,MAAM,oBAAA,CAAqB,UAAA,CAAW,IAAA,EAAK,EAAG,iBAAiB,CAAA;AAG/D,IAAAA,wBAAA,CAAgB,oBAAA,CAAqB,UAAA,CAAW,IAAA,EAAM,CAAA;AACtD,IAAA,cAAA,GAAiB,IAAA;AAEjB,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,0BAA0B,KAAK,CAAA;AAC7C,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAkBA,eAAsB,WAAA,GAAgC;AACpD,EAAA,IAAI;AACF,IAAA,MAAM,UAAA,GAAa,MAAM,oBAAA,CAAqB,iBAAiB,CAAA;AAE/D,IAAA,IAAI,UAAA,EAAY;AACd,MAAAA,wBAAA,CAAgB,qBAAqB,UAAU,CAAA;AAC/C,MAAA,cAAA,GAAiB,IAAA;AACjB,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,KAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,KAAK,CAAA;AAC9C,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAOO,SAAS,gBAAA,GAA4B;AAC1C,EAAA,OAAO,mBAAA,EAAoB;AAC7B;AAOO,SAAS,gBAAA,GAA4B;AAC1C,EAAA,OAAO,cAAA;AACT;AAMO,SAAS,aAAA,GAAsB;AACpC,EAAA,kBAAA,EAAmB;AACnB,EAAA,cAAA,GAAiB,KAAA;AACnB;AAQO,SAAS,gBAAgB,UAAA,EAA0B;AACxD,EAAA,IAAI,UAAA,IAAc,OAAO,UAAA,KAAe,QAAA,EAAU;AAChD,IAAAA,wBAAA,CAAgB,oBAAA,CAAqB,UAAA,CAAW,IAAA,EAAM,CAAA;AACtD,IAAA,cAAA,GAAiB,IAAA;AAAA,EACnB;AACF;AAOO,SAAS,gBAAA,GAAkC;AAChD,EAAA,OAAO;AAAA,IACL,YAAY,gBAAA,EAAiB;AAAA,IAC7B,SAAA,EAAW;AAAA,GACb;AACF;AASO,SAAS,sBAAsB,UAAA,EAA6B;AACjE,EAAA,IAAI,CAAC,UAAA,IAAc,OAAO,UAAA,KAAe,QAAA,EAAU;AACjD,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,WAAW,IAAA,EAAK;AAGhC,EAAA,OAAO,OAAA,CAAQ,MAAA,IAAU,EAAA,IAAM,OAAA,CAAQ,MAAA,IAAU,GAAA;AACnD","file":"chunk-RLQMHQEV.js","sourcesContent":["/**\r\n * Generic encryption/decryption utilities using Web Crypto API\r\n * Provides obfuscation for license keys stored in localStorage\r\n * \r\n * Note: This provides obfuscation, not true security.\r\n * The decryption key is in client code, so determined attackers can still decrypt.\r\n * For production, combine with SciChart's domain-locking for real protection.\r\n */\r\n\r\nconst ALGORITHM = 'AES-GCM';\r\nconst KEY_LENGTH = 256;\r\nconst STORAGE_KEY = 'RMGRAPH_LICENSE_DATA';\r\n\r\n/**\r\n * Check if Web Crypto API is available\r\n * Web Crypto API requires HTTPS or localhost (secure context)\r\n */\r\nfunction isCryptoAvailable(): boolean {\r\n return (\r\n typeof window !== 'undefined' &&\r\n typeof crypto !== 'undefined' &&\r\n crypto.subtle !== undefined\r\n );\r\n}\r\n\r\n/**\r\n * Simple base64 encoding fallback when Web Crypto is not available\r\n * This provides basic obfuscation (not encryption)\r\n */\r\nfunction simpleEncode(data: string): string {\r\n // Add a simple obfuscation prefix to distinguish from plain text\r\n const obfuscated = `rmgraph:${data}`;\r\n return btoa(obfuscated);\r\n}\r\n\r\n/**\r\n * Simple base64 decoding fallback\r\n */\r\nfunction simpleDecode(encoded: string): string | null {\r\n try {\r\n const decoded = atob(encoded);\r\n if (decoded.startsWith('rmgraph:')) {\r\n return decoded.substring(8); // Remove prefix\r\n }\r\n return null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Derive a consistent cryptographic key from a passphrase\r\n */\r\nasync function deriveKey(passphrase: string): Promise<CryptoKey> {\r\n if (!isCryptoAvailable()) {\r\n throw new Error('Web Crypto API is not available. Requires HTTPS or localhost.');\r\n }\r\n\r\n const encoder = new TextEncoder();\r\n const keyMaterial = await crypto.subtle!.importKey(\r\n 'raw',\r\n encoder.encode(passphrase),\r\n 'PBKDF2',\r\n false,\r\n ['deriveKey']\r\n );\r\n\r\n // Use a fixed salt for consistency across encrypt/decrypt\r\n const salt = encoder.encode('rmgraph-license-salt-v1');\r\n\r\n return crypto.subtle!.deriveKey(\r\n {\r\n name: 'PBKDF2',\r\n salt,\r\n iterations: 100000,\r\n hash: 'SHA-256',\r\n },\r\n keyMaterial,\r\n { name: ALGORITHM, length: KEY_LENGTH },\r\n false,\r\n ['encrypt', 'decrypt']\r\n );\r\n}\r\n\r\n/**\r\n * Encrypt a license key string\r\n * @param licenseKey - The plain text license key\r\n * @param passphrase - The passphrase to derive encryption key from\r\n * @returns Base64 encoded encrypted data\r\n */\r\nexport async function encryptLicense(\r\n licenseKey: string,\r\n passphrase: string\r\n): Promise<string> {\r\n // Fallback to simple encoding if Web Crypto is not available\r\n if (!isCryptoAvailable()) {\r\n return simpleEncode(licenseKey);\r\n }\r\n\r\n const key = await deriveKey(passphrase);\r\n const encoder = new TextEncoder();\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n\r\n const encrypted = await crypto.subtle!.encrypt(\r\n { name: ALGORITHM, iv },\r\n key,\r\n encoder.encode(licenseKey)\r\n );\r\n\r\n // Combine IV + encrypted data and encode as base64\r\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\r\n combined.set(iv);\r\n combined.set(new Uint8Array(encrypted), iv.length);\r\n\r\n return btoa(String.fromCharCode(...combined));\r\n}\r\n\r\n/**\r\n * Decrypt an encrypted license key\r\n * @param encryptedData - Base64 encoded encrypted data\r\n * @param passphrase - The passphrase to derive decryption key from\r\n * @returns The decrypted license key or null if decryption fails\r\n */\r\nexport async function decryptLicense(\r\n encryptedData: string,\r\n passphrase: string\r\n): Promise<string | null> {\r\n try {\r\n // Try simple decode first (for fallback encoding)\r\n const simpleDecoded = simpleDecode(encryptedData);\r\n if (simpleDecoded !== null) {\r\n return simpleDecoded;\r\n }\r\n\r\n // If Web Crypto is not available, we can't decrypt AES-encrypted data\r\n if (!isCryptoAvailable()) {\r\n return null;\r\n }\r\n\r\n // Try AES decryption\r\n const key = await deriveKey(passphrase);\r\n const combined = Uint8Array.from(atob(encryptedData), (c) => c.charCodeAt(0));\r\n\r\n const iv = combined.slice(0, 12);\r\n const data = combined.slice(12);\r\n\r\n const decrypted = await crypto.subtle!.decrypt(\r\n { name: ALGORITHM, iv },\r\n key,\r\n data\r\n );\r\n\r\n return new TextDecoder().decode(decrypted);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Save encrypted license to localStorage\r\n * @param licenseKey - The plain text license key\r\n * @param passphrase - The passphrase for encryption\r\n */\r\nexport async function saveEncryptedLicense(\r\n licenseKey: string,\r\n passphrase: string\r\n): Promise<void> {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n throw new Error('localStorage is not available');\r\n }\r\n const encrypted = await encryptLicense(licenseKey, passphrase);\r\n localStorage.setItem(STORAGE_KEY, encrypted);\r\n}\r\n\r\n/**\r\n * Load and decrypt license from localStorage\r\n * @param passphrase - The passphrase for decryption\r\n * @returns The decrypted license key or null if not found/decryption fails\r\n */\r\nexport async function loadEncryptedLicense(\r\n passphrase: string\r\n): Promise<string | null> {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return null;\r\n }\r\n const encrypted = localStorage.getItem(STORAGE_KEY);\r\n if (!encrypted) return null;\r\n return decryptLicense(encrypted, passphrase);\r\n}\r\n\r\n/**\r\n * Check if an encrypted license exists in localStorage\r\n */\r\nexport function hasEncryptedLicense(): boolean {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return false;\r\n }\r\n return localStorage.getItem(STORAGE_KEY) !== null;\r\n}\r\n\r\n/**\r\n * Clear stored license from localStorage\r\n */\r\nexport function clearStoredLicense(): void {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return;\r\n }\r\n localStorage.removeItem(STORAGE_KEY);\r\n}\r\n\r\n/**\r\n * Get the storage key used for license data\r\n */\r\nexport function getLicenseStorageKey(): string {\r\n return STORAGE_KEY;\r\n}\r\n","/**\r\n * License management module for @rm-graph packages\r\n * \r\n * Provides encrypted storage and retrieval of SciChart license keys.\r\n * License keys are encrypted using AES-256-GCM before storing in localStorage.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { setLicense, loadLicense, configureLicenseEncryption } from '@rm-graph/core';\r\n * \r\n * // Optional: Configure custom passphrase\r\n * configureLicenseEncryption({ passphrase: 'your-app-secret' });\r\n * \r\n * // Save a license (encrypts and stores in localStorage)\r\n * await setLicense('your-scichart-license-key');\r\n * \r\n * // Load license on app startup\r\n * await loadLicense();\r\n * ```\r\n */\r\n\r\nimport { SciChartSurface } from 'scichart';\r\nimport {\r\n encryptLicense,\r\n decryptLicense,\r\n saveEncryptedLicense,\r\n loadEncryptedLicense,\r\n hasEncryptedLicense,\r\n clearStoredLicense,\r\n getLicenseStorageKey,\r\n} from './crypto';\r\n\r\n// Re-export crypto utilities for advanced usage\r\nexport {\r\n encryptLicense,\r\n decryptLicense,\r\n saveEncryptedLicense,\r\n loadEncryptedLicense,\r\n hasEncryptedLicense,\r\n clearStoredLicense,\r\n getLicenseStorageKey,\r\n};\r\n\r\n/**\r\n * Configuration options for license encryption\r\n */\r\nexport interface LicenseConfig {\r\n /** Custom passphrase for encryption/decryption (optional) */\r\n passphrase?: string;\r\n}\r\n\r\n/**\r\n * License status information\r\n */\r\nexport interface LicenseStatus {\r\n /** Whether a license is stored */\r\n hasLicense: boolean;\r\n /** Whether the license was successfully loaded and applied */\r\n isApplied: boolean;\r\n /** Error message if any */\r\n error?: string;\r\n}\r\n\r\n// Default passphrase (can be overridden by the application)\r\nconst DEFAULT_PASSPHRASE = 'rmgraph-default-key-2024';\r\n\r\n// Current passphrase (mutable)\r\nlet currentPassphrase = DEFAULT_PASSPHRASE;\r\n\r\n// Track if license has been applied\r\nlet licenseApplied = false;\r\n\r\n/**\r\n * Configure the license encryption passphrase\r\n * Call this before saving or loading licenses if you want to use a custom passphrase\r\n * \r\n * @param config - Configuration options\r\n * \r\n * @example\r\n * ```typescript\r\n * configureLicenseEncryption({ passphrase: 'my-app-secret-key' });\r\n * ```\r\n */\r\nexport function configureLicenseEncryption(config: LicenseConfig): void {\r\n if (config.passphrase) {\r\n currentPassphrase = config.passphrase;\r\n }\r\n}\r\n\r\n/**\r\n * Get the current passphrase (for internal use)\r\n */\r\nexport function getCurrentPassphrase(): string {\r\n return currentPassphrase;\r\n}\r\n\r\n/**\r\n * Reset passphrase to default\r\n */\r\nexport function resetPassphrase(): void {\r\n currentPassphrase = DEFAULT_PASSPHRASE;\r\n}\r\n\r\n/**\r\n * Save and apply a SciChart license key\r\n * Encrypts the key and stores it in localStorage, then applies it to SciChart\r\n * \r\n * @param licenseKey - The SciChart license key to save\r\n * @returns Promise resolving to true if successful, false otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * const success = await setLicense('your-scichart-license-key');\r\n * if (success) {\r\n * console.log('License saved and applied!');\r\n * }\r\n * ```\r\n */\r\nexport async function setLicense(licenseKey: string): Promise<boolean> {\r\n try {\r\n if (!licenseKey || typeof licenseKey !== 'string') {\r\n throw new Error('Invalid license key');\r\n }\r\n\r\n // Save encrypted to localStorage\r\n await saveEncryptedLicense(licenseKey.trim(), currentPassphrase);\r\n\r\n // Apply to SciChart\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey.trim());\r\n licenseApplied = true;\r\n\r\n return true;\r\n } catch (error) {\r\n console.error('Failed to set license:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Load license from localStorage and apply to SciChart\r\n * \r\n * @returns Promise resolving to true if license was found and applied, false otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * // Call on app startup\r\n * const loaded = await loadLicense();\r\n * if (loaded) {\r\n * console.log('License loaded from storage');\r\n * } else {\r\n * console.log('No license found - charts will show watermark');\r\n * }\r\n * ```\r\n */\r\nexport async function loadLicense(): Promise<boolean> {\r\n try {\r\n const licenseKey = await loadEncryptedLicense(currentPassphrase);\r\n\r\n if (licenseKey) {\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey);\r\n licenseApplied = true;\r\n return true;\r\n }\r\n\r\n return false;\r\n } catch (error) {\r\n console.error('Failed to load license:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Check if a license is stored in localStorage\r\n * \r\n * @returns true if a license exists in storage\r\n */\r\nexport function hasStoredLicense(): boolean {\r\n return hasEncryptedLicense();\r\n}\r\n\r\n/**\r\n * Check if a license has been applied to SciChart in this session\r\n * \r\n * @returns true if a license has been applied\r\n */\r\nexport function isLicenseApplied(): boolean {\r\n return licenseApplied;\r\n}\r\n\r\n/**\r\n * Remove stored license from localStorage\r\n * Note: This doesn't remove the license from SciChart (requires page reload)\r\n */\r\nexport function removeLicense(): void {\r\n clearStoredLicense();\r\n licenseApplied = false;\r\n}\r\n\r\n/**\r\n * Apply a license key directly without storing it\r\n * Useful for temporary/session-only license application\r\n * \r\n * @param licenseKey - The SciChart license key\r\n */\r\nexport function applyLicenseKey(licenseKey: string): void {\r\n if (licenseKey && typeof licenseKey === 'string') {\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey.trim());\r\n licenseApplied = true;\r\n }\r\n}\r\n\r\n/**\r\n * Get current license status\r\n * \r\n * @returns License status information\r\n */\r\nexport function getLicenseStatus(): LicenseStatus {\r\n return {\r\n hasLicense: hasStoredLicense(),\r\n isApplied: licenseApplied,\r\n };\r\n}\r\n\r\n/**\r\n * Validate a license key format (basic validation)\r\n * Note: This doesn't validate if the license is actually valid with SciChart\r\n * \r\n * @param licenseKey - The license key to validate\r\n * @returns true if the format appears valid\r\n */\r\nexport function validateLicenseFormat(licenseKey: string): boolean {\r\n if (!licenseKey || typeof licenseKey !== 'string') {\r\n return false;\r\n }\r\n \r\n const trimmed = licenseKey.trim();\r\n \r\n // Basic validation: must be non-empty and have reasonable length\r\n return trimmed.length >= 10 && trimmed.length <= 5000;\r\n}\r\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunk4JQVY6S5_js = require('./chunk-4JQVY6S5.js');
|
|
4
|
-
var
|
|
4
|
+
var chunkRLQMHQEV_js = require('./chunk-RLQMHQEV.js');
|
|
5
5
|
var chunkDGUM43GV_js = require('./chunk-DGUM43GV.js');
|
|
6
6
|
var scichart = require('scichart');
|
|
7
7
|
var SciChartJSLightTheme = require('scichart/Charting/Themes/SciChartJSLightTheme');
|
|
@@ -1757,7 +1757,7 @@ async function createPRPDChart(container, config) {
|
|
|
1757
1757
|
return chart;
|
|
1758
1758
|
}
|
|
1759
1759
|
async function setupSciChartLicense(options) {
|
|
1760
|
-
const { loadLicense: loadLicense2 } = await import('./license-
|
|
1760
|
+
const { loadLicense: loadLicense2 } = await import('./license-U7ZNTU6D.js');
|
|
1761
1761
|
const { SciChartSurface: SciChartSurface4 } = await import('scichart');
|
|
1762
1762
|
let licenseKey;
|
|
1763
1763
|
if (options.fromEnv) {
|
|
@@ -1841,75 +1841,75 @@ Object.defineProperty(exports, "modernTheme", {
|
|
|
1841
1841
|
});
|
|
1842
1842
|
Object.defineProperty(exports, "applyLicenseKey", {
|
|
1843
1843
|
enumerable: true,
|
|
1844
|
-
get: function () { return
|
|
1844
|
+
get: function () { return chunkRLQMHQEV_js.applyLicenseKey; }
|
|
1845
1845
|
});
|
|
1846
1846
|
Object.defineProperty(exports, "clearStoredLicense", {
|
|
1847
1847
|
enumerable: true,
|
|
1848
|
-
get: function () { return
|
|
1848
|
+
get: function () { return chunkRLQMHQEV_js.clearStoredLicense; }
|
|
1849
1849
|
});
|
|
1850
1850
|
Object.defineProperty(exports, "configureLicenseEncryption", {
|
|
1851
1851
|
enumerable: true,
|
|
1852
|
-
get: function () { return
|
|
1852
|
+
get: function () { return chunkRLQMHQEV_js.configureLicenseEncryption; }
|
|
1853
1853
|
});
|
|
1854
1854
|
Object.defineProperty(exports, "decryptLicense", {
|
|
1855
1855
|
enumerable: true,
|
|
1856
|
-
get: function () { return
|
|
1856
|
+
get: function () { return chunkRLQMHQEV_js.decryptLicense; }
|
|
1857
1857
|
});
|
|
1858
1858
|
Object.defineProperty(exports, "encryptLicense", {
|
|
1859
1859
|
enumerable: true,
|
|
1860
|
-
get: function () { return
|
|
1860
|
+
get: function () { return chunkRLQMHQEV_js.encryptLicense; }
|
|
1861
1861
|
});
|
|
1862
1862
|
Object.defineProperty(exports, "getCurrentPassphrase", {
|
|
1863
1863
|
enumerable: true,
|
|
1864
|
-
get: function () { return
|
|
1864
|
+
get: function () { return chunkRLQMHQEV_js.getCurrentPassphrase; }
|
|
1865
1865
|
});
|
|
1866
1866
|
Object.defineProperty(exports, "getLicenseStatus", {
|
|
1867
1867
|
enumerable: true,
|
|
1868
|
-
get: function () { return
|
|
1868
|
+
get: function () { return chunkRLQMHQEV_js.getLicenseStatus; }
|
|
1869
1869
|
});
|
|
1870
1870
|
Object.defineProperty(exports, "getLicenseStorageKey", {
|
|
1871
1871
|
enumerable: true,
|
|
1872
|
-
get: function () { return
|
|
1872
|
+
get: function () { return chunkRLQMHQEV_js.getLicenseStorageKey; }
|
|
1873
1873
|
});
|
|
1874
1874
|
Object.defineProperty(exports, "hasEncryptedLicense", {
|
|
1875
1875
|
enumerable: true,
|
|
1876
|
-
get: function () { return
|
|
1876
|
+
get: function () { return chunkRLQMHQEV_js.hasEncryptedLicense; }
|
|
1877
1877
|
});
|
|
1878
1878
|
Object.defineProperty(exports, "hasStoredLicense", {
|
|
1879
1879
|
enumerable: true,
|
|
1880
|
-
get: function () { return
|
|
1880
|
+
get: function () { return chunkRLQMHQEV_js.hasStoredLicense; }
|
|
1881
1881
|
});
|
|
1882
1882
|
Object.defineProperty(exports, "isLicenseApplied", {
|
|
1883
1883
|
enumerable: true,
|
|
1884
|
-
get: function () { return
|
|
1884
|
+
get: function () { return chunkRLQMHQEV_js.isLicenseApplied; }
|
|
1885
1885
|
});
|
|
1886
1886
|
Object.defineProperty(exports, "loadEncryptedLicense", {
|
|
1887
1887
|
enumerable: true,
|
|
1888
|
-
get: function () { return
|
|
1888
|
+
get: function () { return chunkRLQMHQEV_js.loadEncryptedLicense; }
|
|
1889
1889
|
});
|
|
1890
1890
|
Object.defineProperty(exports, "loadLicense", {
|
|
1891
1891
|
enumerable: true,
|
|
1892
|
-
get: function () { return
|
|
1892
|
+
get: function () { return chunkRLQMHQEV_js.loadLicense; }
|
|
1893
1893
|
});
|
|
1894
1894
|
Object.defineProperty(exports, "removeLicense", {
|
|
1895
1895
|
enumerable: true,
|
|
1896
|
-
get: function () { return
|
|
1896
|
+
get: function () { return chunkRLQMHQEV_js.removeLicense; }
|
|
1897
1897
|
});
|
|
1898
1898
|
Object.defineProperty(exports, "resetPassphrase", {
|
|
1899
1899
|
enumerable: true,
|
|
1900
|
-
get: function () { return
|
|
1900
|
+
get: function () { return chunkRLQMHQEV_js.resetPassphrase; }
|
|
1901
1901
|
});
|
|
1902
1902
|
Object.defineProperty(exports, "saveEncryptedLicense", {
|
|
1903
1903
|
enumerable: true,
|
|
1904
|
-
get: function () { return
|
|
1904
|
+
get: function () { return chunkRLQMHQEV_js.saveEncryptedLicense; }
|
|
1905
1905
|
});
|
|
1906
1906
|
Object.defineProperty(exports, "setLicense", {
|
|
1907
1907
|
enumerable: true,
|
|
1908
|
-
get: function () { return
|
|
1908
|
+
get: function () { return chunkRLQMHQEV_js.setLicense; }
|
|
1909
1909
|
});
|
|
1910
1910
|
Object.defineProperty(exports, "validateLicenseFormat", {
|
|
1911
1911
|
enumerable: true,
|
|
1912
|
-
get: function () { return
|
|
1912
|
+
get: function () { return chunkRLQMHQEV_js.validateLicenseFormat; }
|
|
1913
1913
|
});
|
|
1914
1914
|
Object.defineProperty(exports, "SciChartSurface", {
|
|
1915
1915
|
enumerable: true,
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ThemeManager } from './chunk-7GF5X23V.mjs';
|
|
2
2
|
export { ThemeManager, darkTheme, getThemeManager, lightTheme, midnightTheme, modernTheme } from './chunk-7GF5X23V.mjs';
|
|
3
|
-
export { applyLicenseKey, clearStoredLicense, configureLicenseEncryption, decryptLicense, encryptLicense, getCurrentPassphrase, getLicenseStatus, getLicenseStorageKey, hasEncryptedLicense, hasStoredLicense, isLicenseApplied, loadEncryptedLicense, loadLicense, removeLicense, resetPassphrase, saveEncryptedLicense, setLicense, validateLicenseFormat } from './chunk-
|
|
3
|
+
export { applyLicenseKey, clearStoredLicense, configureLicenseEncryption, decryptLicense, encryptLicense, getCurrentPassphrase, getLicenseStatus, getLicenseStorageKey, hasEncryptedLicense, hasStoredLicense, isLicenseApplied, loadEncryptedLicense, loadLicense, removeLicense, resetPassphrase, saveEncryptedLicense, setLicense, validateLicenseFormat } from './chunk-PKJHVSFI.mjs';
|
|
4
4
|
import { __require } from './chunk-BJTO5JO5.mjs';
|
|
5
5
|
import { SciChart3DSurface, NumericAxis3D, MouseWheelZoomModifier3D, OrbitModifier3D, CameraController, Vector3, UniformGridDataSeries3D, GradientColorPalette, SurfaceMeshRenderableSeries3D, EDrawMeshAs, SciChartJSLightTheme, ResetCamera3DModifier, NumberRange, XyzDataSeries3D, ColumnRenderableSeries3D, CylinderPointMarker3D, PointLineRenderableSeries3D, TooltipModifier3D, SciChartSurface, NumericAxis, EAxisAlignment, ENumericFormat, EAutoRange, CursorModifier, RubberBandXyZoomModifier, ZoomExtentsModifier, HeatmapColorMap, UniformHeatmapDataSeries, UniformHeatmapRenderableSeries, XyDataSeries, FastLineRenderableSeries, HeatmapLegend, NumericLabelProvider } from 'scichart';
|
|
6
6
|
export { SciChartSurface } from 'scichart';
|
|
@@ -1756,7 +1756,7 @@ async function createPRPDChart(container, config) {
|
|
|
1756
1756
|
return chart;
|
|
1757
1757
|
}
|
|
1758
1758
|
async function setupSciChartLicense(options) {
|
|
1759
|
-
const { loadLicense: loadLicense2 } = await import('./license-
|
|
1759
|
+
const { loadLicense: loadLicense2 } = await import('./license-MTK7WNNA.mjs');
|
|
1760
1760
|
const { SciChartSurface: SciChartSurface4 } = await import('scichart');
|
|
1761
1761
|
let licenseKey;
|
|
1762
1762
|
if (options.fromEnv) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { applyLicenseKey, clearStoredLicense, configureLicenseEncryption, decryptLicense, encryptLicense, getCurrentPassphrase, getLicenseStatus, getLicenseStorageKey, hasEncryptedLicense, hasStoredLicense, isLicenseApplied, loadEncryptedLicense, loadLicense, removeLicense, resetPassphrase, saveEncryptedLicense, setLicense, validateLicenseFormat } from './chunk-
|
|
1
|
+
export { applyLicenseKey, clearStoredLicense, configureLicenseEncryption, decryptLicense, encryptLicense, getCurrentPassphrase, getLicenseStatus, getLicenseStorageKey, hasEncryptedLicense, hasStoredLicense, isLicenseApplied, loadEncryptedLicense, loadLicense, removeLicense, resetPassphrase, saveEncryptedLicense, setLicense, validateLicenseFormat } from './chunk-PKJHVSFI.mjs';
|
|
2
2
|
import './chunk-BJTO5JO5.mjs';
|
|
3
|
-
//# sourceMappingURL=license-
|
|
4
|
-
//# sourceMappingURL=license-
|
|
3
|
+
//# sourceMappingURL=license-MTK7WNNA.mjs.map
|
|
4
|
+
//# sourceMappingURL=license-MTK7WNNA.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"license-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"license-MTK7WNNA.mjs"}
|
|
@@ -1,81 +1,81 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkRLQMHQEV_js = require('./chunk-RLQMHQEV.js');
|
|
4
4
|
require('./chunk-DGUM43GV.js');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "applyLicenseKey", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunkRLQMHQEV_js.applyLicenseKey; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "clearStoredLicense", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkRLQMHQEV_js.clearStoredLicense; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "configureLicenseEncryption", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkRLQMHQEV_js.configureLicenseEncryption; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "decryptLicense", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkRLQMHQEV_js.decryptLicense; }
|
|
23
23
|
});
|
|
24
24
|
Object.defineProperty(exports, "encryptLicense", {
|
|
25
25
|
enumerable: true,
|
|
26
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkRLQMHQEV_js.encryptLicense; }
|
|
27
27
|
});
|
|
28
28
|
Object.defineProperty(exports, "getCurrentPassphrase", {
|
|
29
29
|
enumerable: true,
|
|
30
|
-
get: function () { return
|
|
30
|
+
get: function () { return chunkRLQMHQEV_js.getCurrentPassphrase; }
|
|
31
31
|
});
|
|
32
32
|
Object.defineProperty(exports, "getLicenseStatus", {
|
|
33
33
|
enumerable: true,
|
|
34
|
-
get: function () { return
|
|
34
|
+
get: function () { return chunkRLQMHQEV_js.getLicenseStatus; }
|
|
35
35
|
});
|
|
36
36
|
Object.defineProperty(exports, "getLicenseStorageKey", {
|
|
37
37
|
enumerable: true,
|
|
38
|
-
get: function () { return
|
|
38
|
+
get: function () { return chunkRLQMHQEV_js.getLicenseStorageKey; }
|
|
39
39
|
});
|
|
40
40
|
Object.defineProperty(exports, "hasEncryptedLicense", {
|
|
41
41
|
enumerable: true,
|
|
42
|
-
get: function () { return
|
|
42
|
+
get: function () { return chunkRLQMHQEV_js.hasEncryptedLicense; }
|
|
43
43
|
});
|
|
44
44
|
Object.defineProperty(exports, "hasStoredLicense", {
|
|
45
45
|
enumerable: true,
|
|
46
|
-
get: function () { return
|
|
46
|
+
get: function () { return chunkRLQMHQEV_js.hasStoredLicense; }
|
|
47
47
|
});
|
|
48
48
|
Object.defineProperty(exports, "isLicenseApplied", {
|
|
49
49
|
enumerable: true,
|
|
50
|
-
get: function () { return
|
|
50
|
+
get: function () { return chunkRLQMHQEV_js.isLicenseApplied; }
|
|
51
51
|
});
|
|
52
52
|
Object.defineProperty(exports, "loadEncryptedLicense", {
|
|
53
53
|
enumerable: true,
|
|
54
|
-
get: function () { return
|
|
54
|
+
get: function () { return chunkRLQMHQEV_js.loadEncryptedLicense; }
|
|
55
55
|
});
|
|
56
56
|
Object.defineProperty(exports, "loadLicense", {
|
|
57
57
|
enumerable: true,
|
|
58
|
-
get: function () { return
|
|
58
|
+
get: function () { return chunkRLQMHQEV_js.loadLicense; }
|
|
59
59
|
});
|
|
60
60
|
Object.defineProperty(exports, "removeLicense", {
|
|
61
61
|
enumerable: true,
|
|
62
|
-
get: function () { return
|
|
62
|
+
get: function () { return chunkRLQMHQEV_js.removeLicense; }
|
|
63
63
|
});
|
|
64
64
|
Object.defineProperty(exports, "resetPassphrase", {
|
|
65
65
|
enumerable: true,
|
|
66
|
-
get: function () { return
|
|
66
|
+
get: function () { return chunkRLQMHQEV_js.resetPassphrase; }
|
|
67
67
|
});
|
|
68
68
|
Object.defineProperty(exports, "saveEncryptedLicense", {
|
|
69
69
|
enumerable: true,
|
|
70
|
-
get: function () { return
|
|
70
|
+
get: function () { return chunkRLQMHQEV_js.saveEncryptedLicense; }
|
|
71
71
|
});
|
|
72
72
|
Object.defineProperty(exports, "setLicense", {
|
|
73
73
|
enumerable: true,
|
|
74
|
-
get: function () { return
|
|
74
|
+
get: function () { return chunkRLQMHQEV_js.setLicense; }
|
|
75
75
|
});
|
|
76
76
|
Object.defineProperty(exports, "validateLicenseFormat", {
|
|
77
77
|
enumerable: true,
|
|
78
|
-
get: function () { return
|
|
78
|
+
get: function () { return chunkRLQMHQEV_js.validateLicenseFormat; }
|
|
79
79
|
});
|
|
80
|
-
//# sourceMappingURL=license-
|
|
81
|
-
//# sourceMappingURL=license-
|
|
80
|
+
//# sourceMappingURL=license-U7ZNTU6D.js.map
|
|
81
|
+
//# sourceMappingURL=license-U7ZNTU6D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"license-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"license-U7ZNTU6D.js"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/license/crypto.ts","../src/license/index.ts"],"names":[],"mappings":"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","file":"chunk-BNXHM7UU.mjs","sourcesContent":["/**\r\n * Generic encryption/decryption utilities using Web Crypto API\r\n * Provides obfuscation for license keys stored in localStorage\r\n * \r\n * Note: This provides obfuscation, not true security.\r\n * The decryption key is in client code, so determined attackers can still decrypt.\r\n * For production, combine with SciChart's domain-locking for real protection.\r\n */\r\n\r\nconst ALGORITHM = 'AES-GCM';\r\nconst KEY_LENGTH = 256;\r\nconst STORAGE_KEY = 'RMGRAPH_LICENSE_DATA';\r\n\r\n/**\r\n * Derive a consistent cryptographic key from a passphrase\r\n */\r\nasync function deriveKey(passphrase: string): Promise<CryptoKey> {\r\n const encoder = new TextEncoder();\r\n const keyMaterial = await crypto.subtle.importKey(\r\n 'raw',\r\n encoder.encode(passphrase),\r\n 'PBKDF2',\r\n false,\r\n ['deriveKey']\r\n );\r\n\r\n // Use a fixed salt for consistency across encrypt/decrypt\r\n const salt = encoder.encode('rmgraph-license-salt-v1');\r\n\r\n return crypto.subtle.deriveKey(\r\n {\r\n name: 'PBKDF2',\r\n salt,\r\n iterations: 100000,\r\n hash: 'SHA-256',\r\n },\r\n keyMaterial,\r\n { name: ALGORITHM, length: KEY_LENGTH },\r\n false,\r\n ['encrypt', 'decrypt']\r\n );\r\n}\r\n\r\n/**\r\n * Encrypt a license key string\r\n * @param licenseKey - The plain text license key\r\n * @param passphrase - The passphrase to derive encryption key from\r\n * @returns Base64 encoded encrypted data\r\n */\r\nexport async function encryptLicense(\r\n licenseKey: string,\r\n passphrase: string\r\n): Promise<string> {\r\n const key = await deriveKey(passphrase);\r\n const encoder = new TextEncoder();\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n\r\n const encrypted = await crypto.subtle.encrypt(\r\n { name: ALGORITHM, iv },\r\n key,\r\n encoder.encode(licenseKey)\r\n );\r\n\r\n // Combine IV + encrypted data and encode as base64\r\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\r\n combined.set(iv);\r\n combined.set(new Uint8Array(encrypted), iv.length);\r\n\r\n return btoa(String.fromCharCode(...combined));\r\n}\r\n\r\n/**\r\n * Decrypt an encrypted license key\r\n * @param encryptedData - Base64 encoded encrypted data\r\n * @param passphrase - The passphrase to derive decryption key from\r\n * @returns The decrypted license key or null if decryption fails\r\n */\r\nexport async function decryptLicense(\r\n encryptedData: string,\r\n passphrase: string\r\n): Promise<string | null> {\r\n try {\r\n const key = await deriveKey(passphrase);\r\n const combined = Uint8Array.from(atob(encryptedData), (c) => c.charCodeAt(0));\r\n\r\n const iv = combined.slice(0, 12);\r\n const data = combined.slice(12);\r\n\r\n const decrypted = await crypto.subtle.decrypt(\r\n { name: ALGORITHM, iv },\r\n key,\r\n data\r\n );\r\n\r\n return new TextDecoder().decode(decrypted);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Save encrypted license to localStorage\r\n * @param licenseKey - The plain text license key\r\n * @param passphrase - The passphrase for encryption\r\n */\r\nexport async function saveEncryptedLicense(\r\n licenseKey: string,\r\n passphrase: string\r\n): Promise<void> {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n throw new Error('localStorage is not available');\r\n }\r\n const encrypted = await encryptLicense(licenseKey, passphrase);\r\n localStorage.setItem(STORAGE_KEY, encrypted);\r\n}\r\n\r\n/**\r\n * Load and decrypt license from localStorage\r\n * @param passphrase - The passphrase for decryption\r\n * @returns The decrypted license key or null if not found/decryption fails\r\n */\r\nexport async function loadEncryptedLicense(\r\n passphrase: string\r\n): Promise<string | null> {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return null;\r\n }\r\n const encrypted = localStorage.getItem(STORAGE_KEY);\r\n if (!encrypted) return null;\r\n return decryptLicense(encrypted, passphrase);\r\n}\r\n\r\n/**\r\n * Check if an encrypted license exists in localStorage\r\n */\r\nexport function hasEncryptedLicense(): boolean {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return false;\r\n }\r\n return localStorage.getItem(STORAGE_KEY) !== null;\r\n}\r\n\r\n/**\r\n * Clear stored license from localStorage\r\n */\r\nexport function clearStoredLicense(): void {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return;\r\n }\r\n localStorage.removeItem(STORAGE_KEY);\r\n}\r\n\r\n/**\r\n * Get the storage key used for license data\r\n */\r\nexport function getLicenseStorageKey(): string {\r\n return STORAGE_KEY;\r\n}\r\n","/**\r\n * License management module for @rm-graph packages\r\n * \r\n * Provides encrypted storage and retrieval of SciChart license keys.\r\n * License keys are encrypted using AES-256-GCM before storing in localStorage.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { setLicense, loadLicense, configureLicenseEncryption } from '@rm-graph/core';\r\n * \r\n * // Optional: Configure custom passphrase\r\n * configureLicenseEncryption({ passphrase: 'your-app-secret' });\r\n * \r\n * // Save a license (encrypts and stores in localStorage)\r\n * await setLicense('your-scichart-license-key');\r\n * \r\n * // Load license on app startup\r\n * await loadLicense();\r\n * ```\r\n */\r\n\r\nimport { SciChartSurface } from 'scichart';\r\nimport {\r\n encryptLicense,\r\n decryptLicense,\r\n saveEncryptedLicense,\r\n loadEncryptedLicense,\r\n hasEncryptedLicense,\r\n clearStoredLicense,\r\n getLicenseStorageKey,\r\n} from './crypto';\r\n\r\n// Re-export crypto utilities for advanced usage\r\nexport {\r\n encryptLicense,\r\n decryptLicense,\r\n saveEncryptedLicense,\r\n loadEncryptedLicense,\r\n hasEncryptedLicense,\r\n clearStoredLicense,\r\n getLicenseStorageKey,\r\n};\r\n\r\n/**\r\n * Configuration options for license encryption\r\n */\r\nexport interface LicenseConfig {\r\n /** Custom passphrase for encryption/decryption (optional) */\r\n passphrase?: string;\r\n}\r\n\r\n/**\r\n * License status information\r\n */\r\nexport interface LicenseStatus {\r\n /** Whether a license is stored */\r\n hasLicense: boolean;\r\n /** Whether the license was successfully loaded and applied */\r\n isApplied: boolean;\r\n /** Error message if any */\r\n error?: string;\r\n}\r\n\r\n// Default passphrase (can be overridden by the application)\r\nconst DEFAULT_PASSPHRASE = 'rmgraph-default-key-2024';\r\n\r\n// Current passphrase (mutable)\r\nlet currentPassphrase = DEFAULT_PASSPHRASE;\r\n\r\n// Track if license has been applied\r\nlet licenseApplied = false;\r\n\r\n/**\r\n * Configure the license encryption passphrase\r\n * Call this before saving or loading licenses if you want to use a custom passphrase\r\n * \r\n * @param config - Configuration options\r\n * \r\n * @example\r\n * ```typescript\r\n * configureLicenseEncryption({ passphrase: 'my-app-secret-key' });\r\n * ```\r\n */\r\nexport function configureLicenseEncryption(config: LicenseConfig): void {\r\n if (config.passphrase) {\r\n currentPassphrase = config.passphrase;\r\n }\r\n}\r\n\r\n/**\r\n * Get the current passphrase (for internal use)\r\n */\r\nexport function getCurrentPassphrase(): string {\r\n return currentPassphrase;\r\n}\r\n\r\n/**\r\n * Reset passphrase to default\r\n */\r\nexport function resetPassphrase(): void {\r\n currentPassphrase = DEFAULT_PASSPHRASE;\r\n}\r\n\r\n/**\r\n * Save and apply a SciChart license key\r\n * Encrypts the key and stores it in localStorage, then applies it to SciChart\r\n * \r\n * @param licenseKey - The SciChart license key to save\r\n * @returns Promise resolving to true if successful, false otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * const success = await setLicense('your-scichart-license-key');\r\n * if (success) {\r\n * console.log('License saved and applied!');\r\n * }\r\n * ```\r\n */\r\nexport async function setLicense(licenseKey: string): Promise<boolean> {\r\n try {\r\n if (!licenseKey || typeof licenseKey !== 'string') {\r\n throw new Error('Invalid license key');\r\n }\r\n\r\n // Save encrypted to localStorage\r\n await saveEncryptedLicense(licenseKey.trim(), currentPassphrase);\r\n\r\n // Apply to SciChart\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey.trim());\r\n licenseApplied = true;\r\n\r\n return true;\r\n } catch (error) {\r\n console.error('Failed to set license:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Load license from localStorage and apply to SciChart\r\n * \r\n * @returns Promise resolving to true if license was found and applied, false otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * // Call on app startup\r\n * const loaded = await loadLicense();\r\n * if (loaded) {\r\n * console.log('License loaded from storage');\r\n * } else {\r\n * console.log('No license found - charts will show watermark');\r\n * }\r\n * ```\r\n */\r\nexport async function loadLicense(): Promise<boolean> {\r\n try {\r\n const licenseKey = await loadEncryptedLicense(currentPassphrase);\r\n\r\n if (licenseKey) {\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey);\r\n licenseApplied = true;\r\n return true;\r\n }\r\n\r\n return false;\r\n } catch (error) {\r\n console.error('Failed to load license:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Check if a license is stored in localStorage\r\n * \r\n * @returns true if a license exists in storage\r\n */\r\nexport function hasStoredLicense(): boolean {\r\n return hasEncryptedLicense();\r\n}\r\n\r\n/**\r\n * Check if a license has been applied to SciChart in this session\r\n * \r\n * @returns true if a license has been applied\r\n */\r\nexport function isLicenseApplied(): boolean {\r\n return licenseApplied;\r\n}\r\n\r\n/**\r\n * Remove stored license from localStorage\r\n * Note: This doesn't remove the license from SciChart (requires page reload)\r\n */\r\nexport function removeLicense(): void {\r\n clearStoredLicense();\r\n licenseApplied = false;\r\n}\r\n\r\n/**\r\n * Apply a license key directly without storing it\r\n * Useful for temporary/session-only license application\r\n * \r\n * @param licenseKey - The SciChart license key\r\n */\r\nexport function applyLicenseKey(licenseKey: string): void {\r\n if (licenseKey && typeof licenseKey === 'string') {\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey.trim());\r\n licenseApplied = true;\r\n }\r\n}\r\n\r\n/**\r\n * Get current license status\r\n * \r\n * @returns License status information\r\n */\r\nexport function getLicenseStatus(): LicenseStatus {\r\n return {\r\n hasLicense: hasStoredLicense(),\r\n isApplied: licenseApplied,\r\n };\r\n}\r\n\r\n/**\r\n * Validate a license key format (basic validation)\r\n * Note: This doesn't validate if the license is actually valid with SciChart\r\n * \r\n * @param licenseKey - The license key to validate\r\n * @returns true if the format appears valid\r\n */\r\nexport function validateLicenseFormat(licenseKey: string): boolean {\r\n if (!licenseKey || typeof licenseKey !== 'string') {\r\n return false;\r\n }\r\n \r\n const trimmed = licenseKey.trim();\r\n \r\n // Basic validation: must be non-empty and have reasonable length\r\n return trimmed.length >= 10 && trimmed.length <= 5000;\r\n}\r\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/license/crypto.ts","../src/license/index.ts"],"names":["SciChartSurface"],"mappings":"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","file":"chunk-QFDC4NU3.js","sourcesContent":["/**\r\n * Generic encryption/decryption utilities using Web Crypto API\r\n * Provides obfuscation for license keys stored in localStorage\r\n * \r\n * Note: This provides obfuscation, not true security.\r\n * The decryption key is in client code, so determined attackers can still decrypt.\r\n * For production, combine with SciChart's domain-locking for real protection.\r\n */\r\n\r\nconst ALGORITHM = 'AES-GCM';\r\nconst KEY_LENGTH = 256;\r\nconst STORAGE_KEY = 'RMGRAPH_LICENSE_DATA';\r\n\r\n/**\r\n * Derive a consistent cryptographic key from a passphrase\r\n */\r\nasync function deriveKey(passphrase: string): Promise<CryptoKey> {\r\n const encoder = new TextEncoder();\r\n const keyMaterial = await crypto.subtle.importKey(\r\n 'raw',\r\n encoder.encode(passphrase),\r\n 'PBKDF2',\r\n false,\r\n ['deriveKey']\r\n );\r\n\r\n // Use a fixed salt for consistency across encrypt/decrypt\r\n const salt = encoder.encode('rmgraph-license-salt-v1');\r\n\r\n return crypto.subtle.deriveKey(\r\n {\r\n name: 'PBKDF2',\r\n salt,\r\n iterations: 100000,\r\n hash: 'SHA-256',\r\n },\r\n keyMaterial,\r\n { name: ALGORITHM, length: KEY_LENGTH },\r\n false,\r\n ['encrypt', 'decrypt']\r\n );\r\n}\r\n\r\n/**\r\n * Encrypt a license key string\r\n * @param licenseKey - The plain text license key\r\n * @param passphrase - The passphrase to derive encryption key from\r\n * @returns Base64 encoded encrypted data\r\n */\r\nexport async function encryptLicense(\r\n licenseKey: string,\r\n passphrase: string\r\n): Promise<string> {\r\n const key = await deriveKey(passphrase);\r\n const encoder = new TextEncoder();\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n\r\n const encrypted = await crypto.subtle.encrypt(\r\n { name: ALGORITHM, iv },\r\n key,\r\n encoder.encode(licenseKey)\r\n );\r\n\r\n // Combine IV + encrypted data and encode as base64\r\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\r\n combined.set(iv);\r\n combined.set(new Uint8Array(encrypted), iv.length);\r\n\r\n return btoa(String.fromCharCode(...combined));\r\n}\r\n\r\n/**\r\n * Decrypt an encrypted license key\r\n * @param encryptedData - Base64 encoded encrypted data\r\n * @param passphrase - The passphrase to derive decryption key from\r\n * @returns The decrypted license key or null if decryption fails\r\n */\r\nexport async function decryptLicense(\r\n encryptedData: string,\r\n passphrase: string\r\n): Promise<string | null> {\r\n try {\r\n const key = await deriveKey(passphrase);\r\n const combined = Uint8Array.from(atob(encryptedData), (c) => c.charCodeAt(0));\r\n\r\n const iv = combined.slice(0, 12);\r\n const data = combined.slice(12);\r\n\r\n const decrypted = await crypto.subtle.decrypt(\r\n { name: ALGORITHM, iv },\r\n key,\r\n data\r\n );\r\n\r\n return new TextDecoder().decode(decrypted);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Save encrypted license to localStorage\r\n * @param licenseKey - The plain text license key\r\n * @param passphrase - The passphrase for encryption\r\n */\r\nexport async function saveEncryptedLicense(\r\n licenseKey: string,\r\n passphrase: string\r\n): Promise<void> {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n throw new Error('localStorage is not available');\r\n }\r\n const encrypted = await encryptLicense(licenseKey, passphrase);\r\n localStorage.setItem(STORAGE_KEY, encrypted);\r\n}\r\n\r\n/**\r\n * Load and decrypt license from localStorage\r\n * @param passphrase - The passphrase for decryption\r\n * @returns The decrypted license key or null if not found/decryption fails\r\n */\r\nexport async function loadEncryptedLicense(\r\n passphrase: string\r\n): Promise<string | null> {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return null;\r\n }\r\n const encrypted = localStorage.getItem(STORAGE_KEY);\r\n if (!encrypted) return null;\r\n return decryptLicense(encrypted, passphrase);\r\n}\r\n\r\n/**\r\n * Check if an encrypted license exists in localStorage\r\n */\r\nexport function hasEncryptedLicense(): boolean {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return false;\r\n }\r\n return localStorage.getItem(STORAGE_KEY) !== null;\r\n}\r\n\r\n/**\r\n * Clear stored license from localStorage\r\n */\r\nexport function clearStoredLicense(): void {\r\n if (typeof window === 'undefined' || !window.localStorage) {\r\n return;\r\n }\r\n localStorage.removeItem(STORAGE_KEY);\r\n}\r\n\r\n/**\r\n * Get the storage key used for license data\r\n */\r\nexport function getLicenseStorageKey(): string {\r\n return STORAGE_KEY;\r\n}\r\n","/**\r\n * License management module for @rm-graph packages\r\n * \r\n * Provides encrypted storage and retrieval of SciChart license keys.\r\n * License keys are encrypted using AES-256-GCM before storing in localStorage.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { setLicense, loadLicense, configureLicenseEncryption } from '@rm-graph/core';\r\n * \r\n * // Optional: Configure custom passphrase\r\n * configureLicenseEncryption({ passphrase: 'your-app-secret' });\r\n * \r\n * // Save a license (encrypts and stores in localStorage)\r\n * await setLicense('your-scichart-license-key');\r\n * \r\n * // Load license on app startup\r\n * await loadLicense();\r\n * ```\r\n */\r\n\r\nimport { SciChartSurface } from 'scichart';\r\nimport {\r\n encryptLicense,\r\n decryptLicense,\r\n saveEncryptedLicense,\r\n loadEncryptedLicense,\r\n hasEncryptedLicense,\r\n clearStoredLicense,\r\n getLicenseStorageKey,\r\n} from './crypto';\r\n\r\n// Re-export crypto utilities for advanced usage\r\nexport {\r\n encryptLicense,\r\n decryptLicense,\r\n saveEncryptedLicense,\r\n loadEncryptedLicense,\r\n hasEncryptedLicense,\r\n clearStoredLicense,\r\n getLicenseStorageKey,\r\n};\r\n\r\n/**\r\n * Configuration options for license encryption\r\n */\r\nexport interface LicenseConfig {\r\n /** Custom passphrase for encryption/decryption (optional) */\r\n passphrase?: string;\r\n}\r\n\r\n/**\r\n * License status information\r\n */\r\nexport interface LicenseStatus {\r\n /** Whether a license is stored */\r\n hasLicense: boolean;\r\n /** Whether the license was successfully loaded and applied */\r\n isApplied: boolean;\r\n /** Error message if any */\r\n error?: string;\r\n}\r\n\r\n// Default passphrase (can be overridden by the application)\r\nconst DEFAULT_PASSPHRASE = 'rmgraph-default-key-2024';\r\n\r\n// Current passphrase (mutable)\r\nlet currentPassphrase = DEFAULT_PASSPHRASE;\r\n\r\n// Track if license has been applied\r\nlet licenseApplied = false;\r\n\r\n/**\r\n * Configure the license encryption passphrase\r\n * Call this before saving or loading licenses if you want to use a custom passphrase\r\n * \r\n * @param config - Configuration options\r\n * \r\n * @example\r\n * ```typescript\r\n * configureLicenseEncryption({ passphrase: 'my-app-secret-key' });\r\n * ```\r\n */\r\nexport function configureLicenseEncryption(config: LicenseConfig): void {\r\n if (config.passphrase) {\r\n currentPassphrase = config.passphrase;\r\n }\r\n}\r\n\r\n/**\r\n * Get the current passphrase (for internal use)\r\n */\r\nexport function getCurrentPassphrase(): string {\r\n return currentPassphrase;\r\n}\r\n\r\n/**\r\n * Reset passphrase to default\r\n */\r\nexport function resetPassphrase(): void {\r\n currentPassphrase = DEFAULT_PASSPHRASE;\r\n}\r\n\r\n/**\r\n * Save and apply a SciChart license key\r\n * Encrypts the key and stores it in localStorage, then applies it to SciChart\r\n * \r\n * @param licenseKey - The SciChart license key to save\r\n * @returns Promise resolving to true if successful, false otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * const success = await setLicense('your-scichart-license-key');\r\n * if (success) {\r\n * console.log('License saved and applied!');\r\n * }\r\n * ```\r\n */\r\nexport async function setLicense(licenseKey: string): Promise<boolean> {\r\n try {\r\n if (!licenseKey || typeof licenseKey !== 'string') {\r\n throw new Error('Invalid license key');\r\n }\r\n\r\n // Save encrypted to localStorage\r\n await saveEncryptedLicense(licenseKey.trim(), currentPassphrase);\r\n\r\n // Apply to SciChart\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey.trim());\r\n licenseApplied = true;\r\n\r\n return true;\r\n } catch (error) {\r\n console.error('Failed to set license:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Load license from localStorage and apply to SciChart\r\n * \r\n * @returns Promise resolving to true if license was found and applied, false otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * // Call on app startup\r\n * const loaded = await loadLicense();\r\n * if (loaded) {\r\n * console.log('License loaded from storage');\r\n * } else {\r\n * console.log('No license found - charts will show watermark');\r\n * }\r\n * ```\r\n */\r\nexport async function loadLicense(): Promise<boolean> {\r\n try {\r\n const licenseKey = await loadEncryptedLicense(currentPassphrase);\r\n\r\n if (licenseKey) {\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey);\r\n licenseApplied = true;\r\n return true;\r\n }\r\n\r\n return false;\r\n } catch (error) {\r\n console.error('Failed to load license:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Check if a license is stored in localStorage\r\n * \r\n * @returns true if a license exists in storage\r\n */\r\nexport function hasStoredLicense(): boolean {\r\n return hasEncryptedLicense();\r\n}\r\n\r\n/**\r\n * Check if a license has been applied to SciChart in this session\r\n * \r\n * @returns true if a license has been applied\r\n */\r\nexport function isLicenseApplied(): boolean {\r\n return licenseApplied;\r\n}\r\n\r\n/**\r\n * Remove stored license from localStorage\r\n * Note: This doesn't remove the license from SciChart (requires page reload)\r\n */\r\nexport function removeLicense(): void {\r\n clearStoredLicense();\r\n licenseApplied = false;\r\n}\r\n\r\n/**\r\n * Apply a license key directly without storing it\r\n * Useful for temporary/session-only license application\r\n * \r\n * @param licenseKey - The SciChart license key\r\n */\r\nexport function applyLicenseKey(licenseKey: string): void {\r\n if (licenseKey && typeof licenseKey === 'string') {\r\n SciChartSurface.setRuntimeLicenseKey(licenseKey.trim());\r\n licenseApplied = true;\r\n }\r\n}\r\n\r\n/**\r\n * Get current license status\r\n * \r\n * @returns License status information\r\n */\r\nexport function getLicenseStatus(): LicenseStatus {\r\n return {\r\n hasLicense: hasStoredLicense(),\r\n isApplied: licenseApplied,\r\n };\r\n}\r\n\r\n/**\r\n * Validate a license key format (basic validation)\r\n * Note: This doesn't validate if the license is actually valid with SciChart\r\n * \r\n * @param licenseKey - The license key to validate\r\n * @returns true if the format appears valid\r\n */\r\nexport function validateLicenseFormat(licenseKey: string): boolean {\r\n if (!licenseKey || typeof licenseKey !== 'string') {\r\n return false;\r\n }\r\n \r\n const trimmed = licenseKey.trim();\r\n \r\n // Basic validation: must be non-empty and have reasonable length\r\n return trimmed.length >= 10 && trimmed.length <= 5000;\r\n}\r\n"]}
|