@memberjunction/react-runtime 2.112.0 → 2.113.1

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