@memberjunction/react-runtime 2.111.0 → 2.112.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.
Files changed (43) hide show
  1. package/.turbo/turbo-build.log +10 -11
  2. package/CHANGELOG.md +6 -6
  3. package/dist/compiler/component-compiler.d.ts.map +1 -1
  4. package/dist/compiler/component-compiler.js +66 -56
  5. package/dist/compiler/component-compiler.js.map +1 -1
  6. package/dist/component-manager/component-manager.d.ts.map +1 -1
  7. package/dist/component-manager/component-manager.js +48 -42
  8. package/dist/component-manager/component-manager.js.map +1 -1
  9. package/dist/component-manager/types.d.ts +1 -1
  10. package/dist/component-manager/types.d.ts.map +1 -1
  11. package/dist/component-manager/types.js.map +1 -1
  12. package/dist/registry/component-registry-service.d.ts +1 -1
  13. package/dist/registry/component-registry-service.d.ts.map +1 -1
  14. package/dist/registry/component-registry-service.js +34 -34
  15. package/dist/registry/component-registry-service.js.map +1 -1
  16. package/dist/registry/component-resolver.d.ts +1 -1
  17. package/dist/registry/component-resolver.d.ts.map +1 -1
  18. package/dist/registry/component-resolver.js +10 -11
  19. package/dist/registry/component-resolver.js.map +1 -1
  20. package/dist/runtime/component-hierarchy.d.ts +1 -1
  21. package/dist/runtime/component-hierarchy.d.ts.map +1 -1
  22. package/dist/runtime/component-hierarchy.js +43 -43
  23. package/dist/runtime/component-hierarchy.js.map +1 -1
  24. package/dist/runtime/prop-builder.d.ts.map +1 -1
  25. package/dist/runtime/prop-builder.js +22 -24
  26. package/dist/runtime/prop-builder.js.map +1 -1
  27. package/dist/runtime.umd.js +494 -511
  28. package/dist/types/index.d.ts.map +1 -1
  29. package/dist/types/index.js.map +1 -1
  30. package/dist/utilities/library-registry.d.ts +1 -1
  31. package/dist/utilities/library-registry.d.ts.map +1 -1
  32. package/dist/utilities/library-registry.js +10 -10
  33. package/dist/utilities/library-registry.js.map +1 -1
  34. package/package.json +5 -6
  35. package/src/compiler/component-compiler.ts +186 -164
  36. package/src/component-manager/component-manager.ts +162 -216
  37. package/src/component-manager/types.ts +27 -27
  38. package/src/registry/component-registry-service.ts +190 -218
  39. package/src/registry/component-resolver.ts +87 -98
  40. package/src/runtime/component-hierarchy.ts +57 -94
  41. package/src/runtime/prop-builder.ts +28 -33
  42. package/src/types/index.ts +3 -4
  43. package/src/utilities/library-registry.ts +14 -19
@@ -4,15 +4,8 @@
4
4
  * @module @memberjunction/react-runtime/compiler
5
5
  */
6
6
 
7
- import { UserInfo } from '@memberjunction/core';
8
- import {
9
- CompileOptions,
10
- CompiledComponent,
11
- CompilationResult,
12
- CompilerConfig,
13
- ComponentError,
14
- RuntimeContext
15
- } from '../types';
7
+ import { UserInfo } from '@memberjunction/global';
8
+ import { CompileOptions, CompiledComponent, CompilationResult, CompilerConfig, ComponentError, RuntimeContext } from '../types';
16
9
  import { ComponentStyles, ComponentObject } from '@memberjunction/interactive-component-types';
17
10
  import { LibraryRegistry } from '../utilities/library-registry';
18
11
  import { LibraryLoader } from '../utilities/library-loader';
@@ -25,13 +18,13 @@ import { ComponentLibraryEntity } from '@memberjunction/core-entities';
25
18
  const DEFAULT_COMPILER_CONFIG: CompilerConfig = {
26
19
  babel: {
27
20
  presets: ['react'],
28
- plugins: []
21
+ plugins: [],
29
22
  },
30
23
  minify: false,
31
24
  sourceMaps: false,
32
25
  cache: true,
33
26
  maxCacheSize: 100,
34
- debug: false
27
+ debug: false,
35
28
  };
36
29
 
37
30
  /**
@@ -77,7 +70,7 @@ export class ComponentCompiler {
77
70
  return {
78
71
  success: true,
79
72
  component: cached,
80
- duration: Date.now() - startTime
73
+ duration: Date.now() - startTime,
81
74
  };
82
75
  }
83
76
  }
@@ -89,19 +82,10 @@ export class ComponentCompiler {
89
82
  const loadedLibraries = await this.loadRequiredLibraries(options.libraries!, options.allLibraries);
90
83
 
91
84
  // Transpile the component code
92
- const transpiledCode = this.transpileComponent(
93
- options.componentCode,
94
- options.componentName,
95
- options
96
- );
85
+ const transpiledCode = this.transpileComponent(options.componentCode, options.componentName, options);
97
86
 
98
87
  // Create the component factory with loaded libraries
99
- const componentFactory = this.createComponentFactory(
100
- transpiledCode,
101
- options.componentName,
102
- loadedLibraries,
103
- options
104
- );
88
+ const componentFactory = this.createComponentFactory(transpiledCode, options.componentName, loadedLibraries, options);
105
89
 
106
90
  // Build the compiled component
107
91
  const compiledComponent: CompiledComponent = {
@@ -109,7 +93,7 @@ export class ComponentCompiler {
109
93
  id: this.generateComponentId(options.componentName),
110
94
  name: options.componentName,
111
95
  compiledAt: new Date(),
112
- warnings: []
96
+ warnings: [],
113
97
  };
114
98
 
115
99
  // Cache if enabled
@@ -122,14 +106,13 @@ export class ComponentCompiler {
122
106
  component: compiledComponent,
123
107
  duration: Date.now() - startTime,
124
108
  size: transpiledCode.length,
125
- loadedLibraries: loadedLibraries
109
+ loadedLibraries: loadedLibraries,
126
110
  };
127
-
128
111
  } catch (error) {
129
112
  return {
130
113
  success: false,
131
114
  error: this.createCompilationError(error, options.componentName),
132
- duration: Date.now() - startTime
115
+ duration: Date.now() - startTime,
133
116
  };
134
117
  }
135
118
  }
@@ -141,11 +124,7 @@ export class ComponentCompiler {
141
124
  * @param options - Compilation options
142
125
  * @returns Transpiled JavaScript code
143
126
  */
144
- private transpileComponent(
145
- code: string,
146
- componentName: string,
147
- options: CompileOptions
148
- ): string {
127
+ private transpileComponent(code: string, componentName: string, options: CompileOptions): string {
149
128
  if (!this.babelInstance) {
150
129
  throw new Error('Babel instance not set. Call setBabelInstance() first.');
151
130
  }
@@ -158,7 +137,7 @@ export class ComponentCompiler {
158
137
  plugins: options.babelPlugins || this.config.babel.plugins,
159
138
  filename: `${componentName}.jsx`,
160
139
  sourceMaps: this.config.sourceMaps,
161
- minified: this.config.minify
140
+ minified: this.config.minify,
162
141
  });
163
142
 
164
143
  return result.code;
@@ -178,22 +157,32 @@ export class ComponentCompiler {
178
157
  // Core libraries that are passed as parameters to createComponent and should not be destructured
179
158
  private readonly CORE_LIBRARIES = new Set(['React', 'ReactDOM']);
180
159
 
181
- private wrapComponentCode(componentCode: string, componentName: string, libraries?: any[], dependencies?: Array<{ name: string }>): string {
160
+ private wrapComponentCode(
161
+ componentCode: string,
162
+ componentName: string,
163
+ libraries?: any[],
164
+ dependencies?: Array<{ name: string }>
165
+ ): string {
182
166
  const debug = this.config.debug;
183
167
  // Generate library declarations if libraries are provided
184
168
  // Skip core libraries as they're passed as parameters to createComponent
185
- const libraryDeclarations = libraries && libraries.length > 0
186
- ? libraries
187
- .filter(lib => lib.globalVariable && !this.CORE_LIBRARIES.has(lib.globalVariable)) // Skip core libraries
188
- .map(lib => `const ${lib.globalVariable} = libraries['${lib.globalVariable}'];`)
189
- .join('\n ')
190
- : '';
191
- const libraryLogChecks = libraries && libraries.length > 0
192
- ? libraries
193
- .filter(lib => lib.globalVariable && !this.CORE_LIBRARIES.has(lib.globalVariable)) // Skip core libraries
194
- .map(lib => `\nif (!${lib.globalVariable}) { console.error('[React-Runtime-JS] Library "${lib.globalVariable}" is not defined'); } else { ${debug ? `console.log('[React-Runtime-JS] Library "${lib.globalVariable}" is defined');` : ''} }`)
195
- .join('\n ')
196
- : '';
169
+ const libraryDeclarations =
170
+ libraries && libraries.length > 0
171
+ ? libraries
172
+ .filter((lib) => lib.globalVariable && !this.CORE_LIBRARIES.has(lib.globalVariable)) // Skip core libraries
173
+ .map((lib) => `const ${lib.globalVariable} = libraries['${lib.globalVariable}'];`)
174
+ .join('\n ')
175
+ : '';
176
+ const libraryLogChecks =
177
+ libraries && libraries.length > 0
178
+ ? libraries
179
+ .filter((lib) => lib.globalVariable && !this.CORE_LIBRARIES.has(lib.globalVariable)) // Skip core libraries
180
+ .map(
181
+ (lib) =>
182
+ `\nif (!${lib.globalVariable}) { console.error('[React-Runtime-JS] Library "${lib.globalVariable}" is not defined'); } else { ${debug ? `console.log('[React-Runtime-JS] Library "${lib.globalVariable}" is defined');` : ''} }`
183
+ )
184
+ .join('\n ')
185
+ : '';
197
186
 
198
187
  // Generate component declarations if dependencies are provided
199
188
  // Filter out the component being compiled to avoid naming conflicts
@@ -201,7 +190,7 @@ export class ComponentCompiler {
201
190
  const seenDependencies = new Set<string>();
202
191
  const uniqueDependencies: Array<{ name: string; code?: string }> = [];
203
192
  const duplicates: string[] = [];
204
-
193
+
205
194
  if (dependencies && dependencies.length > 0) {
206
195
  for (const dep of dependencies) {
207
196
  if (dep.name === componentName) {
@@ -216,40 +205,58 @@ export class ComponentCompiler {
216
205
  }
217
206
  }
218
207
  }
219
-
208
+
220
209
  // Generate warning for duplicates
221
- const duplicateWarnings = duplicates.length > 0
222
- ? duplicates
223
- .map(name => `console.warn('[React-Runtime-JS] WARNING: Component "${name}" is registered multiple times as a dependency. Using first occurrence only.');`)
224
- .join('\n ')
225
- : '';
226
-
227
- const componentDeclarations = uniqueDependencies.length > 0
228
- ? uniqueDependencies
229
- .map(dep => `const ${dep.name}Raw = componentsOuter['${dep.name}'];
230
- ${debug ? `console.log('[React-Runtime-JS] Extracting ${dep.name}:');
210
+ const duplicateWarnings =
211
+ duplicates.length > 0
212
+ ? duplicates
213
+ .map(
214
+ (name) =>
215
+ `console.warn('[React-Runtime-JS] WARNING: Component "${name}" is registered multiple times as a dependency. Using first occurrence only.');`
216
+ )
217
+ .join('\n ')
218
+ : '';
219
+
220
+ const componentDeclarations =
221
+ uniqueDependencies.length > 0
222
+ ? uniqueDependencies
223
+ .map(
224
+ (dep) => `const ${dep.name}Raw = componentsOuter['${dep.name}'];
225
+ ${
226
+ debug
227
+ ? `console.log('[React-Runtime-JS] Extracting ${dep.name}:');
231
228
  console.log(' - Raw value type:', typeof ${dep.name}Raw);
232
229
  console.log(' - Raw value:', ${dep.name}Raw);
233
230
  if (${dep.name}Raw && typeof ${dep.name}Raw === 'object') {
234
231
  console.log(' - Has .component property:', 'component' in ${dep.name}Raw);
235
232
  console.log(' - .component type:', typeof ${dep.name}Raw.component);
236
- }` : ''}
233
+ }`
234
+ : ''
235
+ }
237
236
  const ${dep.name} = ${dep.name}Raw?.component || ${dep.name}Raw;
238
- ${debug ? `console.log(' - Final ${dep.name} type:', typeof ${dep.name});
239
- console.log(' - Final ${dep.name} is function:', typeof ${dep.name} === 'function');` : ''}`)
240
- .join('\n ')
241
- : '';
242
-
243
- const componentLogChecks = uniqueDependencies.length > 0
244
- ? uniqueDependencies
245
- .map(dep => `if (!${dep.name}) { console.error('[React-Runtime-JS] Dependency "${dep.name}" is not defined'); } else { ${debug ? `console.log('[React-Runtime-JS] Dependency "${dep.name}" is defined');` : ''} }`)
246
- .join('\n ')
247
- : '';
248
-
237
+ ${
238
+ debug
239
+ ? `console.log(' - Final ${dep.name} type:', typeof ${dep.name});
240
+ console.log(' - Final ${dep.name} is function:', typeof ${dep.name} === 'function');`
241
+ : ''
242
+ }`
243
+ )
244
+ .join('\n ')
245
+ : '';
246
+
247
+ const componentLogChecks =
248
+ uniqueDependencies.length > 0
249
+ ? uniqueDependencies
250
+ .map(
251
+ (dep) =>
252
+ `if (!${dep.name}) { console.error('[React-Runtime-JS] Dependency "${dep.name}" is not defined'); } else { ${debug ? `console.log('[React-Runtime-JS] Dependency "${dep.name}" is defined');` : ''} }`
253
+ )
254
+ .join('\n ')
255
+ : '';
249
256
 
250
257
  const wrappedCode = `
251
258
  function createComponent(
252
- React, ReactDOM,
259
+ React, ReactDOM,
253
260
  useState, useEffect, useCallback, useMemo, useRef, useContext, useReducer, useLayoutEffect,
254
261
  libraries, styles, console, components,
255
262
  unwrapLibraryComponent, unwrapLibraryComponents, unwrapAllLibraryComponents
@@ -263,10 +270,10 @@ export class ComponentCompiler {
263
270
  const unwrapComponent = unwrapLibraryComponent;
264
271
  const unwrapComponents = unwrapLibraryComponents;
265
272
  const unwrapAllComponents = unwrapAllLibraryComponents;
266
-
273
+
267
274
  // Code for ${componentName}
268
275
  ${componentCode}
269
-
276
+
270
277
  // Ensure the component exists
271
278
  if (typeof ${componentName} === 'undefined') {
272
279
  throw new Error('Component "${componentName}" is not defined in the provided code');
@@ -274,7 +281,7 @@ export class ComponentCompiler {
274
281
  else {
275
282
  ${debug ? `console.log('[React-Runtime-JS] Component "${componentName}" is defined');` : ''}
276
283
  }
277
-
284
+
278
285
  // Store the component in a variable so we don't lose it
279
286
  const UserComponent = ${componentName};
280
287
 
@@ -283,9 +290,11 @@ export class ComponentCompiler {
283
290
  const ActualComponent = (typeof UserComponent === 'object' && UserComponent !== null && 'component' in UserComponent)
284
291
  ? UserComponent.component
285
292
  : UserComponent;
286
-
293
+
287
294
  // Debug logging to understand what we're getting
288
- ${debug ? `
295
+ ${
296
+ debug
297
+ ? `
289
298
  console.log('[React-Runtime-JS]Component ${componentName} type:', typeof UserComponent);
290
299
  if (typeof UserComponent === 'object' && UserComponent !== null) {
291
300
  console.log('[React-Runtime-JS]Component ${componentName} keys:', Object.keys(UserComponent));
@@ -293,8 +302,10 @@ export class ComponentCompiler {
293
302
  if ('component' in UserComponent) {
294
303
  console.log('[React-Runtime-JS]Component ${componentName}.component type:', typeof UserComponent.component);
295
304
  }
296
- }` : ''}
297
-
305
+ }`
306
+ : ''
307
+ }
308
+
298
309
  // Validate that we have a function (React component)
299
310
  if (typeof ActualComponent !== 'function') {
300
311
  console.error('[React-Runtime-JS] Invalid component type for ${componentName}:', typeof ActualComponent);
@@ -311,7 +322,9 @@ export class ComponentCompiler {
311
322
  if (!utilitiesOuter) {
312
323
  utilitiesOuter = props?.utilities;
313
324
  }
314
- ${debug ? `
325
+ ${
326
+ debug
327
+ ? `
315
328
  console.log('[React-Runtime-JS] DestructureWrapperUserComponent for ${componentName}:');
316
329
  console.log(' - Props:', props);
317
330
  console.log(' - componentsOuter type:', typeof componentsOuter);
@@ -329,42 +342,44 @@ export class ComponentCompiler {
329
342
  }
330
343
  console.log(' - styles:', styles);
331
344
  console.log(' - utilities:', utilitiesOuter);
332
- console.log(' - libraries:', libraries);` : ''}
345
+ console.log(' - libraries:', libraries);`
346
+ : ''
347
+ }
333
348
  ${duplicateWarnings ? '// Duplicate dependency warnings\n ' + duplicateWarnings + '\n ' : ''}
334
349
  ${libraryDeclarations ? '// Destructure Libraries\n' + libraryDeclarations + '\n ' : ''}
335
350
  ${componentDeclarations ? '// Destructure Dependencies\n' + componentDeclarations + '\n ' : ''}
336
351
  ${libraryLogChecks}
337
- ${componentLogChecks}
352
+ ${componentLogChecks}
338
353
 
339
354
  const newProps = {
340
355
  ...props,
341
356
  components: componentsOuter,
342
- utilities: utilitiesOuter
357
+ utilities: utilitiesOuter
343
358
  }
344
359
  return ActualComponent(newProps);
345
360
  };
346
-
361
+
347
362
  // Create a fresh method registry for each factory call
348
363
  const methodRegistry = new Map();
349
-
364
+
350
365
  // Create a wrapper component that provides RegisterMethod in callbacks
351
366
  const ComponentWithMethodRegistry = (props) => {
352
367
  // Register methods on mount
353
368
  React.useEffect(() => {
354
369
  // Clear previous methods
355
370
  methodRegistry.clear();
356
-
371
+
357
372
  // Provide RegisterMethod callback if callbacks exist
358
373
  if (props.callbacks && typeof props.callbacks.RegisterMethod === 'function') {
359
374
  // Component can now register its methods
360
375
  // This will be called from within the component
361
376
  }
362
377
  }, [props.callbacks]);
363
-
378
+
364
379
  // Create enhanced callbacks with RegisterMethod
365
380
  const enhancedCallbacks = React.useMemo(() => {
366
381
  if (!props.callbacks) return {};
367
-
382
+
368
383
  return {
369
384
  ...props.callbacks,
370
385
  RegisterMethod: (methodName, handler) => {
@@ -374,36 +389,36 @@ export class ComponentCompiler {
374
389
  }
375
390
  };
376
391
  }, [props.callbacks]);
377
-
392
+
378
393
  // Render the original component with enhanced callbacks
379
394
  return React.createElement(DestructureWrapperUserComponent, {
380
395
  ...props,
381
396
  callbacks: enhancedCallbacks
382
397
  });
383
398
  };
384
-
399
+
385
400
  ComponentWithMethodRegistry.displayName = '${componentName}WithMethods';
386
-
401
+
387
402
  // Return the component object with method access
388
403
  return {
389
404
  component: ComponentWithMethodRegistry,
390
-
391
- print: function() {
405
+
406
+ print: function() {
392
407
  const printMethod = methodRegistry.get('print');
393
408
  if (printMethod) {
394
409
  printMethod();
395
410
  } else if (typeof window !== 'undefined' && window.print) {
396
- window.print();
411
+ window.print();
397
412
  }
398
413
  },
399
- refresh: function(data) {
414
+ refresh: function(data) {
400
415
  const refreshMethod = methodRegistry.get('refresh');
401
416
  if (refreshMethod) {
402
417
  refreshMethod(data);
403
418
  }
404
419
  // Refresh functionality is handled by the host environment
405
420
  },
406
-
421
+
407
422
  // Standard method accessors with type safety
408
423
  getCurrentDataState: function() {
409
424
  const method = methodRegistry.get('getCurrentDataState');
@@ -433,7 +448,7 @@ export class ComponentCompiler {
433
448
  const method = methodRegistry.get('focus');
434
449
  if (method) method(target);
435
450
  },
436
-
451
+
437
452
  // Generic method invoker for custom methods
438
453
  invokeMethod: function(methodName, ...args) {
439
454
  const method = methodRegistry.get(methodName);
@@ -443,7 +458,7 @@ export class ComponentCompiler {
443
458
  console.warn(\`[React-Runtime-JS] Method '\${methodName}' is not registered on component ${componentName}\`);
444
459
  return undefined;
445
460
  },
446
-
461
+
447
462
  // Check if a method exists
448
463
  hasMethod: function(methodName) {
449
464
  return methodRegistry.has(methodName);
@@ -463,14 +478,14 @@ export class ComponentCompiler {
463
478
  */
464
479
  private async loadRequiredLibraries(libraries: any[], componentLibraries: ComponentLibraryEntity[]): Promise<Map<string, any>> {
465
480
  const loadedLibraries = new Map<string, any>();
466
-
481
+
467
482
  if (this.config.debug) {
468
483
  console.log('🔍 loadRequiredLibraries called with:', {
469
484
  librariesCount: libraries?.length || 0,
470
- libraries: libraries?.map(l => ({ name: l.name, version: l.version, globalVariable: l.globalVariable }))
485
+ libraries: libraries?.map((l) => ({ name: l.name, version: l.version, globalVariable: l.globalVariable })),
471
486
  });
472
487
  }
473
-
488
+
474
489
  if (!libraries || libraries.length === 0) {
475
490
  if (this.config.debug) {
476
491
  console.log('📚 No libraries to load, returning empty map');
@@ -492,25 +507,25 @@ export class ComponentCompiler {
492
507
  }
493
508
 
494
509
  // Filter out React, ReactDOM, and invalid library entries
495
- const filteredLibraries = libraries.filter(lib => {
510
+ const filteredLibraries = libraries.filter((lib) => {
496
511
  // Check if library object is valid
497
512
  if (!lib || typeof lib !== 'object' || !lib.name) {
498
513
  console.warn(`⚠️ Invalid library entry detected (missing name):`, lib);
499
514
  return false;
500
515
  }
501
-
516
+
502
517
  // Filter out entries with 'unknown' name or missing globalVariable
503
518
  if (lib.name === 'unknown' || lib.name === 'null' || lib.name === 'undefined') {
504
519
  console.warn(`⚠️ Filtering out invalid library with name '${lib.name}':`, lib);
505
520
  return false;
506
521
  }
507
-
522
+
508
523
  // Check for missing or invalid globalVariable
509
524
  if (!lib.globalVariable || lib.globalVariable === 'undefined' || lib.globalVariable === 'null') {
510
525
  console.warn(`⚠️ Filtering out library '${lib.name}' with invalid globalVariable:`, lib.globalVariable);
511
526
  return false;
512
527
  }
513
-
528
+
514
529
  const libNameLower = lib.name.toLowerCase();
515
530
  if (libNameLower === 'react' || libNameLower === 'reactdom') {
516
531
  console.warn(`⚠️ Library '${lib.name}' is automatically loaded by the React runtime and should not be requested separately`);
@@ -518,16 +533,14 @@ export class ComponentCompiler {
518
533
  }
519
534
  return true;
520
535
  });
521
-
536
+
522
537
  // Extract library names from the filtered libraries (with extra safety)
523
- const libraryNames = filteredLibraries
524
- .map(lib => lib.name)
525
- .filter(name => name && typeof name === 'string');
526
-
538
+ const libraryNames = filteredLibraries.map((lib) => lib.name).filter((name) => name && typeof name === 'string');
539
+
527
540
  if (this.config.debug) {
528
541
  console.log('📦 Using dependency-aware loading for libraries:', libraryNames);
529
542
  }
530
-
543
+
531
544
  // If all libraries were filtered out, return empty map
532
545
  if (filteredLibraries.length === 0) {
533
546
  if (this.config.debug) {
@@ -538,12 +551,9 @@ export class ComponentCompiler {
538
551
 
539
552
  try {
540
553
  // Use the new dependency-aware loading
541
- const loadedLibraryMap = await LibraryLoader.loadLibrariesWithDependencies(
542
- libraryNames,
543
- componentLibraries,
544
- 'component-compiler',
545
- { debug: this.config.debug }
546
- );
554
+ const loadedLibraryMap = await LibraryLoader.loadLibrariesWithDependencies(libraryNames, componentLibraries, 'component-compiler', {
555
+ debug: this.config.debug,
556
+ });
547
557
 
548
558
  // Map the results to match the expected format
549
559
  // We need to map from library name to global variable
@@ -557,7 +567,7 @@ export class ComponentCompiler {
557
567
 
558
568
  // Get the loaded library from the map
559
569
  const loadedValue = loadedLibraryMap.get(lib.name);
560
-
570
+
561
571
  if (loadedValue) {
562
572
  // Store by global variable name for component access
563
573
  loadedLibraries.set(lib.globalVariable, loadedValue);
@@ -580,12 +590,12 @@ export class ComponentCompiler {
580
590
  }
581
591
  } catch (error: any) {
582
592
  console.error('Failed to load libraries with dependencies:', error);
583
-
593
+
584
594
  // Fallback to old loading method if dependency resolution fails
585
595
  if (this.config.debug) {
586
596
  console.warn('⚠️ Falling back to non-dependency-aware loading due to error');
587
597
  }
588
-
598
+
589
599
  // Load each library independently (old method)
590
600
  for (const lib of libraries) {
591
601
  if ((window as any)[lib.globalVariable]) {
@@ -596,7 +606,7 @@ export class ComponentCompiler {
596
606
  if (libraryDef) {
597
607
  const resolvedVersion = LibraryRegistry.resolveVersion(lib.name, lib.version);
598
608
  const cdnUrl = LibraryRegistry.getCdnUrl(lib.name, resolvedVersion);
599
-
609
+
600
610
  if (cdnUrl) {
601
611
  await this.loadScript(cdnUrl, lib.globalVariable);
602
612
  const libraryValue = (window as any)[lib.globalVariable];
@@ -608,12 +618,12 @@ export class ComponentCompiler {
608
618
  }
609
619
  }
610
620
  }
611
-
621
+
612
622
  if (this.config.debug) {
613
623
  console.log(`✅ All libraries loaded successfully. Total: ${loadedLibraries.size}`);
614
624
  console.log('📚 Loaded libraries map:', Array.from(loadedLibraries.keys()));
615
625
  }
616
-
626
+
617
627
  return loadedLibraries;
618
628
  }
619
629
 
@@ -623,7 +633,7 @@ export class ComponentCompiler {
623
633
  * @returns Promise that resolves when all stylesheets are loaded
624
634
  */
625
635
  private async loadStyles(urls: string[]): Promise<void> {
626
- const loadPromises = urls.map(url => {
636
+ const loadPromises = urls.map((url) => {
627
637
  return new Promise<void>((resolve) => {
628
638
  // Check if stylesheet already exists
629
639
  const existingLink = document.querySelector(`link[href="${url}"]`);
@@ -636,7 +646,7 @@ export class ComponentCompiler {
636
646
  const link = document.createElement('link');
637
647
  link.rel = 'stylesheet';
638
648
  link.href = url;
639
-
649
+
640
650
  // CSS load events are not reliable cross-browser, so resolve immediately
641
651
  // The CSS will load asynchronously but won't block component rendering
642
652
  document.head.appendChild(link);
@@ -679,13 +689,13 @@ export class ComponentCompiler {
679
689
  const script = document.createElement('script');
680
690
  script.src = url;
681
691
  script.async = true;
682
-
692
+
683
693
  script.onload = () => {
684
694
  // More robust checking with multiple attempts
685
695
  let attempts = 0;
686
696
  const maxAttempts = 20; // 2 seconds total
687
697
  const checkInterval = 100; // Check every 100ms
688
-
698
+
689
699
  const checkGlobal = () => {
690
700
  if ((window as any)[globalName]) {
691
701
  if (this.config.debug) {
@@ -697,7 +707,7 @@ export class ComponentCompiler {
697
707
  if (this.config.debug) {
698
708
  console.error(` ❌ ${globalName} not found after ${attempts * checkInterval}ms`);
699
709
  // Only log matching property names, not the entire window object
700
- const matchingKeys = Object.keys(window).filter(k => k.toLowerCase().includes(globalName.toLowerCase()));
710
+ const matchingKeys = Object.keys(window).filter((k) => k.toLowerCase().includes(globalName.toLowerCase()));
701
711
  console.log(` ℹ️ Matching window properties: ${matchingKeys.join(', ') || 'none'}`);
702
712
  }
703
713
  reject(new Error(`${globalName} not found after loading script from ${url}`));
@@ -706,15 +716,15 @@ export class ComponentCompiler {
706
716
  setTimeout(checkGlobal, checkInterval);
707
717
  }
708
718
  };
709
-
719
+
710
720
  // Start checking immediately (don't wait 100ms first)
711
721
  checkGlobal();
712
722
  };
713
-
723
+
714
724
  script.onerror = () => {
715
725
  reject(new Error(`Failed to load script: ${url}`));
716
726
  };
717
-
727
+
718
728
  document.head.appendChild(script);
719
729
  });
720
730
  }
@@ -728,7 +738,7 @@ export class ComponentCompiler {
728
738
  * @returns Component factory function
729
739
  */
730
740
  private createComponentFactory(
731
- transpiledCode: string,
741
+ transpiledCode: string,
732
742
  componentName: string,
733
743
  loadedLibraries: Map<string, any>,
734
744
  options: CompileOptions
@@ -736,17 +746,30 @@ export class ComponentCompiler {
736
746
  try {
737
747
  // Create the factory function with all React hooks and utility functions
738
748
  const factoryCreator = new Function(
739
- 'React', 'ReactDOM',
740
- 'useState', 'useEffect', 'useCallback', 'useMemo', 'useRef', 'useContext', 'useReducer', 'useLayoutEffect',
741
- 'libraries', 'styles', 'console', 'components',
742
- 'unwrapLibraryComponent', 'unwrapLibraryComponents', 'unwrapAllLibraryComponents',
749
+ 'React',
750
+ 'ReactDOM',
751
+ 'useState',
752
+ 'useEffect',
753
+ 'useCallback',
754
+ 'useMemo',
755
+ 'useRef',
756
+ 'useContext',
757
+ 'useReducer',
758
+ 'useLayoutEffect',
759
+ 'libraries',
760
+ 'styles',
761
+ 'console',
762
+ 'components',
763
+ 'unwrapLibraryComponent',
764
+ 'unwrapLibraryComponents',
765
+ 'unwrapAllLibraryComponents',
743
766
  `${transpiledCode}; return createComponent;`
744
767
  );
745
768
 
746
769
  // Return a function that executes the factory with runtime context
747
770
  return (context: RuntimeContext, styles: any = {}, components: Record<string, any> = {}) => {
748
771
  const { React, ReactDOM, libraries = {} } = context;
749
-
772
+
750
773
  // Diagnostic: Check if React is null when creating component
751
774
  if (!React) {
752
775
  console.error('🔴 CRITICAL: React is NULL in createComponentFactory!');
@@ -754,7 +777,7 @@ export class ComponentCompiler {
754
777
  console.error('Context keys:', Object.keys(context));
755
778
  throw new Error('React is null in runtime context when creating component factory');
756
779
  }
757
-
780
+
758
781
  // Additional diagnostic for React hooks
759
782
  if (!React.useState || !React.useEffect) {
760
783
  console.error('🔴 CRITICAL: React hooks are missing!');
@@ -762,18 +785,16 @@ export class ComponentCompiler {
762
785
  console.error('useState:', typeof React?.useState);
763
786
  console.error('useEffect:', typeof React?.useEffect);
764
787
  }
765
-
788
+
766
789
  // Merge loaded libraries with context libraries
767
790
  // IMPORTANT: Only include libraries that are NOT dependency-only
768
791
  // We need to filter based on the libraries array from options
769
792
  const mergedLibraries = { ...libraries };
770
-
793
+
771
794
  // Only add libraries that are explicitly requested in the component
772
795
  // This prevents dependency-only libraries from being accessible
773
- const specLibraryNames = new Set(
774
- (options.libraries || []).map((lib: any) => lib.globalVariable).filter(Boolean)
775
- );
776
-
796
+ const specLibraryNames = new Set((options.libraries || []).map((lib: any) => lib.globalVariable).filter(Boolean));
797
+
777
798
  loadedLibraries.forEach((value, key) => {
778
799
  // Only add if this library is in the spec (not just a dependency)
779
800
  if (specLibraryNames.has(key)) {
@@ -785,7 +806,8 @@ export class ComponentCompiler {
785
806
 
786
807
  // Create bound versions of unwrap functions with debug flag
787
808
  const boundUnwrapLibraryComponent = (lib: any, name: string) => unwrapLibraryComponent(lib, name, this.config.debug);
788
- const boundUnwrapLibraryComponents = (lib: any, ...names: string[]) => unwrapLibraryComponents(lib, ...names, this.config.debug as any);
809
+ const boundUnwrapLibraryComponents = (lib: any, ...names: string[]) =>
810
+ unwrapLibraryComponents(lib, ...names, this.config.debug as any);
789
811
  const boundUnwrapAllLibraryComponents = (lib: any) => unwrapAllLibraryComponents(lib, this.config.debug);
790
812
 
791
813
  // Execute the factory creator to get the createComponent function
@@ -851,7 +873,6 @@ export class ComponentCompiler {
851
873
  }
852
874
  }
853
875
 
854
-
855
876
  /**
856
877
  * Validates compilation options
857
878
  * @param options - Options to validate
@@ -862,8 +883,8 @@ export class ComponentCompiler {
862
883
  if (!options) {
863
884
  throw new Error(
864
885
  'Component compilation failed: No options provided.\n' +
865
- 'Expected an object with componentName and componentCode properties.\n' +
866
- 'Example: { componentName: "MyComponent", componentCode: "function MyComponent() { ... }" }'
886
+ 'Expected an object with componentName and componentCode properties.\n' +
887
+ 'Example: { componentName: "MyComponent", componentCode: "function MyComponent() { ... }" }'
867
888
  );
868
889
  }
869
890
 
@@ -872,9 +893,9 @@ export class ComponentCompiler {
872
893
  const providedKeys = Object.keys(options).join(', ');
873
894
  throw new Error(
874
895
  'Component compilation failed: Component name is required.\n' +
875
- `Received options with keys: [${providedKeys}]\n` +
876
- 'Please ensure your component spec includes a "name" property.\n' +
877
- 'Example: { name: "MyComponent", code: "..." }'
896
+ `Received options with keys: [${providedKeys}]\n` +
897
+ 'Please ensure your component spec includes a "name" property.\n' +
898
+ 'Example: { name: "MyComponent", code: "..." }'
878
899
  );
879
900
  }
880
901
 
@@ -882,8 +903,8 @@ export class ComponentCompiler {
882
903
  if (!options.componentCode) {
883
904
  throw new Error(
884
905
  `Component compilation failed: Component code is required for "${options.componentName}".\n` +
885
- 'Please ensure your component spec includes a "code" property with the component source code.\n' +
886
- 'Example: { name: "MyComponent", code: "function MyComponent() { return <div>Hello</div>; }" }'
906
+ 'Please ensure your component spec includes a "code" property with the component source code.\n' +
907
+ 'Example: { name: "MyComponent", code: "function MyComponent() { return <div>Hello</div>; }" }'
887
908
  );
888
909
  }
889
910
 
@@ -892,9 +913,9 @@ export class ComponentCompiler {
892
913
  const actualType = typeof options.componentCode;
893
914
  throw new Error(
894
915
  `Component compilation failed: Component code must be a string for "${options.componentName}".\n` +
895
- `Received type: ${actualType}\n` +
896
- `Received value: ${JSON.stringify(options.componentCode).substring(0, 100)}...\n` +
897
- 'Please ensure the code property contains a string of JavaScript/JSX code.'
916
+ `Received type: ${actualType}\n` +
917
+ `Received value: ${JSON.stringify(options.componentCode).substring(0, 100)}...\n` +
918
+ 'Please ensure the code property contains a string of JavaScript/JSX code.'
898
919
  );
899
920
  }
900
921
 
@@ -902,7 +923,7 @@ export class ComponentCompiler {
902
923
  if (options.componentCode.trim().length === 0) {
903
924
  throw new Error(
904
925
  `Component compilation failed: Component code is empty for "${options.componentName}".\n` +
905
- 'The code property must contain valid JavaScript/JSX code defining a React component.'
926
+ 'The code property must contain valid JavaScript/JSX code defining a React component.'
906
927
  );
907
928
  }
908
929
 
@@ -910,9 +931,11 @@ export class ComponentCompiler {
910
931
  if (!options.componentCode.includes(options.componentName)) {
911
932
  throw new Error(
912
933
  `Component compilation failed: Component code must define a component named "${options.componentName}".\n` +
913
- 'The function/component name in the code must match the componentName property.\n' +
914
- `Expected to find: function ${options.componentName}(...) or const ${options.componentName} = ...\n` +
915
- 'Code preview: ' + options.componentCode.substring(0, 200) + '...'
934
+ 'The function/component name in the code must match the componentName property.\n' +
935
+ `Expected to find: function ${options.componentName}(...) or const ${options.componentName} = ...\n` +
936
+ 'Code preview: ' +
937
+ options.componentCode.substring(0, 200) +
938
+ '...'
916
939
  );
917
940
  }
918
941
  }
@@ -949,7 +972,7 @@ export class ComponentCompiler {
949
972
  let hash = 0;
950
973
  for (let i = 0; i < code.length; i++) {
951
974
  const char = code.charCodeAt(i);
952
- hash = ((hash << 5) - hash) + char;
975
+ hash = (hash << 5) - hash + char;
953
976
  hash = hash & hash; // Convert to 32-bit integer
954
977
  }
955
978
  return `${componentName}_${hash.toString(36)}`;
@@ -965,8 +988,7 @@ export class ComponentCompiler {
965
988
  if (this.compilationCache.size >= this.config.maxCacheSize) {
966
989
  // Remove oldest entry (first in map)
967
990
  const firstKey = this.compilationCache.keys().next().value;
968
- if (firstKey)
969
- this.compilationCache.delete(firstKey);
991
+ if (firstKey) this.compilationCache.delete(firstKey);
970
992
  }
971
993
 
972
994
  const cacheKey = this.createCacheKey(component.name, code);
@@ -985,7 +1007,7 @@ export class ComponentCompiler {
985
1007
  stack: error.stack,
986
1008
  componentName,
987
1009
  phase: 'compilation',
988
- details: error
1010
+ details: error,
989
1011
  };
990
1012
  }
991
1013
 
@@ -1011,4 +1033,4 @@ export class ComponentCompiler {
1011
1033
  updateConfig(config: Partial<CompilerConfig>): void {
1012
1034
  this.config = { ...this.config, ...config };
1013
1035
  }
1014
- }
1036
+ }