@memberjunction/react-runtime 2.93.0 → 2.95.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 (64) hide show
  1. package/.turbo/turbo-build.log +6 -6
  2. package/CHANGELOG.md +28 -0
  3. package/README.md +180 -2
  4. package/dist/compiler/component-compiler.d.ts +1 -0
  5. package/dist/compiler/component-compiler.d.ts.map +1 -1
  6. package/dist/compiler/component-compiler.js +253 -61
  7. package/dist/compiler/component-compiler.js.map +1 -1
  8. package/dist/index.d.ts +3 -2
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +15 -5
  11. package/dist/index.js.map +1 -1
  12. package/dist/registry/component-registry-service.d.ts +6 -3
  13. package/dist/registry/component-registry-service.d.ts.map +1 -1
  14. package/dist/registry/component-registry-service.js +38 -11
  15. package/dist/registry/component-registry-service.js.map +1 -1
  16. package/dist/registry/component-registry.d.ts +6 -3
  17. package/dist/registry/component-registry.d.ts.map +1 -1
  18. package/dist/registry/component-registry.js +17 -0
  19. package/dist/registry/component-registry.js.map +1 -1
  20. package/dist/registry/component-resolver.d.ts +2 -1
  21. package/dist/registry/component-resolver.d.ts.map +1 -1
  22. package/dist/registry/component-resolver.js +101 -14
  23. package/dist/registry/component-resolver.js.map +1 -1
  24. package/dist/runtime/component-hierarchy.d.ts.map +1 -1
  25. package/dist/runtime/component-hierarchy.js +75 -13
  26. package/dist/runtime/component-hierarchy.js.map +1 -1
  27. package/dist/runtime/prop-builder.d.ts +2 -2
  28. package/dist/runtime/prop-builder.d.ts.map +1 -1
  29. package/dist/runtime/prop-builder.js +32 -14
  30. package/dist/runtime/prop-builder.js.map +1 -1
  31. package/dist/runtime.umd.js +1 -1
  32. package/dist/types/dependency-types.d.ts +62 -0
  33. package/dist/types/dependency-types.d.ts.map +1 -0
  34. package/dist/types/dependency-types.js +3 -0
  35. package/dist/types/dependency-types.js.map +1 -0
  36. package/dist/types/index.d.ts +8 -10
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/dist/types/index.js +1 -0
  39. package/dist/types/index.js.map +1 -1
  40. package/dist/utilities/index.d.ts +1 -0
  41. package/dist/utilities/index.d.ts.map +1 -1
  42. package/dist/utilities/index.js +1 -0
  43. package/dist/utilities/index.js.map +1 -1
  44. package/dist/utilities/library-dependency-resolver.d.ts +19 -0
  45. package/dist/utilities/library-dependency-resolver.d.ts.map +1 -0
  46. package/dist/utilities/library-dependency-resolver.js +419 -0
  47. package/dist/utilities/library-dependency-resolver.js.map +1 -0
  48. package/dist/utilities/library-loader.d.ts +9 -0
  49. package/dist/utilities/library-loader.d.ts.map +1 -1
  50. package/dist/utilities/library-loader.js +164 -0
  51. package/dist/utilities/library-loader.js.map +1 -1
  52. package/package.json +5 -5
  53. package/src/compiler/component-compiler.ts +280 -82
  54. package/src/index.ts +20 -5
  55. package/src/registry/component-registry-service.ts +53 -14
  56. package/src/registry/component-registry.ts +36 -7
  57. package/src/registry/component-resolver.ts +130 -16
  58. package/src/runtime/component-hierarchy.ts +101 -27
  59. package/src/runtime/prop-builder.ts +38 -18
  60. package/src/types/dependency-types.ts +110 -0
  61. package/src/types/index.ts +17 -21
  62. package/src/utilities/index.ts +1 -0
  63. package/src/utilities/library-dependency-resolver.ts +613 -0
  64. package/src/utilities/library-loader.ts +274 -0
@@ -13,7 +13,9 @@ import {
13
13
  ComponentError,
14
14
  RuntimeContext
15
15
  } from '../types';
16
+ import { ComponentStyles, ComponentObject } from '@memberjunction/interactive-component-types';
16
17
  import { LibraryRegistry } from '../utilities/library-registry';
18
+ import { LibraryLoader } from '../utilities/library-loader';
17
19
  import { ComponentLibraryEntity } from '@memberjunction/core-entities';
18
20
 
19
21
  /**
@@ -27,7 +29,8 @@ const DEFAULT_COMPILER_CONFIG: CompilerConfig = {
27
29
  minify: false,
28
30
  sourceMaps: false,
29
31
  cache: true,
30
- maxCacheSize: 100
32
+ maxCacheSize: 100,
33
+ debug: false
31
34
  };
32
35
 
33
36
  /**
@@ -100,7 +103,7 @@ export class ComponentCompiler {
100
103
 
101
104
  // Build the compiled component
102
105
  const compiledComponent: CompiledComponent = {
103
- component: componentFactory,
106
+ factory: componentFactory,
104
107
  id: this.generateComponentId(options.componentName),
105
108
  name: options.componentName,
106
109
  compiledAt: new Date(),
@@ -169,67 +172,241 @@ export class ComponentCompiler {
169
172
  * @param dependencies - Optional child component dependencies
170
173
  * @returns Wrapped component code
171
174
  */
175
+ // Core libraries that are passed as parameters to createComponent and should not be destructured
176
+ private readonly CORE_LIBRARIES = new Set(['React', 'ReactDOM']);
177
+
172
178
  private wrapComponentCode(componentCode: string, componentName: string, libraries?: any[], dependencies?: Array<{ name: string }>): string {
173
179
  // Generate library declarations if libraries are provided
180
+ // Skip core libraries as they're passed as parameters to createComponent
174
181
  const libraryDeclarations = libraries && libraries.length > 0
175
182
  ? libraries
176
- .filter(lib => lib.globalVariable) // Only include libraries with globalVariable
183
+ .filter(lib => lib.globalVariable && !this.CORE_LIBRARIES.has(lib.globalVariable)) // Skip core libraries
177
184
  .map(lib => `const ${lib.globalVariable} = libraries['${lib.globalVariable}'];`)
178
185
  .join('\n ')
179
186
  : '';
180
-
187
+ const libraryLogChecks = libraries && libraries.length > 0
188
+ ? libraries
189
+ .filter(lib => lib.globalVariable && !this.CORE_LIBRARIES.has(lib.globalVariable)) // Skip core libraries
190
+ .map(lib => `\nif (!${lib.globalVariable}) { console.error('[React-Runtime-JS] Library "${lib.globalVariable}" is not defined'); } else { console.log('[React-Runtime-JS] Library "${lib.globalVariable}" is defined'); }`)
191
+ .join('\n ')
192
+ : '';
193
+
181
194
  // Generate component declarations if dependencies are provided
195
+ // Filter out the component being compiled to avoid naming conflicts
182
196
  const componentDeclarations = dependencies && dependencies.length > 0
183
197
  ? dependencies
184
- .map(dep => `const ${dep.name} = components['${dep.name}'];`)
198
+ .filter(dep => dep.name !== componentName) // Don't destructure the component being compiled itself
199
+ .map(dep => `const ${dep.name} = componentsOuter['${dep.name}'];`)
200
+ .join('\n ')
201
+ : '';
202
+ const componentLogChecks = dependencies && dependencies.length > 0
203
+ ? dependencies
204
+ .filter(dep => dep.name !== componentName) // Don't destructure the component being compiled itself
205
+ .map(dep => `if (!${dep.name}) { console.error('[React-Runtime-JS] Dependency "${dep.name}" is not defined'); } else { console.log('[React-Runtime-JS] Dependency "${dep.name}" is defined'); }`)
185
206
  .join('\n ')
186
207
  : '';
187
208
 
188
- return `
209
+ const wrappedCode = `
189
210
  function createComponent(
190
211
  React, ReactDOM,
191
212
  useState, useEffect, useCallback, useMemo, useRef, useContext, useReducer, useLayoutEffect,
192
213
  libraries, styles, console, components
193
214
  ) {
194
- ${libraryDeclarations ? libraryDeclarations + '\n ' : ''}${componentDeclarations ? componentDeclarations + '\n ' : ''}${componentCode}
215
+ // Code for ${componentName}
216
+ ${componentCode}
195
217
 
196
218
  // Ensure the component exists
197
219
  if (typeof ${componentName} === 'undefined') {
198
220
  throw new Error('Component "${componentName}" is not defined in the provided code');
199
221
  }
222
+ else {
223
+ console.log('[React-Runtime-JS] Component "${componentName}" is defined');
224
+ }
200
225
 
201
- // Return the component with utilities
226
+ // Store the component in a variable so we don't lose it
227
+ const UserComponent = ${componentName};
228
+
229
+ // Check if the component is already a ComponentObject (has a .component property)
230
+ // If so, extract the actual React component
231
+ const ActualComponent = (typeof UserComponent === 'object' && UserComponent !== null && 'component' in UserComponent)
232
+ ? UserComponent.component
233
+ : UserComponent;
234
+
235
+ // Debug logging to understand what we're getting
236
+ console.log('[React-Runtime-JS]Component ${componentName} type:', typeof UserComponent);
237
+ if (typeof UserComponent === 'object' && UserComponent !== null) {
238
+ console.log('[React-Runtime-JS]Component ${componentName} keys:', Object.keys(UserComponent));
239
+ console.log('[React-Runtime-JS]Component ${componentName} has .component:', 'component' in UserComponent);
240
+ if ('component' in UserComponent) {
241
+ console.log('[React-Runtime-JS]Component ${componentName}.component type:', typeof UserComponent.component);
242
+ }
243
+ }
244
+
245
+ // Validate that we have a function (React component)
246
+ if (typeof ActualComponent !== 'function') {
247
+ console.error('[React-Runtime-JS] Invalid component type for ${componentName}:', typeof ActualComponent);
248
+ console.error('[React-Runtime-JS] ActualComponent value:', ActualComponent);
249
+ console.error('[React-Runtime-JS] Original UserComponent value:', UserComponent);
250
+ throw new Error('[React-Runtime-JS] Component "${componentName}" must be a function (React component) or an object with a .component property that is a function. Got: ' + typeof ActualComponent);
251
+ }
252
+
253
+ let componentsOuter = null, utilitiesOuter = null;
254
+ const DestructureWrapperUserComponent = (props) => {
255
+ if (!componentsOuter) {
256
+ componentsOuter = props?.components || components;
257
+ }
258
+ if (!utilitiesOuter) {
259
+ utilitiesOuter = props?.utilities;
260
+ }
261
+ console.log('Props for ${componentName}:', props);
262
+ console.log('components for ${componentName}:', componentsOuter);
263
+ console.log('styles for ${componentName}:', styles);
264
+ console.log('utilities for ${componentName}:', utilitiesOuter);
265
+ console.log('libraries for ${componentName}:', libraries);
266
+ ${libraryDeclarations ? '// Destructure Libraries\n' + libraryDeclarations + '\n ' : ''}
267
+ ${componentDeclarations ? '// Destructure Dependencies\n' + componentDeclarations + '\n ' : ''}
268
+ ${libraryLogChecks}
269
+ ${componentLogChecks}
270
+
271
+ const newProps = {
272
+ ...props,
273
+ components: componentsOuter,
274
+ utilities: utilitiesOuter
275
+ }
276
+ return ActualComponent(newProps);
277
+ };
278
+
279
+ // Create a fresh method registry for each factory call
280
+ const methodRegistry = new Map();
281
+
282
+ // Create a wrapper component that provides RegisterMethod in callbacks
283
+ const ComponentWithMethodRegistry = (props) => {
284
+ // Register methods on mount
285
+ React.useEffect(() => {
286
+ // Clear previous methods
287
+ methodRegistry.clear();
288
+
289
+ // Provide RegisterMethod callback if callbacks exist
290
+ if (props.callbacks && typeof props.callbacks.RegisterMethod === 'function') {
291
+ // Component can now register its methods
292
+ // This will be called from within the component
293
+ }
294
+ }, [props.callbacks]);
295
+
296
+ // Create enhanced callbacks with RegisterMethod
297
+ const enhancedCallbacks = React.useMemo(() => {
298
+ if (!props.callbacks) return {};
299
+
300
+ return {
301
+ ...props.callbacks,
302
+ RegisterMethod: (methodName, handler) => {
303
+ if (methodName && handler) {
304
+ methodRegistry.set(methodName, handler);
305
+ }
306
+ }
307
+ };
308
+ }, [props.callbacks]);
309
+
310
+ // Render the original component with enhanced callbacks
311
+ return React.createElement(DestructureWrapperUserComponent, {
312
+ ...props,
313
+ callbacks: enhancedCallbacks
314
+ });
315
+ };
316
+
317
+ ComponentWithMethodRegistry.displayName = '${componentName}WithMethods';
318
+
319
+ // Return the component object with method access
202
320
  return {
203
- component: ${componentName},
321
+ component: ComponentWithMethodRegistry,
322
+
204
323
  print: function() {
205
- if (typeof window !== 'undefined' && window.print) {
324
+ const printMethod = methodRegistry.get('print');
325
+ if (printMethod) {
326
+ printMethod();
327
+ } else if (typeof window !== 'undefined' && window.print) {
206
328
  window.print();
207
329
  }
208
330
  },
209
331
  refresh: function(data) {
332
+ const refreshMethod = methodRegistry.get('refresh');
333
+ if (refreshMethod) {
334
+ refreshMethod(data);
335
+ }
210
336
  // Refresh functionality is handled by the host environment
337
+ },
338
+
339
+ // Standard method accessors with type safety
340
+ getCurrentDataState: function() {
341
+ const method = methodRegistry.get('getCurrentDataState');
342
+ return method ? method() : undefined;
343
+ },
344
+ getDataStateHistory: function() {
345
+ const method = methodRegistry.get('getDataStateHistory');
346
+ return method ? method() : [];
347
+ },
348
+ validate: function() {
349
+ const method = methodRegistry.get('validate');
350
+ return method ? method() : true;
351
+ },
352
+ isDirty: function() {
353
+ const method = methodRegistry.get('isDirty');
354
+ return method ? method() : false;
355
+ },
356
+ reset: function() {
357
+ const method = methodRegistry.get('reset');
358
+ if (method) method();
359
+ },
360
+ scrollTo: function(target) {
361
+ const method = methodRegistry.get('scrollTo');
362
+ if (method) method(target);
363
+ },
364
+ focus: function(target) {
365
+ const method = methodRegistry.get('focus');
366
+ if (method) method(target);
367
+ },
368
+
369
+ // Generic method invoker for custom methods
370
+ invokeMethod: function(methodName, ...args) {
371
+ const method = methodRegistry.get(methodName);
372
+ if (method) {
373
+ return method(...args);
374
+ }
375
+ console.warn(\`[React-Runtime-JS] Method '\${methodName}' is not registered on component ${componentName}\`);
376
+ return undefined;
377
+ },
378
+
379
+ // Check if a method exists
380
+ hasMethod: function(methodName) {
381
+ return methodRegistry.has(methodName);
211
382
  }
212
383
  };
213
384
  }
214
385
  `;
386
+
387
+ return wrappedCode;
215
388
  }
216
389
 
217
390
  /**
218
- * Load required libraries from the registry
391
+ * Load required libraries from the registry with dependency resolution
219
392
  * @param libraries - Array of library dependencies
220
- * @param contextUser - Context user for accessing library registry
393
+ * @param componentLibraries - All available component libraries for dependency resolution
221
394
  * @returns Map of loaded libraries
222
395
  */
223
396
  private async loadRequiredLibraries(libraries: any[], componentLibraries: ComponentLibraryEntity[]): Promise<Map<string, any>> {
224
397
  const loadedLibraries = new Map<string, any>();
225
398
 
226
- console.log('🔍 loadRequiredLibraries called with:', {
227
- librariesCount: libraries?.length || 0,
228
- libraries: libraries?.map(l => ({ name: l.name, version: l.version, globalVariable: l.globalVariable }))
229
- });
399
+ if (this.config.debug) {
400
+ console.log('🔍 loadRequiredLibraries called with:', {
401
+ librariesCount: libraries?.length || 0,
402
+ libraries: libraries?.map(l => ({ name: l.name, version: l.version, globalVariable: l.globalVariable }))
403
+ });
404
+ }
230
405
 
231
406
  if (!libraries || libraries.length === 0) {
232
- console.log('📚 No libraries to load, returning empty map');
407
+ if (this.config.debug) {
408
+ console.log('📚 No libraries to load, returning empty map');
409
+ }
233
410
  return loadedLibraries;
234
411
  }
235
412
 
@@ -246,75 +423,90 @@ export class ComponentCompiler {
246
423
  console.warn('âš ī¸ No componentLibraries provided for LibraryRegistry initialization');
247
424
  }
248
425
 
249
- const loadPromises = libraries.map(async (lib) => {
250
- console.log(`đŸ“Ļ Processing library: ${lib.name}`);
251
-
252
- // Check if library is approved
253
- const isApproved = LibraryRegistry.isApproved(lib.name);
254
- console.log(` ✓ Approved check for ${lib.name}: ${isApproved}`);
255
-
256
- if (!isApproved) {
257
- console.error(` ❌ Library '${lib.name}' is not approved`);
258
- throw new Error(`Library '${lib.name}' is not approved. Only approved libraries can be used.`);
259
- }
260
-
261
- // Get library definition for complete info
262
- const libraryDef = LibraryRegistry.getLibrary(lib.name);
263
- console.log(` ✓ Library definition found for ${lib.name}: ${!!libraryDef}`);
264
-
265
- if (!libraryDef) {
266
- console.error(` ❌ Library '${lib.name}' not found in registry`);
267
- throw new Error(`Library '${lib.name}' not found in registry`);
268
- }
426
+ // Extract library names from the requested libraries
427
+ const libraryNames = libraries.map(lib => lib.name);
428
+
429
+ if (this.config.debug) {
430
+ console.log('đŸ“Ļ Using dependency-aware loading for libraries:', libraryNames);
431
+ }
269
432
 
270
- // Get CDN URL for the library
271
- const resolvedVersion = LibraryRegistry.resolveVersion(lib.name, lib.version);
272
- console.log(` ✓ Resolved version for ${lib.name}: ${resolvedVersion}`);
273
-
274
- const cdnUrl = LibraryRegistry.getCdnUrl(lib.name, resolvedVersion);
275
- console.log(` ✓ CDN URL for ${lib.name}: ${cdnUrl}`);
276
-
277
- if (!cdnUrl) {
278
- console.error(` ❌ No CDN URL found for library '${lib.name}' version '${lib.version || 'default'}'`);
279
- throw new Error(`No CDN URL found for library '${lib.name}' version '${lib.version || 'default'}'`);
280
- }
433
+ try {
434
+ // Use the new dependency-aware loading
435
+ const loadedLibraryMap = await LibraryLoader.loadLibrariesWithDependencies(
436
+ libraryNames,
437
+ componentLibraries,
438
+ 'component-compiler',
439
+ { debug: this.config.debug }
440
+ );
281
441
 
282
- // Check if already loaded
283
- if ((window as any)[lib.globalVariable]) {
284
- console.log(` â„šī¸ Library ${lib.name} already loaded globally as ${lib.globalVariable}`);
285
- loadedLibraries.set(lib.globalVariable, (window as any)[lib.globalVariable]);
286
- return;
287
- }
442
+ // Map the results to match the expected format
443
+ // We need to map from library name to global variable
444
+ for (const lib of libraries) {
445
+ // Check if library is approved first
446
+ const isApproved = LibraryRegistry.isApproved(lib.name);
447
+ if (!isApproved) {
448
+ console.error(`❌ Library '${lib.name}' is not approved`);
449
+ throw new Error(`Library '${lib.name}' is not approved. Only approved libraries can be used.`);
450
+ }
288
451
 
289
- // Load CSS files if the library requires them
290
- const versionInfo = libraryDef.versions[resolvedVersion || libraryDef.defaultVersion];
291
- if (versionInfo?.cssUrls) {
292
- await this.loadStyles(versionInfo.cssUrls);
452
+ // Get the loaded library from the map
453
+ const loadedValue = loadedLibraryMap.get(lib.name);
454
+
455
+ if (loadedValue) {
456
+ // Store by global variable name for component access
457
+ loadedLibraries.set(lib.globalVariable, loadedValue);
458
+ if (this.config.debug) {
459
+ console.log(`✅ Mapped ${lib.name} to global variable ${lib.globalVariable}`);
460
+ }
461
+ } else {
462
+ // Fallback: check if it's already globally available (might be a dependency)
463
+ const globalValue = (window as any)[lib.globalVariable];
464
+ if (globalValue) {
465
+ loadedLibraries.set(lib.globalVariable, globalValue);
466
+ if (this.config.debug) {
467
+ console.log(`✅ Found ${lib.name} already loaded as ${lib.globalVariable}`);
468
+ }
469
+ } else {
470
+ console.error(`❌ Library '${lib.name}' failed to load`);
471
+ throw new Error(`Library '${lib.name}' failed to load or did not expose '${lib.globalVariable}'`);
472
+ }
473
+ }
293
474
  }
294
-
295
- // Load the library dynamically (cdnUrl is guaranteed to be non-null here due to check above)
296
- console.log(` đŸ“Ĩ Loading script from CDN for ${lib.name}...`);
297
- await this.loadScript(cdnUrl!, lib.globalVariable);
475
+ } catch (error: any) {
476
+ console.error('Failed to load libraries with dependencies:', error);
298
477
 
299
- // Capture the library value from global scope
300
- // Note: Libraries loaded from CDN typically attach to window automatically
301
- // We capture them here to pass through the component's closure
302
- const libraryValue = (window as any)[lib.globalVariable];
303
- console.log(` ✓ Library ${lib.name} loaded successfully, global variable ${lib.globalVariable} is:`, typeof libraryValue);
478
+ // Fallback to old loading method if dependency resolution fails
479
+ if (this.config.debug) {
480
+ console.warn('âš ī¸ Falling back to non-dependency-aware loading due to error');
481
+ }
304
482
 
305
- if (libraryValue) {
306
- loadedLibraries.set(lib.globalVariable, libraryValue);
307
- console.log(` ✅ Added ${lib.name} to loaded libraries map`);
308
- } else {
309
- console.error(` ❌ Library '${lib.name}' failed to expose global variable '${lib.globalVariable}'`);
310
- throw new Error(`Library '${lib.name}' failed to load or did not expose '${lib.globalVariable}'`);
483
+ // Load each library independently (old method)
484
+ for (const lib of libraries) {
485
+ if ((window as any)[lib.globalVariable]) {
486
+ loadedLibraries.set(lib.globalVariable, (window as any)[lib.globalVariable]);
487
+ } else {
488
+ // Try to load using LibraryRegistry
489
+ const libraryDef = LibraryRegistry.getLibrary(lib.name);
490
+ if (libraryDef) {
491
+ const resolvedVersion = LibraryRegistry.resolveVersion(lib.name, lib.version);
492
+ const cdnUrl = LibraryRegistry.getCdnUrl(lib.name, resolvedVersion);
493
+
494
+ if (cdnUrl) {
495
+ await this.loadScript(cdnUrl, lib.globalVariable);
496
+ const libraryValue = (window as any)[lib.globalVariable];
497
+ if (libraryValue) {
498
+ loadedLibraries.set(lib.globalVariable, libraryValue);
499
+ }
500
+ }
501
+ }
502
+ }
311
503
  }
312
- });
313
-
314
- await Promise.all(loadPromises);
504
+ }
315
505
 
316
- console.log(`✅ All libraries loaded successfully. Total: ${loadedLibraries.size}`);
317
- console.log('📚 Loaded libraries map:', Array.from(loadedLibraries.keys()));
506
+ if (this.config.debug) {
507
+ console.log(`✅ All libraries loaded successfully. Total: ${loadedLibraries.size}`);
508
+ console.log('📚 Loaded libraries map:', Array.from(loadedLibraries.keys()));
509
+ }
318
510
 
319
511
  return loadedLibraries;
320
512
  }
@@ -390,12 +582,18 @@ export class ComponentCompiler {
390
582
 
391
583
  const checkGlobal = () => {
392
584
  if ((window as any)[globalName]) {
393
- console.log(` ✓ Global variable ${globalName} found after ${attempts * checkInterval}ms`);
585
+ if (this.config.debug) {
586
+ console.log(` ✓ Global variable ${globalName} found after ${attempts * checkInterval}ms`);
587
+ }
394
588
  resolve();
395
589
  } else if (attempts >= maxAttempts) {
396
590
  // Final check - some libraries might use a different global name pattern
397
- console.error(` ❌ ${globalName} not found after ${attempts * checkInterval}ms`);
398
- console.log(` â„šī¸ Window properties:`, Object.keys(window).filter(k => k.toLowerCase().includes(globalName.toLowerCase())));
591
+ if (this.config.debug) {
592
+ console.error(` ❌ ${globalName} not found after ${attempts * checkInterval}ms`);
593
+ // Only log matching property names, not the entire window object
594
+ const matchingKeys = Object.keys(window).filter(k => k.toLowerCase().includes(globalName.toLowerCase()));
595
+ console.log(` â„šī¸ Matching window properties: ${matchingKeys.join(', ') || 'none'}`);
596
+ }
399
597
  reject(new Error(`${globalName} not found after loading script from ${url}`));
400
598
  } else {
401
599
  attempts++;
@@ -426,7 +624,7 @@ export class ComponentCompiler {
426
624
  transpiledCode: string,
427
625
  componentName: string,
428
626
  loadedLibraries: Map<string, any>
429
- ): Function {
627
+ ): (context: RuntimeContext, styles?: ComponentStyles) => ComponentObject {
430
628
  try {
431
629
  // Create the factory function with all React hooks
432
630
  const factoryCreator = new Function(
package/src/index.ts CHANGED
@@ -29,7 +29,8 @@ export { ComponentRegistry } from './registry';
29
29
  export {
30
30
  ComponentResolver,
31
31
  ComponentSpec,
32
- ResolvedComponents
32
+ ResolvedComponents,
33
+ ComponentRegistryService
33
34
  } from './registry';
34
35
 
35
36
  // Export runtime APIs
@@ -139,6 +140,7 @@ export const DEFAULT_CONFIGS = {
139
140
  * @param babelInstance - Babel standalone instance for compilation
140
141
  * @param config - Optional configuration overrides
141
142
  * @param runtimeContext - Optional runtime context for registry-based components
143
+ * @param debug - Enable debug logging (defaults to false)
142
144
  * @returns Object containing compiler, registry, and resolver instances
143
145
  */
144
146
  export function createReactRuntime(
@@ -147,18 +149,31 @@ export function createReactRuntime(
147
149
  compiler?: Partial<import('./types').CompilerConfig>;
148
150
  registry?: Partial<import('./types').RegistryConfig>;
149
151
  },
150
- runtimeContext?: import('./types').RuntimeContext
152
+ runtimeContext?: import('./types').RuntimeContext,
153
+ debug: boolean = false
151
154
  ) {
152
- const compiler = new ComponentCompiler(config?.compiler);
155
+ // Merge debug flag into configs
156
+ const compilerConfig = {
157
+ ...config?.compiler,
158
+ debug: config?.compiler?.debug ?? debug
159
+ };
160
+
161
+ const registryConfig = {
162
+ ...config?.registry,
163
+ debug: config?.registry?.debug ?? debug
164
+ };
165
+
166
+ const compiler = new ComponentCompiler(compilerConfig);
153
167
  compiler.setBabelInstance(babelInstance);
154
168
 
155
- const registry = new ComponentRegistry(config?.registry);
169
+ const registry = new ComponentRegistry(registryConfig);
156
170
  const resolver = new ComponentResolver(registry, compiler, runtimeContext);
157
171
 
158
172
  return {
159
173
  compiler,
160
174
  registry,
161
175
  resolver,
162
- version: VERSION
176
+ version: VERSION,
177
+ debug
163
178
  };
164
179
  }