@memberjunction/react-runtime 2.89.0 → 2.90.0

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.
@@ -0,0 +1,644 @@
1
+ /**
2
+ * @fileoverview Library registry for approved third-party libraries
3
+ * Maintains a secure registry of libraries that components can use
4
+ * @module @memberjunction/react-runtime/utilities
5
+ */
6
+
7
+ /**
8
+ * Library definition in the registry
9
+ */
10
+ export interface LibraryDefinition {
11
+ /** Library name (e.g., "Chart.js", "lodash") */
12
+ name: string;
13
+ /** Global variable name when loaded (e.g., "Chart", "_") */
14
+ globalVariable: string;
15
+ /** Category path for organization (e.g., "charting/advanced", "utility/date") */
16
+ category: string;
17
+ /** Available versions with their CDN URLs */
18
+ versions: {
19
+ [version: string]: {
20
+ cdnUrl: string;
21
+ /** Optional CSS URLs for UI libraries */
22
+ cssUrls?: string[];
23
+ };
24
+ };
25
+ /** Default version to use if not specified */
26
+ defaultVersion: string;
27
+ }
28
+
29
+ /**
30
+ * Registry of approved libraries that components can use
31
+ * This is the security boundary - only libraries defined here can be loaded
32
+ */
33
+ export class LibraryRegistry {
34
+ private static libraries: Map<string, LibraryDefinition> = new Map();
35
+
36
+ // Initialize the registry with all approved libraries
37
+ static {
38
+ this.initializeLibraries();
39
+ }
40
+
41
+ private static initializeLibraries(): void {
42
+ const libs: LibraryDefinition[] = [
43
+ // Charting Libraries
44
+ {
45
+ name: 'Chart.js',
46
+ globalVariable: 'Chart',
47
+ category: 'charting/basic',
48
+ versions: {
49
+ '4.4.0': { cdnUrl: 'https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js' },
50
+ '4.3.0': { cdnUrl: 'https://cdn.jsdelivr.net/npm/chart.js@4.3.0/dist/chart.umd.min.js' }
51
+ },
52
+ defaultVersion: '4.4.0'
53
+ },
54
+ {
55
+ name: 'Recharts',
56
+ globalVariable: 'Recharts',
57
+ category: 'charting/react',
58
+ versions: {
59
+ '2.10.4': { cdnUrl: 'https://cdn.jsdelivr.net/npm/recharts@2.10.4/dist/Recharts.js' }
60
+ },
61
+ defaultVersion: '2.10.4'
62
+ },
63
+ {
64
+ name: 'Plotly',
65
+ globalVariable: 'Plotly',
66
+ category: 'charting/scientific',
67
+ versions: {
68
+ '2.27.1': { cdnUrl: 'https://cdn.plot.ly/plotly-2.27.1.min.js' }
69
+ },
70
+ defaultVersion: '2.27.1'
71
+ },
72
+ {
73
+ name: 'ApexCharts',
74
+ globalVariable: 'ApexCharts',
75
+ category: 'charting/interactive',
76
+ versions: {
77
+ '3.45.1': {
78
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/apexcharts@3.45.1/dist/apexcharts.min.js',
79
+ cssUrls: ['https://cdn.jsdelivr.net/npm/apexcharts@3.45.1/dist/apexcharts.css']
80
+ }
81
+ },
82
+ defaultVersion: '3.45.1'
83
+ },
84
+ {
85
+ name: 'ECharts',
86
+ globalVariable: 'echarts',
87
+ category: 'charting/advanced',
88
+ versions: {
89
+ '5.4.3': { cdnUrl: 'https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js' }
90
+ },
91
+ defaultVersion: '5.4.3'
92
+ },
93
+ {
94
+ name: 'Highcharts',
95
+ globalVariable: 'Highcharts',
96
+ category: 'charting/enterprise',
97
+ versions: {
98
+ '11.2.0': { cdnUrl: 'https://code.highcharts.com/11.2.0/highcharts.js' }
99
+ },
100
+ defaultVersion: '11.2.0'
101
+ },
102
+ {
103
+ name: 'Victory',
104
+ globalVariable: 'Victory',
105
+ category: 'charting/react',
106
+ versions: {
107
+ '36.9.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/victory@36.9.1/dist/victory.min.js' }
108
+ },
109
+ defaultVersion: '36.9.1'
110
+ },
111
+ {
112
+ name: 'd3',
113
+ globalVariable: 'd3',
114
+ category: 'charting/low-level',
115
+ versions: {
116
+ '7.8.5': { cdnUrl: 'https://cdn.jsdelivr.net/npm/d3@7.8.5/dist/d3.min.js' }
117
+ },
118
+ defaultVersion: '7.8.5'
119
+ },
120
+ {
121
+ name: 'topojson-client',
122
+ globalVariable: 'topojson',
123
+ category: 'maps/topology',
124
+ versions: {
125
+ '3.1.0': { cdnUrl: 'https://cdn.jsdelivr.net/npm/topojson-client@3.1.0/dist/topojson-client.min.js' }
126
+ },
127
+ defaultVersion: '3.1.0'
128
+ },
129
+
130
+ // Date/Time Libraries
131
+ {
132
+ name: 'dayjs',
133
+ globalVariable: 'dayjs',
134
+ category: 'utility/date',
135
+ versions: {
136
+ '1.11.10': { cdnUrl: 'https://cdn.jsdelivr.net/npm/dayjs@1.11.10/dayjs.min.js' }
137
+ },
138
+ defaultVersion: '1.11.10'
139
+ },
140
+ {
141
+ name: 'moment',
142
+ globalVariable: 'moment',
143
+ category: 'utility/date',
144
+ versions: {
145
+ '2.29.4': { cdnUrl: 'https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js' }
146
+ },
147
+ defaultVersion: '2.29.4'
148
+ },
149
+ {
150
+ name: 'date-fns',
151
+ globalVariable: 'dateFns',
152
+ category: 'utility/date',
153
+ versions: {
154
+ '3.0.6': { cdnUrl: 'https://cdn.jsdelivr.net/npm/date-fns@3.0.6/index.js' }
155
+ },
156
+ defaultVersion: '3.0.6'
157
+ },
158
+
159
+ // Utility Libraries
160
+ {
161
+ name: 'lodash',
162
+ globalVariable: '_',
163
+ category: 'utility/general',
164
+ versions: {
165
+ '4.17.21': { cdnUrl: 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js' }
166
+ },
167
+ defaultVersion: '4.17.21'
168
+ },
169
+ {
170
+ name: 'axios',
171
+ globalVariable: 'axios',
172
+ category: 'utility/http',
173
+ versions: {
174
+ '1.6.5': { cdnUrl: 'https://cdn.jsdelivr.net/npm/axios@1.6.5/dist/axios.min.js' }
175
+ },
176
+ defaultVersion: '1.6.5'
177
+ },
178
+ {
179
+ name: 'uuid',
180
+ globalVariable: 'uuid',
181
+ category: 'utility/general',
182
+ versions: {
183
+ '9.0.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/uuid@9.0.1/dist/umd/uuid.min.js' }
184
+ },
185
+ defaultVersion: '9.0.1'
186
+ },
187
+ {
188
+ name: 'classnames',
189
+ globalVariable: 'classNames',
190
+ category: 'utility/css',
191
+ versions: {
192
+ '2.5.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/classnames@2.5.1/index.js' }
193
+ },
194
+ defaultVersion: '2.5.1'
195
+ },
196
+ {
197
+ name: 'DOMPurify',
198
+ globalVariable: 'DOMPurify',
199
+ category: 'utility/security',
200
+ versions: {
201
+ '3.0.8': { cdnUrl: 'https://cdn.jsdelivr.net/npm/dompurify@3.0.8/dist/purify.min.js' }
202
+ },
203
+ defaultVersion: '3.0.8'
204
+ },
205
+ {
206
+ name: 'numeral',
207
+ globalVariable: 'numeral',
208
+ category: 'utility/formatting',
209
+ versions: {
210
+ '2.0.6': { cdnUrl: 'https://cdn.jsdelivr.net/npm/numeral@2.0.6/numeral.min.js' }
211
+ },
212
+ defaultVersion: '2.0.6'
213
+ },
214
+ {
215
+ name: 'accounting',
216
+ globalVariable: 'accounting',
217
+ category: 'utility/formatting',
218
+ versions: {
219
+ '0.4.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/accounting@0.4.1/accounting.min.js' }
220
+ },
221
+ defaultVersion: '0.4.1'
222
+ },
223
+
224
+ // UI Component Libraries
225
+ {
226
+ name: 'antd',
227
+ globalVariable: 'antd',
228
+ category: 'ui/components',
229
+ versions: {
230
+ '5.11.0': {
231
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/antd@5.11.0/dist/antd.min.js',
232
+ cssUrls: ['https://cdn.jsdelivr.net/npm/antd@5.11.0/dist/reset.css']
233
+ }
234
+ },
235
+ defaultVersion: '5.11.0'
236
+ },
237
+ {
238
+ name: '@mui/material',
239
+ globalVariable: 'MaterialUI',
240
+ category: 'ui/components',
241
+ versions: {
242
+ '5.15.2': { cdnUrl: 'https://cdn.jsdelivr.net/npm/@mui/material@5.15.2/umd/material-ui.production.min.js' }
243
+ },
244
+ defaultVersion: '5.15.2'
245
+ },
246
+ {
247
+ name: 'bootstrap',
248
+ globalVariable: 'bootstrap',
249
+ category: 'ui/framework',
250
+ versions: {
251
+ '5.3.2': {
252
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js',
253
+ cssUrls: ['https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css']
254
+ }
255
+ },
256
+ defaultVersion: '5.3.2'
257
+ },
258
+ {
259
+ name: 'semantic-ui',
260
+ globalVariable: 'semanticUI',
261
+ category: 'ui/framework',
262
+ versions: {
263
+ '2.5.0': {
264
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.js',
265
+ cssUrls: ['https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.css']
266
+ }
267
+ },
268
+ defaultVersion: '2.5.0'
269
+ },
270
+
271
+ // Data Grid/Table Libraries
272
+ {
273
+ name: 'ag-grid',
274
+ globalVariable: 'agGrid',
275
+ category: 'grid/enterprise',
276
+ versions: {
277
+ '31.0.1': {
278
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/ag-grid-community@31.0.1/dist/ag-grid-community.min.js',
279
+ cssUrls: [
280
+ 'https://cdn.jsdelivr.net/npm/ag-grid-community@31.0.1/dist/styles/ag-grid.css',
281
+ 'https://cdn.jsdelivr.net/npm/ag-grid-community@31.0.1/dist/styles/ag-theme-alpine.css'
282
+ ]
283
+ }
284
+ },
285
+ defaultVersion: '31.0.1'
286
+ },
287
+ {
288
+ name: 'react-table',
289
+ globalVariable: 'ReactTable',
290
+ category: 'grid/lightweight',
291
+ versions: {
292
+ '7.8.0': { cdnUrl: 'https://cdn.jsdelivr.net/npm/react-table@7.8.0/dist/react-table.production.min.js' }
293
+ },
294
+ defaultVersion: '7.8.0'
295
+ },
296
+ {
297
+ name: 'material-table',
298
+ globalVariable: 'MaterialTable',
299
+ category: 'grid/material',
300
+ versions: {
301
+ '2.0.5': { cdnUrl: 'https://cdn.jsdelivr.net/npm/material-table@2.0.5/dist/material-table.min.js' }
302
+ },
303
+ defaultVersion: '2.0.5'
304
+ },
305
+
306
+ // Map Libraries
307
+ {
308
+ name: 'leaflet',
309
+ globalVariable: 'L',
310
+ category: 'maps/opensource',
311
+ versions: {
312
+ '1.9.4': {
313
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js',
314
+ cssUrls: ['https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css']
315
+ }
316
+ },
317
+ defaultVersion: '1.9.4'
318
+ },
319
+ {
320
+ name: 'mapbox-gl',
321
+ globalVariable: 'mapboxgl',
322
+ category: 'maps/vector',
323
+ versions: {
324
+ '3.0.1': {
325
+ cdnUrl: 'https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.js',
326
+ cssUrls: ['https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.css']
327
+ }
328
+ },
329
+ defaultVersion: '3.0.1'
330
+ },
331
+
332
+ // Animation Libraries
333
+ {
334
+ name: 'framer-motion',
335
+ globalVariable: 'FramerMotion',
336
+ category: 'animation/react',
337
+ versions: {
338
+ '10.16.16': { cdnUrl: 'https://cdn.jsdelivr.net/npm/framer-motion@10.16.16/dist/framer-motion.js' }
339
+ },
340
+ defaultVersion: '10.16.16'
341
+ },
342
+ {
343
+ name: 'gsap',
344
+ globalVariable: 'gsap',
345
+ category: 'animation/general',
346
+ versions: {
347
+ '3.12.4': { cdnUrl: 'https://cdn.jsdelivr.net/npm/gsap@3.12.4/dist/gsap.min.js' }
348
+ },
349
+ defaultVersion: '3.12.4'
350
+ },
351
+ {
352
+ name: 'lottie-web',
353
+ globalVariable: 'lottie',
354
+ category: 'animation/svg',
355
+ versions: {
356
+ '5.12.2': { cdnUrl: 'https://cdn.jsdelivr.net/npm/lottie-web@5.12.2/build/player/lottie.min.js' }
357
+ },
358
+ defaultVersion: '5.12.2'
359
+ },
360
+
361
+ // Form Libraries
362
+ {
363
+ name: 'react-hook-form',
364
+ globalVariable: 'ReactHookForm',
365
+ category: 'forms/react',
366
+ versions: {
367
+ '7.48.2': { cdnUrl: 'https://cdn.jsdelivr.net/npm/react-hook-form@7.48.2/dist/index.umd.production.min.js' }
368
+ },
369
+ defaultVersion: '7.48.2'
370
+ },
371
+ {
372
+ name: 'formik',
373
+ globalVariable: 'Formik',
374
+ category: 'forms/react',
375
+ versions: {
376
+ '2.4.5': { cdnUrl: 'https://cdn.jsdelivr.net/npm/formik@2.4.5/dist/formik.umd.production.min.js' }
377
+ },
378
+ defaultVersion: '2.4.5'
379
+ },
380
+ {
381
+ name: 'react-select',
382
+ globalVariable: 'ReactSelect',
383
+ category: 'forms/select',
384
+ versions: {
385
+ '5.8.0': { cdnUrl: 'https://cdn.jsdelivr.net/npm/react-select@5.8.0/dist/react-select.min.js' }
386
+ },
387
+ defaultVersion: '5.8.0'
388
+ },
389
+
390
+ // Validation Libraries
391
+ {
392
+ name: 'joi',
393
+ globalVariable: 'Joi',
394
+ category: 'validation/schema',
395
+ versions: {
396
+ '17.11.0': { cdnUrl: 'https://cdn.jsdelivr.net/npm/joi-browser@13.4.0/dist/joi-browser.min.js' }
397
+ },
398
+ defaultVersion: '17.11.0'
399
+ },
400
+ {
401
+ name: 'yup',
402
+ globalVariable: 'yup',
403
+ category: 'validation/schema',
404
+ versions: {
405
+ '1.3.3': { cdnUrl: 'https://cdn.jsdelivr.net/npm/yup@1.3.3/lib/index.umd.js' }
406
+ },
407
+ defaultVersion: '1.3.3'
408
+ },
409
+
410
+ // State Management
411
+ {
412
+ name: 'zustand',
413
+ globalVariable: 'zustand',
414
+ category: 'state/lightweight',
415
+ versions: {
416
+ '4.4.7': { cdnUrl: 'https://cdn.jsdelivr.net/npm/zustand@4.4.7/dist/umd.production.js' }
417
+ },
418
+ defaultVersion: '4.4.7'
419
+ },
420
+ {
421
+ name: 'valtio',
422
+ globalVariable: 'valtio',
423
+ category: 'state/proxy',
424
+ versions: {
425
+ '1.12.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/valtio@1.12.1/dist/index.umd.js' }
426
+ },
427
+ defaultVersion: '1.12.1'
428
+ },
429
+
430
+ // Math & Statistics
431
+ {
432
+ name: 'simple-statistics',
433
+ globalVariable: 'ss',
434
+ category: 'math/statistics',
435
+ versions: {
436
+ '7.8.3': { cdnUrl: 'https://cdn.jsdelivr.net/npm/simple-statistics@7.8.3/dist/simple-statistics.min.js' }
437
+ },
438
+ defaultVersion: '7.8.3'
439
+ },
440
+ {
441
+ name: 'mathjs',
442
+ globalVariable: 'math',
443
+ category: 'math/general',
444
+ versions: {
445
+ '12.2.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/mathjs@12.2.1/lib/browser/math.js' }
446
+ },
447
+ defaultVersion: '12.2.1'
448
+ },
449
+
450
+ // Color Manipulation
451
+ {
452
+ name: 'chroma-js',
453
+ globalVariable: 'chroma',
454
+ category: 'color/manipulation',
455
+ versions: {
456
+ '2.4.2': { cdnUrl: 'https://cdn.jsdelivr.net/npm/chroma-js@2.4.2/chroma.min.js' }
457
+ },
458
+ defaultVersion: '2.4.2'
459
+ },
460
+ {
461
+ name: 'tinycolor2',
462
+ globalVariable: 'tinycolor',
463
+ category: 'color/manipulation',
464
+ versions: {
465
+ '1.6.0': { cdnUrl: 'https://cdn.jsdelivr.net/npm/tinycolor2@1.6.0/dist/tinycolor-min.js' }
466
+ },
467
+ defaultVersion: '1.6.0'
468
+ },
469
+
470
+ // Rich Text Editors
471
+ {
472
+ name: 'quill',
473
+ globalVariable: 'Quill',
474
+ category: 'editor/rich-text',
475
+ versions: {
476
+ '1.3.7': {
477
+ cdnUrl: 'https://cdn.quilljs.com/1.3.7/quill.min.js',
478
+ cssUrls: ['https://cdn.quilljs.com/1.3.7/quill.snow.css']
479
+ }
480
+ },
481
+ defaultVersion: '1.3.7'
482
+ },
483
+ {
484
+ name: 'tinymce',
485
+ globalVariable: 'tinymce',
486
+ category: 'editor/rich-text',
487
+ versions: {
488
+ '6.7.3': { cdnUrl: 'https://cdn.tiny.cloud/1/no-api-key/tinymce/6/tinymce.min.js' }
489
+ },
490
+ defaultVersion: '6.7.3'
491
+ },
492
+
493
+ // File Upload
494
+ {
495
+ name: 'dropzone',
496
+ globalVariable: 'Dropzone',
497
+ category: 'file/upload',
498
+ versions: {
499
+ '6.0.0-beta.2': {
500
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/dropzone@6.0.0-beta.2/dist/dropzone-min.js',
501
+ cssUrls: ['https://cdn.jsdelivr.net/npm/dropzone@6.0.0-beta.2/dist/dropzone.css']
502
+ }
503
+ },
504
+ defaultVersion: '6.0.0-beta.2'
505
+ },
506
+ {
507
+ name: 'filepond',
508
+ globalVariable: 'FilePond',
509
+ category: 'file/upload',
510
+ versions: {
511
+ '4.30.6': {
512
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/filepond@4.30.6/dist/filepond.min.js',
513
+ cssUrls: ['https://cdn.jsdelivr.net/npm/filepond@4.30.6/dist/filepond.min.css']
514
+ }
515
+ },
516
+ defaultVersion: '4.30.6'
517
+ },
518
+
519
+ // Notification/Toast Libraries
520
+ {
521
+ name: 'toastify-js',
522
+ globalVariable: 'Toastify',
523
+ category: 'notification/toast',
524
+ versions: {
525
+ '1.12.0': {
526
+ cdnUrl: 'https://cdn.jsdelivr.net/npm/toastify-js@1.12.0/src/toastify.min.js',
527
+ cssUrls: ['https://cdn.jsdelivr.net/npm/toastify-js@1.12.0/src/toastify.min.css']
528
+ }
529
+ },
530
+ defaultVersion: '1.12.0'
531
+ },
532
+ {
533
+ name: 'sweetalert2',
534
+ globalVariable: 'Swal',
535
+ category: 'notification/modal',
536
+ versions: {
537
+ '11.10.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/sweetalert2@11.10.1/dist/sweetalert2.all.min.js' }
538
+ },
539
+ defaultVersion: '11.10.1'
540
+ },
541
+
542
+ // PDF Generation
543
+ {
544
+ name: 'jspdf',
545
+ globalVariable: 'jsPDF',
546
+ category: 'document/pdf',
547
+ versions: {
548
+ '2.5.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/jspdf@2.5.1/dist/jspdf.umd.min.js' }
549
+ },
550
+ defaultVersion: '2.5.1'
551
+ },
552
+ {
553
+ name: 'pdfmake',
554
+ globalVariable: 'pdfMake',
555
+ category: 'document/pdf',
556
+ versions: {
557
+ '0.2.9': { cdnUrl: 'https://cdn.jsdelivr.net/npm/pdfmake@0.2.9/build/pdfmake.min.js' }
558
+ },
559
+ defaultVersion: '0.2.9'
560
+ },
561
+
562
+ // Excel/CSV Libraries
563
+ {
564
+ name: 'xlsx',
565
+ globalVariable: 'XLSX',
566
+ category: 'document/spreadsheet',
567
+ versions: {
568
+ '0.20.1': { cdnUrl: 'https://cdn.sheetjs.com/xlsx-0.20.1/package/dist/xlsx.full.min.js' }
569
+ },
570
+ defaultVersion: '0.20.1'
571
+ },
572
+ {
573
+ name: 'papaparse',
574
+ globalVariable: 'Papa',
575
+ category: 'document/csv',
576
+ versions: {
577
+ '5.4.1': { cdnUrl: 'https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js' }
578
+ },
579
+ defaultVersion: '5.4.1'
580
+ }
581
+ ];
582
+
583
+ // Register all libraries
584
+ libs.forEach(lib => this.libraries.set(lib.name, lib));
585
+ }
586
+
587
+ /**
588
+ * Get library definition by name
589
+ */
590
+ static getLibrary(name: string): LibraryDefinition | undefined {
591
+ return this.libraries.get(name);
592
+ }
593
+
594
+ /**
595
+ * Get CDN URL for a library
596
+ * @param name Library name
597
+ * @param version Optional version (uses default if not specified)
598
+ * @returns CDN URL or undefined if library/version not found
599
+ */
600
+ static getCdnUrl(name: string, version?: string): string | undefined {
601
+ const library = this.libraries.get(name);
602
+ if (!library) return undefined;
603
+
604
+ const targetVersion = version || library.defaultVersion;
605
+ return library.versions[targetVersion]?.cdnUrl;
606
+ }
607
+
608
+ /**
609
+ * Check if a library is approved
610
+ */
611
+ static isApproved(name: string): boolean {
612
+ return this.libraries.has(name);
613
+ }
614
+
615
+ /**
616
+ * Resolve library version based on semver-like pattern
617
+ * For now, just returns exact match or default
618
+ * TODO: Implement proper semver resolution
619
+ */
620
+ static resolveVersion(name: string, versionPattern?: string): string | undefined {
621
+ const library = this.libraries.get(name);
622
+ if (!library) return undefined;
623
+
624
+ if (!versionPattern) return library.defaultVersion;
625
+
626
+ // For now, just check exact match
627
+ // TODO: Implement proper semver resolution for patterns like "^4.0.0"
628
+ if (library.versions[versionPattern]) {
629
+ return versionPattern;
630
+ }
631
+
632
+ // If no exact match, return default
633
+ return library.defaultVersion;
634
+ }
635
+
636
+ /**
637
+ * Add a library to the registry (for future extensibility)
638
+ * This would typically be called during app initialization
639
+ * with libraries loaded from a database
640
+ */
641
+ static registerLibrary(definition: LibraryDefinition): void {
642
+ this.libraries.set(definition.name, definition);
643
+ }
644
+ }